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     */
020    package org.apache.directory.shared.ldap.codec.controls.replication.syncStateValue;
021    
022    
023    import org.apache.directory.shared.asn1.ber.IAsn1Container;
024    import org.apache.directory.shared.asn1.ber.grammar.AbstractGrammar;
025    import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
026    import org.apache.directory.shared.asn1.ber.grammar.GrammarTransition;
027    import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
028    import org.apache.directory.shared.asn1.ber.grammar.IStates;
029    import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
030    import org.apache.directory.shared.asn1.ber.tlv.Value;
031    import org.apache.directory.shared.asn1.codec.DecoderException;
032    import org.apache.directory.shared.asn1.util.BooleanDecoder;
033    import org.apache.directory.shared.asn1.util.BooleanDecoderException;
034    import org.apache.directory.shared.asn1.util.IntegerDecoder;
035    import org.apache.directory.shared.asn1.util.IntegerDecoderException;
036    import org.apache.directory.shared.ldap.message.control.replication.SyncStateTypeEnum;
037    import org.apache.directory.shared.ldap.message.control.replication.SynchronizationModeEnum;
038    import org.apache.directory.shared.ldap.util.StringTools;
039    import org.slf4j.Logger;
040    import org.slf4j.LoggerFactory;
041    
042    
043    /**
044     * This class implements the SyncStateValueControl. All the actions are declared in
045     * this class. As it is a singleton, these declaration are only done once.
046     * 
047     * The decoded grammar is the following :
048     * 
049     *  syncStateValue ::= SEQUENCE {
050     *       state ENUMERATED {
051     *            present (0),
052     *            add (1),
053     *            modify (2),
054     *            delete (3)
055     *       },
056     *       entryUUID syncUUID,
057     *       cookie    syncCookie OPTIONAL
058     *  }
059     * 
060     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
061     * @version $Rev: 741888 $, $Date: 2009-02-07 13:57:03 +0100 (Sat, 07 Feb 2009) $, 
062     */
063    public class SyncStateValueControlGrammar extends AbstractGrammar
064    {
065        /** The logger */
066        static final Logger LOG = LoggerFactory.getLogger( SyncStateValueControlGrammar.class );
067    
068        /** Speedup for logs */
069        static final boolean IS_DEBUG = LOG.isDebugEnabled();
070    
071        /** The instance of grammar. SyncStateValueControlGrammar is a singleton */
072        private static IGrammar instance = new SyncStateValueControlGrammar();
073    
074    
075        /**
076         * Creates a new SyncStateValueControlGrammar object.
077         */
078        private SyncStateValueControlGrammar()
079        {
080            name = SyncStateValueControlGrammar.class.getName();
081            statesEnum = SyncStateValueControlStatesEnum.getInstance();
082    
083            // Create the transitions table
084            super.transitions = new GrammarTransition[SyncStateValueControlStatesEnum.LAST_SYNC_STATE_VALUE_STATE][256];
085    
086            /** 
087             * Transition from initial state to SyncStateValue sequence
088             * SyncRequestValue ::= SEQUENCE OF {
089             *     ...
090             *     
091             * Initialize the syncStateValue object
092             */
093            super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
094                IStates.INIT_GRAMMAR_STATE, SyncStateValueControlStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
095                UniversalTag.SEQUENCE_TAG, new GrammarAction( "Init SyncStateValueControl" )
096                {
097                    public void action( IAsn1Container container )
098                    {
099                        SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
100                        SyncStateValueControlCodec control = new SyncStateValueControlCodec();
101                        syncStateValueContainer.setSyncStateValueControl( control );
102                    }
103                } );
104    
105            /** 
106             * Transition from SyncStateValue sequence to state type enum
107             * SyncRequestValue ::= SEQUENCE OF {
108             *       state ENUMERATED {
109             *            present (0),
110             *            add (1),
111             *            modify (2),
112             *            delete (3)
113             *       },
114             *     ...
115             *     
116             * Stores the sync state type value
117             */
118            super.transitions[SyncStateValueControlStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
119                SyncStateValueControlStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
120                SyncStateValueControlStatesEnum.SYNC_TYPE_STATE, UniversalTag.ENUMERATED_TAG, new GrammarAction(
121                    "Set SyncStateValueControl state type" )
122                {
123                    public void action( IAsn1Container container ) throws DecoderException
124                    {
125                        SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
126                        Value value = syncStateValueContainer.getCurrentTLV().getValue();
127    
128                        try
129                        {
130                            // Check that the value is into the allowed interval
131                            int syncStateType = IntegerDecoder.parse( value, SyncStateTypeEnum.PRESENT.getValue(),
132                                SyncStateTypeEnum.DELETE.getValue() );
133    
134                            SyncStateTypeEnum syncStateTypeEnum = SyncStateTypeEnum.getSyncStateType( syncStateType );
135    
136                            if ( IS_DEBUG )
137                            {
138                                LOG.debug( "SyncStateType = {}", syncStateTypeEnum );
139                            }
140    
141                            syncStateValueContainer.getSyncStateValueControl().setSyncStateType( syncStateTypeEnum );
142    
143                            // move on to the entryUUID transistion
144                            syncStateValueContainer.grammarEndAllowed( false );
145                        }
146                        catch ( IntegerDecoderException e )
147                        {
148                            String msg = "failed to decode the mode for SyncStateValueControl";
149                            LOG.error( msg, e );
150                            throw new DecoderException( msg );
151                        }
152                    }
153                } );
154    
155            /** 
156             * Transition from sync state tpe to entryUUID
157             * SyncStateValue ::= SEQUENCE OF {
158             *     ...
159             *     entryUUID     syncUUID
160             *     ...
161             *     
162             * Stores the entryUUID
163             */
164            super.transitions[SyncStateValueControlStatesEnum.SYNC_TYPE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
165                SyncStateValueControlStatesEnum.SYNC_TYPE_STATE, SyncStateValueControlStatesEnum.SYNC_UUID_STATE,
166                UniversalTag.OCTET_STRING_TAG, new GrammarAction( "Set SyncStateValueControl entryUUID" )
167                {
168                    public void action( IAsn1Container container ) throws DecoderException
169                    {
170                        SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
171                        Value value = syncStateValueContainer.getCurrentTLV().getValue();
172    
173                        byte[] entryUUID = value.getData();
174    
175                        if ( IS_DEBUG )
176                        {
177                            LOG.debug( "entryUUID = {}", StringTools.dumpBytes( entryUUID ) );
178                        }
179    
180                        syncStateValueContainer.getSyncStateValueControl().setEntryUUID( entryUUID );
181    
182                        // We can have an END transition
183                        syncStateValueContainer.grammarEndAllowed( true );
184                    }
185                } );
186    
187            /** 
188             * Transition from entryUUID to cookie
189             * SyncRequestValue ::= SEQUENCE OF {
190             *     ...
191             *     cookie    syncCookie OPTIONAL
192             * }
193             *     
194             * Stores the reloadHint flag
195             */
196            super.transitions[SyncStateValueControlStatesEnum.SYNC_UUID_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
197                SyncStateValueControlStatesEnum.SYNC_UUID_STATE, SyncStateValueControlStatesEnum.COOKIE_STATE,
198                UniversalTag.OCTET_STRING_TAG, new GrammarAction( "Set SyncStateValueControl cookie value" )
199                {
200                    public void action( IAsn1Container container ) throws DecoderException
201                    {
202                        SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
203                        Value value = syncStateValueContainer.getCurrentTLV().getValue();
204    
205                        byte[] cookie = value.getData();
206    
207                        if ( IS_DEBUG )
208                        {
209                            LOG.debug( "cookie = {}", cookie );
210                        }
211    
212                        syncStateValueContainer.getSyncStateValueControl().setCookie( cookie );
213    
214                        // terminal state
215                        syncStateValueContainer.grammarEndAllowed( true );
216                    }
217                } );
218        }
219    
220    
221        /**
222         * This class is a singleton.
223         * 
224         * @return An instance on this grammar
225         */
226        public static IGrammar getInstance()
227        {
228            return instance;
229        }
230    }