/**
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.base.evaluators;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.drools.RuntimeDroolsException;
import org.drools.base.ValueType;
import org.drools.common.DroolsObjectInput;
import org.drools.spi.Evaluator;
/**
* A registry class for all available evaluators
*
* @author etirelli
*/
public class EvaluatorRegistry
implements
Externalizable {
private static final long serialVersionUID = 510l;
private Map<String, EvaluatorDefinition> evaluators;
private ClassLoader classloader;
/**
* Default constructor. The registry will use the context classloader (if available)
* to load the evaluator definition classes or this class classloader if it is
* not available.
*/
public EvaluatorRegistry() {
this( null );
}
/**
* Creates a new EvaluatorRegistry using the given classloader to load
* the evaluator definition classes.
*
* @param classloader the classloader to use to load evaluator definition
* classes. If it is null, try to obtain the context
* classloader. If it is also null, uses the same classloader
* that loaded this class.
*
*/
public EvaluatorRegistry(ClassLoader classloader) {
this.evaluators = new HashMap<String, EvaluatorDefinition>();
if ( classloader != null ) {
this.classloader = classloader;
} else {
this.classloader = getDefaultClassLoader();
}
// loading default built in evaluators
this.addEvaluatorDefinition( new EqualityEvaluatorsDefinition() );
this.addEvaluatorDefinition( new ComparableEvaluatorsDefinition() );
this.addEvaluatorDefinition( new SetEvaluatorsDefinition() );
this.addEvaluatorDefinition( new MatchesEvaluatorsDefinition() );
this.addEvaluatorDefinition( new SoundslikeEvaluatorsDefinition() );
this.addEvaluatorDefinition( new BeforeEvaluatorDefinition() );
this.addEvaluatorDefinition( new AfterEvaluatorDefinition() );
this.addEvaluatorDefinition( new MeetsEvaluatorDefinition() );
this.addEvaluatorDefinition( new MetByEvaluatorDefinition() );
this.addEvaluatorDefinition( new OverlapsEvaluatorDefinition() );
this.addEvaluatorDefinition( new OverlappedByEvaluatorDefinition() );
this.addEvaluatorDefinition( new IncludesEvaluatorDefinition() );
this.addEvaluatorDefinition( new DuringEvaluatorDefinition() );
this.addEvaluatorDefinition( new FinishesEvaluatorDefinition() );
this.addEvaluatorDefinition( new FinishedByEvaluatorDefinition() );
this.addEvaluatorDefinition( new StartsEvaluatorDefinition() );
this.addEvaluatorDefinition( new StartedByEvaluatorDefinition() );
this.addEvaluatorDefinition( new CoincidesEvaluatorDefinition() );
this.addEvaluatorDefinition( new StrEvaluatorDefinition() );
}
/**
* Return the set of registered keys.
* @return a Set of Strings
*/
public Set<String> keySet(){
return evaluators.keySet();
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
evaluators = (Map<String, EvaluatorDefinition>)in.readObject();
if (in instanceof DroolsObjectInput) {
classloader = ((DroolsObjectInput)in).getClassLoader();
} else {
classloader = getDefaultClassLoader();
}
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(evaluators);
}
private static ClassLoader getDefaultClassLoader() {
if (Thread.currentThread().getContextClassLoader() != null)
return Thread.currentThread().getContextClassLoader();
return EvaluatorRegistry.class.getClassLoader();
}
/**
* Adds an evaluator definition class to the registry using the
* evaluator class name. The class will be loaded and the corresponting
* evaluator ID will be added to the registry. In case there exists
* an implementation for that ID already, the new implementation will
* replace the previous one.
*
* @param className the name of the class for the implementation definition.
* The class must implement the EvaluatorDefinition interface.
*
* @return true if the new class implementation is replacing an old
* implementation for the same evaluator ID. False otherwise.
*/
public void addEvaluatorDefinition(String className) {
try {
Class<EvaluatorDefinition> defClass = (Class<EvaluatorDefinition>) this.classloader.loadClass( className );
EvaluatorDefinition def = defClass.newInstance();
addEvaluatorDefinition( def );
} catch ( ClassNotFoundException e ) {
throw new RuntimeDroolsException( "Class not found for evaluator definition: " + className,
e );
} catch ( InstantiationException e ) {
throw new RuntimeDroolsException( "Error instantiating class for evaluator definition: " + className,
e );
} catch ( IllegalAccessException e ) {
throw new RuntimeDroolsException( "Illegal access instantiating class for evaluator definition: " + className,
e );
}
}
/**
* Adds an evaluator definition class to the registry. In case there exists
* an implementation for that evaluator ID already, the new implementation will
* replace the previous one.
*
* @param def the evaluator definition to be added.
*/
public void addEvaluatorDefinition(EvaluatorDefinition def) {
for ( String id : def.getEvaluatorIds() ) {
this.evaluators.put( id,
def );
}
}
/**
* Returns the evaluator definition for the given evaluator ID
* or null if no one was found
*
* @param evaluatorId
* @return
*/
public EvaluatorDefinition getEvaluatorDefinition(String evaluatorId) {
return this.evaluators.get( evaluatorId );
}
/**
* Returns the evaluator definition for the given operator
* or null if no one was found
*
* @param operator the operator implemented by the evaluator definition
* @return
*/
public EvaluatorDefinition getEvaluatorDefinition(Operator operator) {
return this.evaluators.get( operator.getOperatorString() );
}
/**
* Returns the evaluator instance for the given type and the
* defined parameterText
*
* @param type the type of the attributes this evaluator will
* operate on. This is important because the evaluator
* may do optimizations and type coercion based on the
* types it is evaluating. It is also possible that
* this evaluator does not support a given type.
*
* @param operatorId the string identifier of the evaluator
*
* @param isNegated true if the evaluator instance to be returned is
* the negated version of the evaluator.
*
* @param parameterText some evaluators support parameters and these
* parameters are defined as a String that is
* parsed by the evaluator itself.
*
* @return an Evaluator instance capable of evaluating expressions
* between values of the given type, or null in case the type
* is not supported.
*/
public Evaluator getEvaluator(ValueType type,
String operatorId,
boolean isNegated,
String parameterText) {
return this.getEvaluatorDefinition( operatorId ).getEvaluator( type,
operatorId,
isNegated,
parameterText );
}
/**
* Returns the evaluator instance for the given type and the
* defined parameterText
*
* @param type the type of the attributes this evaluator will
* operate on. This is important because the evaluator
* may do optimizations and type coercion based on the
* types it is evaluating. It is also possible that
* this evaluator does not support a given type.
*
* @param operator the operator that evaluator implements
*
* @param parameterText some evaluators support parameters and these
* parameters are defined as a String that is
* parsed by the evaluator itself.
*
* @return an Evaluator instance capable of evaluating expressions
* between values of the given type, or null in case the type
* is not supported.
*/
public Evaluator getEvaluator(ValueType type,
Operator operator,
String parameterText) {
return this.getEvaluatorDefinition( operator ).getEvaluator( type,
operator,
parameterText );
}
/**
* Returns the evaluator instance for the given type and the
* defined parameterText
*
* @param type the type of the attributes this evaluator will
* operate on. This is important because the evaluator
* may do optimizations and type coercion based on the
* types it is evaluating. It is also possible that
* this evaluator does not support a given type.
*
* @param operator the operator that evaluator implements
*
* @return an Evaluator instance capable of evaluating expressions
* between values of the given type, or null in case the type
* is not supported.
*/
public Evaluator getEvaluator(ValueType type,
Operator operator) {
return this.getEvaluatorDefinition( operator ).getEvaluator( type,
operator );
}
}