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.ldap.util.StringTools;
035    import org.slf4j.Logger;
036    import org.slf4j.LoggerFactory;
037    
038    
039    /**
040     * 
041     * Implementation of SyncDoneValueControl. All the actions are declared in
042     * this class. As it is a singleton, these declaration are only done once.
043     *
044     *  The decoded grammar is as follows :
045     *  
046     *  syncDoneValue ::= SEQUENCE 
047     *  {
048     *       cookie          syncCookie OPTIONAL,
049     *       refreshDeletes  BOOLEAN DEFAULT FALSE
050     *  }
051     *  
052     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
053     * @version $Rev$, $Date$
054     */
055    public class SyncDoneValueControlGrammar extends AbstractGrammar
056    {
057    
058        /** the logger */
059        private static final Logger LOG = LoggerFactory.getLogger( SyncDoneValueControlGrammar.class );
060    
061        /** speedup for logger */
062        private static final boolean IS_DEBUG = LOG.isDebugEnabled();
063    
064        /** SyncDoneValueControlGrammar singleton instance */
065        private static final SyncDoneValueControlGrammar INSTANCE = new SyncDoneValueControlGrammar();
066    
067    
068        /**
069         * 
070         * Creates a new instance of SyncDoneValueControlGrammar.
071         *
072         */
073        private SyncDoneValueControlGrammar()
074        {
075            name = SyncDoneValueControlGrammar.class.getName();
076            statesEnum = SyncDoneValueControlStatesEnum.getInstance();
077    
078            super.transitions = new GrammarTransition[SyncDoneValueControlStatesEnum.LAST_SYNC_DONE_VALUE_STATE][256];
079    
080            /** 
081             * Transition from initial state to SyncDoneValue sequence
082             * SyncDoneValue ::= SEQUENCE {
083             *     ...
084             *     
085             * Initialize the syncDoneValue object
086             */
087            super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
088                IStates.INIT_GRAMMAR_STATE, SyncDoneValueControlStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE, UniversalTag.SEQUENCE_TAG,
089                new GrammarAction( "Init SyncDoneValueControl" )
090                {
091                    public void action( IAsn1Container container ) throws DecoderException
092                    {
093                        SyncDoneValueControlContainer syncDoneValueContainer = ( SyncDoneValueControlContainer ) container;
094                        SyncDoneValueControlCodec control = new SyncDoneValueControlCodec();
095                        syncDoneValueContainer.setSyncDoneValueControl( control );
096                        
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 = "failed to decode the refreshDeletes flag for SyncDoneValueControl";
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    }