blob: 9987d8b486fad3aac9ff41f34244e920f6ca1f0c [file] [log] [blame]
package org.eclipse.jst.jsf.core.tagmatcher;
import org.eclipse.jst.jsf.common.sets.AxiomaticSet;
import org.w3c.dom.Node;
/**
* An algorithm that can be applied at a particular DOM node. The result
* may be expressed as a boolean or a set of matching nodes. The following
* are equivalent:
*
* false and empty set
* true and non-empty set
*
* Concrete implementations must be idempotent on evaluate():
*
* 1) evaluate(node) must always return the same set if called repeatedly on
* the same node in the same DOM tree.
* 2) evaluate must be able to be called on any number of nodes in order and always
* produce the same result independent of what was called before and in what order.
*
* @author cbateman
*
*/
public abstract class TagMatchingAlgorithm
{
private boolean _isInvalid; // = false;
private boolean _isInitialized;
/**
* The expression being passed to the algorithm
*/
protected final String _expression;
/**
* Constructor.
*
* @param expression
*/
protected TagMatchingAlgorithm(String expression)
{
_expression = expression;
}
/**
* Called exactly once to initialize any pre-evaluation setup for
* the expression set for the algorithm. This is public to allow
* the client control when this initialization occurs in case it is expensive.
* evaluate() will call this method automatically if it has never been called
* @throws InvalidExpressionException if the underlying algorithm throws an
* exception during init
* @throws IllegalStateException if it has already been determined that the
* expression is invalid.
*/
public final void initialize()
{
if (_isInvalid)
{
throw new IllegalStateException("Expression: "+_expression+" has already been determined to be invalid");
}
if (!_isInitialized)
{
try
{
doInitialize();
}
catch (Exception e)
{
_isInvalid = true;
throw new InvalidExpressionException(e);
}
_isInitialized = true;
}
}
/**
* @param applyTo
* @return the set matching the configured expression applied to applyTo
* using the algorithm represented by this instance.
* @throws InvalidExpressionException of a problem occurs initializing the expression
* @throws EvaluationException if the internal algorithm throws an exception while
* evaluating.
* @throws IllegalStateException if evaluate is called again once InvalidExpressionException
* has already been thrown.
*/
public final AxiomaticSet evaluate(Node applyTo)
{
initialize();
return doEvaluate(applyTo);
}
/**
* Implementers must override to the evaluation of the target,expression pair
* @param target
* @return the algorithm evaluated with
*/
protected abstract AxiomaticSet doEvaluate(Node target);
/**
* Do any initialization that is required before the algorithm is used
* to evaluate an expression on any node. This will get called exactly once and
* is guaranteed to be called, at latest, immediately before doEvaluate
*
* Method may throw runtime exceptions. These will be repropagated as
* InvalidExpressionException's with the original exception wrapped.
* @throws Exception
*/
protected abstract void doInitialize() throws Exception;
}