001    /*
002     * Copyright 2007-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2016 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldif;
022    
023    
024    
025    import java.util.ArrayList;
026    import java.util.Collection;
027    import java.util.HashSet;
028    import java.util.Iterator;
029    import java.util.List;
030    
031    import com.unboundid.asn1.ASN1OctetString;
032    import com.unboundid.ldap.sdk.AddRequest;
033    import com.unboundid.ldap.sdk.Attribute;
034    import com.unboundid.ldap.sdk.ChangeType;
035    import com.unboundid.ldap.sdk.Control;
036    import com.unboundid.ldap.sdk.Entry;
037    import com.unboundid.ldap.sdk.LDAPException;
038    import com.unboundid.ldap.sdk.LDAPInterface;
039    import com.unboundid.ldap.sdk.LDAPResult;
040    import com.unboundid.util.ByteStringBuffer;
041    import com.unboundid.util.NotMutable;
042    import com.unboundid.util.ThreadSafety;
043    import com.unboundid.util.ThreadSafetyLevel;
044    
045    import static com.unboundid.util.Debug.*;
046    import static com.unboundid.util.StaticUtils.*;
047    import static com.unboundid.util.Validator.*;
048    
049    
050    
051    /**
052     * This class defines an LDIF add change record, which can be used to represent
053     * an LDAP add request.  See the documentation for the {@link LDIFChangeRecord}
054     * class for an example demonstrating the process for interacting with LDIF
055     * change records.
056     */
057    @NotMutable()
058    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
059    public final class LDIFAddChangeRecord
060           extends LDIFChangeRecord
061    {
062      /**
063       * The serial version UID for this serializable class.
064       */
065      private static final long serialVersionUID = 4722916031463878423L;
066    
067    
068    
069      // The set of attributes for this add change record.
070      private final Attribute[] attributes;
071    
072    
073    
074      /**
075       * Creates a new LDIF add change record with the provided DN and attributes.
076       *
077       * @param  dn          The DN for this LDIF add change record.  It must not be
078       *                     {@code null}.
079       * @param  attributes  The set of attributes for this LDIF add change record.
080       *                     It must not be {@code null} or empty.
081       */
082      public LDIFAddChangeRecord(final String dn, final Attribute... attributes)
083      {
084        this(dn, attributes, null);
085      }
086    
087    
088    
089      /**
090       * Creates a new LDIF add change record with the provided DN and attributes.
091       *
092       * @param  dn          The DN for this LDIF add change record.  It must not be
093       *                     {@code null}.
094       * @param  attributes  The set of attributes for this LDIF add change record.
095       *                     It must not be {@code null} or empty.
096       * @param  controls    The set of controls for this LDIF add change record.
097       *                     It may be {@code null} or empty if there are no
098       *                     controls.
099       */
100      public LDIFAddChangeRecord(final String dn, final Attribute[] attributes,
101                                 final List<Control> controls)
102      {
103        super(dn, controls);
104    
105        ensureNotNull(attributes);
106        ensureTrue(attributes.length > 0,
107                   "LDIFAddChangeRecord.attributes must not be empty.");
108    
109        this.attributes = attributes;
110      }
111    
112    
113    
114      /**
115       * Creates a new LDIF add change record with the provided DN and attributes.
116       *
117       * @param  dn          The DN for this LDIF add change record.  It must not be
118       *                     {@code null}.
119       * @param  attributes  The set of attributes for this LDIF add change record.
120       *                     It must not be {@code null} or empty.
121       */
122      public LDIFAddChangeRecord(final String dn, final List<Attribute> attributes)
123      {
124        this(dn, attributes, null);
125      }
126    
127    
128    
129      /**
130       * Creates a new LDIF add change record with the provided DN and attributes.
131       *
132       * @param  dn          The DN for this LDIF add change record.  It must not be
133       *                     {@code null}.
134       * @param  attributes  The set of attributes for this LDIF add change record.
135       *                     It must not be {@code null} or empty.
136       * @param  controls    The set of controls for this LDIF add change record.
137       *                     It may be {@code null} or empty if there are no
138       *                     controls.
139       */
140      public LDIFAddChangeRecord(final String dn, final List<Attribute> attributes,
141                                 final List<Control> controls)
142      {
143        super(dn, controls);
144    
145        ensureNotNull(attributes);
146        ensureFalse(attributes.isEmpty(),
147                    "LDIFAddChangeRecord.attributes must not be empty.");
148    
149        this.attributes = new Attribute[attributes.size()];
150        attributes.toArray(this.attributes);
151      }
152    
153    
154    
155      /**
156       * Creates a new LDIF add change record from the provided entry.
157       *
158       * @param  entry  The entry to use to create this LDIF add change record.  It
159       *                must not be {@code null}.
160       */
161      public LDIFAddChangeRecord(final Entry entry)
162      {
163        this(entry, null);
164      }
165    
166    
167    
168      /**
169       * Creates a new LDIF add change record from the provided entry.
170       *
171       * @param  entry     The entry to use to create this LDIF add change record.
172       *                   It must not be {@code null}.
173       * @param  controls  The set of controls for this LDIF add change record.  It
174       *                   may be {@code null} or empty if there are no controls.
175       */
176      public LDIFAddChangeRecord(final Entry entry, final List<Control> controls)
177      {
178        super(entry.getDN(), controls);
179    
180        final Collection<Attribute> attrs = entry.getAttributes();
181        attributes = new Attribute[attrs.size()];
182    
183        final Iterator<Attribute> iterator = attrs.iterator();
184        for (int i=0; i < attributes.length; i++)
185        {
186          attributes[i] = iterator.next();
187        }
188      }
189    
190    
191    
192      /**
193       * Creates a new LDIF add change record from the provided add request.
194       *
195       * @param  addRequest  The add request to use to create this LDIF add change
196       *                     record.  It must not be {@code null}.
197       */
198      public LDIFAddChangeRecord(final AddRequest addRequest)
199      {
200        super(addRequest.getDN(), addRequest.getControlList());
201    
202        final List<Attribute> attrs = addRequest.getAttributes();
203        attributes = new Attribute[attrs.size()];
204    
205        final Iterator<Attribute> iterator = attrs.iterator();
206        for (int i=0; i < attributes.length; i++)
207        {
208          attributes[i] = iterator.next();
209        }
210      }
211    
212    
213    
214      /**
215       * Retrieves the set of attributes for this add change record.
216       *
217       * @return  The set of attributes for this add change record.
218       */
219      public Attribute[] getAttributes()
220      {
221        return attributes;
222      }
223    
224    
225    
226      /**
227       * Retrieves the entry that would be created by this add change record.
228       *
229       * @return  The entry that would be created by this add change record.
230       */
231      public Entry getEntryToAdd()
232      {
233        return new Entry(getDN(), attributes);
234      }
235    
236    
237    
238      /**
239       * Creates an add request from this LDIF add change record.    Any controls
240       * included in this change record will be included in the request.
241       *
242       * @return  The add request created from this LDIF add change record.
243       */
244      public AddRequest toAddRequest()
245      {
246        return toAddRequest(true);
247      }
248    
249    
250    
251      /**
252       * Creates an add request from this LDIF add change record, optionally
253       * including any change record controls in the request.
254       *
255       * @param  includeControls  Indicates whether to include any controls in the
256       *                          request.
257       *
258       * @return  The add request created from this LDIF add change record.
259       */
260      public AddRequest toAddRequest(final boolean includeControls)
261      {
262        final AddRequest addRequest = new AddRequest(getDN(), attributes);
263        if (includeControls)
264        {
265          addRequest.setControls(getControls());
266        }
267    
268        return addRequest;
269      }
270    
271    
272    
273      /**
274       * {@inheritDoc}
275       */
276      @Override()
277      public ChangeType getChangeType()
278      {
279        return ChangeType.ADD;
280      }
281    
282    
283    
284      /**
285       * {@inheritDoc}
286       */
287      @Override()
288      public LDAPResult processChange(final LDAPInterface connection,
289                                      final boolean includeControls)
290             throws LDAPException
291      {
292        return connection.add(toAddRequest(includeControls));
293      }
294    
295    
296    
297      /**
298       * {@inheritDoc}
299       */
300      @Override()
301      public String[] toLDIF(final int wrapColumn)
302      {
303        List<String> ldifLines = new ArrayList<String>(2*attributes.length);
304        encodeNameAndValue("dn", new ASN1OctetString(getDN()), ldifLines);
305    
306        for (final Control c : getControls())
307        {
308          encodeNameAndValue("control", encodeControlString(c), ldifLines);
309        }
310    
311        ldifLines.add("changetype: add");
312    
313        for (final Attribute a : attributes)
314        {
315          final String name = a.getName();
316          for (final ASN1OctetString value : a.getRawValues())
317          {
318            encodeNameAndValue(name, value, ldifLines);
319          }
320        }
321    
322        if (wrapColumn > 2)
323        {
324          ldifLines = LDIFWriter.wrapLines(wrapColumn, ldifLines);
325        }
326    
327        final String[] ldifArray = new String[ldifLines.size()];
328        ldifLines.toArray(ldifArray);
329        return ldifArray;
330      }
331    
332    
333    
334      /**
335       * {@inheritDoc}
336       */
337      @Override()
338      public void toLDIF(final ByteStringBuffer buffer, final int wrapColumn)
339      {
340        LDIFWriter.encodeNameAndValue("dn", new ASN1OctetString(getDN()), buffer,
341             wrapColumn);
342        buffer.append(EOL_BYTES);
343    
344        for (final Control c : getControls())
345        {
346          LDIFWriter.encodeNameAndValue("control", encodeControlString(c), buffer,
347               wrapColumn);
348          buffer.append(EOL_BYTES);
349        }
350    
351        LDIFWriter.encodeNameAndValue("changetype", new ASN1OctetString("add"),
352                                      buffer, wrapColumn);
353        buffer.append(EOL_BYTES);
354    
355        for (final Attribute a : attributes)
356        {
357          final String name = a.getName();
358          for (final ASN1OctetString value : a.getRawValues())
359          {
360            LDIFWriter.encodeNameAndValue(name, value, buffer, wrapColumn);
361            buffer.append(EOL_BYTES);
362          }
363        }
364      }
365    
366    
367    
368      /**
369       * {@inheritDoc}
370       */
371      @Override()
372      public void toLDIFString(final StringBuilder buffer, final int wrapColumn)
373      {
374        LDIFWriter.encodeNameAndValue("dn", new ASN1OctetString(getDN()), buffer,
375             wrapColumn);
376        buffer.append(EOL);
377    
378        for (final Control c : getControls())
379        {
380          LDIFWriter.encodeNameAndValue("control", encodeControlString(c), buffer,
381               wrapColumn);
382          buffer.append(EOL);
383        }
384    
385        LDIFWriter.encodeNameAndValue("changetype", new ASN1OctetString("add"),
386                                      buffer, wrapColumn);
387        buffer.append(EOL);
388    
389        for (final Attribute a : attributes)
390        {
391          final String name = a.getName();
392          for (final ASN1OctetString value : a.getRawValues())
393          {
394            LDIFWriter.encodeNameAndValue(name, value, buffer, wrapColumn);
395            buffer.append(EOL);
396          }
397        }
398      }
399    
400    
401    
402      /**
403       * {@inheritDoc}
404       */
405      @Override()
406      public int hashCode()
407      {
408        try
409        {
410          int hashCode = getParsedDN().hashCode();
411          for (final Attribute a : attributes)
412          {
413            hashCode += a.hashCode();
414          }
415    
416          return hashCode;
417        }
418        catch (final Exception e)
419        {
420          debugException(e);
421          return new Entry(getDN(), attributes).hashCode();
422        }
423      }
424    
425    
426    
427      /**
428       * {@inheritDoc}
429       */
430      @Override()
431      public boolean equals(final Object o)
432      {
433        if (o == null)
434        {
435          return false;
436        }
437    
438        if (o == this)
439        {
440          return true;
441        }
442    
443        if (! (o instanceof LDIFAddChangeRecord))
444        {
445          return false;
446        }
447    
448        final LDIFAddChangeRecord r = (LDIFAddChangeRecord) o;
449    
450        final HashSet<Control> c1 = new HashSet<Control>(getControls());
451        final HashSet<Control> c2 = new HashSet<Control>(r.getControls());
452        if (! c1.equals(c2))
453        {
454          return false;
455        }
456    
457        final Entry e1 = new Entry(getDN(), attributes);
458        final Entry e2 = new Entry(r.getDN(), r.attributes);
459        return e1.equals(e2);
460      }
461    
462    
463    
464      /**
465       * {@inheritDoc}
466       */
467      @Override()
468      public void toString(final StringBuilder buffer)
469      {
470        buffer.append("LDIFAddChangeRecord(dn='");
471        buffer.append(getDN());
472        buffer.append("', attrs={");
473    
474        for (int i=0; i < attributes.length; i++)
475        {
476          if (i > 0)
477          {
478            buffer.append(", ");
479          }
480          attributes[i].toString(buffer);
481        }
482        buffer.append('}');
483    
484        final List<Control> controls = getControls();
485        if (! controls.isEmpty())
486        {
487          buffer.append(", controls={");
488    
489          final Iterator<Control> iterator = controls.iterator();
490          while (iterator.hasNext())
491          {
492            iterator.next().toString(buffer);
493            if (iterator.hasNext())
494            {
495              buffer.append(',');
496            }
497          }
498    
499          buffer.append('}');
500        }
501    
502        buffer.append(')');
503      }
504    }