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.message;
021
022
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.Iterator;
027import java.util.List;
028
029import org.apache.directory.api.ldap.model.entry.Attribute;
030import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
031import org.apache.directory.api.ldap.model.entry.DefaultModification;
032import org.apache.directory.api.ldap.model.entry.Modification;
033import org.apache.directory.api.ldap.model.entry.ModificationOperation;
034import org.apache.directory.api.ldap.model.name.Dn;
035import org.apache.directory.api.util.StringConstants;
036
037
038/**
039 * Lockable ModifyRequest implementation.
040 * 
041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
042 */
043public class ModifyRequestImpl extends AbstractAbandonableRequest implements ModifyRequest
044{
045    static final long serialVersionUID = -505803669028990304L;
046
047    /** Dn of the entry to modify or PDU's <b>object</b> field */
048    private Dn name;
049
050    /** Sequence of modifications or PDU's <b>modification</b> sequence field */
051    private List<Modification> mods = new ArrayList<Modification>();
052
053    /** The associated response */
054    private ModifyResponse response;
055
056
057    // -----------------------------------------------------------------------
058    // Constructors
059    // -----------------------------------------------------------------------
060    /**
061     * Creates a ModifyRequest implementing object used to modify the
062     * attributes of an entry.
063     */
064    public ModifyRequestImpl()
065    {
066        super( -1, MessageTypeEnum.MODIFY_REQUEST );
067    }
068
069
070    // ------------------------------------------------------------------------
071    // ModifyRequest Interface Method Implementations
072    // ------------------------------------------------------------------------
073    /**
074     * {@inheritDoc}
075     */
076    public Collection<Modification> getModifications()
077    {
078        return Collections.unmodifiableCollection( mods );
079    }
080
081
082    /**
083     * {@inheritDoc}
084     */
085    public Dn getName()
086    {
087        return name;
088    }
089
090
091    /**
092     * {@inheritDoc}
093     */
094    public ModifyRequest setName( Dn name )
095    {
096        this.name = name;
097
098        return this;
099    }
100
101
102    /**
103     * {@inheritDoc}
104     */
105    public ModifyRequest addModification( Modification mod )
106    {
107        mods.add( mod );
108
109        return this;
110    }
111
112
113    private void addModification( ModificationOperation modOp, String attributeName, byte[]... attributeValue )
114    {
115        Attribute attr = new DefaultAttribute( attributeName, attributeValue );
116        addModification( attr, modOp );
117    }
118
119
120    private void addModification( ModificationOperation modOp, String attributeName, String... attributeValue )
121    {
122        Attribute attr = new DefaultAttribute( attributeName, attributeValue );
123        addModification( attr, modOp );
124    }
125
126
127    /**
128     * {@inheritDoc}
129     */
130    public ModifyRequest addModification( Attribute attr, ModificationOperation modOp )
131    {
132        mods.add( new DefaultModification( modOp, attr ) );
133
134        return this;
135    }
136
137
138    /**
139     *{@inheritDoc}
140     */
141    public ModifyRequest add( String attributeName, String... attributeValue )
142    {
143        addModification( ModificationOperation.ADD_ATTRIBUTE, attributeName, attributeValue );
144
145        return this;
146    }
147
148
149    /**
150     * @see #add(String, String...)
151     */
152    public ModifyRequest add( String attributeName, byte[]... attributeValue )
153    {
154        addModification( ModificationOperation.ADD_ATTRIBUTE, attributeName, attributeValue );
155
156        return this;
157    }
158
159
160    /**
161     *{@inheritDoc}
162     */
163    public ModifyRequest add( Attribute attr )
164    {
165        addModification( attr, ModificationOperation.ADD_ATTRIBUTE );
166
167        return this;
168    }
169
170
171    /**
172     * @see #replace(String, String...)
173     */
174    public ModifyRequest replace( String attributeName )
175    {
176        addModification( ModificationOperation.REPLACE_ATTRIBUTE, attributeName, StringConstants.EMPTY_STRINGS );
177
178        return this;
179    }
180
181
182    /**
183     *{@inheritDoc}
184     */
185    public ModifyRequest replace( String attributeName, String... attributeValue )
186    {
187        addModification( ModificationOperation.REPLACE_ATTRIBUTE, attributeName, attributeValue );
188
189        return this;
190    }
191
192
193    /**
194     * @see #replace(String, String...)
195     */
196    public ModifyRequest replace( String attributeName, byte[]... attributeValue )
197    {
198        addModification( ModificationOperation.REPLACE_ATTRIBUTE, attributeName, attributeValue );
199
200        return this;
201    }
202
203
204    /**
205     *{@inheritDoc}
206     */
207    public ModifyRequest replace( Attribute attr )
208    {
209        addModification( attr, ModificationOperation.REPLACE_ATTRIBUTE );
210
211        return this;
212    }
213
214
215    /**
216     * {@inheritDoc}
217     */
218    public ModifyRequest removeModification( Modification mod )
219    {
220        mods.remove( mod );
221
222        return this;
223    }
224
225
226    /**
227     * {@inheritDoc}
228     */
229    public ModifyRequest remove( String attributeName, String... attributeValue )
230    {
231        addModification( ModificationOperation.REMOVE_ATTRIBUTE, attributeName, attributeValue );
232
233        return this;
234    }
235
236
237    /**
238     * {@inheritDoc}
239     */
240    public ModifyRequest remove( String attributeName, byte[]... attributeValue )
241    {
242        addModification( ModificationOperation.REMOVE_ATTRIBUTE, attributeName, attributeValue );
243
244        return this;
245    }
246
247
248    /**
249     * {@inheritDoc}
250     */
251    public ModifyRequest remove( Attribute attr )
252    {
253        addModification( attr, ModificationOperation.REMOVE_ATTRIBUTE );
254
255        return this;
256    }
257
258
259    /**
260     * {@inheritDoc}
261     */
262    public ModifyRequest setMessageId( int messageId )
263    {
264        super.setMessageId( messageId );
265
266        return this;
267    }
268
269
270    /**
271     * {@inheritDoc}
272     */
273    public ModifyRequest addControl( Control control )
274    {
275        return ( ModifyRequest ) super.addControl( control );
276    }
277
278
279    /**
280     * {@inheritDoc}
281     */
282    public ModifyRequest addAllControls( Control[] controls )
283    {
284        return ( ModifyRequest ) super.addAllControls( controls );
285    }
286
287
288    /**
289     * {@inheritDoc}
290     */
291    public ModifyRequest removeControl( Control control )
292    {
293        return ( ModifyRequest ) super.removeControl( control );
294    }
295
296
297    // ------------------------------------------------------------------------
298    // SingleReplyRequest Interface Method Implementations
299    // ------------------------------------------------------------------------
300
301    /**
302     * Gets the protocol response message type for this request which produces
303     * at least one response.
304     * 
305     * @return the message type of the response.
306     */
307    public MessageTypeEnum getResponseType()
308    {
309        return MessageTypeEnum.MODIFY_RESPONSE;
310    }
311
312
313    /**
314     * The result containing response for this request.
315     * 
316     * @return the result containing response for this request
317     */
318    public ModifyResponse getResultResponse()
319    {
320        if ( response == null )
321        {
322            response = new ModifyResponseImpl( getMessageId() );
323        }
324
325        return response;
326    }
327
328
329    /**
330     * {@inheritDoc}
331     */
332    @Override
333    public int hashCode()
334    {
335        int hash = 37;
336        if ( name != null )
337        {
338            hash = hash * 17 + name.hashCode();
339        }
340        hash = hash * 17 + mods.size();
341        for ( int i = 0; i < mods.size(); i++ )
342        {
343            hash = hash * 17 + ( ( DefaultModification ) mods.get( i ) ).hashCode();
344        }
345        hash = hash * 17 + super.hashCode();
346
347        return hash;
348    }
349
350
351    /**
352     * Checks to see if ModifyRequest stub equals another by factoring in checks
353     * for the name and modification items of the request.
354     * 
355     * @param obj
356     *            the object to compare this ModifyRequest to
357     * @return true if obj equals this ModifyRequest, false otherwise
358     */
359    public boolean equals( Object obj )
360    {
361        if ( obj == this )
362        {
363            return true;
364        }
365
366        if ( !super.equals( obj ) )
367        {
368            return false;
369        }
370
371        ModifyRequest req = ( ModifyRequest ) obj;
372
373        if ( name != null && req.getName() == null )
374        {
375            return false;
376        }
377
378        if ( name == null && req.getName() != null )
379        {
380            return false;
381        }
382
383        if ( name != null && req.getName() != null && !name.equals( req.getName() ) )
384        {
385            return false;
386        }
387
388        if ( req.getModifications().size() != mods.size() )
389        {
390            return false;
391        }
392
393        Iterator<Modification> list = req.getModifications().iterator();
394
395        for ( int i = 0; i < mods.size(); i++ )
396        {
397            Modification item = list.next();
398
399            if ( item == null )
400            {
401                if ( mods.get( i ) != null )
402                {
403                    return false;
404                }
405            }
406            else
407
408            if ( !item.equals( mods.get( i ) ) )
409            {
410                return false;
411            }
412        }
413
414        return true;
415    }
416
417
418    /**
419     * Get a String representation of a ModifyRequest
420     * 
421     * @return A ModifyRequest String
422     */
423    public String toString()
424    {
425
426        StringBuffer sb = new StringBuffer();
427
428        sb.append( "    Modify Request\n" );
429        sb.append( "        Object : '" ).append( name ).append( "'\n" );
430
431        if ( mods != null )
432        {
433
434            for ( int i = 0; i < mods.size(); i++ )
435            {
436
437                DefaultModification modification = ( DefaultModification ) mods.get( i );
438
439                sb.append( "            Modification[" ).append( i ).append( "]\n" );
440                sb.append( "                Operation : " );
441
442                switch ( modification.getOperation() )
443                {
444                    case ADD_ATTRIBUTE:
445                        sb.append( " add\n" );
446                        break;
447
448                    case REPLACE_ATTRIBUTE:
449                        sb.append( " replace\n" );
450                        break;
451
452                    case REMOVE_ATTRIBUTE:
453                        sb.append( " delete\n" );
454                        break;
455                }
456
457                sb.append( "                Modification\n" );
458                sb.append( modification.getAttribute() );
459            }
460        }
461
462        // The controls
463        sb.append( super.toString() );
464
465        return super.toString( sb.toString() );
466    }
467}