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