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 static org.apache.directory.api.ldap.codec.controls.sort.SortRequestDecorator.ORDERING_RULE_TAG;
24  import static org.apache.directory.api.ldap.codec.controls.sort.SortRequestDecorator.REVERSE_ORDER_TAG;
25  
26  import org.apache.directory.api.asn1.DecoderException;
27  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
28  import org.apache.directory.api.asn1.ber.grammar.Grammar;
29  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
30  import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
31  import org.apache.directory.api.asn1.ber.tlv.BerValue;
32  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
33  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
34  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
35  import org.apache.directory.api.ldap.model.message.controls.SortKey;
36  import org.apache.directory.api.util.Strings;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  
41  /**
42   * Grammar used for decoding a SortRequestControl. It's defined in https://tools.ietf.org/html/rfc2891
43   * 
44   * <pre>
45   * SortKeyList ::= SEQUENCE OF SEQUENCE {
46   *               attributeType   AttributeDescription,
47   *               orderingRule    [0] MatchingRuleId OPTIONAL,
48   *               reverseOrder    [1] BOOLEAN DEFAULT FALSE }
49   * </pre>
50   *
51   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
52   */
53  public final class SortRequestGrammar extends AbstractGrammar<SortRequestContainer>
54  {
55      /** The logger */
56      static final Logger LOG = LoggerFactory.getLogger( SortRequestGrammar.class );
57  
58      /** Speedup for logs */
59      static final boolean IS_DEBUG = LOG.isDebugEnabled();
60  
61      /** The instance of grammar. SortRequestGrammar is a singleton */
62      private static Grammar<SortRequestContainer> instance = new SortRequestGrammar();
63  
64  
65      @SuppressWarnings("unchecked")
66      private SortRequestGrammar()
67      {
68          setName( SortRequestGrammar.class.getName() );
69  
70          GrammarAction<SortRequestContainer> addSortKey = new GrammarAction<SortRequestContainer>()
71          {
72  
73              @Override
74              public void action( SortRequestContainer container ) throws DecoderException
75              {
76                  BerValue value = container.getCurrentTLV().getValue();
77  
78                  String atDesc = Strings.utf8ToString( value.getData() );
79                  if ( IS_DEBUG )
80                  {
81                      LOG.debug( "AttributeTypeDesc = " + atDesc );
82                  }
83  
84                  SortKey sk = new SortKey( atDesc );
85                  container.setCurrentKey( sk );
86                  container.getControl().addSortKey( sk );
87                  container.setGrammarEndAllowed( true );
88              }
89  
90          };
91  
92          GrammarAction<SortRequestContainer> storeReverseOrder = new GrammarAction<SortRequestContainer>()
93          {
94  
95              @Override
96              public void action( SortRequestContainer container ) throws DecoderException
97              {
98                  BerValue value = container.getCurrentTLV().getValue();
99  
100                 try
101                 {
102                     boolean reverseOrder = BooleanDecoder.parse( value );
103 
104                     if ( IS_DEBUG )
105                     {
106                         LOG.debug( "ReverseOrder = " + reverseOrder );
107                     }
108 
109                     container.getCurrentKey().setReverseOrder( reverseOrder );
110 
111                     container.setGrammarEndAllowed( true );
112                 }
113                 catch ( BooleanDecoderException bde )
114                 {
115                     throw new DecoderException( bde.getMessage(), bde );
116                 }
117             }
118 
119         };
120 
121         // Create the transitions table
122         super.transitions = new GrammarTransition[SortRequestStates.END_STATE.ordinal()][256];
123 
124         super.transitions[SortRequestStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
125             new GrammarTransition<SortRequestContainer>( SortRequestStates.START_STATE,
126                 SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE,
127                 UniversalTag.SEQUENCE.getValue(), null );
128 
129         super.transitions[SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
130             new GrammarTransition<SortRequestContainer>( SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE,
131                 SortRequestStates.SORT_KEY_SEQUENCE_STATE,
132                 UniversalTag.SEQUENCE.getValue(), null );
133 
134         super.transitions[SortRequestStates.SORT_KEY_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
135             new GrammarTransition<SortRequestContainer>( SortRequestStates.SORT_KEY_SEQUENCE_STATE,
136                 SortRequestStates.AT_DESC_STATE,
137                 UniversalTag.OCTET_STRING.getValue(), addSortKey );
138 
139         super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][ORDERING_RULE_TAG] =
140             new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
141                 SortRequestStates.ORDER_RULE_STATE,
142                 ORDERING_RULE_TAG, new GrammarAction<SortRequestContainer>()
143                 {
144 
145                     @Override
146                     public void action( SortRequestContainer container ) throws DecoderException
147                     {
148                         BerValue value = container.getCurrentTLV().getValue();
149 
150                         String matchingRuleOid = Strings.utf8ToString( value.getData() );
151 
152                         if ( IS_DEBUG )
153                         {
154                             LOG.debug( "MatchingRuleOid = " + matchingRuleOid );
155                         }
156 
157                         container.getCurrentKey().setMatchingRuleId( matchingRuleOid );
158                         container.setGrammarEndAllowed( true );
159                     }
160 
161                 } );
162 
163         super.transitions[SortRequestStates.ORDER_RULE_STATE.ordinal()][REVERSE_ORDER_TAG] =
164             new GrammarTransition<SortRequestContainer>( SortRequestStates.ORDER_RULE_STATE,
165                 SortRequestStates.REVERSE_ORDER_STATE,
166                 REVERSE_ORDER_TAG, storeReverseOrder );
167 
168         super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][REVERSE_ORDER_TAG] =
169             new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
170                 SortRequestStates.REVERSE_ORDER_STATE,
171                 REVERSE_ORDER_TAG, storeReverseOrder );
172 
173         super.transitions[SortRequestStates.REVERSE_ORDER_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
174             new GrammarTransition<SortRequestContainer>( SortRequestStates.REVERSE_ORDER_STATE,
175                 SortRequestStates.SORT_KEY_SEQUENCE_STATE,
176                 UniversalTag.SEQUENCE.getValue(), null );
177 
178         super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
179             new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
180                 SortRequestStates.SORT_KEY_SEQUENCE_STATE,
181                 UniversalTag.SEQUENCE.getValue(), null );
182 
183     }
184 
185 
186     /**
187      * This class is a singleton.
188      * 
189      * @return An instance on this grammar
190      */
191     public static Grammar<?> getInstance()
192     {
193         return instance;
194     }
195 }