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.asn1.ber.grammar;
021
022
023 import org.apache.directory.shared.asn1.ber.IAsn1Container;
024 import org.apache.directory.shared.asn1.codec.DecoderException;
025 import org.apache.directory.shared.asn1.util.Asn1StringUtils;
026
027 import org.slf4j.Logger;
028 import org.slf4j.LoggerFactory;
029
030
031 /**
032 * The abstract IGrammar which is the Mother of all the grammars. It contains
033 * the transitions table.
034 *
035 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
036 * @version $Rev: 664290 $, $Date: 2008-06-07 08:28:06 +0200 (Sam, 07 jui 2008) $
037 */
038 public abstract class AbstractGrammar implements IGrammar
039 {
040 // ~ Static fields/initializers
041 // -----------------------------------------------------------------
042
043 /** The logger */
044 private static final Logger log = LoggerFactory.getLogger( AbstractGrammar.class );
045
046 /** Speedup for logs */
047 private static final boolean IS_DEBUG = log.isDebugEnabled();
048
049 // ~ Instance fields
050 // ----------------------------------------------------------------------------
051
052 /**
053 * Table of transitions. It's a two dimension array, the first dimension
054 * indice the states, the second dimension indices the Tag value, so it is
055 * 256 wide.
056 */
057 protected GrammarTransition[][] transitions;
058
059 /** The grammar name */
060 protected String name;
061
062 /** The grammar's states */
063 protected IStates statesEnum;
064
065 /** Default constructor */
066 public AbstractGrammar()
067 {
068 }
069
070
071 // ~ Methods
072 // ------------------------------------------------------------------------------------
073
074 /**
075 * Return the grammar's name
076 *
077 * @return The grammar name
078 */
079 public String getName()
080 {
081 return name;
082 }
083
084
085 /**
086 * Set the grammar's name
087 *
088 * @param name The new grammar name
089 */
090 public void setName( String name )
091 {
092 this.name = name;
093 }
094
095 /**
096 * Get the transition associated with the state and tag
097 *
098 * @param state The current state
099 * @param tag The current tag
100 * @return A valid transition if any, or null.
101 */
102 public GrammarTransition getTransition( int state, int tag )
103 {
104 return transitions[state][tag & 0x00FF];
105 }
106
107
108 /**
109 * The main function. This is where an action is executed. If the action is
110 * null, nothing is done.
111 *
112 * @param container The Asn1Container
113 * @throws DecoderException Thrown if anything went wrong
114 */
115 public void executeAction( IAsn1Container container ) throws DecoderException
116 {
117
118 int currentState = container.getTransition();
119 IGrammar currentGrammar = container.getGrammar();
120
121 // We have to deal with the special case of a GRAMMAR_END state
122 if ( currentState == IStates.END_STATE )
123 {
124 return;
125 }
126
127 byte tagByte = container.getCurrentTLV().getTag();
128
129 // We will loop until no more actions are to be executed
130 GrammarTransition transition = ( ( AbstractGrammar ) container.getGrammar() ).getTransition( currentState, tagByte );
131
132 if ( transition == null )
133 {
134
135 String errorMessage = "Bad transition from state "
136 + currentGrammar.getStatesEnum().getState( currentState )
137 + ", tag " + Asn1StringUtils.dumpByte( tagByte );
138
139 log.error( errorMessage );
140
141 // If we have no more grammar on the stack, then this is an
142 // error
143 throw new DecoderException( "Bad transition !" );
144 }
145
146 if ( IS_DEBUG )
147 {
148 log.debug( transition.toString( currentGrammar.getStatesEnum() ) );
149 }
150
151 if ( transition.hasAction() )
152 {
153 transition.getAction().action( container );
154 }
155
156 container.setTransition( transition.getCurrentState() );
157 }
158
159
160 /**
161 * Get the states of the current grammar
162 *
163 * @return Returns the statesEnum.
164 */
165 public IStates getStatesEnum()
166 {
167 return statesEnum;
168 }
169
170
171 /**
172 * Set the states for this grammar
173 *
174 * @param statesEnum The statesEnum to set.
175 */
176 public void setStatesEnum( IStates statesEnum )
177 {
178 this.statesEnum = statesEnum;
179 }
180 }