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 com.unboundid.ldap.sdk.ChangeType;
026 import com.unboundid.ldap.sdk.DN;
027 import com.unboundid.ldap.sdk.Entry;
028 import com.unboundid.ldap.sdk.LDAPException;
029 import com.unboundid.ldap.sdk.LDAPInterface;
030 import com.unboundid.ldap.sdk.LDAPResult;
031 import com.unboundid.util.ByteStringBuffer;
032 import com.unboundid.util.NotExtensible;
033 import com.unboundid.util.ThreadSafety;
034 import com.unboundid.util.ThreadSafetyLevel;
035
036 import static com.unboundid.util.Validator.*;
037
038
039
040 /**
041 * This class provides a base class for LDIF change records, which can be used
042 * to represent add, delete, modify, and modify DN operations in LDIF form.
043 * <BR><BR>
044 * <H2>Example</H2>
045 * The following example iterates through all of the change records contained in
046 * an LDIF file and attempts to apply those changes to a directory server:
047 * <PRE>
048 * LDIFReader ldifReader = new LDIFReader(pathToLDIFFile);
049 *
050 * while (true)
051 * {
052 * LDIFChangeRecord changeRecord;
053 * try
054 * {
055 * changeRecord = ldifReader.readChangeRecord();
056 * if (changeRecord == null)
057 * {
058 * System.err.println("All changes have been processed.");
059 * break;
060 * }
061 * }
062 * catch (LDIFException le)
063 * {
064 * if (le.mayContinueReading())
065 * {
066 * System.err.println("A recoverable occurred while attempting to " +
067 * "read a change record at or near line number " +
068 * le.getLineNumber() + ": " + le.getMessage());
069 * System.err.println("The change record will be skipped.");
070 * continue;
071 * }
072 * else
073 * {
074 * System.err.println("An unrecoverable occurred while attempting to " +
075 * "read a change record at or near line number " +
076 * le.getLineNumber() + ": " + le.getMessage());
077 * System.err.println("LDIF processing will be aborted.");
078 * break;
079 * }
080 * }
081 * catch (IOException ioe)
082 * {
083 * System.err.println("An I/O error occurred while attempting to read " +
084 * "from the LDIF file: " + ioe.getMessage());
085 * System.err.println("LDIF processing will be aborted.");
086 * break;
087 * }
088 *
089 * try
090 * {
091 * LDAPResult result = changeRecord.processChange(connection);
092 * System.out.println(changeRecord.getChangeType().getName() +
093 * " successful for entry " + changeRecord.getDN());
094 * }
095 * catch (LDAPException le)
096 * {
097 * System.err.println(changeRecord.getChangeType().getName() +
098 * " failed for entry " + changeRecord.getDN() + " -- " +
099 * le.getMessage());
100 * }
101 * }
102 *
103 * ldifReader.close();
104 * </PRE>
105 */
106 @NotExtensible()
107 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
108 public abstract class LDIFChangeRecord
109 implements LDIFRecord
110 {
111 /**
112 * The serial version UID for this serializable class.
113 */
114 private static final long serialVersionUID = 2394617613961232499L;
115
116
117
118 // The parsed DN for this LDIF change record.
119 private volatile DN parsedDN;
120
121 // The DN for this LDIF change record.
122 private final String dn;
123
124
125
126 /**
127 * Creates a new LDIF change record with the provided DN.
128 *
129 * @param dn The DN of the LDIF change record to create. It must not be
130 * {@code null}.
131 */
132 protected LDIFChangeRecord(final String dn)
133 {
134 ensureNotNull(dn);
135
136 this.dn = dn;
137 }
138
139
140
141 /**
142 * Retrieves the DN for this LDIF change record.
143 *
144 * @return The DN for this LDIF change record.
145 */
146 public final String getDN()
147 {
148 return dn;
149 }
150
151
152
153 /**
154 * Retrieves the parsed DN for this LDIF change record.
155 *
156 * @return The DN for this LDIF change record.
157 *
158 * @throws LDAPException If a problem occurs while trying to parse the DN.
159 */
160 public final DN getParsedDN()
161 throws LDAPException
162 {
163 if (parsedDN == null)
164 {
165 parsedDN = new DN(dn);
166 }
167
168 return parsedDN;
169 }
170
171
172
173 /**
174 * Retrieves the type of operation represented by this LDIF change record.
175 *
176 * @return The type of operation represented by this LDIF change record.
177 */
178 public abstract ChangeType getChangeType();
179
180
181
182 /**
183 * Apply the change represented by this LDIF change record to a directory
184 * server using the provided connection.
185 *
186 * @param connection The connection to use to apply the change.
187 *
188 * @return An object providing information about the result of the operation.
189 *
190 * @throws LDAPException If an error occurs while processing this change
191 * in the associated directory server.
192 */
193 public abstract LDAPResult processChange(final LDAPInterface connection)
194 throws LDAPException;
195
196
197
198 /**
199 * Retrieves an {@code Entry} representation of this change record. This is
200 * intended only for internal use by the LDIF reader when operating
201 * asynchronously in the case that it is not possible to know ahead of time
202 * whether a user will attempt to read an LDIF record by {@code readEntry} or
203 * {@code readChangeRecord}. In the event that the LDIF file has an entry
204 * whose first attribute is "changetype" and the client wants to read it as
205 * an entry rather than a change record, then this may be used to generate an
206 * entry representing the change record.
207 *
208 * @return The entry representation of this change record.
209 *
210 * @throws LDIFException If this change record cannot be represented as a
211 * valid entry.
212 */
213 final Entry toEntry()
214 throws LDIFException
215 {
216 return new Entry(toLDIF());
217 }
218
219
220
221 /**
222 * Retrieves a string array whose lines contain an LDIF representation of this
223 * change record.
224 *
225 * @return A string array whose lines contain an LDIF representation of this
226 * change record.
227 */
228 public final String[] toLDIF()
229 {
230 return toLDIF(0);
231 }
232
233
234
235 /**
236 * Retrieves a string array whose lines contain an LDIF representation of this
237 * change record.
238 *
239 * @param wrapColumn The column at which to wrap long lines. A value that
240 * is less than or equal to two indicates that no
241 * wrapping should be performed.
242 *
243 * @return A string array whose lines contain an LDIF representation of this
244 * change record.
245 */
246 public abstract String[] toLDIF(final int wrapColumn);
247
248
249
250 /**
251 * Appends an LDIF string representation of this change record to the provided
252 * buffer.
253 *
254 * @param buffer The buffer to which to append an LDIF representation of
255 * this change record.
256 */
257 public final void toLDIF(final ByteStringBuffer buffer)
258 {
259 toLDIF(buffer, 0);
260 }
261
262
263
264 /**
265 * Appends an LDIF string representation of this change record to the provided
266 * buffer.
267 *
268 * @param buffer The buffer to which to append an LDIF representation of
269 * this change record.
270 * @param wrapColumn The column at which to wrap long lines. A value that
271 * is less than or equal to two indicates that no
272 * wrapping should be performed.
273 */
274 public abstract void toLDIF(final ByteStringBuffer buffer,
275 final int wrapColumn);
276
277
278
279 /**
280 * Retrieves an LDIF string representation of this change record.
281 *
282 * @return An LDIF string representation of this change record.
283 */
284 public final String toLDIFString()
285 {
286 final StringBuilder buffer = new StringBuilder();
287 toLDIFString(buffer, 0);
288 return buffer.toString();
289 }
290
291
292
293 /**
294 * Retrieves an LDIF string representation of this change record.
295 *
296 * @param wrapColumn The column at which to wrap long lines. A value that
297 * is less than or equal to two indicates that no
298 * wrapping should be performed.
299 *
300 * @return An LDIF string representation of this change record.
301 */
302 public final String toLDIFString(final int wrapColumn)
303 {
304 final StringBuilder buffer = new StringBuilder();
305 toLDIFString(buffer, wrapColumn);
306 return buffer.toString();
307 }
308
309
310
311 /**
312 * Appends an LDIF string representation of this change record to the provided
313 * buffer.
314 *
315 * @param buffer The buffer to which to append an LDIF representation of
316 * this change record.
317 */
318 public final void toLDIFString(final StringBuilder buffer)
319 {
320 toLDIFString(buffer, 0);
321 }
322
323
324
325 /**
326 * Appends an LDIF string representation of this change record to the provided
327 * buffer.
328 *
329 * @param buffer The buffer to which to append an LDIF representation of
330 * this change record.
331 * @param wrapColumn The column at which to wrap long lines. A value that
332 * is less than or equal to two indicates that no
333 * wrapping should be performed.
334 */
335 public abstract void toLDIFString(final StringBuilder buffer,
336 final int wrapColumn);
337
338
339
340 /**
341 * Retrieves a hash code for this change record.
342 *
343 * @return A hash code for this change record.
344 */
345 @Override()
346 public abstract int hashCode();
347
348
349
350 /**
351 * Indicates whether the provided object is equal to this LDIF change record.
352 *
353 * @param o The object for which to make the determination.
354 *
355 * @return {@code true} if the provided object is equal to this LDIF change
356 * record, or {@code false} if not.
357 */
358 @Override()
359 public abstract boolean equals(final Object o);
360
361
362
363 /**
364 * Retrieves a single-line string representation of this change record.
365 *
366 * @return A single-line string representation of this change record.
367 */
368 @Override()
369 public final String toString()
370 {
371 final StringBuilder buffer = new StringBuilder();
372 toString(buffer);
373 return buffer.toString();
374 }
375
376
377
378 /**
379 * Appends a single-line string representation of this change record to the
380 * provided buffer.
381 *
382 * @param buffer The buffer to which the information should be written.
383 */
384 public abstract void toString(final StringBuilder buffer);
385 }