001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2014 ForgeRock AS.
016 */
017package org.opends.server.types;
018
019import java.io.IOException;
020import java.util.ArrayList;
021
022import org.forgerock.i18n.LocalizableMessage;
023import org.forgerock.i18n.slf4j.LocalizedLogger;
024import org.forgerock.opendj.io.ASN1Reader;
025import org.forgerock.opendj.io.ASN1Writer;
026import org.forgerock.opendj.ldap.ByteString;
027import org.forgerock.opendj.ldap.ModificationType;
028import org.opends.server.protocols.ldap.LDAPModification;
029
030import static org.opends.messages.ProtocolMessages.*;
031import static org.opends.server.protocols.ldap.LDAPConstants.*;
032import static org.opends.server.protocols.ldap.LDAPResultCode.*;
033
034/**
035 * This class defines the data structures and methods to use when
036 * interacting with a raw modification, which describes a change that
037 * should be made to an attribute.
038 */
039@org.opends.server.types.PublicAPI(
040     stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
041     mayInstantiate=true,
042     mayExtend=false,
043     mayInvoke=true)
044public abstract class RawModification
045{
046  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
047
048  /**
049   * Creates a new raw modification with the provided type and
050   * attribute.
051   *
052   * @param  modificationType  The modification type for this
053   *                           modification.
054   * @param  attribute         The attribute for this modification.
055   *
056   * @return  The constructed raw modification.
057   */
058  public static RawModification
059                     create(ModificationType modificationType,
060                            RawAttribute attribute)
061  {
062    return new LDAPModification(modificationType, attribute);
063  }
064
065
066
067  /**
068   * Creates a new raw modification with the provided type and
069   * attribute.
070   *
071   * @param  modificationType  The modification type for this
072   *                           modification.
073   * @param  attributeType     The name of the attribute type for this
074   *                           modification.
075   *
076   * @return  The constructed raw modification.
077   */
078  public static RawModification
079                     create(ModificationType modificationType,
080                            String attributeType)
081  {
082    RawAttribute rawAttribute = RawAttribute.create(attributeType);
083
084    return new LDAPModification(modificationType, rawAttribute);
085  }
086
087
088
089  /**
090   * Creates a new raw modification with the provided type and
091   * attribute.
092   *
093   * @param  modificationType  The modification type for this
094   *                           modification.
095   * @param  attributeType     The name of the attribute type for this
096   *                           modification.
097   * @param  attributeValue    The attribute value for this
098   *                           modification.
099   *
100   * @return  The constructed raw modification.
101   */
102  public static RawModification
103                     create(ModificationType modificationType,
104                            String attributeType,
105                            String attributeValue)
106  {
107    RawAttribute rawAttribute =
108         RawAttribute.create(attributeType, attributeValue);
109
110    return new LDAPModification(modificationType, rawAttribute);
111  }
112
113
114
115  /**
116   * Creates a new raw modification with the provided type and
117   * attribute.
118   *
119   * @param  modificationType  The modification type for this
120   *                           modification.
121   * @param  attributeType     The name of the attribute type for this
122   *                           modification.
123   * @param  attributeValue    The attribute value for this
124   *                           modification.
125   *
126   * @return  The constructed raw modification.
127   */
128  public static RawModification
129                     create(ModificationType modificationType,
130                            String attributeType,
131                            ByteString attributeValue)
132  {
133    RawAttribute rawAttribute =
134         RawAttribute.create(attributeType, attributeValue);
135
136    return new LDAPModification(modificationType, rawAttribute);
137  }
138
139
140
141  /**
142   * Creates a new raw modification with the provided type and
143   * attribute.
144   *
145   * @param  modificationType  The modification type for this
146   *                           modification.
147   * @param  attributeType     The name of the attribute type for this
148   *                           modification.
149   * @param  attributeValues   The set of attribute values for this
150   *                           modification.
151   *
152   * @return  The constructed raw modification.
153   */
154  public static RawModification
155                     create(ModificationType modificationType,
156                            String attributeType,
157                            ArrayList<ByteString> attributeValues)
158  {
159    RawAttribute rawAttribute =
160         RawAttribute.create(attributeType, attributeValues);
161
162    return new LDAPModification(modificationType, rawAttribute);
163  }
164
165
166
167  /**
168   * Retrieves the modification type for this modification.
169   *
170   * @return  The modification type for this modification.
171   */
172  public abstract ModificationType getModificationType();
173
174
175
176  /**
177   * Specifies the modification type for this modification.
178   *
179   * @param  modificationType  The modification type for this
180   *                           modification.
181   */
182  public abstract void setModificationType(
183                            ModificationType modificationType);
184
185
186
187  /**
188   * Retrieves the attribute for this modification.
189   *
190   * @return  The attribute for this modification.
191   */
192  public abstract RawAttribute getAttribute();
193
194
195
196  /**
197   * Specifies the attribute for this modification.
198   *
199   * @param  attribute  The attribute for this modification.
200   */
201  public abstract void setAttribute(RawAttribute attribute);
202
203
204
205  /**
206   * Writes this modification to an ASN.1 stream.
207   *
208   * @param stream The ASN.1 output stream to write to.
209   * @throws IOException If a problem occurs while writing to the
210   *                     stream.
211   */
212  public void write(ASN1Writer stream) throws IOException
213  {
214    stream.writeStartSequence();
215    stream.writeEnumerated(getModificationType().intValue());
216    getAttribute().write(stream);
217    stream.writeEndSequence();
218  }
219
220
221  /**
222   * Decodes the elements from the provided ASN.1 reader as an
223   * LDAP modification.
224   *
225   * @param  reader The ASN.1 reader.
226   *
227   * @return  The decoded LDAP modification.
228   *
229   * @throws  LDAPException  If a problem occurs while attempting to
230   *                         decode the provided ASN.1 element as a
231   *                         raw modification.
232   */
233  public static LDAPModification decode(ASN1Reader reader)
234         throws LDAPException
235  {
236    try
237    {
238      reader.readStartSequence();
239    }
240    catch (Exception e)
241    {
242      logger.traceException(e);
243
244      LocalizableMessage message = ERR_LDAP_MODIFICATION_DECODE_SEQUENCE.get(e);
245      throw new LDAPException(PROTOCOL_ERROR, message, e);
246    }
247
248
249    ModificationType modificationType;
250    try
251    {
252      int type = (int)reader.readInteger();
253      switch (type)
254      {
255        case MOD_TYPE_ADD:
256          modificationType = ModificationType.ADD;
257          break;
258        case MOD_TYPE_DELETE:
259          modificationType = ModificationType.DELETE;
260          break;
261        case MOD_TYPE_REPLACE:
262          modificationType = ModificationType.REPLACE;
263          break;
264        case MOD_TYPE_INCREMENT:
265          modificationType = ModificationType.INCREMENT;
266          break;
267        default:
268          LocalizableMessage message =
269              ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE.
270                get(type);
271          throw new LDAPException(PROTOCOL_ERROR, message);
272      }
273    }
274    catch (LDAPException le)
275    {
276      throw le;
277    }
278    catch (Exception e)
279    {
280      logger.traceException(e);
281
282      LocalizableMessage message = ERR_LDAP_MODIFICATION_DECODE_MOD_TYPE.get(e);
283      throw new LDAPException(PROTOCOL_ERROR, message, e);
284    }
285
286
287    RawAttribute attribute;
288    try
289    {
290      attribute = RawAttribute.decode(reader);
291    }
292    catch (Exception e)
293    {
294      logger.traceException(e);
295
296      LocalizableMessage message = ERR_LDAP_MODIFICATION_DECODE_ATTR.get(e);
297      throw new LDAPException(PROTOCOL_ERROR, message, e);
298    }
299
300    try
301    {
302      reader.readEndSequence();
303    }
304    catch (Exception e)
305    {
306      logger.traceException(e);
307
308      LocalizableMessage message = ERR_LDAP_MODIFICATION_DECODE_SEQUENCE.get(e);
309      throw new LDAPException(PROTOCOL_ERROR, message, e);
310    }
311
312
313    return new LDAPModification(modificationType, attribute);
314  }
315
316
317
318  /**
319   * Creates a new core {@code Modification} object from this raw
320   * modification.
321   *
322   * @return  The decoded modification.
323   *
324   * @throws  LDAPException  If a problem occurs while trying to
325   *                         convert the raw modification to a core
326   *                         {@code Modification}.
327   */
328  public abstract Modification toModification()
329         throws LDAPException;
330
331
332
333  /**
334   * Retrieves a string representation of this modification.
335   *
336   * @return  A string representation of this modification.
337   */
338  @Override
339  public String toString()
340  {
341    StringBuilder buffer = new StringBuilder();
342    toString(buffer);
343    return buffer.toString();
344  }
345
346
347
348  /**
349   * Appends a string representation of this modification to the
350   * provided buffer.
351   *
352   * @param  buffer  The buffer to which the information should be
353   *                 appended.
354   */
355  public abstract void toString(StringBuilder buffer);
356
357
358
359  /**
360   * Appends a multi-line string representation of this LDAP
361   * modification to the provided buffer.
362   *
363   * @param  buffer  The buffer to which the information should be
364   *                 appended.
365   * @param  indent  The number of spaces from the margin that the
366   *                 lines should be indented.
367   */
368  public abstract void toString(StringBuilder buffer, int indent);
369}
370