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