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.syncDoneValue;
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.i18n.I18n;
035    import org.apache.directory.shared.ldap.util.StringTools;
036    import org.slf4j.Logger;
037    import org.slf4j.LoggerFactory;
038    
039    
040    /**
041     * 
042     * Implementation of SyncDoneValueControl. All the actions are declared in
043     * this class. As it is a singleton, these declaration are only done once.
044     *
045     *  The decoded grammar is as follows :
046     *  
047     *  syncDoneValue ::= SEQUENCE 
048     *  {
049     *       cookie          syncCookie OPTIONAL,
050     *       refreshDeletes  BOOLEAN DEFAULT FALSE
051     *  }
052     *  
053     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
054     * @version $Rev$, $Date$
055     */
056    public class SyncDoneValueControlGrammar extends AbstractGrammar
057    {
058    
059        /** the logger */
060        private static final Logger LOG = LoggerFactory.getLogger( SyncDoneValueControlGrammar.class );
061    
062        /** speedup for logger */
063        private static final boolean IS_DEBUG = LOG.isDebugEnabled();
064    
065        /** SyncDoneValueControlGrammar singleton instance */
066        private static final SyncDoneValueControlGrammar INSTANCE = new SyncDoneValueControlGrammar();
067    
068    
069        /**
070         * 
071         * Creates a new instance of SyncDoneValueControlGrammar.
072         *
073         */
074        private SyncDoneValueControlGrammar()
075        {
076            name = SyncDoneValueControlGrammar.class.getName();
077            statesEnum = SyncDoneValueControlStatesEnum.getInstance();
078    
079            super.transitions = new GrammarTransition[SyncDoneValueControlStatesEnum.LAST_SYNC_DONE_VALUE_STATE][256];
080    
081            /** 
082             * Transition from initial state to SyncDoneValue sequence
083             * SyncDoneValue ::= SEQUENCE {
084             *     ...
085             *     
086             * Initialize the syncDoneValue object
087             */
088            super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
089                IStates.INIT_GRAMMAR_STATE, SyncDoneValueControlStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE, UniversalTag.SEQUENCE_TAG,
090                new GrammarAction( "Initiaization" )
091                {
092                    public void action( IAsn1Container container ) throws DecoderException
093                    {
094                        SyncDoneValueControlContainer syncDoneValueContainer = ( SyncDoneValueControlContainer ) container;
095    
096                        // As all the values are optional or defaulted, we can end here
097                        syncDoneValueContainer.grammarEndAllowed( true );
098                    }
099                }  );
100    
101            /**
102             * transition from start to cookie
103             * {
104             *    cookie          syncCookie OPTIONAL
105             *    ....
106             * }
107             */
108            super.transitions[SyncDoneValueControlStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
109                SyncDoneValueControlStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE, SyncDoneValueControlStatesEnum.COOKIE_STATE,
110                UniversalTag.OCTET_STRING_TAG, new GrammarAction( "Set SyncDoneValueControl cookie" )
111                {
112                    public void action( IAsn1Container container ) throws DecoderException
113                    {
114                        SyncDoneValueControlContainer syncDoneValueContainer = ( SyncDoneValueControlContainer ) container;
115                        Value value = syncDoneValueContainer.getCurrentTLV().getValue();
116    
117                        byte[] cookie = value.getData();
118    
119                        if ( IS_DEBUG )
120                        {
121                            LOG.debug( "cookie = {}", StringTools.dumpBytes( cookie ) );
122                        }
123    
124                        syncDoneValueContainer.getSyncDoneValueControl().setCookie( cookie );
125    
126                        syncDoneValueContainer.grammarEndAllowed( true );
127                    }
128                } );
129    
130            GrammarAction refreshDeletesTagAction = new GrammarAction( "set SyncDoneValueControl refreshDeletes flag" )
131            {
132                public void action( IAsn1Container container ) throws DecoderException
133                {
134                    SyncDoneValueControlContainer syncDoneValueContainer = ( SyncDoneValueControlContainer ) container;
135                    Value value = syncDoneValueContainer.getCurrentTLV().getValue();
136    
137                    try
138                    {
139                        boolean refreshDeletes = BooleanDecoder.parse( value );
140    
141                        if ( IS_DEBUG )
142                        {
143                            LOG.debug( "refreshDeletes = {}", refreshDeletes );
144                        }
145    
146                        syncDoneValueContainer.getSyncDoneValueControl().setRefreshDeletes( refreshDeletes );
147    
148                        // the END transition for grammar
149                        syncDoneValueContainer.grammarEndAllowed( true );
150                    }
151                    catch ( BooleanDecoderException be )
152                    {
153                        String msg = I18n.err( I18n.ERR_04024 );
154                        LOG.error( msg, be );
155                        throw new DecoderException( msg );
156                    }
157    
158                }
159            }; 
160            /**
161             * transition from cookie to refreshDeletes
162             * {
163             *    ....
164             *    refreshDeletes BOOLEAN DEFAULT FALSE
165             * }
166             */
167            super.transitions[SyncDoneValueControlStatesEnum.COOKIE_STATE][UniversalTag.BOOLEAN_TAG] = new GrammarTransition(
168                SyncDoneValueControlStatesEnum.COOKIE_STATE, SyncDoneValueControlStatesEnum.REFRESH_DELETES_STATE,
169                UniversalTag.BOOLEAN_TAG, refreshDeletesTagAction );
170            
171            /**
172             * transition from SEQUENCE to refreshDeletes
173             * {
174             *    ....
175             *    refreshDeletes BOOLEAN DEFAULT FALSE
176             * }
177             */
178            super.transitions[SyncDoneValueControlStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE][UniversalTag.BOOLEAN_TAG] = new GrammarTransition(
179                SyncDoneValueControlStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE, SyncDoneValueControlStatesEnum.REFRESH_DELETES_STATE,
180                UniversalTag.BOOLEAN_TAG, refreshDeletesTagAction );
181    
182        }
183    
184    
185        /**
186         * @return the singleton instance of the SyncDoneValueControlGrammar
187         */
188        public static IGrammar getInstance()
189        {
190            return INSTANCE;
191        }
192    }