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