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