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<>();
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    @Override
077    public Collection<Modification> getModifications()
078    {
079        return Collections.unmodifiableCollection( mods );
080    }
081
082
083    /**
084     * {@inheritDoc}
085     */
086    @Override
087    public Dn getName()
088    {
089        return name;
090    }
091
092
093    /**
094     * {@inheritDoc}
095     */
096    @Override
097    public ModifyRequest setName( Dn name )
098    {
099        this.name = name;
100
101        return this;
102    }
103
104
105    /**
106     * {@inheritDoc}
107     */
108    @Override
109    public ModifyRequest addModification( Modification mod )
110    {
111        mods.add( mod );
112
113        return this;
114    }
115
116
117    private void addModification( ModificationOperation modOp, String attributeName, byte[]... attributeValue )
118    {
119        Attribute attr = new DefaultAttribute( attributeName, attributeValue );
120        addModification( attr, modOp );
121    }
122
123
124    private void addModification( ModificationOperation modOp, String attributeName, String... attributeValue )
125    {
126        Attribute attr = new DefaultAttribute( attributeName, attributeValue );
127        addModification( attr, modOp );
128    }
129
130
131    /**
132     * {@inheritDoc}
133     */
134    @Override
135    public ModifyRequest addModification( Attribute attr, ModificationOperation modOp )
136    {
137        mods.add( new DefaultModification( modOp, attr ) );
138
139        return this;
140    }
141
142
143    /**
144     *{@inheritDoc}
145     */
146    @Override
147    public ModifyRequest add( String attributeName, String... attributeValue )
148    {
149        addModification( ModificationOperation.ADD_ATTRIBUTE, attributeName, attributeValue );
150
151        return this;
152    }
153
154
155    /**
156     * @see #add(String, String...)
157     */
158    public ModifyRequest add( String attributeName, byte[]... attributeValue )
159    {
160        addModification( ModificationOperation.ADD_ATTRIBUTE, attributeName, attributeValue );
161
162        return this;
163    }
164
165
166    /**
167     *{@inheritDoc}
168     */
169    @Override
170    public ModifyRequest add( Attribute attr )
171    {
172        addModification( attr, ModificationOperation.ADD_ATTRIBUTE );
173
174        return this;
175    }
176
177
178    /**
179     * @see #replace(String, String...)
180     */
181    @Override
182    public ModifyRequest replace( String attributeName )
183    {
184        addModification( ModificationOperation.REPLACE_ATTRIBUTE, attributeName, StringConstants.EMPTY_STRINGS );
185
186        return this;
187    }
188
189
190    /**
191     *{@inheritDoc}
192     */
193    @Override
194    public ModifyRequest replace( String attributeName, String... attributeValue )
195    {
196        addModification( ModificationOperation.REPLACE_ATTRIBUTE, attributeName, attributeValue );
197
198        return this;
199    }
200
201
202    /**
203     * @see #replace(String, String...)
204     */
205    public ModifyRequest replace( String attributeName, byte[]... attributeValue )
206    {
207        addModification( ModificationOperation.REPLACE_ATTRIBUTE, attributeName, attributeValue );
208
209        return this;
210    }
211
212
213    /**
214     *{@inheritDoc}
215     */
216    @Override
217    public ModifyRequest replace( Attribute attr )
218    {
219        addModification( attr, ModificationOperation.REPLACE_ATTRIBUTE );
220
221        return this;
222    }
223
224
225    /**
226     * {@inheritDoc}
227     */
228    @Override
229    public ModifyRequest removeModification( Modification mod )
230    {
231        mods.remove( mod );
232
233        return this;
234    }
235
236
237    /**
238     * {@inheritDoc}
239     */
240    @Override
241    public ModifyRequest remove( String attributeName, String... attributeValue )
242    {
243        addModification( ModificationOperation.REMOVE_ATTRIBUTE, attributeName, attributeValue );
244
245        return this;
246    }
247
248
249    /**
250     * {@inheritDoc}
251     */
252    public ModifyRequest remove( String attributeName, byte[]... attributeValue )
253    {
254        addModification( ModificationOperation.REMOVE_ATTRIBUTE, attributeName, attributeValue );
255
256        return this;
257    }
258
259
260    /**
261     * {@inheritDoc}
262     */
263    @Override
264    public ModifyRequest remove( Attribute attr )
265    {
266        addModification( attr, ModificationOperation.REMOVE_ATTRIBUTE );
267
268        return this;
269    }
270
271
272    /**
273     * {@inheritDoc}
274     */
275    @Override
276    public ModifyRequest remove( String attributerName )
277    {
278        addModification( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, attributerName ) );
279
280        return this;
281    }
282
283
284    /**
285     * {@inheritDoc}
286     */
287    @Override
288    public ModifyRequest setMessageId( int messageId )
289    {
290        super.setMessageId( messageId );
291
292        return this;
293    }
294
295
296    /**
297     * {@inheritDoc}
298     */
299    @Override
300    public ModifyRequest addControl( Control control )
301    {
302        return ( ModifyRequest ) super.addControl( control );
303    }
304
305
306    /**
307     * {@inheritDoc}
308     */
309    @Override
310    public ModifyRequest addAllControls( Control[] controls )
311    {
312        return ( ModifyRequest ) super.addAllControls( controls );
313    }
314
315
316    /**
317     * {@inheritDoc}
318     */
319    @Override
320    public ModifyRequest removeControl( Control control )
321    {
322        return ( ModifyRequest ) super.removeControl( control );
323    }
324
325
326    // ------------------------------------------------------------------------
327    // SingleReplyRequest Interface Method Implementations
328    // ------------------------------------------------------------------------
329
330    /**
331     * Gets the protocol response message type for this request which produces
332     * at least one response.
333     * 
334     * @return the message type of the response.
335     */
336    @Override
337    public MessageTypeEnum getResponseType()
338    {
339        return MessageTypeEnum.MODIFY_RESPONSE;
340    }
341
342
343    /**
344     * The result containing response for this request.
345     * 
346     * @return the result containing response for this request
347     */
348    @Override
349    public ModifyResponse getResultResponse()
350    {
351        if ( response == null )
352        {
353            response = new ModifyResponseImpl( getMessageId() );
354        }
355
356        return response;
357    }
358
359
360    /**
361     * {@inheritDoc}
362     */
363    @Override
364    public int hashCode()
365    {
366        int hash = 37;
367        if ( name != null )
368        {
369            hash = hash * 17 + name.hashCode();
370        }
371        hash = hash * 17 + mods.size();
372        for ( int i = 0; i < mods.size(); i++ )
373        {
374            hash = hash * 17 + ( ( DefaultModification ) mods.get( i ) ).hashCode();
375        }
376        hash = hash * 17 + super.hashCode();
377
378        return hash;
379    }
380
381
382    /**
383     * Checks to see if ModifyRequest stub equals another by factoring in checks
384     * for the name and modification items of the request.
385     * 
386     * @param obj
387     *            the object to compare this ModifyRequest to
388     * @return true if obj equals this ModifyRequest, false otherwise
389     */
390    @Override
391    public boolean equals( Object obj )
392    {
393        if ( obj == this )
394        {
395            return true;
396        }
397
398        if ( !super.equals( obj ) )
399        {
400            return false;
401        }
402
403        ModifyRequest req = ( ModifyRequest ) obj;
404
405        if ( name != null && req.getName() == null )
406        {
407            return false;
408        }
409
410        if ( name == null && req.getName() != null )
411        {
412            return false;
413        }
414
415        if ( name != null && req.getName() != null && !name.equals( req.getName() ) )
416        {
417            return false;
418        }
419
420        if ( req.getModifications().size() != mods.size() )
421        {
422            return false;
423        }
424
425        Iterator<Modification> list = req.getModifications().iterator();
426
427        for ( int i = 0; i < mods.size(); i++ )
428        {
429            Modification item = list.next();
430
431            if ( item == null )
432            {
433                if ( mods.get( i ) != null )
434                {
435                    return false;
436                }
437            }
438            else
439
440            if ( !item.equals( mods.get( i ) ) )
441            {
442                return false;
443            }
444        }
445
446        return true;
447    }
448
449
450    /**
451     * Get a String representation of a ModifyRequest
452     * 
453     * @return A ModifyRequest String
454     */
455    @Override
456    public String toString()
457    {
458        StringBuilder sb = new StringBuilder();
459
460        sb.append( "    Modify Request\n" );
461        sb.append( "        Object : '" ).append( name ).append( "'\n" );
462
463        if ( mods != null )
464        {
465
466            for ( int i = 0; i < mods.size(); i++ )
467            {
468
469                DefaultModification modification = ( DefaultModification ) mods.get( i );
470
471                sb.append( "            Modification[" ).append( i ).append( "]\n" );
472                sb.append( "                Operation : " );
473
474                switch ( modification.getOperation() )
475                {
476                    case ADD_ATTRIBUTE:
477                        sb.append( " add\n" );
478                        break;
479
480                    case REPLACE_ATTRIBUTE:
481                        sb.append( " replace\n" );
482                        break;
483
484                    case REMOVE_ATTRIBUTE:
485                        sb.append( " delete\n" );
486                        break;
487
488                    default:
489                        throw new IllegalArgumentException( "Unexpected ModificationOperation "
490                            + modification.getOperation() );
491                }
492
493                sb.append( "                Modification\n" );
494                sb.append( modification.getAttribute() );
495            }
496        }
497
498        // The controls
499        sb.append( super.toString() );
500
501        return super.toString( sb.toString() );
502    }
503}