/*
* Reference ETL Parser for Java
* Copyright (c) 2000-2009 Constantine A Plotnikov
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.sf.etl.parsers.internal.term_parser.states;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import net.sf.etl.parsers.PhraseParser;
import net.sf.etl.parsers.TermContext;
import net.sf.etl.parsers.internal.term_parser.AbstractPeer;
import net.sf.etl.parsers.internal.term_parser.DefaultTermParser;
import net.sf.etl.parsers.internal.term_parser.PeerFactory;
/**
* This is a peer factory for state machine peers.
*
* @author const
*/
// NOTE POST 0.2: make this class serializable. So it will be possible to read
// it again
// and execute it. This would require some indirection interface
// NOTE POST 0.2: implement compilation to Java bytecode and test performance.
public class StateMachinePeerFactory implements PeerFactory {
/**
* This suffix is added to context name to get a name of activation for
* statement sequence associated with context.
*/
public final static String STATEMENT_SEQUENCE_ACTIVATION_SUFFIX = "-statements";
/**
* This suffix is added to context name to get a name of activation for
* specific operator level associated with context. Clients should also add
* specific level number to get a full name of activation factory.
*/
public final static String EXPRESSION_LEVEL_ACTIVATION_SUFFIX = "-level-";
/** Map from context name to operation level to expression activation */
private final Map<String, TreeMap<Integer, ActivationFactoryImpl>> contextToLevelToFactory = new HashMap<String, TreeMap<Integer, ActivationFactoryImpl>>();
/** Map from context name to operation level to statements activation */
private final Map<String, ActivationFactoryImpl> contextToStatementsFactory = new HashMap<String, ActivationFactoryImpl>();
/** Map from activation factory name to activation factory */
private final Map<String, ActivationFactoryImpl> nameToFactory = new HashMap<String, ActivationFactoryImpl>();
/** default term context */
TermContext defaultTermContext;
/** a set of system identifiers that were used to build this grammar */
private Set<String> grammarDependencies;
/**
* A constructor
*/
public StateMachinePeerFactory() {
super();
}
/**
* Get numbers associated with operator levels in the grammar
*
* @param contextName
* a name of context
* @return a sorted map of operator levels or null if there are no
* expressions associated with context.
*/
SortedMap<Integer, ActivationFactoryImpl> operatorLevels(String contextName) {
final SortedMap<Integer, ActivationFactoryImpl> levelsToFactory = contextToLevelToFactory
.get(contextName);
if (levelsToFactory == null) {
return null;
}
return Collections
.<Integer, ActivationFactoryImpl> unmodifiableSortedMap(levelsToFactory);
}
/**
* {@inheritDoc}
*/
public AbstractPeer createPeer(DefaultTermParser termParser,
PhraseParser phraseParser) {
return new StateMachinePeer(this, termParser, phraseParser);
}
/**
* {@inheritDoc}
*/
public String defaultContext() {
return defaultTermContext.context();
}
/**
* Set default term context
*
* @param context
* a default context
*/
public void setDefaultContext(TermContext context) {
defaultTermContext = context;
}
/**
* Register activation in the peer factory
*
* @param context
* a name of context
* @param impl
* an activation implementation
*/
public void registerSegmentSequenceActivation(TermContext context,
ActivationFactoryImpl impl) {
assert !contextToStatementsFactory.containsKey(context.context()) : "There should be only one statement activation for context "
+ context;
contextToStatementsFactory.put(context.context(), impl);
nameToFactory.put(impl.name(), impl);
}
/**
* Register activation in the peer factory
*
* @param context
* a name of context
* @param priority
* an operator level with which this activation is associated
* @param impl
* an activation implementation
*/
public void registerExpressionActivation(TermContext context, int priority,
ActivationFactoryImpl impl) {
TreeMap<Integer, ActivationFactoryImpl> map = contextToLevelToFactory
.get(context.context());
if (map == null) {
map = new TreeMap<Integer, ActivationFactoryImpl>();
contextToLevelToFactory.put(context.context(), map);
}
final Integer key = new Integer(priority);
assert !map.containsKey(key) : "The activation for level " + priority
+ " should be registered only once for context " + context;
map.put(key, impl);
nameToFactory.put(impl.name(), impl);
}
/**
* This method returns either factory itself if it belongs to this state
* machine or proxy activation factory.
*
* @param activationFactory
* a statement sequence
* @return an activation or activate proxy
*/
public ActivationFactory getActivationFactoryReference(
ActivationFactoryImpl activationFactory) {
// NOTE POST 0.2: support proxy references.
return activationFactory;
}
/**
* Get segment sequence activation factory by context name
*
* @param grammarContext
* a grammar context name
* @return activation factory or null
*/
public ActivationFactory getSegmentSequenceProduction(String grammarContext) {
return contextToStatementsFactory.get(grammarContext);
}
/**
* {@inheritDoc}
*/
public boolean supportsStartContext(String contextName) {
if (contextName == null) {
contextName = defaultContext();
}
return getSegmentSequenceProduction(contextName) != null;
}
/**
* {@inheritDoc}
*/
public Collection<String> usedGrammars() {
return grammarDependencies;
}
/**
* Set dependencies for this peer.
*
* @param deps
* a dependency set
*/
public void setDependencies(Set<String> deps) {
this.grammarDependencies = deps;
}
}