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.codec.decorators;
021
022
023import java.nio.BufferOverflowException;
024import java.nio.ByteBuffer;
025
026import org.apache.directory.api.asn1.EncoderException;
027import org.apache.directory.api.asn1.ber.tlv.BerValue;
028import org.apache.directory.api.asn1.ber.tlv.TLV;
029import org.apache.directory.api.i18n.I18n;
030import org.apache.directory.api.ldap.codec.api.LdapApiService;
031import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
032import org.apache.directory.api.ldap.model.message.Control;
033import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
034import org.apache.directory.api.ldap.model.name.Dn;
035import org.apache.directory.api.ldap.model.name.Rdn;
036import org.apache.directory.api.util.Strings;
037
038
039/**
040 * A decorator for the ModifyDnRequest message
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044public class ModifyDnRequestDecorator extends SingleReplyRequestDecorator<ModifyDnRequest>
045    implements ModifyDnRequest
046{
047    /** The modify Dn request length */
048    private int modifyDnRequestLength;
049
050
051    /**
052     * Makes a ModifyDnRequest encodable.
053     *
054     * @param decoratedMessage the decorated ModifyDnRequest
055     */
056    public ModifyDnRequestDecorator( LdapApiService codec, ModifyDnRequest decoratedMessage )
057    {
058        super( codec, decoratedMessage );
059    }
060
061
062    /**
063     * @param modifyDnRequestLength The encoded ModifyDnRequest's length
064     */
065    public void setModifyDnRequestLength( int modifyDnRequestLength )
066    {
067        this.modifyDnRequestLength = modifyDnRequestLength;
068    }
069
070
071    /**
072     * Stores the encoded length for the ModifyDnRequest
073     * @return the encoded length
074     */
075    public int getModifyDnResponseLength()
076    {
077        return modifyDnRequestLength;
078    }
079
080
081    //-------------------------------------------------------------------------
082    // The ModifyDnResponse methods
083    //-------------------------------------------------------------------------
084
085    /**
086     * {@inheritDoc}
087     */
088    public Dn getName()
089    {
090        return getDecorated().getName();
091    }
092
093
094    /**
095     * {@inheritDoc}
096     */
097    public ModifyDnRequest setName( Dn name )
098    {
099        getDecorated().setName( name );
100
101        return this;
102    }
103
104
105    /**
106     * {@inheritDoc}
107     */
108    public Rdn getNewRdn()
109    {
110        return getDecorated().getNewRdn();
111    }
112
113
114    /**
115     * {@inheritDoc}
116     */
117    public ModifyDnRequest setNewRdn( Rdn newRdn )
118    {
119        getDecorated().setNewRdn( newRdn );
120
121        return this;
122    }
123
124
125    /**
126     * {@inheritDoc}
127     */
128    public boolean getDeleteOldRdn()
129    {
130        return getDecorated().getDeleteOldRdn();
131    }
132
133
134    /**
135     * {@inheritDoc}
136     */
137    public ModifyDnRequest setDeleteOldRdn( boolean deleteOldRdn )
138    {
139        getDecorated().setDeleteOldRdn( deleteOldRdn );
140
141        return this;
142    }
143
144
145    /**
146     * {@inheritDoc}
147     */
148    public Dn getNewSuperior()
149    {
150        return getDecorated().getNewSuperior();
151    }
152
153
154    /**
155     * {@inheritDoc}
156     */
157    public ModifyDnRequest setNewSuperior( Dn newSuperior )
158    {
159        getDecorated().setNewSuperior( newSuperior );
160
161        return this;
162    }
163
164
165    /**
166     * {@inheritDoc}
167     */
168    public boolean isMove()
169    {
170        return getDecorated().isMove();
171    }
172
173
174    /**
175     * {@inheritDoc}
176     */
177    public ModifyDnRequest setMessageId( int messageId )
178    {
179        super.setMessageId( messageId );
180
181        return this;
182    }
183
184
185    /**
186     * {@inheritDoc}
187     */
188    public ModifyDnRequest addControl( Control control )
189    {
190        return ( ModifyDnRequest ) super.addControl( control );
191    }
192
193
194    /**
195     * {@inheritDoc}
196     */
197    public ModifyDnRequest addAllControls( Control[] controls )
198    {
199        return ( ModifyDnRequest ) super.addAllControls( controls );
200    }
201
202
203    /**
204     * {@inheritDoc}
205     */
206    public ModifyDnRequest removeControl( Control control )
207    {
208        return ( ModifyDnRequest ) super.removeControl( control );
209    }
210
211
212    //-------------------------------------------------------------------------
213    // The Decorator methods
214    //-------------------------------------------------------------------------
215
216    /**
217     * Compute the ModifyDNRequest length
218     * 
219     * ModifyDNRequest :
220     * <pre>
221     * 0x6C L1
222     *  |
223     *  +--> 0x04 L2 entry
224     *  +--> 0x04 L3 newRDN
225     *  +--> 0x01 0x01 (true/false) deleteOldRDN (3 bytes)
226     * [+--> 0x80 L4 newSuperior ] 
227     * 
228     * L2 = Length(0x04) + Length(Length(entry)) + Length(entry) 
229     * L3 = Length(0x04) + Length(Length(newRDN)) + Length(newRDN) 
230     * L4 = Length(0x80) + Length(Length(newSuperior)) + Length(newSuperior)
231     * L1 = L2 + L3 + 3 [+ L4] 
232     * 
233     * Length(ModifyDNRequest) = Length(0x6C) + Length(L1) + L1
234     * </pre>
235     * 
236     * @return The PDU's length of a ModifyDN Request
237     */
238    public int computeLength()
239    {
240        int newRdnlength = Strings.getBytesUtf8( getNewRdn().getName() ).length;
241
242        int modifyDNRequestLength = 1 + TLV.getNbBytes( Dn.getNbBytes( getName() ) )
243            + Dn.getNbBytes( getName() ) + 1 + TLV.getNbBytes( newRdnlength ) + newRdnlength + 1 + 1
244            + 1; // deleteOldRDN
245
246        if ( getNewSuperior() != null )
247        {
248            modifyDNRequestLength += 1 + TLV.getNbBytes( Dn.getNbBytes( getNewSuperior() ) )
249                + Dn.getNbBytes( getNewSuperior() );
250        }
251
252        setModifyDnRequestLength( modifyDNRequestLength );
253
254        return 1 + TLV.getNbBytes( modifyDNRequestLength ) + modifyDNRequestLength;
255    }
256
257
258    /**
259     * Encode the ModifyDNRequest message to a PDU. 
260     * 
261     * ModifyDNRequest :
262     * <pre>
263     * 0x6C LL
264     *   0x04 LL entry
265     *   0x04 LL newRDN
266     *   0x01 0x01 deleteOldRDN
267     *   [0x80 LL newSuperior]
268     * </pre>
269     * @param buffer The buffer where to put the PDU
270     * @return The PDU.
271     */
272    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
273    {
274        try
275        {
276            // The ModifyDNRequest Tag
277            buffer.put( LdapCodecConstants.MODIFY_DN_REQUEST_TAG );
278            buffer.put( TLV.getBytes( getModifyDnResponseLength() ) );
279
280            // The entry
281
282            BerValue.encode( buffer, Dn.getBytes( getName() ) );
283
284            // The newRDN
285            BerValue.encode( buffer, getNewRdn().getName() );
286
287            // The flag deleteOldRdn
288            BerValue.encode( buffer, getDeleteOldRdn() );
289
290            // The new superior, if any
291            if ( getNewSuperior() != null )
292            {
293                // Encode the reference
294                buffer.put( ( byte ) LdapCodecConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG );
295
296                int newSuperiorLength = Dn.getNbBytes( getNewSuperior() );
297
298                buffer.put( TLV.getBytes( newSuperiorLength ) );
299
300                if ( newSuperiorLength != 0 )
301                {
302                    buffer.put( Dn.getBytes( getNewSuperior() ) );
303                }
304            }
305        }
306        catch ( BufferOverflowException boe )
307        {
308            throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
309        }
310
311        return buffer;
312    }
313}