View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  package org.apache.directory.api.ldap.codec.controls.sort;
21  
22  
23  import java.nio.ByteBuffer;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.apache.directory.api.asn1.Asn1Object;
28  import org.apache.directory.api.asn1.DecoderException;
29  import org.apache.directory.api.asn1.EncoderException;
30  import org.apache.directory.api.asn1.ber.Asn1Decoder;
31  import org.apache.directory.api.asn1.ber.tlv.BerValue;
32  import org.apache.directory.api.asn1.ber.tlv.TLV;
33  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
34  import org.apache.directory.api.i18n.I18n;
35  import org.apache.directory.api.ldap.codec.api.ControlDecorator;
36  import org.apache.directory.api.ldap.codec.api.LdapApiService;
37  import org.apache.directory.api.ldap.model.message.controls.SortKey;
38  import org.apache.directory.api.ldap.model.message.controls.SortRequest;
39  import org.apache.directory.api.ldap.model.message.controls.SortRequestControlImpl;
40  import org.apache.directory.api.util.Strings;
41  
42  
43  /**
44   * Decorator of SortRequestControl.
45   *
46   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
47   */
48  public class SortRequestDecorator extends ControlDecorator<SortRequest> implements SortRequest
49  {
50      private Asn1Decoder decoder = new Asn1Decoder();
51  
52      private int sortReqLen = 0;
53  
54      private List<Integer> sortKeyLenList = new ArrayList<Integer>();
55  
56  
57      /**
58       * Creates a new instance of SortRequestDecorator.
59       *
60       * @param codec the LDAP codec
61       */
62      public SortRequestDecorator( LdapApiService codec )
63      {
64          super( codec, new SortRequestControlImpl() );
65      }
66  
67  
68      /**
69       * Creates a new instance of SortRequestDecorator.
70       *
71       * @param codec the LDAP codec
72       * @param control the control instance
73       */
74      public SortRequestDecorator( LdapApiService codec, SortRequest control )
75      {
76          super( codec, control );
77      }
78  
79  
80      /**
81       * 
82       */
83      @Override
84      public int computeLength()
85      {
86          sortReqLen = 0;
87          sortKeyLenList.clear();
88          valueLength = 0;
89  
90          for ( SortKey sk : getSortKeys() )
91          {
92              int skLen = 0;
93  
94              byte[] atBytes = Strings.getBytesUtf8( sk.getAttributeTypeDesc() );
95              skLen += 1 + TLV.getNbBytes( atBytes.length ) + atBytes.length;
96  
97              if ( sk.getMatchingRuleId() != null )
98              {
99                  byte[] mrBytes = Strings.getBytesUtf8( sk.getMatchingRuleId() );
100                 skLen += 1 + TLV.getNbBytes( mrBytes.length ) + mrBytes.length;
101             }
102 
103             // reverse order flag
104             skLen += 1 + 1 + 1;
105 
106             sortKeyLenList.add( skLen );
107 
108             // the sequence
109             sortReqLen += 1 + TLV.getNbBytes( skLen ) + skLen;
110         }
111 
112         valueLength = 1 + TLV.getNbBytes( sortReqLen ) + sortReqLen;
113 
114         return valueLength;
115     }
116 
117 
118     @Override
119     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
120     {
121         if ( buffer == null )
122         {
123             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
124         }
125 
126         buffer.put( UniversalTag.SEQUENCE.getValue() );
127         buffer.put( TLV.getBytes( sortReqLen ) );
128 
129         List<SortKey> lst = getSortKeys();
130 
131         for ( int i = 0; i < lst.size(); i++ )
132         {
133             SortKey sk = lst.get( i );
134             int skLen = sortKeyLenList.get( i );
135 
136             buffer.put( UniversalTag.SEQUENCE.getValue() );
137             buffer.put( TLV.getBytes( skLen ) );
138 
139             BerValue.encode( buffer, sk.getAttributeTypeDesc() );
140 
141             if ( sk.getMatchingRuleId() != null )
142             {
143                 BerValue.encode( buffer, sk.getMatchingRuleId() );
144             }
145 
146             BerValue.encode( buffer, sk.isReverseOrder() );
147         }
148 
149         return buffer;
150     }
151 
152 
153     @Override
154     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
155     {
156         ByteBuffer buffer = ByteBuffer.wrap( controlBytes );
157         SortRequestContainer container = new SortRequestContainer( getCodecService(), this );
158         decoder.decode( buffer, container );
159         return this;
160     }
161 
162 
163     /**
164      * {@inheritDoc}
165      */
166     public byte[] getValue()
167     {
168         if ( value == null )
169         {
170             try
171             {
172                 computeLength();
173                 ByteBuffer buffer = ByteBuffer.allocate( valueLength );
174 
175                 value = encode( buffer ).array();
176             }
177             catch ( Exception e )
178             {
179                 return null;
180             }
181         }
182 
183         return value;
184     }
185 
186 
187     @Override
188     public void setSortKeys( List<SortKey> sortKeys )
189     {
190         getDecorated().setSortKeys( sortKeys );
191     }
192 
193 
194     @Override
195     public List<SortKey> getSortKeys()
196     {
197         return getDecorated().getSortKeys();
198     }
199 
200 
201     @Override
202     public void addSortKey( SortKey sortKey )
203     {
204         getDecorated().addSortKey( sortKey );
205     }
206 
207 }