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 */
020 package org.apache.directory.shared.ldap.entry;
021
022 import java.io.IOException;
023 import java.io.ObjectInput;
024 import java.io.ObjectOutput;
025
026 import org.apache.directory.shared.i18n.I18n;
027 import org.apache.directory.shared.ldap.entry.client.ClientModification;
028 import org.apache.directory.shared.ldap.exception.LdapException;
029 import org.apache.directory.shared.ldap.schema.AttributeType;
030 import org.apache.directory.shared.ldap.schema.SchemaManager;
031 import org.slf4j.Logger;
032 import org.slf4j.LoggerFactory;
033
034 /**
035 * An internal implementation for a ModificationItem. The name has been
036 * chosen so that it does not conflict with @see ModificationItem
037 *
038 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
039 * @version $Rev$, $Date$
040 */
041 public class ServerModification implements Modification
042 {
043 public static final long serialVersionUID = 1L;
044
045 /** logger for reporting errors that might not be handled properly upstream */
046 private static final Logger LOG = LoggerFactory.getLogger( ServerModification.class );
047
048 /** The modification operation */
049 private ModificationOperation operation;
050
051 /** The attribute which contains the modification */
052 private EntryAttribute attribute;
053
054
055 //-------------------------------------------------------------------------
056 // Constructors
057 //-------------------------------------------------------------------------
058 /**
059 * Create a new instance of a ServerModification.
060 */
061 public ServerModification()
062 {
063 }
064
065
066 /**
067 * Create a new instance of a ServerModification.
068 *
069 * @param operation the Modification operation (one of add, replace or remove)
070 * @param attribute the modified attribute
071 */
072 public ServerModification( ModificationOperation operation, EntryAttribute attribute )
073 {
074 this.operation = operation;
075 this.attribute = attribute;
076 }
077
078
079 public ServerModification( SchemaManager schemaManager, Modification modification )
080 {
081 operation = modification.getOperation();
082
083 EntryAttribute modAttribute = modification.getAttribute();
084
085 try
086 {
087 AttributeType at = null;
088
089 if ( modAttribute instanceof DefaultServerAttribute )
090 {
091 at = ((EntryAttribute)modAttribute).getAttributeType();
092 }
093 else
094 {
095 at = schemaManager.lookupAttributeTypeRegistry( modAttribute.getId() );
096 }
097
098 attribute = new DefaultServerAttribute( at, modAttribute );
099 }
100 catch ( LdapException ne )
101 {
102 // The attributeType is incorrect. Log, but do nothing otherwise.
103 LOG.error( I18n.err( I18n.ERR_04472, modAttribute.getId() ) );
104 }
105 }
106
107
108 //-------------------------------------------------------------------------
109 // API
110 //-------------------------------------------------------------------------
111 /**
112 * @return the operation
113 */
114 public ModificationOperation getOperation()
115 {
116 return operation;
117 }
118
119
120 /**
121 * Store the modification operation
122 *
123 * @param operation The DirContext value to assign
124 */
125 public void setOperation( int operation )
126 {
127 this.operation = ModificationOperation.getOperation( operation );
128 }
129
130
131 /**
132 * Store the modification operation
133 *
134 * @param operation The DirContext value to assign
135 */
136 public void setOperation( ModificationOperation operation )
137 {
138 this.operation = operation;
139 }
140
141
142 /**
143 * @return the attribute containing the modifications
144 */
145 public EntryAttribute getAttribute()
146 {
147 return attribute;
148 }
149
150
151 /**
152 * Set the attribute's modification
153 *
154 * @param attribute The modified attribute
155 */
156 public void setAttribute( EntryAttribute attribute )
157 {
158 this.attribute = (EntryAttribute)attribute;
159 }
160
161
162 /**
163 * Convert the current ServerModification to a ClientModification instance
164 *
165 * @return a new ClientModification instance
166 */
167 public Modification toClientModification()
168 {
169 ModificationOperation newOperation = operation;
170 EntryAttribute newAttribute = attribute.toClientAttribute();
171 Modification newModification = new ClientModification( newOperation, newAttribute );
172
173 return newModification;
174 }
175
176 //-------------------------------------------------------------------------
177 // Overloaded Object class methods
178 //-------------------------------------------------------------------------
179 /**
180 * Compute the modification @see Object#hashCode
181 * @return the instance's hash code
182 */
183 public int hashCode()
184 {
185 int h = 37;
186
187 h += h*17 + operation.getValue();
188 h += h*17 + attribute.hashCode();
189
190 return h;
191 }
192
193
194 /**
195 * @see Object#equals(Object)
196 */
197 public boolean equals( Object that )
198 {
199 // Shortcut
200 if ( this == that )
201 {
202 return true;
203 }
204
205 if ( ! ( that instanceof ServerModification ) )
206 {
207 return false;
208 }
209
210 ServerModification modification = (ServerModification)that;
211
212 if ( operation != modification.getOperation() )
213 {
214 return false;
215 }
216
217 if ( attribute == null )
218 {
219 return modification.getAttribute() == null;
220 }
221
222 return attribute.equals( modification.getAttribute() );
223 }
224
225
226 /**
227 * Create a clone instance
228 */
229 public ServerModification clone()
230 {
231 try
232 {
233 ServerModification clone = (ServerModification)super.clone();
234
235 clone.attribute = (EntryAttribute)this.attribute.clone();
236 return clone;
237 }
238 catch ( CloneNotSupportedException cnse )
239 {
240 return null;
241 }
242 }
243
244
245 /**
246 * @see java.io.Externalizable#writeExternal(ObjectOutput)
247 *
248 * We can't use this method for a ServerModification.
249 */
250 public void writeExternal( ObjectOutput out ) throws IOException
251 {
252 throw new IllegalStateException( I18n.err( I18n.ERR_04469 ) );
253 }
254
255
256 /**
257 * @see java.io.Externalizable#readExternal(ObjectInput)
258 *
259 * We can't use this method for a ServerModification.
260 */
261 public void readExternal( ObjectInput in ) throws IOException
262 {
263 throw new IllegalStateException( I18n.err( I18n.ERR_04469 ) );
264 }
265
266
267 /**
268 * Deserialize a ServerModification
269 *
270 * @param in The buffer containing the serialized value
271 * @param atRegistry The AttributeType registry
272 * @throws IOException If we weren't able to deserialize the data
273 * @throws ClassNotFoundException if we weren't able to construct a Modification instance
274 * @throws LdapException If we didn't found the AttributeType in the registries
275 */
276 public void deserialize( ObjectInput in, SchemaManager schemaManager ) throws IOException, ClassNotFoundException, LdapException
277 {
278 // Read the operation
279 int op = in.readInt();
280
281 operation = ModificationOperation.getOperation( op );
282
283 // Read the attribute OID
284 String oid = in.readUTF();
285
286 // Lookup for tha associated AttributeType
287 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( oid );
288
289 attribute = new DefaultServerAttribute( attributeType );
290
291 // Read the attribute
292 ((DefaultServerAttribute)attribute).deserialize( in );
293 }
294
295
296 /**
297 * Serialize a ServerModification.
298 */
299 public void serialize( ObjectOutput out ) throws IOException
300 {
301 if ( attribute == null )
302 {
303 throw new IOException( I18n.err( I18n.ERR_04471 ) );
304 }
305
306 // Write the operation
307 out.writeInt( operation.getValue() );
308
309 AttributeType at = ((DefaultServerAttribute)attribute).getAttributeType();
310
311 // Write the attribute's oid
312 out.writeUTF( at.getOid() );
313
314 // Write the attribute
315 ((DefaultServerAttribute)attribute).serialize( out );
316 }
317
318
319 /**
320 * @see Object#toString()
321 */
322 public String toString()
323 {
324 StringBuilder sb = new StringBuilder();
325
326 sb.append( "Modification: " ).
327 append( operation ).
328 append( "\n" ).
329 append( ", attribute : " ).
330 append( attribute );
331
332 return sb.toString();
333 }
334 }