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 */
020
021package org.apache.directory.api.ldap.extras.controls.vlv_impl;
022
023
024import java.nio.ByteBuffer;
025
026import org.apache.directory.api.asn1.Asn1Object;
027import org.apache.directory.api.asn1.DecoderException;
028import org.apache.directory.api.asn1.EncoderException;
029import org.apache.directory.api.asn1.ber.Asn1Decoder;
030import org.apache.directory.api.asn1.ber.tlv.BerValue;
031import org.apache.directory.api.asn1.ber.tlv.TLV;
032import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
033import org.apache.directory.api.i18n.I18n;
034import org.apache.directory.api.ldap.codec.api.ControlDecorator;
035import org.apache.directory.api.ldap.codec.api.LdapApiService;
036import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequest;
037import org.apache.directory.api.ldap.extras.controls.vlv.VirtualListViewRequestImpl;
038
039
040/**
041 * The VirtualListView decorator
042 *
043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
044 */
045public class VirtualListViewRequestDecorator extends ControlDecorator<VirtualListViewRequest> implements
046    VirtualListViewRequest
047{
048    private int vlvSeqLength;
049    private int targetSeqLength;
050
051    private static final Asn1Decoder DECODER = new Asn1Decoder();
052
053
054    /**
055     * Creates a new instance of VirtualListViewRequestDecorator.
056     * 
057     * @param codec The LDAP Service to use
058     */
059    public VirtualListViewRequestDecorator( LdapApiService codec )
060    {
061        this( codec, new VirtualListViewRequestImpl() );
062    }
063
064
065    /**
066     * Creates a new instance of VirtualListViewRequestDecorator.
067     * 
068     * @param codec The LDAP Service to use
069     * @param vlvRequest The VLV request to use
070     */
071    public VirtualListViewRequestDecorator( LdapApiService codec, VirtualListViewRequest vlvRequest )
072    {
073        super( codec, vlvRequest );
074    }
075
076
077    /**
078     * {@inheritDoc}
079     */
080    @Override
081    public int computeLength()
082    {
083        vlvSeqLength = 1 + 1 + BerValue.getNbBytes( getBeforeCount() );
084        vlvSeqLength += 1 + 1 + BerValue.getNbBytes( getAfterCount() );
085
086        if ( hasOffset() )
087        {
088            targetSeqLength = 1 + 1 + BerValue.getNbBytes( getOffset() );
089            targetSeqLength += 1 + 1 + BerValue.getNbBytes( getContentCount() );
090
091            vlvSeqLength += 1 + 1 + targetSeqLength;
092        }
093        else
094        {
095            byte[] assertionValue = getAssertionValue();
096
097            if ( assertionValue != null )
098            {
099                targetSeqLength = 1 + TLV.getNbBytes( assertionValue.length ) + assertionValue.length;
100            }
101            else
102            {
103                targetSeqLength = 1 + 1;
104            }
105
106            vlvSeqLength += targetSeqLength;
107        }
108
109        if ( getContextId() != null )
110        {
111            vlvSeqLength += 1 + TLV.getNbBytes( getContextId().length ) + getContextId().length;
112        }
113
114        valueLength = 1 + TLV.getNbBytes( vlvSeqLength ) + vlvSeqLength;
115
116        return valueLength;
117    }
118
119
120    /**
121     * {@inheritDoc}
122     */
123    @Override
124    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
125    {
126        if ( buffer == null )
127        {
128            throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
129        }
130
131        buffer.put( UniversalTag.SEQUENCE.getValue() );
132        buffer.put( TLV.getBytes( vlvSeqLength ) );
133
134        BerValue.encode( buffer, getBeforeCount() );
135        BerValue.encode( buffer, getAfterCount() );
136
137        if ( hasOffset() )
138        {
139            // The byOffset tag
140            buffer.put( ( byte ) VirtualListViewerTags.BY_OFFSET_TAG.getValue() );
141            buffer.put( TLV.getBytes( targetSeqLength ) );
142
143            // The by offset values
144            BerValue.encode( buffer, getOffset() );
145            BerValue.encode( buffer, getContentCount() );
146        }
147        else
148        {
149            buffer.put( ( byte ) VirtualListViewerTags.ASSERTION_VALUE_TAG.getValue() );
150            byte[] value = getAssertionValue();
151
152            if ( value != null )
153            {
154                buffer.put( TLV.getBytes( value.length ) );
155
156                // The by assertionValue value
157                buffer.put( value );
158            }
159            else
160            {
161                buffer.put( TLV.getBytes( 0 ) );
162            }
163        }
164
165        if ( getContextId() != null )
166        {
167            BerValue.encode( buffer, getContextId() );
168        }
169
170        return buffer;
171    }
172
173
174    /**
175     * {@inheritDoc}
176     */
177    @Override
178    public byte[] getValue()
179    {
180        if ( value == null )
181        {
182            try
183            {
184                computeLength();
185                ByteBuffer buffer = ByteBuffer.allocate( valueLength );
186
187                value = encode( buffer ).array();
188            }
189            catch ( Exception e )
190            {
191                return null;
192            }
193        }
194
195        return value;
196    }
197
198
199    /**
200     * {@inheritDoc}
201     */
202    @Override
203    public Asn1Object decode( byte[] controlBytes ) throws DecoderException
204    {
205        ByteBuffer buffer = ByteBuffer.wrap( controlBytes );
206        VirtualListViewRequestContainer container = new VirtualListViewRequestContainer( this, getCodecService() );
207        DECODER.decode( buffer, container );
208        return this;
209    }
210
211
212    /**
213     * {@inheritDoc}
214     */
215    @Override
216    public int getBeforeCount()
217    {
218        return getDecorated().getBeforeCount();
219    }
220
221
222    /**
223     * {@inheritDoc}
224     */
225    @Override
226    public void setBeforeCount( int beforeCount )
227    {
228        getDecorated().setBeforeCount( beforeCount );
229    }
230
231
232    /**
233     * {@inheritDoc}
234     */
235    @Override
236    public int getAfterCount()
237    {
238        return getDecorated().getAfterCount();
239    }
240
241
242    /**
243     * {@inheritDoc}
244     */
245    @Override
246    public void setAfterCount( int afterCount )
247    {
248        getDecorated().setAfterCount( afterCount );
249    }
250
251
252    /**
253     * {@inheritDoc}
254     */
255    @Override
256    public int getOffset()
257    {
258        return getDecorated().getOffset();
259    }
260
261
262    /**
263     * {@inheritDoc}
264     */
265    @Override
266    public void setOffset( int offset )
267    {
268        getDecorated().setOffset( offset );
269    }
270
271
272    /**
273     * {@inheritDoc}
274     */
275    @Override
276    public int getContentCount()
277    {
278        return getDecorated().getContentCount();
279    }
280
281
282    /**
283     * {@inheritDoc}
284     */
285    @Override
286    public void setContentCount( int contentCount )
287    {
288        getDecorated().setContentCount( contentCount );
289    }
290
291
292    /**
293     * {@inheritDoc}
294     */
295    @Override
296    public byte[] getContextId()
297    {
298        return getDecorated().getContextId();
299    }
300
301
302    /**
303     * {@inheritDoc}
304     */
305    @Override
306    public void setContextId( byte[] contextId )
307    {
308        getDecorated().setContextId( contextId );
309    }
310
311
312    /**
313     * {@inheritDoc}
314     */
315    @Override
316    public byte[] getAssertionValue()
317    {
318        return getDecorated().getAssertionValue();
319    }
320
321
322    /**
323     * {@inheritDoc}
324     */
325    @Override
326    public void setAssertionValue( byte[] assertionValue )
327    {
328        getDecorated().setAssertionValue( assertionValue );
329    }
330
331
332    /**
333     * {@inheritDoc}
334     */
335    @Override
336    public boolean hasOffset()
337    {
338        return getDecorated().hasOffset();
339    }
340
341
342    /**
343     * {@inheritDoc}
344     */
345    @Override
346    public boolean hasAssertionValue()
347    {
348        return getDecorated().hasAssertionValue();
349    }
350
351}