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 * http://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 } 063 064 065 /** 066 * Creates a new instance of DefaultModification. 067 * 068 * @param operation The modification operation 069 * @param attribute The associated attribute 070 */ 071 public DefaultModification( ModificationOperation operation, Attribute attribute ) 072 { 073 this.operation = operation; 074 this.attribute = attribute; 075 } 076 077 078 /** 079 * Creates a new instance of DefaultModification. 080 * 081 * @param operation The modification operation 082 * @param attributeId The associated attribute ID 083 * @param values the associated values 084 */ 085 public DefaultModification( ModificationOperation operation, String attributeId, String... values ) 086 { 087 this.operation = operation; 088 this.attribute = new DefaultAttribute( attributeId, values ); 089 } 090 091 092 /** 093 * Creates a new instance of DefaultModification. 094 * 095 * @param operation The modification operation 096 * @param attributeId The associated attribute ID 097 * @param values the associated values 098 */ 099 public DefaultModification( ModificationOperation operation, String attributeId, byte[]... values ) 100 { 101 this.operation = operation; 102 this.attribute = new DefaultAttribute( attributeId, values ); 103 } 104 105 106 /** 107 * Creates a new instance of DefaultModification. 108 * 109 * @param operation The modification operation 110 * @param attributeId The associated attribute ID 111 * @param values the associated values 112 */ 113 public DefaultModification( ModificationOperation operation, String attributeId, Value<?>... values ) 114 { 115 this.operation = operation; 116 this.attribute = new DefaultAttribute( attributeId, values ); 117 } 118 119 120 /** 121 * Creates a new instance of DefaultModification with no value 122 * 123 * @param operation The modification operation 124 * @param attributeId The associated attribute ID 125 */ 126 public DefaultModification( ModificationOperation operation, String attributeId ) 127 { 128 this.operation = operation; 129 this.attribute = new DefaultAttribute( attributeId ); 130 } 131 132 133 /** 134 * Creates a new instance of DefaultModification. 135 * 136 * @param operation The modification operation 137 * @param attributeType The associated attributeType 138 * @param values the associated values 139 * @throws LdapInvalidAttributeValueException If one of the value is not valid 140 */ 141 public DefaultModification( ModificationOperation operation, AttributeType attributeType, String... values ) 142 throws LdapInvalidAttributeValueException 143 { 144 this.operation = operation; 145 this.attribute = new DefaultAttribute( attributeType, values ); 146 } 147 148 149 /** 150 * Creates a new instance of DefaultModification. 151 * 152 * @param operation The modification operation 153 * @param attributeType The associated attributeType 154 * @param values the associated values 155 * @throws LdapInvalidAttributeValueException If one of the value is not valid 156 */ 157 public DefaultModification( ModificationOperation operation, AttributeType attributeType, byte[]... values ) 158 throws LdapInvalidAttributeValueException 159 { 160 this.operation = operation; 161 this.attribute = new DefaultAttribute( attributeType, values ); 162 } 163 164 165 /** 166 * Creates a new instance of DefaultModification. 167 * 168 * @param operation The modification operation 169 * @param attributeType The associated attributeType 170 * @param values the associated values 171 * @throws LdapInvalidAttributeValueException If one of the value is not valid 172 */ 173 public DefaultModification( ModificationOperation operation, AttributeType attributeType, Value<?>... values ) 174 throws LdapInvalidAttributeValueException 175 { 176 this.operation = operation; 177 this.attribute = new DefaultAttribute( attributeType, values ); 178 } 179 180 181 /** 182 * Creates a new instance of DefaultModification with no value. 183 * 184 * @param operation The modification operation 185 * @param attributeType The associated attributeType 186 * @throws LdapInvalidAttributeValueException If one of the value is not valid 187 */ 188 public DefaultModification( ModificationOperation operation, AttributeType attributeType ) 189 throws LdapInvalidAttributeValueException 190 { 191 this.operation = operation; 192 this.attribute = new DefaultAttribute( attributeType ); 193 } 194 195 196 /** 197 * Creates a new instance of DefaultModification. 198 * 199 * @param schemaManager The schema manager 200 * @param modification The modification 201 */ 202 public DefaultModification( SchemaManager schemaManager, Modification modification ) 203 { 204 operation = modification.getOperation(); 205 206 Attribute modAttribute = modification.getAttribute(); 207 208 try 209 { 210 AttributeType at = modAttribute.getAttributeType(); 211 212 if ( at == null ) 213 { 214 at = schemaManager.lookupAttributeTypeRegistry( modAttribute.getId() ); 215 } 216 217 attribute = new DefaultAttribute( at, modAttribute ); 218 } 219 catch ( LdapException ne ) 220 { 221 // The attributeType is incorrect. Log, but do nothing otherwise. 222 LOG.error( I18n.err( I18n.ERR_04472, modAttribute.getId() ) ); 223 } 224 } 225 226 227 /** 228 * {@inheritDoc} 229 */ 230 @Override 231 public ModificationOperation getOperation() 232 { 233 return operation; 234 } 235 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override 241 public void setOperation( int operation ) 242 { 243 this.operation = ModificationOperation.getOperation( operation ); 244 } 245 246 247 /** 248 * {@inheritDoc} 249 */ 250 @Override 251 public void setOperation( ModificationOperation operation ) 252 { 253 this.operation = operation; 254 } 255 256 257 /** 258 * {@inheritDoc} 259 */ 260 @Override 261 public Attribute getAttribute() 262 { 263 return attribute; 264 } 265 266 267 /** 268 * {@inheritDoc} 269 */ 270 @Override 271 public void setAttribute( Attribute attribute ) 272 { 273 this.attribute = attribute; 274 } 275 276 277 /** 278 * {@inheritDoc} 279 */ 280 @Override 281 public void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException 282 { 283 this.attributeType = attributeType; 284 285 if ( attribute != null ) 286 { 287 attribute.apply( attributeType ); 288 } 289 } 290 291 292 /** 293 * @return The associated AttributeType 294 */ 295 public AttributeType getAttributeType() 296 { 297 return attributeType; 298 } 299 300 301 /** 302 * @see Object#equals(Object) 303 * @return <code>true</code> if both values are equal 304 */ 305 @Override 306 public boolean equals( Object that ) 307 { 308 // Basic equals checks 309 if ( this == that ) 310 { 311 return true; 312 } 313 314 if ( !( that instanceof Modification ) ) 315 { 316 return false; 317 } 318 319 Modification otherModification = ( Modification ) that; 320 321 // Check the operation 322 if ( operation != otherModification.getOperation() ) 323 { 324 return false; 325 } 326 327 // Check the attribute 328 if ( attribute == null ) 329 { 330 return otherModification.getAttribute() == null; 331 } 332 333 return attribute.equals( otherModification.getAttribute() ); 334 } 335 336 337 /** 338 * Compute the modification @see Object#hashCode 339 * @return the instance's hash code 340 */ 341 @Override 342 public int hashCode() 343 { 344 int h = 37; 345 346 h += h * 17 + operation.getValue(); 347 h += h * 17 + attribute.hashCode(); 348 349 return h; 350 } 351 352 353 /** 354 * @see java.io.Externalizable#readExternal(ObjectInput) 355 */ 356 @Override 357 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException 358 { 359 // The operation 360 operation = ModificationOperation.getOperation( in.readInt() ); 361 362 // The EntryAttribute if we have some 363 boolean hasAttribute = in.readBoolean(); 364 365 if ( hasAttribute ) 366 { 367 attribute = new DefaultAttribute(); 368 attribute.readExternal( in ); 369 } 370 } 371 372 373 /** 374 * @see java.io.Externalizable#writeExternal(ObjectOutput) 375 */ 376 @Override 377 public void writeExternal( ObjectOutput out ) throws IOException 378 { 379 // The operation 380 out.writeInt( operation.getValue() ); 381 382 // The EntryAttribute if not null 383 if ( attribute != null ) 384 { 385 out.writeBoolean( true ); 386 attribute.writeExternal( out ); 387 } 388 else 389 { 390 out.writeBoolean( false ); 391 } 392 393 out.flush(); 394 } 395 396 397 /** 398 * {@inheritDoc} 399 */ 400 @Override 401 public DefaultModification clone() 402 { 403 try 404 { 405 DefaultModification clone = ( DefaultModification ) super.clone(); 406 407 clone.attribute = this.attribute.clone(); 408 return clone; 409 } 410 catch ( CloneNotSupportedException cnse ) 411 { 412 return null; 413 } 414 } 415 416 417 /** 418 * @see Object#toString() 419 */ 420 @Override 421 public String toString() 422 { 423 StringBuilder sb = new StringBuilder(); 424 425 sb.append( "Modification: " ). 426 append( operation ). 427 append( "\n" ). 428 append( ", attribute : " ). 429 append( attribute ); 430 431 return sb.toString(); 432 } 433}