001/*
002 * Copyright 2007-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2008-2017 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 */
021package com.unboundid.ldif;
022
023
024
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.HashSet;
028import java.util.Iterator;
029import java.util.List;
030
031import com.unboundid.asn1.ASN1OctetString;
032import com.unboundid.ldap.sdk.AddRequest;
033import com.unboundid.ldap.sdk.Attribute;
034import com.unboundid.ldap.sdk.ChangeType;
035import com.unboundid.ldap.sdk.Control;
036import com.unboundid.ldap.sdk.Entry;
037import com.unboundid.ldap.sdk.LDAPException;
038import com.unboundid.ldap.sdk.LDAPInterface;
039import com.unboundid.ldap.sdk.LDAPResult;
040import com.unboundid.util.ByteStringBuffer;
041import com.unboundid.util.NotMutable;
042import com.unboundid.util.ThreadSafety;
043import com.unboundid.util.ThreadSafetyLevel;
044
045import static com.unboundid.util.Debug.*;
046import static com.unboundid.util.StaticUtils.*;
047import 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)
059public 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}