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