001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.model.entry; 021 022 023import java.io.IOException; 024import java.io.ObjectInput; 025import java.io.ObjectOutput; 026 027import org.apache.directory.api.i18n.I18n; 028import org.apache.directory.api.ldap.model.exception.LdapException; 029import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; 030import org.apache.directory.api.ldap.model.schema.AttributeType; 031import org.apache.directory.api.ldap.model.schema.SchemaManager; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035 036/** 037 * An internal implementation for a ModificationItem. The name has been 038 * chosen so that it does not conflict with @see ModificationItem 039 * 040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 041 */ 042public class DefaultModification implements Modification 043{ 044 /** The modification operation */ 045 private ModificationOperation operation; 046 047 /** The attribute which contains the modification */ 048 private Attribute attribute; 049 050 /** The AtributeType */ 051 private AttributeType attributeType; 052 053 /** logger for reporting errors that might not be handled properly upstream */ 054 protected static final Logger LOG = LoggerFactory.getLogger( Modification.class ); 055 056 057 /** 058 * Creates a new instance of DefaultModification. 059 */ 060 public DefaultModification() 061 { 062 // Default empty constructor 063 } 064 065 066 /** 067 * Creates a new instance of DefaultModification. 068 * 069 * @param operation The modification operation 070 * @param attribute The associated attribute 071 */ 072 public DefaultModification( ModificationOperation operation, Attribute attribute ) 073 { 074 this.operation = operation; 075 this.attribute = attribute; 076 } 077 078 079 /** 080 * Creates a new instance of DefaultModification. 081 * 082 * @param operation The modification operation 083 * @param attributeId The associated attribute ID 084 * @param values the associated values 085 */ 086 public DefaultModification( ModificationOperation operation, String attributeId, String... values ) 087 { 088 this.operation = operation; 089 this.attribute = new DefaultAttribute( attributeId, values ); 090 } 091 092 093 /** 094 * Creates a new instance of DefaultModification. 095 * 096 * @param operation The modification operation 097 * @param attributeId The associated attribute ID 098 * @param values the associated values 099 */ 100 public DefaultModification( ModificationOperation operation, String attributeId, byte[]... values ) 101 { 102 this.operation = operation; 103 this.attribute = new DefaultAttribute( attributeId, values ); 104 } 105 106 107 /** 108 * Creates a new instance of DefaultModification. 109 * 110 * @param operation The modification operation 111 * @param attributeId The associated attribute ID 112 * @param values the associated values 113 */ 114 public DefaultModification( ModificationOperation operation, String attributeId, Value... values ) 115 { 116 this.operation = operation; 117 this.attribute = new DefaultAttribute( attributeId, values ); 118 } 119 120 121 /** 122 * Creates a new instance of DefaultModification with no value 123 * 124 * @param operation The modification operation 125 * @param attributeId The associated attribute ID 126 */ 127 public DefaultModification( ModificationOperation operation, String attributeId ) 128 { 129 this.operation = operation; 130 this.attribute = new DefaultAttribute( attributeId ); 131 } 132 133 134 /** 135 * Creates a new instance of DefaultModification. 136 * 137 * @param operation The modification operation 138 * @param attributeType The associated attributeType 139 * @param values the associated values 140 * @throws LdapInvalidAttributeValueException If the value is invalid 141 */ 142 public DefaultModification( ModificationOperation operation, AttributeType attributeType, String... values ) 143 throws LdapInvalidAttributeValueException 144 { 145 this.operation = operation; 146 this.attribute = new DefaultAttribute( attributeType, values ); 147 } 148 149 150 /** 151 * Creates a new instance of DefaultModification. 152 * 153 * @param operation The modification operation 154 * @param attributeType The associated attributeType 155 * @param values the associated values 156 * @throws LdapInvalidAttributeValueException If the value is invalid 157 */ 158 public DefaultModification( ModificationOperation operation, AttributeType attributeType, byte[]... values ) 159 throws LdapInvalidAttributeValueException 160 { 161 this.operation = operation; 162 this.attribute = new DefaultAttribute( attributeType, values ); 163 } 164 165 166 /** 167 * Creates a new instance of DefaultModification. 168 * 169 * @param operation The modification operation 170 * @param attributeType The associated attributeType 171 * @param values the associated values 172 * @throws LdapInvalidAttributeValueException If the value is invalid 173 */ 174 public DefaultModification( ModificationOperation operation, AttributeType attributeType, Value... values ) 175 throws LdapInvalidAttributeValueException 176 { 177 this.operation = operation; 178 this.attribute = new DefaultAttribute( attributeType, values ); 179 } 180 181 182 /** 183 * Creates a new instance of DefaultModification with no value. 184 * 185 * @param operation The modification operation 186 * @param attributeType The associated attributeType 187 * @throws LdapInvalidAttributeValueException If the value is invalid 188 */ 189 public DefaultModification( ModificationOperation operation, AttributeType attributeType ) 190 throws LdapInvalidAttributeValueException 191 { 192 this.operation = operation; 193 this.attribute = new DefaultAttribute( attributeType ); 194 } 195 196 197 /** 198 * Creates a new instance of DefaultModification. 199 * 200 * @param schemaManager The schema manager 201 * @param modification The modification 202 */ 203 public DefaultModification( SchemaManager schemaManager, Modification modification ) 204 { 205 operation = modification.getOperation(); 206 207 Attribute modAttribute = modification.getAttribute(); 208 209 try 210 { 211 AttributeType at = modAttribute.getAttributeType(); 212 213 if ( at == null ) 214 { 215 at = schemaManager.lookupAttributeTypeRegistry( modAttribute.getId() ); 216 } 217 218 attribute = new DefaultAttribute( at, modAttribute ); 219 } 220 catch ( LdapException ne ) 221 { 222 // The attributeType is incorrect. Log, but do nothing otherwise. 223 LOG.error( I18n.err( I18n.ERR_13230_INCORRECT_ATTRIBUTE, modAttribute.getId() ) ); 224 } 225 } 226 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 public ModificationOperation getOperation() 233 { 234 return operation; 235 } 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 @Override 242 public void setOperation( int operation ) 243 { 244 this.operation = ModificationOperation.getOperation( operation ); 245 } 246 247 248 /** 249 * {@inheritDoc} 250 */ 251 @Override 252 public void setOperation( ModificationOperation operation ) 253 { 254 this.operation = operation; 255 } 256 257 258 /** 259 * {@inheritDoc} 260 */ 261 @Override 262 public Attribute getAttribute() 263 { 264 return attribute; 265 } 266 267 268 /** 269 * {@inheritDoc} 270 */ 271 @Override 272 public void setAttribute( Attribute attribute ) 273 { 274 this.attribute = attribute; 275 } 276 277 278 /** 279 * {@inheritDoc} 280 */ 281 @Override 282 public void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException 283 { 284 this.attributeType = attributeType; 285 286 if ( attribute != null ) 287 { 288 attribute.apply( attributeType ); 289 } 290 } 291 292 293 /** 294 * @return The associated AttributeType 295 */ 296 public AttributeType getAttributeType() 297 { 298 return attributeType; 299 } 300 301 302 /** 303 * @see Object#equals(Object) 304 * @return <code>true</code> if both values are equal 305 */ 306 @Override 307 public boolean equals( Object that ) 308 { 309 // Basic equals checks 310 if ( this == that ) 311 { 312 return true; 313 } 314 315 if ( !( that instanceof Modification ) ) 316 { 317 return false; 318 } 319 320 Modification otherModification = ( Modification ) that; 321 322 // Check the operation 323 if ( operation != otherModification.getOperation() ) 324 { 325 return false; 326 } 327 328 // Check the attribute 329 if ( attribute == null ) 330 { 331 return otherModification.getAttribute() == null; 332 } 333 334 return attribute.equals( otherModification.getAttribute() ); 335 } 336 337 338 /** 339 * Compute the modification @see Object#hashCode 340 * @return the instance's hash code 341 */ 342 @Override 343 public int hashCode() 344 { 345 int h = 37; 346 347 h += h * 17 + operation.getValue(); 348 h += h * 17 + attribute.hashCode(); 349 350 return h; 351 } 352 353 354 /** 355 * @see java.io.Externalizable#readExternal(ObjectInput) 356 */ 357 @Override 358 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException 359 { 360 // The operation 361 operation = ModificationOperation.getOperation( in.readInt() ); 362 363 // The EntryAttribute if we have some 364 boolean hasAttribute = in.readBoolean(); 365 366 if ( hasAttribute ) 367 { 368 attribute = new DefaultAttribute(); 369 attribute.readExternal( in ); 370 } 371 } 372 373 374 /** 375 * @see java.io.Externalizable#writeExternal(ObjectOutput) 376 */ 377 @Override 378 public void writeExternal( ObjectOutput out ) throws IOException 379 { 380 // The operation 381 out.writeInt( operation.getValue() ); 382 383 // The EntryAttribute if not null 384 if ( attribute != null ) 385 { 386 out.writeBoolean( true ); 387 attribute.writeExternal( out ); 388 } 389 else 390 { 391 out.writeBoolean( false ); 392 } 393 394 out.flush(); 395 } 396 397 398 /** 399 * {@inheritDoc} 400 */ 401 @Override 402 public DefaultModification clone() 403 { 404 try 405 { 406 DefaultModification clone = ( DefaultModification ) super.clone(); 407 408 clone.attribute = this.attribute.clone(); 409 return clone; 410 } 411 catch ( CloneNotSupportedException cnse ) 412 { 413 return null; 414 } 415 } 416 417 418 /** 419 * @see Object#toString() 420 */ 421 @Override 422 public String toString() 423 { 424 StringBuilder sb = new StringBuilder(); 425 426 sb.append( "Modification: " ). 427 append( operation ). 428 append( ", [" ). 429 append( attribute.getId() ); 430 431 if ( attribute.size() == 0 ) 432 { 433 if ( operation == ModificationOperation.INCREMENT_ATTRIBUTE ) 434 { 435 sb.append( " : 1" ); 436 } 437 } 438 else 439 { 440 sb.append( " : " ).append( attribute ); 441 } 442 443 sb.append( "]" ); 444 445 return sb.toString(); 446 } 447}