001/* 002 * Copyright 2007-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2007-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldif; 037 038 039 040import java.util.ArrayList; 041import java.util.HashSet; 042import java.util.Iterator; 043import java.util.List; 044 045import com.unboundid.asn1.ASN1OctetString; 046import com.unboundid.ldap.sdk.ChangeType; 047import com.unboundid.ldap.sdk.Control; 048import com.unboundid.ldap.sdk.DeleteRequest; 049import com.unboundid.ldap.sdk.LDAPException; 050import com.unboundid.ldap.sdk.LDAPInterface; 051import com.unboundid.ldap.sdk.LDAPResult; 052import com.unboundid.util.ByteStringBuffer; 053import com.unboundid.util.Debug; 054import com.unboundid.util.NotMutable; 055import com.unboundid.util.NotNull; 056import com.unboundid.util.Nullable; 057import com.unboundid.util.StaticUtils; 058import com.unboundid.util.ThreadSafety; 059import com.unboundid.util.ThreadSafetyLevel; 060 061 062 063/** 064 * This class defines an LDIF delete change record, which can be used to 065 * represent an LDAP delete request. See the documentation for the 066 * {@link LDIFChangeRecord} class for an example demonstrating the process for 067 * interacting with LDIF change records. 068 */ 069@NotMutable() 070@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 071public final class LDIFDeleteChangeRecord 072 extends LDIFChangeRecord 073{ 074 /** 075 * The serial version UID for this serializable class. 076 */ 077 private static final long serialVersionUID = 9173178539060889790L; 078 079 080 081 /** 082 * Creates a new LDIF delete change record with the provided DN. 083 * 084 * @param dn The DN of the entry to delete. It must not be {@code null}. 085 */ 086 public LDIFDeleteChangeRecord(@NotNull final String dn) 087 { 088 this(dn, null); 089 } 090 091 092 093 /** 094 * Creates a new LDIF delete change record with the provided DN. 095 * 096 * @param dn The DN of the entry to delete. It must not be 097 * {@code null}. 098 * @param controls The set of controls for this LDIF delete change record. 099 * It may be {@code null} or empty if there are no controls. 100 */ 101 public LDIFDeleteChangeRecord(@NotNull final String dn, 102 @Nullable final List<Control> controls) 103 { 104 super(dn, controls); 105 } 106 107 108 109 /** 110 * Creates a new LDIF delete change record from the provided delete request. 111 * 112 * @param deleteRequest The delete request to use to create this LDIF delete 113 * change record. It must not be {@code null}. 114 */ 115 public LDIFDeleteChangeRecord(@NotNull final DeleteRequest deleteRequest) 116 { 117 super(deleteRequest.getDN(), deleteRequest.getControlList()); 118 } 119 120 121 122 /** 123 * Creates a delete request from this LDIF delete change record. Any change 124 * record controls will be included in the request 125 * 126 * @return The delete request created from this LDIF delete change record. 127 */ 128 @NotNull() 129 public DeleteRequest toDeleteRequest() 130 { 131 return toDeleteRequest(true); 132 } 133 134 135 136 /** 137 * Creates a delete request from this LDIF delete change record, optionally 138 * including any change record controls in the request. 139 * 140 * @param includeControls Indicates whether to include any controls in the 141 * request. 142 * 143 * @return The delete request created from this LDIF delete change record. 144 */ 145 @NotNull() 146 public DeleteRequest toDeleteRequest(final boolean includeControls) 147 { 148 final DeleteRequest deleteRequest = new DeleteRequest(getDN()); 149 if (includeControls) 150 { 151 deleteRequest.setControls(getControls()); 152 } 153 154 return deleteRequest; 155 } 156 157 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override() 163 @NotNull() 164 public ChangeType getChangeType() 165 { 166 return ChangeType.DELETE; 167 } 168 169 170 171 /** 172 * {@inheritDoc} 173 */ 174 @Override() 175 @NotNull() 176 public LDIFDeleteChangeRecord duplicate(@Nullable final Control... controls) 177 { 178 return new LDIFDeleteChangeRecord(getDN(), StaticUtils.toList(controls)); 179 } 180 181 182 183 /** 184 * {@inheritDoc} 185 */ 186 @Override() 187 @NotNull() 188 public LDAPResult processChange(@NotNull final LDAPInterface connection, 189 final boolean includeControls) 190 throws LDAPException 191 { 192 return connection.delete(toDeleteRequest(includeControls)); 193 } 194 195 196 197 /** 198 * {@inheritDoc} 199 */ 200 @Override() 201 @NotNull() 202 public String[] toLDIF(final int wrapColumn) 203 { 204 List<String> ldifLines = new ArrayList<>(5); 205 encodeNameAndValue("dn", new ASN1OctetString(getDN()), ldifLines); 206 207 for (final Control c : getControls()) 208 { 209 encodeNameAndValue("control", encodeControlString(c), ldifLines); 210 } 211 212 ldifLines.add("changetype: delete"); 213 214 if (wrapColumn > 2) 215 { 216 ldifLines = LDIFWriter.wrapLines(wrapColumn, ldifLines); 217 } 218 219 final String[] ldifArray = new String[ldifLines.size()]; 220 ldifLines.toArray(ldifArray); 221 return ldifArray; 222 } 223 224 225 226 /** 227 * {@inheritDoc} 228 */ 229 @Override() 230 public void toLDIF(@NotNull final ByteStringBuffer buffer, 231 final int wrapColumn) 232 { 233 LDIFWriter.encodeNameAndValue("dn", new ASN1OctetString(getDN()), buffer, 234 wrapColumn); 235 buffer.append(StaticUtils.EOL_BYTES); 236 237 for (final Control c : getControls()) 238 { 239 LDIFWriter.encodeNameAndValue("control", encodeControlString(c), buffer, 240 wrapColumn); 241 buffer.append(StaticUtils.EOL_BYTES); 242 } 243 244 LDIFWriter.encodeNameAndValue("changetype", new ASN1OctetString("delete"), 245 buffer, wrapColumn); 246 buffer.append(StaticUtils.EOL_BYTES); 247 } 248 249 250 251 /** 252 * {@inheritDoc} 253 */ 254 @Override() 255 public void toLDIFString(@NotNull final StringBuilder buffer, 256 final int wrapColumn) 257 { 258 LDIFWriter.encodeNameAndValue("dn", new ASN1OctetString(getDN()), buffer, 259 wrapColumn); 260 buffer.append(StaticUtils.EOL); 261 262 for (final Control c : getControls()) 263 { 264 LDIFWriter.encodeNameAndValue("control", encodeControlString(c), buffer, 265 wrapColumn); 266 buffer.append(StaticUtils.EOL); 267 } 268 269 LDIFWriter.encodeNameAndValue("changetype", new ASN1OctetString("delete"), 270 buffer, wrapColumn); 271 buffer.append(StaticUtils.EOL); 272 } 273 274 275 276 /** 277 * {@inheritDoc} 278 */ 279 @Override() 280 public int hashCode() 281 { 282 try 283 { 284 return getParsedDN().hashCode(); 285 } 286 catch (final Exception e) 287 { 288 Debug.debugException(e); 289 return StaticUtils.toLowerCase(getDN()).hashCode(); 290 } 291 } 292 293 294 295 /** 296 * {@inheritDoc} 297 */ 298 @Override() 299 public boolean equals(@Nullable final Object o) 300 { 301 if (o == null) 302 { 303 return false; 304 } 305 306 if (o == this) 307 { 308 return true; 309 } 310 311 if (! (o instanceof LDIFDeleteChangeRecord)) 312 { 313 return false; 314 } 315 316 final LDIFDeleteChangeRecord r = (LDIFDeleteChangeRecord) o; 317 318 final HashSet<Control> c1 = new HashSet<>(getControls()); 319 final HashSet<Control> c2 = new HashSet<>(r.getControls()); 320 if (! c1.equals(c2)) 321 { 322 return false; 323 } 324 325 try 326 { 327 return getParsedDN().equals(r.getParsedDN()); 328 } 329 catch (final Exception e) 330 { 331 Debug.debugException(e); 332 return StaticUtils.toLowerCase(getDN()).equals( 333 StaticUtils.toLowerCase(r.getDN())); 334 } 335 } 336 337 338 339 /** 340 * {@inheritDoc} 341 */ 342 @Override() 343 public void toString(@NotNull final StringBuilder buffer) 344 { 345 buffer.append("LDIFDeleteChangeRecord(dn='"); 346 buffer.append(getDN()); 347 buffer.append('\''); 348 349 final List<Control> controls = getControls(); 350 if (! controls.isEmpty()) 351 { 352 buffer.append(", controls={"); 353 354 final Iterator<Control> iterator = controls.iterator(); 355 while (iterator.hasNext()) 356 { 357 iterator.next().toString(buffer); 358 if (iterator.hasNext()) 359 { 360 buffer.append(','); 361 } 362 } 363 364 buffer.append('}'); 365 } 366 367 buffer.append(')'); 368 } 369}