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 import org.apache.directory.shared.i18n.I18n;
027
028 import org.slf4j.Logger;
029 import org.slf4j.LoggerFactory;
030
031
032 /**
033 * The abstract IGrammar which is the Mother of all the grammars. It contains
034 * the transitions table.
035 *
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 * @version $Rev: 912399 $, $Date: 2010-02-21 22:52:31 +0200 (Sun, 21 Feb 2010) $
038 */
039 public abstract class AbstractGrammar implements IGrammar
040 {
041 // ~ Static fields/initializers
042 // -----------------------------------------------------------------
043
044 /** The logger */
045 private static final Logger log = LoggerFactory.getLogger( AbstractGrammar.class );
046
047 /** Speedup for logs */
048 private static final boolean IS_DEBUG = log.isDebugEnabled();
049
050 // ~ Instance fields
051 // ----------------------------------------------------------------------------
052
053 /**
054 * Table of transitions. It's a two dimension array, the first dimension
055 * indice the states, the second dimension indices the Tag value, so it is
056 * 256 wide.
057 */
058 protected GrammarTransition[][] transitions;
059
060 /** The grammar name */
061 protected String name;
062
063 /** The grammar's states */
064 protected IStates statesEnum;
065
066 /** Default constructor */
067 public AbstractGrammar()
068 {
069 }
070
071
072 // ~ Methods
073 // ------------------------------------------------------------------------------------
074
075 /**
076 * Return the grammar's name
077 *
078 * @return The grammar name
079 */
080 public String getName()
081 {
082 return name;
083 }
084
085
086 /**
087 * Set the grammar's name
088 *
089 * @param name The new grammar name
090 */
091 public void setName( String name )
092 {
093 this.name = name;
094 }
095
096 /**
097 * Get the transition associated with the state and tag
098 *
099 * @param state The current state
100 * @param tag The current tag
101 * @return A valid transition if any, or null.
102 */
103 public GrammarTransition getTransition( int state, int tag )
104 {
105 return transitions[state][tag & 0x00FF];
106 }
107
108
109 /**
110 * The main function. This is where an action is executed. If the action is
111 * null, nothing is done.
112 *
113 * @param container The Asn1Container
114 * @throws DecoderException Thrown if anything went wrong
115 */
116 public void executeAction( IAsn1Container container ) throws DecoderException
117 {
118
119 int currentState = container.getTransition();
120 IGrammar currentGrammar = container.getGrammar();
121
122 // We have to deal with the special case of a GRAMMAR_END state
123 if ( currentState == IStates.END_STATE )
124 {
125 return;
126 }
127
128 byte tagByte = container.getCurrentTLV().getTag();
129
130 // We will loop until no more actions are to be executed
131 GrammarTransition transition = ( ( AbstractGrammar ) container.getGrammar() ).getTransition( currentState, tagByte );
132
133 if ( transition == null )
134 {
135
136 String errorMessage = I18n.err( I18n.ERR_00001, currentGrammar.getStatesEnum().getState( currentState ),
137 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( I18n.err( I18n.ERR_00002 ) );
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 }