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