001 /*
002 * Copyright 2007-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2014 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 ldifLines.add(LDIFWriter.encodeNameAndValue("dn",
305 new ASN1OctetString(getDN())));
306
307 for (final Control c : getControls())
308 {
309 ldifLines.add(LDIFWriter.encodeNameAndValue("control",
310 encodeControlString(c)));
311 }
312
313 ldifLines.add("changetype: add");
314
315 for (final Attribute a : attributes)
316 {
317 final String name = a.getName();
318 for (final ASN1OctetString value : a.getRawValues())
319 {
320 ldifLines.add(LDIFWriter.encodeNameAndValue(name, value));
321 }
322 }
323
324 if (wrapColumn > 2)
325 {
326 ldifLines = LDIFWriter.wrapLines(wrapColumn, ldifLines);
327 }
328
329 final String[] ldifArray = new String[ldifLines.size()];
330 ldifLines.toArray(ldifArray);
331 return ldifArray;
332 }
333
334
335
336 /**
337 * {@inheritDoc}
338 */
339 @Override()
340 public void toLDIF(final ByteStringBuffer buffer, final int wrapColumn)
341 {
342 LDIFWriter.encodeNameAndValue("dn", new ASN1OctetString(getDN()), buffer,
343 wrapColumn);
344 buffer.append(EOL_BYTES);
345
346 for (final Control c : getControls())
347 {
348 LDIFWriter.encodeNameAndValue("control", encodeControlString(c), buffer,
349 wrapColumn);
350 buffer.append(EOL_BYTES);
351 }
352
353 LDIFWriter.encodeNameAndValue("changetype", new ASN1OctetString("add"),
354 buffer, wrapColumn);
355 buffer.append(EOL_BYTES);
356
357 for (final Attribute a : attributes)
358 {
359 final String name = a.getName();
360 for (final ASN1OctetString value : a.getRawValues())
361 {
362 LDIFWriter.encodeNameAndValue(name, value, buffer, wrapColumn);
363 buffer.append(EOL_BYTES);
364 }
365 }
366 }
367
368
369
370 /**
371 * {@inheritDoc}
372 */
373 @Override()
374 public void toLDIFString(final StringBuilder buffer, final int wrapColumn)
375 {
376 LDIFWriter.encodeNameAndValue("dn", new ASN1OctetString(getDN()), buffer,
377 wrapColumn);
378 buffer.append(EOL);
379
380 for (final Control c : getControls())
381 {
382 LDIFWriter.encodeNameAndValue("control", encodeControlString(c), buffer,
383 wrapColumn);
384 buffer.append(EOL);
385 }
386
387 LDIFWriter.encodeNameAndValue("changetype", new ASN1OctetString("add"),
388 buffer, wrapColumn);
389 buffer.append(EOL);
390
391 for (final Attribute a : attributes)
392 {
393 final String name = a.getName();
394 for (final ASN1OctetString value : a.getRawValues())
395 {
396 LDIFWriter.encodeNameAndValue(name, value, buffer, wrapColumn);
397 buffer.append(EOL);
398 }
399 }
400 }
401
402
403
404 /**
405 * {@inheritDoc}
406 */
407 @Override()
408 public int hashCode()
409 {
410 try
411 {
412 int hashCode = getParsedDN().hashCode();
413 for (final Attribute a : attributes)
414 {
415 hashCode += a.hashCode();
416 }
417
418 return hashCode;
419 }
420 catch (final Exception e)
421 {
422 debugException(e);
423 return new Entry(getDN(), attributes).hashCode();
424 }
425 }
426
427
428
429 /**
430 * {@inheritDoc}
431 */
432 @Override()
433 public boolean equals(final Object o)
434 {
435 if (o == null)
436 {
437 return false;
438 }
439
440 if (o == this)
441 {
442 return true;
443 }
444
445 if (! (o instanceof LDIFAddChangeRecord))
446 {
447 return false;
448 }
449
450 final LDIFAddChangeRecord r = (LDIFAddChangeRecord) o;
451
452 final HashSet<Control> c1 = new HashSet<Control>(getControls());
453 final HashSet<Control> c2 = new HashSet<Control>(r.getControls());
454 if (! c1.equals(c2))
455 {
456 return false;
457 }
458
459 final Entry e1 = new Entry(getDN(), attributes);
460 final Entry e2 = new Entry(r.getDN(), r.attributes);
461 return e1.equals(e2);
462 }
463
464
465
466 /**
467 * {@inheritDoc}
468 */
469 @Override()
470 public void toString(final StringBuilder buffer)
471 {
472 buffer.append("LDIFAddChangeRecord(dn='");
473 buffer.append(getDN());
474 buffer.append("', attrs={");
475
476 for (int i=0; i < attributes.length; i++)
477 {
478 if (i > 0)
479 {
480 buffer.append(", ");
481 }
482 attributes[i].toString(buffer);
483 }
484 buffer.append('}');
485
486 final List<Control> controls = getControls();
487 if (! controls.isEmpty())
488 {
489 buffer.append(", controls={");
490
491 final Iterator<Control> iterator = controls.iterator();
492 while (iterator.hasNext())
493 {
494 iterator.next().toString(buffer);
495 if (iterator.hasNext())
496 {
497 buffer.append(',');
498 }
499 }
500
501 buffer.append('}');
502 }
503
504 buffer.append(')');
505 }
506 }