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    }