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