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.syncInfoValue;
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.message.control.replication.SynchronizationInfoEnum;
035    import org.apache.directory.shared.ldap.util.StringTools;
036    import org.slf4j.Logger;
037    import org.slf4j.LoggerFactory;
038    
039    
040    /**
041     * This class implements the SyncInfoValueControl. 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 the following :
045     * 
046     * syncInfoValue ::= CHOICE {
047     *     newcookie      [0] syncCookie,
048     *     refreshDelete  [1] SEQUENCE {
049     *         cookie         syncCookie OPTIONAL,
050     *         refreshDone    BOOLEAN DEFAULT TRUE
051     *     },
052     *     refreshPresent [2] SEQUENCE {
053     *         cookie         syncCookie OPTIONAL,
054     *         refreshDone    BOOLEAN DEFAULT TRUE
055     *     },
056     *     syncIdSet      [3] SEQUENCE {
057     *         cookie         syncCookie OPTIONAL,
058     *         refreshDeletes BOOLEAN DEFAULT FALSE,
059     *         syncUUIDs      SET OF syncUUID
060     *     }
061     * }
062     * 
063     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
064     * @version $Rev: 741888 $, $Date: 2009-02-07 13:57:03 +0100 (Sat, 07 Feb 2009) $, 
065     */
066    public class SyncInfoValueControlGrammar extends AbstractGrammar
067    {
068        /** The logger */
069        static final Logger LOG = LoggerFactory.getLogger( SyncInfoValueControlGrammar.class );
070    
071        /** Speedup for logs */
072        static final boolean IS_DEBUG = LOG.isDebugEnabled();
073    
074        /** The instance of grammar. SyncInfoValueControlGrammar is a singleton */
075        private static IGrammar instance = new SyncInfoValueControlGrammar();
076    
077    
078        /**
079         * Creates a new SyncInfoValueControlGrammar object.
080         */
081        private SyncInfoValueControlGrammar()
082        {
083            name = SyncInfoValueControlGrammar.class.getName();
084            statesEnum = SyncInfoValueControlStatesEnum.getInstance();
085    
086            // Create the transitions table
087            super.transitions = new GrammarTransition[SyncInfoValueControlStatesEnum.LAST_SYNC_INFO_VALUE_STATE][256];
088    
089            /** 
090             * Transition from initial state to SyncInfoValue newCookie choice
091             * SyncInfoValue ::= CHOICE {
092             *     newCookie [0] syncCookie,
093             *     ...
094             *     
095             * Initialize the syncInfoValue object
096             */
097            super.transitions[IStates.INIT_GRAMMAR_STATE][SyncInfoValueTags.NEW_COOKIE_TAG.getValue()] = 
098                new GrammarTransition( IStates.INIT_GRAMMAR_STATE, 
099                                        SyncInfoValueControlStatesEnum.NEW_COOKIE_STATE, 
100                                        SyncInfoValueTags.NEW_COOKIE_TAG.getValue(), 
101                    new GrammarAction( "NewCookie choice for SyncInfoValueControl" )
102                {
103                    public void action( IAsn1Container container )
104                    {
105                        SyncInfoValueControlContainer syncInfoValueContainer = 
106                            ( SyncInfoValueControlContainer ) container;
107                        SyncInfoValueControlCodec control = 
108                            new SyncInfoValueControlCodec( SynchronizationInfoEnum.NEW_COOKIE);
109                        
110                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
111    
112                        byte[] newCookie = value.getData();
113    
114                        if ( IS_DEBUG )
115                        {
116                            LOG.debug( "newcookie = " + StringTools.dumpBytes( newCookie ) );
117                        }
118    
119                        control.setCookie( newCookie );
120    
121                        // We can have an END transition
122                        syncInfoValueContainer.grammarEndAllowed( true );
123                        
124                        syncInfoValueContainer.setSyncInfoValueControl( control );
125                    }
126                } );
127    
128    
129            /** 
130             * Transition from initial state to SyncInfoValue refreshDelete choice
131             * SyncInfoValue ::= CHOICE {
132             *     ...
133             *     refreshDelete [1] SEQUENCE {
134             *     ...
135             *     
136             * Initialize the syncInfoValue object
137             */
138            super.transitions[IStates.INIT_GRAMMAR_STATE][SyncInfoValueTags.REFRESH_DELETE_TAG.getValue()] = 
139                new GrammarTransition( IStates.INIT_GRAMMAR_STATE, 
140                                        SyncInfoValueControlStatesEnum.REFRESH_DELETE_STATE, 
141                                        SyncInfoValueTags.REFRESH_DELETE_TAG.getValue(), 
142                    new GrammarAction( "RefreshDelete choice for SyncInfoValueControl" )
143                {
144                    public void action( IAsn1Container container )
145                    {
146                        SyncInfoValueControlContainer syncInfoValueContainer = 
147                            ( SyncInfoValueControlContainer ) container;
148                        SyncInfoValueControlCodec control = 
149                            new SyncInfoValueControlCodec( SynchronizationInfoEnum.REFRESH_DELETE);
150                        
151                        syncInfoValueContainer.setSyncInfoValueControl( control );
152    
153                        // We can have an END transition
154                        syncInfoValueContainer.grammarEndAllowed( true );
155                    }
156                } );
157    
158    
159            /** 
160             * Transition from refreshDelete state to cookie
161             *     refreshDelete [1] SEQUENCE {
162             *         cookie syncCookie OPTIONAL,
163             *     ...
164             *     
165             * Load the cookie object
166             */
167            super.transitions[SyncInfoValueControlStatesEnum.REFRESH_DELETE_STATE][UniversalTag.OCTET_STRING_TAG] = 
168                new GrammarTransition( SyncInfoValueControlStatesEnum.REFRESH_DELETE_STATE, 
169                                        SyncInfoValueControlStatesEnum.REFRESH_DELETE_COOKIE_STATE, 
170                                        UniversalTag.OCTET_STRING_TAG, 
171                    new GrammarAction( "RefreshDelete cookie" )
172                {
173                    public void action( IAsn1Container container )
174                    {
175                        SyncInfoValueControlContainer syncInfoValueContainer = 
176                            ( SyncInfoValueControlContainer ) container;
177                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
178                        
179                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
180    
181                        byte[] cookie = value.getData();
182    
183                        if ( IS_DEBUG )
184                        {
185                            LOG.debug( "cookie = " + StringTools.dumpBytes( cookie ) );
186                        }
187    
188                        syncInfoValueContainer.getSyncInfoValueControl().setCookie( cookie );
189                        syncInfoValueContainer.setSyncInfoValueControl( control );
190    
191                        // We can have an END transition
192                        syncInfoValueContainer.grammarEndAllowed( true );
193                    }
194                } );
195    
196    
197            /** 
198             * Transition from refreshDelete cookie state to refreshDone
199             *     refreshDelete [1] SEQUENCE {
200             *         ....
201             *         refreshDone BOOLEAN DEFAULT TRUE
202             *     }
203             *     
204             * Load the refreshDone flag
205             */
206            super.transitions[SyncInfoValueControlStatesEnum.REFRESH_DELETE_COOKIE_STATE][UniversalTag.BOOLEAN_TAG] = 
207                new GrammarTransition( SyncInfoValueControlStatesEnum.REFRESH_DELETE_COOKIE_STATE, 
208                                        SyncInfoValueControlStatesEnum.LAST_SYNC_INFO_VALUE_STATE, 
209                                        UniversalTag.BOOLEAN_TAG, 
210                    new GrammarAction( "RefreshDelete refreshDone flag" )
211                {
212                    public void action( IAsn1Container container ) throws DecoderException
213                    {
214                        SyncInfoValueControlContainer syncInfoValueContainer = 
215                            ( SyncInfoValueControlContainer ) container;
216                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
217                        
218                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
219    
220                        try
221                        {
222                            boolean refreshDone = BooleanDecoder.parse( value );
223    
224                            if ( IS_DEBUG )
225                            {
226                                LOG.debug( "refreshDone = {}", refreshDone );
227                            }
228    
229                            control.setRefreshDone( refreshDone );
230    
231                            syncInfoValueContainer.setSyncInfoValueControl( control );
232    
233                            // the END transition for grammar
234                            syncInfoValueContainer.grammarEndAllowed( true );
235                        }
236                        catch ( BooleanDecoderException be )
237                        {
238                            String msg = "failed to decode the refreshDone flag for SyncInfoValueControl";
239                            LOG.error( msg, be );
240                            throw new DecoderException( msg );
241                        }
242    
243    
244                        // We can have an END transition
245                        syncInfoValueContainer.grammarEndAllowed( true );
246                    }
247                } );
248    
249    
250            /** 
251             * Transition from refreshDelete choice state to refreshDone
252             *     refreshDelete [1] SEQUENCE {
253             *         ....
254             *         refreshDone BOOLEAN DEFAULT TRUE
255             *     }
256             *     
257             * Load the refreshDone flag
258             */
259            super.transitions[SyncInfoValueControlStatesEnum.REFRESH_DELETE_STATE][UniversalTag.BOOLEAN_TAG] = 
260                new GrammarTransition( SyncInfoValueControlStatesEnum.REFRESH_DELETE_STATE, 
261                                        SyncInfoValueControlStatesEnum.LAST_SYNC_INFO_VALUE_STATE, 
262                                        UniversalTag.BOOLEAN_TAG, 
263                    new GrammarAction( "RefreshDelete refreshDone flag" )
264                {
265                    public void action( IAsn1Container container ) throws DecoderException
266                    {
267                        SyncInfoValueControlContainer syncInfoValueContainer = 
268                            ( SyncInfoValueControlContainer ) container;
269                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
270                        
271                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
272    
273                        try
274                        {
275                            boolean refreshDone = BooleanDecoder.parse( value );
276    
277                            if ( IS_DEBUG )
278                            {
279                                LOG.debug( "refreshDone = {}", refreshDone );
280                            }
281    
282                            control.setRefreshDone( refreshDone );
283    
284                            syncInfoValueContainer.setSyncInfoValueControl( control );
285    
286                            // the END transition for grammar
287                            syncInfoValueContainer.grammarEndAllowed( true );
288                        }
289                        catch ( BooleanDecoderException be )
290                        {
291                            String msg = "failed to decode the refreshDone flag for SyncInfoValueControl";
292                            LOG.error( msg, be );
293                            throw new DecoderException( msg );
294                        }
295    
296    
297                        // We can have an END transition
298                        syncInfoValueContainer.grammarEndAllowed( true );
299                    }
300                } );
301            
302            
303            /** 
304             * Transition from initial state to SyncInfoValue refreshPresent choice
305             * SyncInfoValue ::= CHOICE {
306             *     ...
307             *     refreshPresent [2] SEQUENCE {
308             *     ...
309             *     
310             * Initialize the syncInfoValue object
311             */
312            super.transitions[IStates.INIT_GRAMMAR_STATE][SyncInfoValueTags.REFRESH_PRESENT_TAG.getValue()] = 
313                new GrammarTransition( IStates.INIT_GRAMMAR_STATE, 
314                                        SyncInfoValueControlStatesEnum.REFRESH_PRESENT_STATE, 
315                                        SyncInfoValueTags.REFRESH_PRESENT_TAG.getValue(), 
316                    new GrammarAction( "RefreshDelete choice for SyncInfoValueControl" )
317                {
318                    public void action( IAsn1Container container )
319                    {
320                        SyncInfoValueControlContainer syncInfoValueContainer = 
321                            ( SyncInfoValueControlContainer ) container;
322                        SyncInfoValueControlCodec control = 
323                            new SyncInfoValueControlCodec( SynchronizationInfoEnum.REFRESH_PRESENT);
324                        
325                        syncInfoValueContainer.setSyncInfoValueControl( control );
326    
327                        // We can have an END transition
328                        syncInfoValueContainer.grammarEndAllowed( true );
329                    }
330                } );
331    
332        
333            /** 
334             * Transition from refreshPresent state to cookie
335             *     refreshPresent [2] SEQUENCE {
336             *         cookie syncCookie OPTIONAL,
337             *     ...
338             *     
339             * Load the cookie object
340             */
341            super.transitions[SyncInfoValueControlStatesEnum.REFRESH_PRESENT_STATE][UniversalTag.OCTET_STRING_TAG] = 
342                new GrammarTransition( SyncInfoValueControlStatesEnum.REFRESH_PRESENT_STATE, 
343                                        SyncInfoValueControlStatesEnum.REFRESH_PRESENT_COOKIE_STATE, 
344                                        UniversalTag.OCTET_STRING_TAG, 
345                    new GrammarAction( "RefreshPresent cookie" )
346                {
347                    public void action( IAsn1Container container )
348                    {
349                        SyncInfoValueControlContainer syncInfoValueContainer = 
350                            ( SyncInfoValueControlContainer ) container;
351                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
352                        
353                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
354    
355                        byte[] cookie = value.getData();
356    
357                        if ( IS_DEBUG )
358                        {
359                            LOG.debug( "cookie = " + StringTools.dumpBytes( cookie ) );
360                        }
361    
362                        syncInfoValueContainer.getSyncInfoValueControl().setCookie( cookie );
363                        syncInfoValueContainer.setSyncInfoValueControl( control );
364    
365                        // We can have an END transition
366                        syncInfoValueContainer.grammarEndAllowed( true );
367                    }
368                } );
369            
370            
371    
372    
373            /** 
374             * Transition from refreshPresent cookie state to refreshDone
375             *     refreshPresent [2] SEQUENCE {
376             *         ....
377             *         refreshDone BOOLEAN DEFAULT TRUE
378             *     }
379             *     
380             * Load the refreshDone flag
381             */
382            super.transitions[SyncInfoValueControlStatesEnum.REFRESH_PRESENT_COOKIE_STATE][UniversalTag.BOOLEAN_TAG] = 
383                new GrammarTransition( SyncInfoValueControlStatesEnum.REFRESH_PRESENT_COOKIE_STATE, 
384                                        SyncInfoValueControlStatesEnum.LAST_SYNC_INFO_VALUE_STATE, 
385                                        UniversalTag.BOOLEAN_TAG, 
386                    new GrammarAction( "RefreshPresent refreshDone flag" )
387                {
388                    public void action( IAsn1Container container ) throws DecoderException
389                    {
390                        SyncInfoValueControlContainer syncInfoValueContainer = 
391                            ( SyncInfoValueControlContainer ) container;
392                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
393                        
394                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
395    
396                        try
397                        {
398                            boolean refreshDone = BooleanDecoder.parse( value );
399    
400                            if ( IS_DEBUG )
401                            {
402                                LOG.debug( "refreshDone = {}", refreshDone );
403                            }
404    
405                            control.setRefreshDone( refreshDone );
406    
407                            syncInfoValueContainer.setSyncInfoValueControl( control );
408    
409                            // the END transition for grammar
410                            syncInfoValueContainer.grammarEndAllowed( true );
411                        }
412                        catch ( BooleanDecoderException be )
413                        {
414                            String msg = "failed to decode the refreshDone flag for SyncInfoValueControl";
415                            LOG.error( msg, be );
416                            throw new DecoderException( msg );
417                        }
418    
419    
420                        // We can have an END transition
421                        syncInfoValueContainer.grammarEndAllowed( true );
422                    }
423                } );
424    
425    
426            /** 
427             * Transition from refreshPresent choice state to refreshDone
428             *     refreshPresent [1] SEQUENCE {
429             *         ....
430             *         refreshDone BOOLEAN DEFAULT TRUE
431             *     }
432             *     
433             * Load the refreshDone flag
434             */
435            super.transitions[SyncInfoValueControlStatesEnum.REFRESH_PRESENT_STATE][UniversalTag.BOOLEAN_TAG] = 
436                new GrammarTransition( SyncInfoValueControlStatesEnum.REFRESH_PRESENT_STATE, 
437                                        SyncInfoValueControlStatesEnum.LAST_SYNC_INFO_VALUE_STATE, 
438                                        UniversalTag.BOOLEAN_TAG, 
439                    new GrammarAction( "RefreshPresent refreshDone flag" )
440                {
441                    public void action( IAsn1Container container ) throws DecoderException
442                    {
443                        SyncInfoValueControlContainer syncInfoValueContainer = 
444                            ( SyncInfoValueControlContainer ) container;
445                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
446                        
447                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
448    
449                        try
450                        {
451                            boolean refreshDone = BooleanDecoder.parse( value );
452    
453                            if ( IS_DEBUG )
454                            {
455                                LOG.debug( "refreshDone = {}", refreshDone );
456                            }
457    
458                            control.setRefreshDone( refreshDone );
459    
460                            syncInfoValueContainer.setSyncInfoValueControl( control );
461    
462                            // the END transition for grammar
463                            syncInfoValueContainer.grammarEndAllowed( true );
464                        }
465                        catch ( BooleanDecoderException be )
466                        {
467                            String msg = "failed to decode the refreshDone flag for SyncInfoValueControl";
468                            LOG.error( msg, be );
469                            throw new DecoderException( msg );
470                        }
471    
472                        // We can have an END transition
473                        syncInfoValueContainer.grammarEndAllowed( true );
474                    }
475                } );
476            
477            
478            /** 
479             * Transition from initial state to SyncInfoValue syncIdSet choice
480             * SyncInfoValue ::= CHOICE {
481             *     ...
482             *     syncIdSet [3] SEQUENCE {
483             *     ...
484             *     
485             * Initialize the syncInfoValue object
486             */
487            super.transitions[IStates.INIT_GRAMMAR_STATE][SyncInfoValueTags.SYNC_ID_SET_TAG.getValue()] = 
488                new GrammarTransition( IStates.INIT_GRAMMAR_STATE, 
489                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE, 
490                                        SyncInfoValueTags.SYNC_ID_SET_TAG.getValue(), 
491                    new GrammarAction( "SyncIdSet choice for SyncInfoValueControl" )
492                {
493                    public void action( IAsn1Container container )
494                    {
495                        SyncInfoValueControlContainer syncInfoValueContainer = 
496                            ( SyncInfoValueControlContainer ) container;
497                        SyncInfoValueControlCodec control = 
498                            new SyncInfoValueControlCodec( SynchronizationInfoEnum.SYNC_ID_SET);
499                        
500                        syncInfoValueContainer.setSyncInfoValueControl( control );
501                    }
502                } );
503            
504            
505            /** 
506             * Transition from syncIdSet state to cookie
507             *     syncIdSet [3] SEQUENCE {
508             *         cookie syncCookie OPTIONAL,
509             *     ...
510             *     
511             * Load the cookie object
512             */
513            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE][UniversalTag.OCTET_STRING_TAG] = 
514                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE, 
515                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_COOKIE_STATE, 
516                                        UniversalTag.OCTET_STRING_TAG, 
517                    new GrammarAction( "SyncIdSet cookie" )
518                {
519                    public void action( IAsn1Container container )
520                    {
521                        SyncInfoValueControlContainer syncInfoValueContainer = 
522                            ( SyncInfoValueControlContainer ) container;
523                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
524                        
525                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
526    
527                        byte[] cookie = value.getData();
528    
529                        if ( IS_DEBUG )
530                        {
531                            LOG.debug( "cookie = " + StringTools.dumpBytes( cookie ) );
532                        }
533    
534                        syncInfoValueContainer.getSyncInfoValueControl().setCookie( cookie );
535                        syncInfoValueContainer.setSyncInfoValueControl( control );
536                    }
537                } );
538            
539            
540            /** 
541             * Transition from syncIdSet state to refreshDeletes
542             *     syncIdSet [3] SEQUENCE {
543             *         ...
544             *         refreshDeletes BOOLEAN DEFAULT FALSE,
545             *     ...
546             *     
547             * Load the refreshDeletes flag
548             */
549            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE][UniversalTag.BOOLEAN_TAG] = 
550                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE, 
551                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE, 
552                                        UniversalTag.BOOLEAN_TAG, 
553                    new GrammarAction( "SyncIdSet refreshDeletes" )
554                {
555                    public void action( IAsn1Container container ) throws DecoderException
556                    {
557                        SyncInfoValueControlContainer syncInfoValueContainer = 
558                            ( SyncInfoValueControlContainer ) container;
559                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
560                        
561                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
562    
563                        try
564                        {
565                            boolean refreshDeletes = BooleanDecoder.parse( value );
566    
567                            if ( IS_DEBUG )
568                            {
569                                LOG.debug( "refreshDeletes = {}", refreshDeletes );
570                            }
571    
572                            control.setRefreshDeletes( refreshDeletes );
573    
574                            syncInfoValueContainer.setSyncInfoValueControl( control );
575                        }
576                        catch ( BooleanDecoderException be )
577                        {
578                            String msg = "failed to decode the refreshDeletes flag for SyncInfoValueControl";
579                            LOG.error( msg, be );
580                            throw new DecoderException( msg );
581                        }
582                    }
583                } );
584            
585            
586            /** 
587             * Transition from syncIdSet cookie state to refreshDeletes
588             *     syncIdSet [3] SEQUENCE {
589             *         ...
590             *         refreshDeletes BOOLEAN DEFAULT FALSE,
591             *     ...
592             *     
593             * Load the refreshDeletes flag
594             */
595            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_COOKIE_STATE][UniversalTag.BOOLEAN_TAG] = 
596                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_COOKIE_STATE, 
597                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE, 
598                                        UniversalTag.BOOLEAN_TAG, 
599                    new GrammarAction( "SyncIdSet refreshDeletes" )
600                {
601                    public void action( IAsn1Container container ) throws DecoderException
602                    {
603                        SyncInfoValueControlContainer syncInfoValueContainer = 
604                            ( SyncInfoValueControlContainer ) container;
605                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
606                        
607                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
608    
609                        try
610                        {
611                            boolean refreshDeletes = BooleanDecoder.parse( value );
612    
613                            if ( IS_DEBUG )
614                            {
615                                LOG.debug( "refreshDeletes = {}", refreshDeletes );
616                            }
617    
618                            control.setRefreshDeletes( refreshDeletes );
619    
620                            syncInfoValueContainer.setSyncInfoValueControl( control );
621                        }
622                        catch ( BooleanDecoderException be )
623                        {
624                            String msg = "failed to decode the refreshDeletes flag for SyncInfoValueControl";
625                            LOG.error( msg, be );
626                            throw new DecoderException( msg );
627                        }
628                    }
629                } );
630            
631            
632            /** 
633             * Transition from syncIdSet state to syncUUIDs
634             *     syncIdSet [3] SEQUENCE {
635             *         ...
636             *         syncUUIDs      *SET OF* syncUUID
637             *     }
638             *     
639             * Initialize the UUID set : no action associated, except allowing a grammar end
640             */
641            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE][UniversalTag.SET_TAG] = 
642                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_STATE, 
643                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE, 
644                                        UniversalTag.SET_TAG, 
645                    new GrammarAction( "SyncIdSet syncUUIDs" )
646                {
647                    public void action( IAsn1Container container ) throws DecoderException
648                    {
649                        SyncInfoValueControlContainer syncInfoValueContainer = 
650                            ( SyncInfoValueControlContainer ) container;
651    
652                        // We can have an END transition
653                        syncInfoValueContainer.grammarEndAllowed( true );
654                    }
655                } );
656            
657            
658            /** 
659             * Transition from syncIdSet cookie state to syncUUIDs
660             *     syncIdSet [3] SEQUENCE {
661             *         ...
662             *         syncUUIDs      *SET OF* syncUUID
663             *     }
664             *     
665             * Initialize the UUID set : no action associated
666             */
667            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_COOKIE_STATE][UniversalTag.SET_TAG] = 
668                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_COOKIE_STATE, 
669                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE, 
670                                        UniversalTag.SET_TAG,
671                    new GrammarAction( "SyncIdSet syncUUIDs" )
672                {
673                    public void action( IAsn1Container container ) throws DecoderException
674                    {
675                        SyncInfoValueControlContainer syncInfoValueContainer = 
676                            ( SyncInfoValueControlContainer ) container;
677    
678                        // We can have an END transition
679                        syncInfoValueContainer.grammarEndAllowed( true );
680                    }
681                } );
682              
683            
684            /** 
685             * Transition from syncIdSet refreshDeletes state to syncUUIDs
686             *     syncIdSet [3] SEQUENCE {
687             *         ...
688             *         syncUUIDs      *SET OF* syncUUID
689             *     }
690             *     
691             * Initialize the UUID set : no action associated
692             */
693            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE][UniversalTag.SET_TAG] = 
694                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE, 
695                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE, 
696                                        UniversalTag.SET_TAG, 
697                    new GrammarAction( "SyncIdSet syncUUIDs" )
698                {
699                    public void action( IAsn1Container container ) throws DecoderException
700                    {
701                        SyncInfoValueControlContainer syncInfoValueContainer = 
702                            ( SyncInfoValueControlContainer ) container;
703    
704                        // We can have an END transition
705                        syncInfoValueContainer.grammarEndAllowed( true );
706                    }
707                } );
708            
709            
710            /** 
711             * Transition from syncIdSet syncUUIDs to syncUUID
712             *     syncIdSet [3] SEQUENCE {
713             *         ...
714             *         syncUUIDs      SET OF *syncUUID*
715             *     }
716             *     
717             * Add the first UUID in the UUIDs list
718             */
719            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE][UniversalTag.OCTET_STRING] = 
720                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE, 
721                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_UUID_STATE, 
722                                        UniversalTag.OCTET_STRING, 
723                    new GrammarAction( "SyncIdSet first UUID" )
724                {
725                    public void action( IAsn1Container container ) throws DecoderException
726                    {
727                        SyncInfoValueControlContainer syncInfoValueContainer = 
728                            ( SyncInfoValueControlContainer ) container;
729                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
730                        
731                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
732    
733                        byte[] uuid = value.getData();
734                        
735                        // UUID must be exactly 16 bytes long
736                        if ( ( uuid == null ) || ( uuid.length != 16 ) )
737                        {
738                            String msg = "Bad UUID value, its length is incorrect ( it should be 16 bytes long)";
739                            LOG.error( msg );
740                            throw new DecoderException( msg );
741                        }
742    
743                        if ( IS_DEBUG )
744                        {
745                            LOG.debug( "UUID = " + StringTools.dumpBytes( uuid ) );
746                        }
747    
748                        // Store the UUID in the UUIDs list
749                        control.getSyncUUIDs().add( uuid );
750                        
751                        // We can have an END transition
752                        syncInfoValueContainer.grammarEndAllowed( true );
753                    }
754                } );
755            
756            
757            /** 
758             * Transition from syncIdSet syncUUID to syncUUID
759             *     syncIdSet [3] SEQUENCE {
760             *         ...
761             *         syncUUIDs      SET OF *syncUUID*
762             *     }
763             *     
764             * Add a new UUID in the UUIDs list
765             */
766            super.transitions[SyncInfoValueControlStatesEnum.SYNC_ID_SET_UUID_STATE][UniversalTag.OCTET_STRING] = 
767                new GrammarTransition( SyncInfoValueControlStatesEnum.SYNC_ID_SET_UUID_STATE, 
768                                        SyncInfoValueControlStatesEnum.SYNC_ID_SET_UUID_STATE, 
769                                        UniversalTag.OCTET_STRING, 
770                    new GrammarAction( "SyncIdSet UUID" )
771                {
772                    public void action( IAsn1Container container ) throws DecoderException
773                    {
774                        SyncInfoValueControlContainer syncInfoValueContainer = 
775                            ( SyncInfoValueControlContainer ) container;
776                        SyncInfoValueControlCodec control = syncInfoValueContainer.getSyncInfoValueControl();
777                        
778                        Value value = syncInfoValueContainer.getCurrentTLV().getValue();
779    
780                        byte[] uuid = value.getData();
781                        
782                        // UUID must be exactly 16 bytes long
783                        if ( ( uuid == null ) || ( uuid.length != 16 ) )
784                        {
785                            String msg = "Bad UUID value, its length is incorrect ( it should be 16 bytes long)";
786                            LOG.error( msg );
787                            throw new DecoderException( msg );
788                        }
789    
790                        if ( IS_DEBUG )
791                        {
792                            LOG.debug( "UUID = " + StringTools.dumpBytes( uuid ) );
793                        }
794    
795                        // Store the UUID in the UUIDs list
796                        control.getSyncUUIDs().add( uuid );
797                        
798                        // We can have an END transition
799                        syncInfoValueContainer.grammarEndAllowed( true );
800                    }
801                } );
802        }
803    
804    
805        /**
806         * This class is a singleton.
807         * 
808         * @return An instance on this grammar
809         */
810        public static IGrammar getInstance()
811        {
812            return instance;
813        }
814    }