View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.extras.controls.syncrepl_impl;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
25  import org.apache.directory.api.asn1.ber.grammar.Grammar;
26  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
27  import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
30  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
31  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.api.i18n.I18n;
33  import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SyncInfoValue;
34  import org.apache.directory.api.ldap.extras.controls.syncrepl.syncInfoValue.SynchronizationInfoEnum;
35  import org.apache.directory.api.util.Strings;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * This class implements the SyncInfoValueControl. All the actions are declared in
42   * this class. As it is a singleton, these declaration are only done once.
43   * 
44   * The decoded grammar is the following :
45   * 
46   * syncInfoValue ::= CHOICE {
47   *     newcookie      [0] syncCookie,
48   *     refreshDelete  [1] SEQUENCE {
49   *         cookie         syncCookie OPTIONAL,
50   *         refreshDone    BOOLEAN DEFAULT TRUE
51   *     },
52   *     refreshPresent [2] SEQUENCE {
53   *         cookie         syncCookie OPTIONAL,
54   *         refreshDone    BOOLEAN DEFAULT TRUE
55   *     },
56   *     syncIdSet      [3] SEQUENCE {
57   *         cookie         syncCookie OPTIONAL,
58   *         refreshDeletes BOOLEAN DEFAULT FALSE,
59   *         syncUUIDs      SET OF syncUUID
60   *     }
61   * }
62   * 
63   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
64   */
65  public final class SyncInfoValueGrammar extends AbstractGrammar<SyncInfoValueContainer>
66  {
67      /** The logger */
68      static final Logger LOG = LoggerFactory.getLogger( SyncInfoValueGrammar.class );
69  
70      /** Speedup for logs */
71      static final boolean IS_DEBUG = LOG.isDebugEnabled();
72  
73      /** The instance of grammar. SyncInfoValueControlGrammar is a singleton */
74      private static Grammar<SyncInfoValueContainer> instance = new SyncInfoValueGrammar();
75  
76  
77      /**
78       * Creates a new SyncInfoValueControlGrammar object.
79       */
80      @SuppressWarnings("unchecked")
81      private SyncInfoValueGrammar()
82      {
83          setName( SyncInfoValueGrammar.class.getName() );
84  
85          // Create the transitions table
86          super.transitions = new GrammarTransition[SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE
87              .ordinal()][256];
88  
89          /** 
90           * Transition from initial state to SyncInfoValue newCookie choice
91           * SyncInfoValue ::= CHOICE {
92           *     newCookie [0] syncCookie,
93           *     ...
94           *     
95           * Initialize the syncInfoValue object
96           */
97          super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.NEW_COOKIE_TAG.getValue()] =
98              new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
99                  SyncInfoValueStatesEnum.NEW_COOKIE_STATE,
100                 SyncInfoValueTags.NEW_COOKIE_TAG.getValue(),
101                 new GrammarAction<SyncInfoValueContainer>( "NewCookie choice for SyncInfoValueControl" )
102                 {
103                     public void action( SyncInfoValueContainer container )
104                     {
105                         SyncInfoValue control = container.getSyncInfoValueControl();
106                         control.setType( SynchronizationInfoEnum.NEW_COOKIE );
107 
108                         BerValue value = container.getCurrentTLV().getValue();
109 
110                         byte[] newCookie = value.getData();
111 
112                         if ( IS_DEBUG )
113                         {
114                             LOG.debug( "newcookie = " + Strings.dumpBytes( newCookie ) );
115                         }
116 
117                         control.setCookie( newCookie );
118 
119                         // We can have an END transition
120                         container.setGrammarEndAllowed( true );
121 
122                         container.setSyncInfoValueControl( control );
123                     }
124                 } );
125 
126         /** 
127          * Transition from initial state to SyncInfoValue refreshDelete choice
128          * SyncInfoValue ::= CHOICE {
129          *     ...
130          *     refreshDelete [1] SEQUENCE {
131          *     ...
132          *     
133          * Initialize the syncInfoValue object
134          */
135         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.REFRESH_DELETE_TAG
136             .getValue()] =
137             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
138                 SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
139                 SyncInfoValueTags.REFRESH_DELETE_TAG.getValue(),
140                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete choice for SyncInfoValueControl" )
141                 {
142                     public void action( SyncInfoValueContainer container )
143                     {
144                         SyncInfoValue control = container.getSyncInfoValueControl();
145                         control.setType( SynchronizationInfoEnum.REFRESH_DELETE );
146 
147                         container.setSyncInfoValueControl( control );
148 
149                         // We can have an END transition
150                         container.setGrammarEndAllowed( true );
151                     }
152                 } );
153 
154         /** 
155          * Transition from refreshDelete state to cookie
156          *     refreshDelete [1] SEQUENCE {
157          *         cookie syncCookie OPTIONAL,
158          *     ...
159          *     
160          * Load the cookie object
161          */
162         super.transitions[SyncInfoValueStatesEnum.REFRESH_DELETE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
163             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
164                 SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE,
165                 UniversalTag.OCTET_STRING.getValue(),
166                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete cookie" )
167                 {
168                     public void action( SyncInfoValueContainer container )
169                     {
170                         SyncInfoValue control = container.getSyncInfoValueControl();
171 
172                         BerValue value = container.getCurrentTLV().getValue();
173 
174                         byte[] cookie = value.getData();
175 
176                         if ( IS_DEBUG )
177                         {
178                             LOG.debug( "cookie = " + Strings.dumpBytes( cookie ) );
179                         }
180 
181                         container.getSyncInfoValueControl().setCookie( cookie );
182                         container.setSyncInfoValueControl( control );
183 
184                         // We can have an END transition
185                         container.setGrammarEndAllowed( true );
186                     }
187                 } );
188 
189         /** 
190          * Transition from refreshDelete cookie state to refreshDone
191          *     refreshDelete [1] SEQUENCE {
192          *         ....
193          *         refreshDone BOOLEAN DEFAULT TRUE
194          *     }
195          *     
196          * Load the refreshDone flag
197          */
198         super.transitions[SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN
199             .getValue()] =
200             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_DELETE_COOKIE_STATE,
201                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
202                 UniversalTag.BOOLEAN.getValue(),
203                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete refreshDone flag" )
204                 {
205                     public void action( SyncInfoValueContainer container ) throws DecoderException
206                     {
207                         SyncInfoValue control = container.getSyncInfoValueControl();
208 
209                         BerValue value = container.getCurrentTLV().getValue();
210 
211                         try
212                         {
213                             boolean refreshDone = BooleanDecoder.parse( value );
214 
215                             if ( IS_DEBUG )
216                             {
217                                 LOG.debug( "refreshDone = {}", refreshDone );
218                             }
219 
220                             control.setRefreshDone( refreshDone );
221 
222                             container.setSyncInfoValueControl( control );
223 
224                             // the END transition for grammar
225                             container.setGrammarEndAllowed( true );
226                         }
227                         catch ( BooleanDecoderException be )
228                         {
229                             String msg = I18n.err( I18n.ERR_04025 );
230                             LOG.error( msg, be );
231                             throw new DecoderException( msg );
232                         }
233 
234                         // We can have an END transition
235                         container.setGrammarEndAllowed( true );
236                     }
237                 } );
238 
239         /** 
240          * Transition from refreshDelete choice state to refreshDone
241          *     refreshDelete [1] SEQUENCE {
242          *         ....
243          *         refreshDone BOOLEAN DEFAULT TRUE
244          *     }
245          *     
246          * Load the refreshDone flag
247          */
248         super.transitions[SyncInfoValueStatesEnum.REFRESH_DELETE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
249             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_DELETE_STATE,
250                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
251                 UniversalTag.BOOLEAN.getValue(),
252                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete refreshDone flag" )
253                 {
254                     public void action( SyncInfoValueContainer container ) throws DecoderException
255                     {
256                         SyncInfoValue control = container.getSyncInfoValueControl();
257 
258                         BerValue value = container.getCurrentTLV().getValue();
259 
260                         try
261                         {
262                             boolean refreshDone = BooleanDecoder.parse( value );
263 
264                             if ( IS_DEBUG )
265                             {
266                                 LOG.debug( "refreshDone = {}", refreshDone );
267                             }
268 
269                             control.setRefreshDone( refreshDone );
270 
271                             container.setSyncInfoValueControl( control );
272 
273                             // the END transition for grammar
274                             container.setGrammarEndAllowed( true );
275                         }
276                         catch ( BooleanDecoderException be )
277                         {
278                             String msg = I18n.err( I18n.ERR_04025 );
279                             LOG.error( msg, be );
280                             throw new DecoderException( msg );
281                         }
282 
283                         // We can have an END transition
284                         container.setGrammarEndAllowed( true );
285                     }
286                 } );
287 
288         /** 
289          * Transition from initial state to SyncInfoValue refreshPresent choice
290          * SyncInfoValue ::= CHOICE {
291          *     ...
292          *     refreshPresent [2] SEQUENCE {
293          *     ...
294          *     
295          * Initialize the syncInfoValue object
296          */
297         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.REFRESH_PRESENT_TAG
298             .getValue()] =
299             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
300                 SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
301                 SyncInfoValueTags.REFRESH_PRESENT_TAG.getValue(),
302                 new GrammarAction<SyncInfoValueContainer>( "RefreshDelete choice for SyncInfoValueControl" )
303                 {
304                     public void action( SyncInfoValueContainer container )
305                     {
306                         SyncInfoValue control = container.getSyncInfoValueControl();
307                         control.setType( SynchronizationInfoEnum.REFRESH_PRESENT );
308 
309                         container.setSyncInfoValueControl( control );
310 
311                         // We can have an END transition
312                         container.setGrammarEndAllowed( true );
313                     }
314                 } );
315 
316         /** 
317          * Transition from refreshPresent state to cookie
318          *     refreshPresent [2] SEQUENCE {
319          *         cookie syncCookie OPTIONAL,
320          *     ...
321          *     
322          * Load the cookie object
323          */
324         super.transitions[SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
325             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
326                 SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE,
327                 UniversalTag.OCTET_STRING.getValue(),
328                 new GrammarAction<SyncInfoValueContainer>( "RefreshPresent cookie" )
329                 {
330                     public void action( SyncInfoValueContainer container )
331                     {
332                         SyncInfoValue control = container.getSyncInfoValueControl();
333 
334                         BerValue value = container.getCurrentTLV().getValue();
335 
336                         byte[] cookie = value.getData();
337 
338                         if ( IS_DEBUG )
339                         {
340                             LOG.debug( "cookie = " + Strings.dumpBytes( cookie ) );
341                         }
342 
343                         container.getSyncInfoValueControl().setCookie( cookie );
344                         container.setSyncInfoValueControl( control );
345 
346                         // We can have an END transition
347                         container.setGrammarEndAllowed( true );
348                     }
349                 } );
350 
351         /** 
352          * Transition from refreshPresent cookie state to refreshDone
353          *     refreshPresent [2] SEQUENCE {
354          *         ....
355          *         refreshDone BOOLEAN DEFAULT TRUE
356          *     }
357          *     
358          * Load the refreshDone flag
359          */
360         super.transitions[SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN
361             .getValue()] =
362             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_PRESENT_COOKIE_STATE,
363                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
364                 UniversalTag.BOOLEAN.getValue(),
365                 new GrammarAction<SyncInfoValueContainer>( "RefreshPresent refreshDone flag" )
366                 {
367                     public void action( SyncInfoValueContainer container ) throws DecoderException
368                     {
369                         SyncInfoValue control = container.getSyncInfoValueControl();
370 
371                         BerValue value = container.getCurrentTLV().getValue();
372 
373                         try
374                         {
375                             boolean refreshDone = BooleanDecoder.parse( value );
376 
377                             if ( IS_DEBUG )
378                             {
379                                 LOG.debug( "refreshDone = {}", refreshDone );
380                             }
381 
382                             control.setRefreshDone( refreshDone );
383 
384                             container.setSyncInfoValueControl( control );
385 
386                             // the END transition for grammar
387                             container.setGrammarEndAllowed( true );
388                         }
389                         catch ( BooleanDecoderException be )
390                         {
391                             String msg = I18n.err( I18n.ERR_04025 );
392                             LOG.error( msg, be );
393                             throw new DecoderException( msg );
394                         }
395 
396                         // We can have an END transition
397                         container.setGrammarEndAllowed( true );
398                     }
399                 } );
400 
401         /** 
402          * Transition from refreshPresent choice state to refreshDone
403          *     refreshPresent [1] SEQUENCE {
404          *         ....
405          *         refreshDone BOOLEAN DEFAULT TRUE
406          *     }
407          *     
408          * Load the refreshDone flag
409          */
410         super.transitions[SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
411             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.REFRESH_PRESENT_STATE,
412                 SyncInfoValueStatesEnum.LAST_SYNC_INFO_VALUE_STATE,
413                 UniversalTag.BOOLEAN.getValue(),
414                 new GrammarAction<SyncInfoValueContainer>( "RefreshPresent refreshDone flag" )
415                 {
416                     public void action( SyncInfoValueContainer container ) throws DecoderException
417                     {
418                         SyncInfoValue control = container.getSyncInfoValueControl();
419 
420                         BerValue value = container.getCurrentTLV().getValue();
421 
422                         try
423                         {
424                             boolean refreshDone = BooleanDecoder.parse( value );
425 
426                             if ( IS_DEBUG )
427                             {
428                                 LOG.debug( "refreshDone = {}", refreshDone );
429                             }
430 
431                             control.setRefreshDone( refreshDone );
432 
433                             container.setSyncInfoValueControl( control );
434 
435                             // the END transition for grammar
436                             container.setGrammarEndAllowed( true );
437                         }
438                         catch ( BooleanDecoderException be )
439                         {
440                             String msg = I18n.err( I18n.ERR_04025 );
441                             LOG.error( msg, be );
442                             throw new DecoderException( msg );
443                         }
444 
445                         // We can have an END transition
446                         container.setGrammarEndAllowed( true );
447                     }
448                 } );
449 
450         /** 
451          * Transition from initial state to SyncInfoValue syncIdSet choice
452          * SyncInfoValue ::= CHOICE {
453          *     ...
454          *     syncIdSet [3] SEQUENCE {
455          *     ...
456          *     
457          * Initialize the syncInfoValue object
458          */
459         super.transitions[SyncInfoValueStatesEnum.START_STATE.ordinal()][SyncInfoValueTags.SYNC_ID_SET_TAG.getValue()] =
460             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.START_STATE,
461                 SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
462                 SyncInfoValueTags.SYNC_ID_SET_TAG.getValue(),
463                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet choice for SyncInfoValueControl" )
464                 {
465                     public void action( SyncInfoValueContainer container )
466                     {
467                         SyncInfoValue control = container.getSyncInfoValueControl();
468                         control.setType( SynchronizationInfoEnum.SYNC_ID_SET );
469 
470                         container.setSyncInfoValueControl( control );
471                     }
472                 } );
473 
474         /** 
475          * Transition from syncIdSet state to cookie
476          *     syncIdSet [3] SEQUENCE {
477          *         cookie syncCookie OPTIONAL,
478          *     ...
479          *     
480          * Load the cookie object
481          */
482         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
483             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
484                 SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
485                 UniversalTag.OCTET_STRING.getValue(),
486                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet cookie" )
487                 {
488                     public void action( SyncInfoValueContainer container )
489                     {
490                         SyncInfoValue control = container.getSyncInfoValueControl();
491 
492                         BerValue value = container.getCurrentTLV().getValue();
493 
494                         byte[] cookie = value.getData();
495 
496                         if ( IS_DEBUG )
497                         {
498                             LOG.debug( "cookie = " + Strings.dumpBytes( cookie ) );
499                         }
500 
501                         container.getSyncInfoValueControl().setCookie( cookie );
502                         container.setSyncInfoValueControl( control );
503                     }
504                 } );
505 
506         /** 
507          * Transition from syncIdSet state to refreshDeletes
508          *     syncIdSet [3] SEQUENCE {
509          *         ...
510          *         refreshDeletes BOOLEAN DEFAULT FALSE,
511          *     ...
512          *     
513          * Load the refreshDeletes flag
514          */
515         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
516             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
517                 SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
518                 UniversalTag.BOOLEAN.getValue(),
519                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet refreshDeletes" )
520                 {
521                     public void action( SyncInfoValueContainer container ) throws DecoderException
522                     {
523                         SyncInfoValue control = container.getSyncInfoValueControl();
524 
525                         BerValue value = container.getCurrentTLV().getValue();
526 
527                         try
528                         {
529                             boolean refreshDeletes = BooleanDecoder.parse( value );
530 
531                             if ( IS_DEBUG )
532                             {
533                                 LOG.debug( "refreshDeletes = {}", refreshDeletes );
534                             }
535 
536                             control.setRefreshDeletes( refreshDeletes );
537 
538                             container.setSyncInfoValueControl( control );
539                         }
540                         catch ( BooleanDecoderException be )
541                         {
542                             String msg = I18n.err( I18n.ERR_04026 );
543                             LOG.error( msg, be );
544                             throw new DecoderException( msg );
545                         }
546                     }
547                 } );
548 
549         /** 
550          * Transition from syncIdSet cookie state to refreshDeletes
551          *     syncIdSet [3] SEQUENCE {
552          *         ...
553          *         refreshDeletes BOOLEAN DEFAULT FALSE,
554          *     ...
555          *     
556          * Load the refreshDeletes flag
557          */
558         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
559             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
560                 SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
561                 UniversalTag.BOOLEAN.getValue(),
562                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet refreshDeletes" )
563                 {
564                     public void action( SyncInfoValueContainer container ) throws DecoderException
565                     {
566                         SyncInfoValue control = container.getSyncInfoValueControl();
567 
568                         BerValue value = container.getCurrentTLV().getValue();
569 
570                         try
571                         {
572                             boolean refreshDeletes = BooleanDecoder.parse( value );
573 
574                             if ( IS_DEBUG )
575                             {
576                                 LOG.debug( "refreshDeletes = {}", refreshDeletes );
577                             }
578 
579                             control.setRefreshDeletes( refreshDeletes );
580 
581                             container.setSyncInfoValueControl( control );
582                         }
583                         catch ( BooleanDecoderException be )
584                         {
585                             String msg = I18n.err( I18n.ERR_04024 );
586                             LOG.error( msg, be );
587                             throw new DecoderException( msg );
588                         }
589                     }
590                 } );
591 
592         /** 
593          * Transition from syncIdSet state to syncUUIDs
594          *     syncIdSet [3] SEQUENCE {
595          *         ...
596          *         syncUUIDs      *SET OF* syncUUID
597          *     }
598          *     
599          * Initialize the UUID set : no action associated, except allowing a grammar end
600          */
601         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_STATE.ordinal()][UniversalTag.SET.getValue()] =
602             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_STATE,
603                 SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
604                 UniversalTag.SET.getValue(),
605                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet syncUUIDs" )
606                 {
607                     public void action( SyncInfoValueContainer container ) throws DecoderException
608                     {
609                         // We can have an END transition
610                         container.setGrammarEndAllowed( true );
611                     }
612                 } );
613 
614         /** 
615          * Transition from syncIdSet cookie state to syncUUIDs
616          *     syncIdSet [3] SEQUENCE {
617          *         ...
618          *         syncUUIDs      *SET OF* syncUUID
619          *     }
620          *     
621          * Initialize the UUID set : no action associated
622          */
623         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE.ordinal()][UniversalTag.SET.getValue()] =
624             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_COOKIE_STATE,
625                 SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
626                 UniversalTag.SET.getValue(),
627                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet syncUUIDs" )
628                 {
629                     public void action( SyncInfoValueContainer container ) throws DecoderException
630                     {
631                         // We can have an END transition
632                         container.setGrammarEndAllowed( true );
633                     }
634                 } );
635 
636         /** 
637          * Transition from syncIdSet refreshDeletes state to syncUUIDs
638          *     syncIdSet [3] SEQUENCE {
639          *         ...
640          *         syncUUIDs      *SET OF* syncUUID
641          *     }
642          *     
643          * Initialize the UUID set : no action associated
644          */
645         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE.ordinal()][UniversalTag.SET
646             .getValue()] =
647             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_REFRESH_DELETES_STATE,
648                 SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
649                 UniversalTag.SET.getValue(),
650                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet syncUUIDs" )
651                 {
652                     public void action( SyncInfoValueContainer container ) throws DecoderException
653                     {
654                         // We can have an END transition
655                         container.setGrammarEndAllowed( true );
656                     }
657                 } );
658 
659         /** 
660          * Transition from syncIdSet syncUUIDs to syncUUID
661          *     syncIdSet [3] SEQUENCE {
662          *         ...
663          *         syncUUIDs      SET OF *syncUUID*
664          *     }
665          *     
666          * Add the first UUID in the UUIDs list
667          */
668         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE.ordinal()][UniversalTag.OCTET_STRING
669             .getValue()] =
670             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_SET_OF_UUIDS_STATE,
671                 SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
672                 UniversalTag.OCTET_STRING.getValue(),
673                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet first UUID" )
674                 {
675                     public void action( SyncInfoValueContainer container ) throws DecoderException
676                     {
677                         SyncInfoValue control = container.getSyncInfoValueControl();
678 
679                         BerValue value = container.getCurrentTLV().getValue();
680 
681                         byte[] uuid = value.getData();
682 
683                         // UUID must be exactly 16 bytes long
684                         if ( ( uuid == null ) || ( uuid.length != 16 ) )
685                         {
686                             String msg = I18n.err( I18n.ERR_04027 );
687                             LOG.error( msg );
688                             throw new DecoderException( msg );
689                         }
690 
691                         if ( IS_DEBUG )
692                         {
693                             LOG.debug( "UUID = " + Strings.dumpBytes( uuid ) );
694                         }
695 
696                         // Store the UUID in the UUIDs list
697                         control.addSyncUUID( uuid );
698 
699                         // We can have an END transition
700                         container.setGrammarEndAllowed( true );
701                     }
702                 } );
703 
704         /** 
705          * Transition from syncIdSet syncUUID to syncUUID
706          *     syncIdSet [3] SEQUENCE {
707          *         ...
708          *         syncUUIDs      SET OF *syncUUID*
709          *     }
710          *     
711          * Add a new UUID in the UUIDs list
712          */
713         super.transitions[SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE.ordinal()][UniversalTag.OCTET_STRING
714             .getValue()] =
715             new GrammarTransition<SyncInfoValueContainer>( SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
716                 SyncInfoValueStatesEnum.SYNC_ID_SET_UUID_STATE,
717                 UniversalTag.OCTET_STRING.getValue(),
718                 new GrammarAction<SyncInfoValueContainer>( "SyncIdSet UUID" )
719                 {
720                     public void action( SyncInfoValueContainer container ) throws DecoderException
721                     {
722                         SyncInfoValue control = container.getSyncInfoValueControl();
723 
724                         BerValue value = container.getCurrentTLV().getValue();
725 
726                         byte[] uuid = value.getData();
727 
728                         // UUID must be exactly 16 bytes long
729                         if ( ( uuid == null ) || ( uuid.length != 16 ) )
730                         {
731                             String msg = I18n.err( I18n.ERR_04027 );
732                             LOG.error( msg );
733                             throw new DecoderException( msg );
734                         }
735 
736                         if ( IS_DEBUG )
737                         {
738                             LOG.debug( "UUID = " + Strings.dumpBytes( uuid ) );
739                         }
740 
741                         // Store the UUID in the UUIDs list
742                         control.getSyncUUIDs().add( uuid );
743 
744                         // We can have an END transition
745                         container.setGrammarEndAllowed( true );
746                     }
747                 } );
748     }
749 
750 
751     /**
752      * This class is a singleton.
753      * 
754      * @return An instance on this grammar
755      */
756     public static Grammar<SyncInfoValueContainer> getInstance()
757     {
758         return instance;
759     }
760 }