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 }