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 *     https://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.controls.sort;
021
022
023import static org.apache.directory.api.ldap.codec.controls.sort.SortRequestFactory.ORDERING_RULE_TAG;
024import static org.apache.directory.api.ldap.codec.controls.sort.SortRequestFactory.REVERSE_ORDER_TAG;
025
026import org.apache.directory.api.asn1.DecoderException;
027import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
028import org.apache.directory.api.asn1.ber.grammar.Grammar;
029import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
030import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
031import org.apache.directory.api.asn1.ber.tlv.BerValue;
032import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
033import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
034import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
035import org.apache.directory.api.i18n.I18n;
036import org.apache.directory.api.ldap.model.message.controls.SortKey;
037import org.apache.directory.api.util.Strings;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041
042/**
043 * Grammar used for decoding a SortRequestControl.
044 *
045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
046 */
047public final class SortRequestGrammar extends AbstractGrammar<SortRequestContainer>
048{
049    /** The logger */
050    static final Logger LOG = LoggerFactory.getLogger( SortRequestGrammar.class );
051
052    /** The instance of grammar. SortRequestGrammar is a singleton */
053    private static Grammar<SortRequestContainer> instance = new SortRequestGrammar();
054
055
056    @SuppressWarnings("unchecked")
057    private SortRequestGrammar()
058    {
059        setName( SortRequestGrammar.class.getName() );
060
061        GrammarAction<SortRequestContainer> addSortKey = new GrammarAction<SortRequestContainer>()
062        {
063
064            @Override
065            public void action( SortRequestContainer container ) throws DecoderException
066            {
067                BerValue value = container.getCurrentTLV().getValue();
068
069                String atDesc = Strings.utf8ToString( value.getData() );
070
071                if ( LOG.isDebugEnabled() )
072                {
073                    LOG.debug( I18n.msg( I18n.MSG_05307_ATTRIBUTE_TYPE_DESC, atDesc ) );
074                }
075
076                SortKey sk = new SortKey( atDesc );
077                container.setCurrentKey( sk );
078                container.getControl().addSortKey( sk );
079                container.setGrammarEndAllowed( true );
080            }
081
082        };
083
084        GrammarAction<SortRequestContainer> storeReverseOrder = new GrammarAction<SortRequestContainer>()
085        {
086
087            @Override
088            public void action( SortRequestContainer container ) throws DecoderException
089            {
090                BerValue value = container.getCurrentTLV().getValue();
091
092                try
093                {
094                    boolean reverseOrder = BooleanDecoder.parse( value );
095
096                    if ( LOG.isDebugEnabled() )
097                    {
098                        LOG.debug( I18n.msg( I18n.MSG_05308_REVERSE_ORDER, reverseOrder ) );
099                    }
100
101                    container.getCurrentKey().setReverseOrder( reverseOrder );
102
103                    container.setGrammarEndAllowed( true );
104                }
105                catch ( BooleanDecoderException bde )
106                {
107                    throw new DecoderException( bde.getMessage(), bde );
108                }
109            }
110
111        };
112
113        // Create the transitions table
114        super.transitions = new GrammarTransition[SortRequestStates.END_STATE.ordinal()][256];
115
116        super.transitions[SortRequestStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
117            new GrammarTransition<SortRequestContainer>( SortRequestStates.START_STATE,
118                SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE,
119                UniversalTag.SEQUENCE.getValue(), null );
120
121        super.transitions[SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
122            new GrammarTransition<SortRequestContainer>( SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE,
123                SortRequestStates.SORT_KEY_SEQUENCE_STATE,
124                UniversalTag.SEQUENCE.getValue(), null );
125
126        super.transitions[SortRequestStates.SORT_KEY_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
127            new GrammarTransition<SortRequestContainer>( SortRequestStates.SORT_KEY_SEQUENCE_STATE,
128                SortRequestStates.AT_DESC_STATE,
129                UniversalTag.OCTET_STRING.getValue(), addSortKey );
130
131        super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][ORDERING_RULE_TAG] =
132            new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
133                SortRequestStates.ORDER_RULE_STATE,
134                ORDERING_RULE_TAG, new GrammarAction<SortRequestContainer>()
135                {
136
137                    @Override
138                    public void action( SortRequestContainer container ) throws DecoderException
139                    {
140                        BerValue value = container.getCurrentTLV().getValue();
141
142                        String matchingRuleOid = Strings.utf8ToString( value.getData() );
143
144                        if ( LOG.isDebugEnabled() )
145                        {
146                            LOG.debug( I18n.msg( I18n.MSG_05309_MATCHING_RULE_OID, matchingRuleOid ) );
147                        }
148
149                        container.getCurrentKey().setMatchingRuleId( matchingRuleOid );
150                        container.setGrammarEndAllowed( true );
151                    }
152
153                } );
154
155        super.transitions[SortRequestStates.ORDER_RULE_STATE.ordinal()][REVERSE_ORDER_TAG] =
156            new GrammarTransition<SortRequestContainer>( SortRequestStates.ORDER_RULE_STATE,
157                SortRequestStates.REVERSE_ORDER_STATE,
158                REVERSE_ORDER_TAG, storeReverseOrder );
159
160        super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][REVERSE_ORDER_TAG] =
161            new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
162                SortRequestStates.REVERSE_ORDER_STATE,
163                REVERSE_ORDER_TAG, storeReverseOrder );
164
165        super.transitions[SortRequestStates.REVERSE_ORDER_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
166            new GrammarTransition<SortRequestContainer>( SortRequestStates.REVERSE_ORDER_STATE,
167                SortRequestStates.SORT_KEY_SEQUENCE_STATE,
168                UniversalTag.SEQUENCE.getValue(), null );
169
170        super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
171            new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE,
172                SortRequestStates.SORT_KEY_SEQUENCE_STATE,
173                UniversalTag.SEQUENCE.getValue(), null );
174
175    }
176
177
178    /**
179     * This class is a singleton.
180     *
181     * @return An instance on this grammar
182     */
183    public static Grammar<?> getInstance()
184    {
185        return instance;
186    }
187}