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   *    https://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.asn1.ber.grammar;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.Asn1Container;
25  import org.apache.directory.api.asn1.util.Asn1StringUtils;
26  import org.apache.directory.api.i18n.I18n;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  
31  /**
32   * The abstract Grammar which is the Mother of all the grammars. It contains
33   * the transitions table.
34   *
35   * @param <C> The container type
36   * 
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   */
39  public abstract class AbstractGrammar<C extends Asn1Container> implements Grammar<C>
40  {
41      /** The logger */
42      private static final Logger LOG = LoggerFactory.getLogger( AbstractGrammar.class );
43  
44      /**
45       * Table of transitions. It's a two dimension array, the first dimension
46       * indices the states, the second dimension indices the Tag value, so it is
47       * 256 wide.
48       */
49      protected GrammarTransition<C>[][] transitions;
50  
51      /** The grammar name */
52      private String name;
53  
54  
55      /** Default constructor */
56      public AbstractGrammar()
57      {
58      }
59  
60  
61      /**
62       * {@inheritDoc}
63       */
64      @Override
65      public String getName()
66      {
67          return name;
68      }
69  
70  
71      /**
72       * {@inheritDoc}
73       */
74      @Override
75      public void setName( String name )
76      {
77          this.name = name;
78      }
79  
80  
81      /**
82       * Get the transition associated with the state and tag
83       *
84       * @param state The current state
85       * @param tag The current tag
86       * @return A valid transition if any, or null.
87       */
88      public GrammarTransition<C> getTransition( Enum<?> state, int tag )
89      {
90          return transitions[state.ordinal()][tag & 0x00FF];
91      }
92  
93  
94      /**
95       * {@inheritDoc}
96       */
97      @Override
98      public void executeAction( C container ) throws DecoderException
99      {
100 
101         Enum<?> currentState = container.getTransition();
102         // We have to deal with the special case of a GRAMMAR_END state
103         if ( ( ( States ) currentState ).isEndState() )
104         {
105             return;
106         }
107 
108         byte tagByte = container.getCurrentTLV().getTag();
109 
110         // We will loop until no more actions are to be executed
111         @SuppressWarnings("unchecked")
112         GrammarTransition<C> transition = ( ( AbstractGrammar<C> ) container.getGrammar() ).getTransition(
113             currentState,
114             tagByte );
115 
116         if ( transition == null )
117         {
118             String errorMessage = I18n.err( I18n.ERR_01200_BAD_TRANSITION_FROM_STATE, currentState,
119                 Asn1StringUtils.dumpByte( tagByte ) );
120 
121             LOG.error( errorMessage );
122 
123             // If we have no more grammar on the stack, then this is an
124             // error
125             throw new DecoderException( errorMessage );
126         }
127 
128         if ( LOG.isDebugEnabled() )
129         {
130             LOG.debug( transition.toString() );
131         }
132 
133         if ( transition.hasAction() )
134         {
135             Action<C> action = transition.getAction();
136             action.action( container );
137         }
138 
139         container.setTransition( transition.getCurrentState() );
140     }
141 }