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 */ 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 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}