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.controls.syncrepl_impl;
021
022
023import org.apache.directory.api.asn1.DecoderException;
024import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
025import org.apache.directory.api.asn1.ber.grammar.Grammar;
026import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
027import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
028import org.apache.directory.api.asn1.ber.tlv.BerValue;
029import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
030import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
031import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
032import org.apache.directory.api.i18n.I18n;
033import org.apache.directory.api.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,
087            UniversalTag.SEQUENCE.getValue(),
088            new GrammarAction<SyncDoneValueContainer>( "Initialization" )
089            {
090                public void action( SyncDoneValueContainer container ) throws DecoderException
091                {
092                    // As all the values are optional or defaulted, we can end here
093                    container.setGrammarEndAllowed( true );
094                }
095            } );
096
097        /**
098         * transition from start to cookie
099         * {
100         *    cookie          syncCookie OPTIONAL
101         *    ....
102         * }
103         */
104        super.transitions[SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING
105            .getValue()] =
106            new GrammarTransition<SyncDoneValueContainer>( SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE,
107                SyncDoneValueStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
108                new GrammarAction<SyncDoneValueContainer>( "Set SyncDoneValueControl cookie" )
109                {
110                    public void action( SyncDoneValueContainer container ) throws DecoderException
111                    {
112                        BerValue value = container.getCurrentTLV().getValue();
113
114                        byte[] cookie = value.getData();
115
116                        if ( IS_DEBUG )
117                        {
118                            LOG.debug( "cookie = {}", Strings.dumpBytes( cookie ) );
119                        }
120
121                        container.getSyncDoneValueControl().setCookie( cookie );
122
123                        container.setGrammarEndAllowed( true );
124                    }
125                } );
126
127        GrammarAction<SyncDoneValueContainer> refreshDeletesTagAction =
128            new GrammarAction<SyncDoneValueContainer>( "set SyncDoneValueControl refreshDeletes flag" )
129            {
130                public void action( SyncDoneValueContainer container ) throws DecoderException
131                {
132                    BerValue value = container.getCurrentTLV().getValue();
133
134                    try
135                    {
136                        boolean refreshDeletes = BooleanDecoder.parse( value );
137
138                        if ( IS_DEBUG )
139                        {
140                            LOG.debug( "refreshDeletes = {}", refreshDeletes );
141                        }
142
143                        container.getSyncDoneValueControl().setRefreshDeletes( refreshDeletes );
144
145                        // the END transition for grammar
146                        container.setGrammarEndAllowed( true );
147                    }
148                    catch ( BooleanDecoderException be )
149                    {
150                        String msg = I18n.err( I18n.ERR_04024 );
151                        LOG.error( msg, be );
152                        throw new DecoderException( msg, be );
153                    }
154
155                }
156            };
157        /**
158         * transition from cookie to refreshDeletes
159         * {
160         *    ....
161         *    refreshDeletes BOOLEAN DEFAULT FALSE
162         * }
163         */
164        super.transitions[SyncDoneValueStatesEnum.COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
165            new GrammarTransition<SyncDoneValueContainer>(
166                SyncDoneValueStatesEnum.COOKIE_STATE, SyncDoneValueStatesEnum.REFRESH_DELETES_STATE,
167                UniversalTag.BOOLEAN.getValue(), refreshDeletesTagAction );
168
169        /**
170         * transition from SEQUENCE to refreshDeletes
171         * {
172         *    ....
173         *    refreshDeletes BOOLEAN DEFAULT FALSE
174         * }
175         */
176        super.transitions[SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.BOOLEAN
177            .getValue()] =
178            new GrammarTransition<SyncDoneValueContainer>( SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE,
179                SyncDoneValueStatesEnum.REFRESH_DELETES_STATE, UniversalTag.BOOLEAN.getValue(), refreshDeletesTagAction );
180    }
181
182
183    /**
184     * @return the singleton instance of the SyncDoneValueControlGrammar
185     */
186    public static Grammar<SyncDoneValueContainer> getInstance()
187    {
188        return INSTANCE;
189    }
190}