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.extras.extended.ads_impl.endTransaction.controls;
021
022import org.apache.directory.api.asn1.DecoderException;
023import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
024import org.apache.directory.api.asn1.ber.grammar.Grammar;
025import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
026import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
027import org.apache.directory.api.asn1.ber.tlv.TLV;
028import org.apache.directory.api.i18n.I18n;
029import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions.AddControl;
030import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions.StoreControlCriticality;
031import org.apache.directory.api.ldap.extras.extended.ads_impl.endTransaction.controls.actions.StoreControlValue;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.BOOLEAN;
036import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.OCTET_STRING;
037import static org.apache.directory.api.asn1.ber.tlv.UniversalTag.SEQUENCE;
038
039/**
040 * A grammar to decode controls in a EndTransactionResponse extended operation
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044public class ControlsGrammar extends AbstractGrammar<ControlsContainer>
045{
046    /** logger */
047    private static final Logger LOG = LoggerFactory.getLogger( ControlsGrammar.class );
048
049    /** The instance of grammar. ControlsGrammar is a singleton */
050    private static Grammar<ControlsContainer> instance = new ControlsGrammar();
051
052
053    /**
054     * Creates a new ControlsGrammar object.
055     */
056    @SuppressWarnings("unchecked")
057    public ControlsGrammar()
058    {
059        setName( ControlsGrammar.class.getName() );
060
061        // Create the transitions table
062        super.transitions = new GrammarTransition[ControlsStates.LAST_STATE.ordinal()][256];
063
064        /**
065         * Transition from init state to Control Sequence
066         * 
067         *  Control ::= SEQUENCE {
068         *     ...
069         *     
070         * Creates the current control instance
071         */
072        super.transitions[ControlsStates.START_STATE.ordinal()][SEQUENCE.getValue()] =
073            new GrammarTransition<ControlsContainer>(
074                ControlsStates.START_STATE,
075                ControlsStates.CONTROL_SEQUENCE_STATE,
076                SEQUENCE, 
077                new GrammarAction<ControlsContainer>( "Init Control" )
078                {
079                    public void action( ControlsContainer container ) throws DecoderException
080                    {
081                        TLV tlv = container.getCurrentTLV();
082                        int expectedLength = tlv.getLength();
083
084                        // The Length should be null
085                        if ( expectedLength == 0 )
086                        {
087                            String msg = I18n.err( I18n.ERR_08213_NULL_CONTROL_LENGTH );
088                            LOG.error( msg );
089
090                            // This will generate a PROTOCOL_ERROR
091                            throw new DecoderException( msg );
092                        }
093                    }
094                } );
095
096        /**
097         * Transition from controlSequence state to control type
098         * 
099         *  Control ::= SEQUENCE {
100         *     controlType             LDAPOID,
101         *     ...
102         *     
103         * Creates the current control instance
104         */
105        super.transitions[ControlsStates.CONTROL_SEQUENCE_STATE.ordinal()][OCTET_STRING.getValue()] =
106            new GrammarTransition<ControlsContainer>(
107                ControlsStates.CONTROL_SEQUENCE_STATE,
108                ControlsStates.CONTROL_TYPE_STATE,
109                OCTET_STRING, 
110                new AddControl() );
111
112        /**
113         * Transition from control type to control criticality
114         * 
115         *  Control ::= SEQUENCE {
116         *     controlType             LDAPOID,
117         *     criticality             BOOLEAN DEFAULT FALSE,
118         *     ...
119         *     
120         * Store the criticality
121         */
122        super.transitions[ControlsStates.CONTROL_TYPE_STATE.ordinal()][BOOLEAN.getValue()] =
123            new GrammarTransition<ControlsContainer>(
124                ControlsStates.CONTROL_TYPE_STATE,
125                ControlsStates.CONTROL_CRITICALITY_STATE,
126                BOOLEAN, 
127                new StoreControlCriticality() );
128
129        /**
130         * Transition from control type to control value
131         * 
132         *  Control ::= SEQUENCE {
133         *     controlType             LDAPOID,
134         *     ...
135         *     controlValue            OCTET STRING OPTIONAL }
136         *     
137         * Store the value
138         */
139        super.transitions[ControlsStates.CONTROL_TYPE_STATE.ordinal()][OCTET_STRING.getValue()] =
140            new GrammarTransition<ControlsContainer>(
141                ControlsStates.CONTROL_TYPE_STATE,
142                ControlsStates.CONTROL_VALUE_STATE,
143                OCTET_STRING, 
144                new StoreControlValue() );
145
146        /**
147         * Transition from control type to control sequence
148         * 
149         *  Control ::= SEQUENCE {
150         *     controlType             LDAPOID,
151         *     
152         * Nothing to do
153         */
154        super.transitions[ControlsStates.CONTROL_TYPE_STATE.ordinal()][SEQUENCE.getValue()] =
155            new GrammarTransition<ControlsContainer>(
156                ControlsStates.CONTROL_TYPE_STATE,
157                ControlsStates.CONTROL_SEQUENCE_STATE,
158                SEQUENCE );
159        
160        /**
161         * Transition from control criticality to control value
162         * 
163         *  Control ::= SEQUENCE {
164         *     ...
165         *     criticality             BOOLEAN DEFAULT FALSE,
166         *     controlValue            OCTET STRING OPTIONAL }
167         *     
168         * Store the value
169         */
170        super.transitions[ControlsStates.CONTROL_CRITICALITY_STATE.ordinal()][OCTET_STRING.getValue()] =
171            new GrammarTransition<ControlsContainer>(
172                ControlsStates.CONTROL_CRITICALITY_STATE,
173                ControlsStates.CONTROL_VALUE_STATE,
174                OCTET_STRING, 
175                new StoreControlValue() );
176        
177        /**
178         * Transition from control criticality to control sequence
179         * 
180         *  Control ::= SEQUENCE {
181         *     ...
182         *     criticality             BOOLEAN DEFAULT FALSE,
183         *     
184         * Nothing to do
185         */
186        super.transitions[ControlsStates.CONTROL_CRITICALITY_STATE.ordinal()][SEQUENCE.getValue()] =
187            new GrammarTransition<ControlsContainer>(
188                ControlsStates.CONTROL_CRITICALITY_STATE,
189                ControlsStates.CONTROL_SEQUENCE_STATE,
190                SEQUENCE );
191
192        /**
193         * Transition from control value to control sequence
194         * 
195         *  Control ::= SEQUENCE {
196         *     
197         * Nothing to do
198         */
199        super.transitions[ControlsStates.CONTROL_VALUE_STATE.ordinal()][SEQUENCE.getValue()] =
200            new GrammarTransition<ControlsContainer>(
201                ControlsStates.CONTROL_VALUE_STATE,
202                ControlsStates.CONTROL_SEQUENCE_STATE,
203                SEQUENCE ); 
204    }
205
206
207    /**
208     * This class is a singleton.
209     * 
210     * @return An instance on this grammar
211     */
212    public static Grammar<ControlsContainer> getInstance()
213    {
214        return instance;
215    }
216}