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