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 *    https://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    /** SyncDoneValueControlGrammar singleton instance */
060    private static final SyncDoneValueGrammar INSTANCE = new SyncDoneValueGrammar();
061
062
063    /**
064     * 
065     * Creates a new instance of SyncDoneValueControlGrammar.
066     *
067     */
068    @SuppressWarnings("unchecked")
069    private SyncDoneValueGrammar()
070    {
071        setName( SyncDoneValueGrammar.class.getName() );
072
073        super.transitions = new GrammarTransition[SyncDoneValueStatesEnum.LAST_SYNC_DONE_VALUE_STATE.ordinal()][256];
074
075        /** 
076         * Transition from initial state to SyncDoneValue sequence
077         * SyncDoneValue ::= SEQUENCE {
078         *     ...
079         *     
080         * Initialize the syncDoneValue object
081         */
082        super.transitions[SyncDoneValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition<SyncDoneValueContainer>(
083            SyncDoneValueStatesEnum.START_STATE, SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE,
084            UniversalTag.SEQUENCE.getValue(),
085            new GrammarAction<SyncDoneValueContainer>( "Initialization" )
086            {
087                public void action( SyncDoneValueContainer container )
088                {
089                    // As all the values are optional or defaulted, we can end here
090                    container.setGrammarEndAllowed( true );
091                }
092            } );
093
094        /**
095         * transition from start to cookie
096         * {
097         *    cookie          syncCookie OPTIONAL
098         *    ....
099         * }
100         */
101        super.transitions[SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING
102            .getValue()] =
103            new GrammarTransition<SyncDoneValueContainer>( SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE,
104                SyncDoneValueStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
105                new GrammarAction<SyncDoneValueContainer>( "Set SyncDoneValueControl cookie" )
106                {
107                    public void action( SyncDoneValueContainer container )
108                    {
109                        BerValue value = container.getCurrentTLV().getValue();
110
111                        byte[] cookie = value.getData();
112
113                        if ( LOG.isDebugEnabled() )
114                        {
115                            LOG.debug( I18n.msg( I18n.MSG_08000_COOKIE, Strings.dumpBytes( cookie ) ) );
116                        }
117
118                        container.getSyncDoneValue().setCookie( cookie );
119
120                        container.setGrammarEndAllowed( true );
121                    }
122                } );
123
124        GrammarAction<SyncDoneValueContainer> refreshDeletesTagAction =
125            new GrammarAction<SyncDoneValueContainer>( "set SyncDoneValueControl refreshDeletes flag" )
126            {
127                public void action( SyncDoneValueContainer container ) throws DecoderException
128                {
129                    BerValue value = container.getCurrentTLV().getValue();
130
131                    try
132                    {
133                        boolean refreshDeletes = BooleanDecoder.parse( value );
134
135                        if ( LOG.isDebugEnabled() )
136                        {
137                            LOG.debug( I18n.msg( I18n.MSG_08001_REFRESH_DELETES, refreshDeletes ) );
138                        }
139
140                        container.getSyncDoneValue().setRefreshDeletes( refreshDeletes );
141
142                        // the END transition for grammar
143                        container.setGrammarEndAllowed( true );
144                    }
145                    catch ( BooleanDecoderException be )
146                    {
147                        String msg = I18n.err( I18n.ERR_08001_CANNOT_DECODE_REFRESH_DELETES );
148                        LOG.error( msg, be );
149                        throw new DecoderException( msg, be );
150                    }
151
152                }
153            };
154        /**
155         * transition from cookie to refreshDeletes
156         * {
157         *    ....
158         *    refreshDeletes BOOLEAN DEFAULT FALSE
159         * }
160         */
161        super.transitions[SyncDoneValueStatesEnum.COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
162            new GrammarTransition<SyncDoneValueContainer>(
163                SyncDoneValueStatesEnum.COOKIE_STATE, SyncDoneValueStatesEnum.REFRESH_DELETES_STATE,
164                UniversalTag.BOOLEAN.getValue(), refreshDeletesTagAction );
165
166        /**
167         * transition from SEQUENCE to refreshDeletes
168         * {
169         *    ....
170         *    refreshDeletes BOOLEAN DEFAULT FALSE
171         * }
172         */
173        super.transitions[SyncDoneValueStatesEnum.SYNC_DONE_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.BOOLEAN
174            .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}