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.UniversalTag;
029import org.apache.directory.shared.asn1.ber.tlv.Value;
030import org.apache.directory.shared.ldap.extras.controls.SyncModifyDnType;
031import org.apache.directory.shared.util.Strings;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035
036/**
037 * This class implements the SyncModifyDnControl. All the actions are declared in
038 * this class. As it is a singleton, these declaration are only done once.
039 * 
040 * The decoded grammar is the following :
041 * 
042 *      syncmodifyDnControl ::= SEQUENCE {
043 *           entry-name LDAPDN,
044 *           Operation
045 *      }
046 * 
047 *      Operation ::= CHOICE {
048 *           move-name       [0] LDAPDN,
049 *           rename          [1] Rename,
050 *           move-and-rename [2] MoveAndRename
051 *      }
052 *     
053 *      Rename SEQUENCE {
054 *          new-rdn Rdn,
055 *          delete-old-rdn BOOLEAN
056 *      }
057 * 
058 *      MoveAndRename SEQUENCE {
059 *          superior-name   LDAPDN
060 *          new-rdn Rdn,
061 *          delete-old-rdn BOOLEAN
062 *      }
063 * 
064 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
065 */
066public final class SyncModifyDnGrammar extends AbstractGrammar
067{
068    /** The logger */
069    static final Logger LOG = LoggerFactory.getLogger( SyncModifyDnGrammar.class );
070
071    /** Speedup for logs */
072    static final boolean IS_DEBUG = LOG.isDebugEnabled();
073
074    /** The instance of grammar. SyncStateValueControlGrammar is a singleton */
075    private static Grammar instance = new SyncModifyDnGrammar();
076
077
078    /**
079     * Creates a new SyncModifyDnControlGrammar object.
080     */
081    private SyncModifyDnGrammar()
082    {
083        setName( SyncModifyDnGrammar.class.getName() );
084
085        // Create the transitions table
086        super.transitions = new GrammarTransition[SyncModifyDnStatesEnum.LAST_SYNC_MODDN_VALUE_STATE.ordinal()][256];
087
088        /** 
089         * Transition from initial state to SyncModifyDnControl sequence
090         * SyncModifyDnControl ::= SEQUENCE OF {
091         *     ...
092         *     
093         * Initialize the SyncModifyDnControl object
094         */
095        super.transitions[SyncModifyDnStatesEnum.START_SYNC_MODDN.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition(
096            SyncModifyDnStatesEnum.START_SYNC_MODDN, SyncModifyDnStatesEnum.SYNC_MODDN_VALUE_SEQUENCE_STATE,
097            UniversalTag.SEQUENCE.getValue(), null );
098
099        /** 
100         * Transition from SyncModifyDnControl sequence to entryDn
101         * move-name ::= SEQUENCE OF {
102         *     Dn        entryDN
103         *     ...
104         *     
105         * Stores the entryDn value
106         */
107        super.transitions[SyncModifyDnStatesEnum.SYNC_MODDN_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition(
108            SyncModifyDnStatesEnum.SYNC_MODDN_VALUE_SEQUENCE_STATE,
109            SyncModifyDnStatesEnum.ENTRY_DN_STATE, UniversalTag.OCTET_STRING.getValue(), 
110            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl entryDn value" )
111            {
112                public void action( SyncModifyDnContainer container ) throws DecoderException
113                {
114                    Value value = container.getCurrentTLV().getValue();
115
116                    // Check that the value is into the allowed interval
117                    String entryDn = Strings.utf8ToString(value.getData());
118                    
119                    if ( IS_DEBUG )
120                    {
121                        LOG.debug( "ModDN entryDn = {}", entryDn );
122                    }
123                    
124                    container.getSyncModifyDnControl().setEntryDn( entryDn );
125                    
126                    // move on to the next transition
127                    container.setGrammarEndAllowed( false );
128                }
129            } );
130
131        /** 
132         * Transition to move choice
133         * Operation ::= CHOICE {
134         *     move-name       [0] LDAPDN
135         *  }
136         *     
137         * Stores the newSuperiorDn value
138         */
139
140        super.transitions[SyncModifyDnStatesEnum.ENTRY_DN_STATE.ordinal()][SyncModifyDnTags.MOVE_TAG.getValue()] = new GrammarTransition(
141            SyncModifyDnStatesEnum.ENTRY_DN_STATE, SyncModifyDnStatesEnum.MOVE_STATE,
142            SyncModifyDnTags.MOVE_TAG.getValue(), 
143            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl newSuperiorDn" )
144            {
145                public void action( SyncModifyDnContainer container ) throws DecoderException
146                {
147                    container.getSyncModifyDnControl().setModDnType( SyncModifyDnType.MOVE );
148
149                    // We need to read the move operation's superiorDN
150                    Value value = container.getCurrentTLV().getValue();
151
152                    // Check that the value is into the allowed interval
153                    String newSuperiorDn = Strings.utf8ToString(value.getData());
154                    
155                    if ( IS_DEBUG )
156                    {
157                        LOG.debug( "ModDN newSuperiorDn = {}", newSuperiorDn );
158                    }
159                    
160                    container.getSyncModifyDnControl().setNewSuperiorDn( newSuperiorDn );
161                    
162                    // move on to the next transition
163                    container.setGrammarEndAllowed( true );
164                }
165            } );
166
167        
168        /**
169         * read the newSuperiorDn
170         * move-name       [0] LDAPDN
171         */
172        super.transitions[SyncModifyDnStatesEnum.ENTRY_DN_STATE.ordinal()][SyncModifyDnTags.RENAME_TAG.getValue()] = new GrammarTransition(
173            SyncModifyDnStatesEnum.ENTRY_DN_STATE, SyncModifyDnStatesEnum.RENAME_STATE,
174            SyncModifyDnTags.RENAME_TAG.getValue(), 
175            new GrammarAction<SyncModifyDnContainer>( "enter SyncModifyDnControl rename choice" )
176            {
177                public void action( SyncModifyDnContainer container ) throws DecoderException
178                {
179                    container.getSyncModifyDnControl().setModDnType( SyncModifyDnType.RENAME );
180                    container.setGrammarEndAllowed( false );
181                }
182            } );
183
184        /** 
185         * Transition from rename's RENAME state to newRdn
186         * 
187         * Rename SEQUENCE {
188         *     new-rdn Rdn,
189         * }
190         *            
191         * Stores the newRdn value
192         */
193        super.transitions[SyncModifyDnStatesEnum.RENAME_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition(
194            SyncModifyDnStatesEnum.RENAME_STATE, SyncModifyDnStatesEnum.RENAME_NEW_RDN_STATE,
195            UniversalTag.OCTET_STRING.getValue(), 
196            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl newRdn value" )
197            {
198                public void action( SyncModifyDnContainer container ) throws DecoderException
199                {
200                    Value value = container.getCurrentTLV().getValue();
201
202                    String newRdn = Strings.utf8ToString(value.getData());
203
204                    if ( IS_DEBUG )
205                    {
206                        LOG.debug( "newRdn = {}", newRdn );
207                    }
208
209                    container.getSyncModifyDnControl().setNewRdn( newRdn );
210
211                    // terminal state
212                    container.setGrammarEndAllowed( false );
213                }
214            } );
215       
216        
217        /** 
218         * Transition from rename's RENAME newRdn to deleteOldRdn
219         * 
220         * Rename SEQUENCE {
221         *   ....
222         *   deleteOldRdn 
223         * }
224         *            
225         * Stores the deleteOldRdn value
226         */
227        super.transitions[SyncModifyDnStatesEnum.RENAME_NEW_RDN_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] = new GrammarTransition(
228            SyncModifyDnStatesEnum.RENAME_NEW_RDN_STATE, SyncModifyDnStatesEnum.RENAME_DEL_OLD_RDN_STATE,
229            UniversalTag.BOOLEAN.getValue(), 
230            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl deleteOldRdn value" )
231            {
232                public void action( SyncModifyDnContainer container ) throws DecoderException
233                {
234                    Value value = container.getCurrentTLV().getValue();
235
236                    byte deleteOldRdn = value.getData()[0];
237
238                    if ( IS_DEBUG )
239                    {
240                        LOG.debug( "deleteOldRdn = {}", deleteOldRdn );
241                    }
242
243                    if( deleteOldRdn != 0 )
244                    {
245                        container.getSyncModifyDnControl().setDeleteOldRdn( true );
246                    }
247
248                    // terminal state
249                    container.setGrammarEndAllowed( true );
250                }
251            } );
252        
253
254        /** 
255         * Transition from entryDN to moveAndRename SEQUENCE
256         *  MoveAndRename SEQUENCE {
257         *     
258         * Stores the deleteOldRdn flag
259         */
260        super.transitions[SyncModifyDnStatesEnum.ENTRY_DN_STATE.ordinal()][SyncModifyDnTags.MOVEANDRENAME_TAG.getValue()] = new GrammarTransition(
261            SyncModifyDnStatesEnum.ENTRY_DN_STATE, SyncModifyDnStatesEnum.MOVE_AND_RENAME_STATE,
262            SyncModifyDnTags.MOVEANDRENAME_TAG.getValue(), 
263            new GrammarAction<SyncModifyDnContainer>( "enter SyncModifyDnControl moveAndRename choice" )
264            {
265                public void action( SyncModifyDnContainer container ) throws DecoderException
266                {
267                    container.getSyncModifyDnControl().setModDnType( SyncModifyDnType.MOVEANDRENAME );
268                    container.setGrammarEndAllowed( false );
269                }
270            } );
271
272        /** 
273         * Transition from MOVE_AND_RENAME_STATE to newSuperiorDn
274         * 
275         * MoveAndRename SEQUENCE {
276         *      superior-name   LDAPDN
277         *      ....
278         *            
279         * Stores the newRdn value
280         */
281        super.transitions[SyncModifyDnStatesEnum.MOVE_AND_RENAME_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition(
282            SyncModifyDnStatesEnum.MOVE_AND_RENAME_STATE, SyncModifyDnStatesEnum.MOVE_AND_RENAME_NEW_SUPERIOR_DN_STATE,
283            UniversalTag.OCTET_STRING.getValue(), 
284            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl moveAndRename state's newSuperirorDN value" )
285            {
286                public void action( SyncModifyDnContainer container ) throws DecoderException
287                {
288                    Value value = container.getCurrentTLV().getValue();
289
290                    String newSuperirorDn = Strings.utf8ToString(value.getData());
291
292                    if ( IS_DEBUG )
293                    {
294                        LOG.debug( "newSuperirorDn = {}", newSuperirorDn );
295                    }
296
297                    container.getSyncModifyDnControl().setNewSuperiorDn( newSuperirorDn );
298
299                    // terminal state
300                    container.setGrammarEndAllowed( false );
301                }
302            } );
303
304        /** 
305         * Transition from moveAndRename's newSuperiorDn to newRdn
306         * 
307         * MoveAndRename SEQUENCE {
308         *      superior-name   LDAPDN
309         *      ....
310         *            
311         * Stores the newRdn value
312         */
313        super.transitions[SyncModifyDnStatesEnum.MOVE_AND_RENAME_NEW_SUPERIOR_DN_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition(
314            SyncModifyDnStatesEnum.MOVE_AND_RENAME_NEW_SUPERIOR_DN_STATE, SyncModifyDnStatesEnum.MOVE_AND_RENAME_NEW_RDN_STATE,
315            UniversalTag.OCTET_STRING.getValue(), 
316            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl moveAndRename state's newRdn value" )
317            {
318                public void action( SyncModifyDnContainer container ) throws DecoderException
319                {
320                    Value value = container.getCurrentTLV().getValue();
321
322                    String newRdn = Strings.utf8ToString(value.getData());
323
324                    if ( IS_DEBUG )
325                    {
326                        LOG.debug( "newRdn = {}", newRdn );
327                    }
328
329                    container.getSyncModifyDnControl().setNewRdn( newRdn );
330
331                    // terminal state
332                    container.setGrammarEndAllowed( false );
333                }
334            } );
335        
336
337        /** 
338         * Transition from moveAndRename's newRdn to deleteOldRdn
339         *  MoveAndRename SEQUENCE {
340         *      ....
341         *      delete-old-rdn BOOLEAN
342         *     
343         * Stores the deleteOldRdn flag
344         */
345        super.transitions[SyncModifyDnStatesEnum.MOVE_AND_RENAME_NEW_RDN_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] = new GrammarTransition(
346            SyncModifyDnStatesEnum.MOVE_AND_RENAME_NEW_RDN_STATE, SyncModifyDnStatesEnum.MOVE_AND_RENAME_DEL_OLD_RDN_STATE,
347            UniversalTag.BOOLEAN.getValue(), 
348            new GrammarAction<SyncModifyDnContainer>( "Set SyncModifyDnControl deleteOldRdn value" )
349            {
350                public void action( SyncModifyDnContainer container ) throws DecoderException
351                {
352                    Value value = container.getCurrentTLV().getValue();
353
354                    byte deleteOldRdn = value.getData()[0];
355
356                    if ( IS_DEBUG )
357                    {
358                        LOG.debug( "deleteOldRdn = {}", deleteOldRdn );
359                    }
360
361                    if( deleteOldRdn != 0 )
362                    {
363                        container.getSyncModifyDnControl().setDeleteOldRdn( true );
364                    }
365
366                    // terminal state
367                    container.setGrammarEndAllowed( true );
368                }
369            } );
370
371    }
372
373
374    /**
375     * This class is a singleton.
376     * 
377     * @return An instance on this grammar
378     */
379    public static Grammar getInstance()
380    {
381        return instance;
382    }
383}