001/* 002 * Copyright 2007-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2017 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 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}