📄 reteoobuilder.java
字号:
package org.drools.reteoo;
/*
* Copyright 2005 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.
*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.drools.InitialFact;
import org.drools.RuleIntegrationException;
import org.drools.base.ClassFieldExtractor;
import org.drools.base.ClassObjectType;
import org.drools.base.DroolsQuery;
import org.drools.base.EvaluatorFactory;
import org.drools.base.FieldFactory;
import org.drools.common.BetaNodeBinder;
import org.drools.common.InstanceEqualsConstraint;
import org.drools.common.InstanceNotEqualsConstraint;
import org.drools.rule.And;
import org.drools.rule.Column;
import org.drools.rule.Declaration;
import org.drools.rule.EvalCondition;
import org.drools.rule.Exists;
import org.drools.rule.GroupElement;
import org.drools.rule.InvalidPatternException;
import org.drools.rule.LiteralConstraint;
import org.drools.rule.Not;
import org.drools.rule.Query;
import org.drools.rule.Rule;
import org.drools.spi.Evaluator;
import org.drools.spi.FieldConstraint;
import org.drools.spi.FieldValue;
import org.drools.spi.ObjectTypeResolver;
/**
* Builds the Rete-OO network for a <code>Package</code>.
*
* @see org.drools.rule.Package
*
* @author <a href="mailto:mark.proctor@jboss.com">Mark Proctor</a>
* @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
*
*/
class ReteooBuilder
implements
Serializable {
// ------------------------------------------------------------
// Instance members
// ------------------------------------------------------------
/**
*
*/
private static final long serialVersionUID = 1737643968218792944L;
/** The RuleBase */
private transient ReteooRuleBase ruleBase;
/** Rete network to build against. */
private transient Rete rete;
private transient ReteooWorkingMemory[] workingMemories;
private final ObjectTypeResolver resolver;
/** Nodes that have been attached. */
private final Map attachedNodes;
private TupleSource tupleSource;
private ObjectSource objectSource;
private Map declarations;
private int id;
private Map rules;
private Map objectType;
private int currentOffsetAdjustment;
/** A factory for object sink lists */
private transient ObjectSinkListFactory sinklistFactory;
// ------------------------------------------------------------
// Constructors
// ------------------------------------------------------------
/**
* Construct a <code>Builder</code> against an existing <code>Rete</code>
* network.
*/
ReteooBuilder(final ReteooRuleBase ruleBase,
final ObjectTypeResolver resolver) {
this.ruleBase = ruleBase;
this.rete = this.ruleBase.getRete();
this.resolver = resolver;
this.attachedNodes = new HashMap();
this.rules = new HashMap();
//Set to 1 as Rete node is set to 0
this.id = 1;
// creating factory
this.sinklistFactory = new ObjectSinkListFactory( this.ruleBase.getConfiguration() );
}
/**
* Allow this to be settable, otherwise we get infinite recursion on serialisation
* @param ruleBase
*/
void setRuleBase(final ReteooRuleBase ruleBase) {
this.ruleBase = ruleBase;
}
/**
* Allow this to be settable, otherwise we get infinite recursion on serialisation
* @param ruleBase
*/
void setRete(final Rete rete) {
}
// ------------------------------------------------------------
// Instance methods
// ------------------------------------------------------------
/**
* Add a <code>Rule</code> to the network.
*
* @param rule
* The rule to add.
*
* @throws RuleIntegrationException
* if an error prevents complete construction of the network for
* the <code>Rule</code>.
* @throws InvalidPatternException
*/
void addRule(final Rule rule) throws InvalidPatternException {
// reset working memories for potential propagation
this.workingMemories = (ReteooWorkingMemory[]) this.ruleBase.getWorkingMemories().toArray( new ReteooWorkingMemory[this.ruleBase.getWorkingMemories().size()] );
this.currentOffsetAdjustment = 0;
final List nodes = new ArrayList();
final And[] and = rule.getTransformedLhs();
for ( int i = 0; i < and.length; i++ ) {
if ( !hasColumns( and[i] ) ) {
addInitialFactMatch( and[i] );
}
addRule( and[i],
rule );
BaseNode node = null;
if ( !(rule instanceof Query) ) {
// Check a consequence is set
if ( rule.getConsequence() == null ) {
throw new InvalidPatternException( "Rule '" + rule.getName() + "' has no Consequence" );
}
node = new TerminalNode( this.id++,
this.tupleSource,
rule );
} else {
// Check there is no consequence
if ( rule.getConsequence() != null ) {
throw new InvalidPatternException( "Query '" + rule.getName() + "' should have no Consequence" );
}
node = new QueryTerminalNode( this.id++,
this.tupleSource,
rule );
}
nodes.add( node );
if ( this.workingMemories.length == 0 ) {
node.attach();
} else {
node.attach( this.workingMemories );
}
}
this.rules.put( rule,
nodes.toArray( new BaseNode[nodes.size()] ) );
}
private boolean hasColumns(final GroupElement ge) {
for ( final Iterator it = ge.getChildren().iterator(); it.hasNext(); ) {
final Object object = it.next();
if ( object instanceof Column || (object instanceof GroupElement && hasColumns( (GroupElement) object )) ) {
return true;
}
}
return false;
}
private void addInitialFactMatch(final And and) {
And temp = null;
// If we have children we know there are no columns but we need to make sure that InitialFact is first
if ( !and.getChildren().isEmpty() ) {
temp = (And) and.clone();
and.getChildren().clear();
}
final Column column = new Column( 0,
new ClassObjectType( InitialFact.class ) );
and.addChild( column );
// now we know InitialFact is first add all the previous constrains
if ( temp != null ) {
and.getChildren().addAll( temp.getChildren() );
}
}
private void addRule(final And and,
final Rule rule) throws InvalidPatternException {
this.objectSource = null;
this.tupleSource = null;
this.declarations = new HashMap();
this.objectType = new LinkedHashMap();
if ( rule instanceof Query ) {
attachQuery( rule.getName() );
}
for ( final Iterator it = and.getChildren().iterator(); it.hasNext(); ) {
final Object object = it.next();
if ( object instanceof EvalCondition ) {
final EvalCondition eval = (EvalCondition) object;
checkUnboundDeclarations( eval.getRequiredDeclarations() );
this.tupleSource = attachNode( new EvalConditionNode( this.id++,
this.tupleSource,
eval ) );
continue;
}
BetaNodeBinder binder;
Column column;
if ( object instanceof Column ) {
column = (Column) object;
binder = attachColumn( (Column) object,
and,
true );
// If a tupleSource does not exist then we need to adapt this
// into
// a TupleSource using LeftInputAdapterNode
if ( this.tupleSource == null ) {
this.tupleSource = attachNode( new LeftInputAdapterNode( this.id++,
this.objectSource,
binder ) );
// objectSource is created by the attachColumn method, if we
// adapt this to
// a TupleSource then we need to null the objectSource
// reference.
this.objectSource = null;
}
} else {
// If its not a Column or EvalCondition then it can either be a Not or an Exists
GroupElement ce = (GroupElement) object;
while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
ce = (GroupElement) ce.getChildren().get( 0 );
}
column = (Column) ce.getChildren().get( 0 );
// If a tupleSource does not exist then we need to adapt an
// InitialFact into a a TupleSource using LeftInputAdapterNode
if ( this.tupleSource == null ) {
// adjusting offset as all tuples will now contain initial-fact at index 0
this.currentOffsetAdjustment = 1;
final ObjectSource objectSource = attachNode( new ObjectTypeNode( this.id++,
this.sinklistFactory.newObjectSinkList( ObjectTypeNode.class ),
new ClassObjectType( InitialFact.class ),
this.rete ) );
this.tupleSource = attachNode( new LeftInputAdapterNode( this.id++,
objectSource ) );
}
binder = attachColumn( column,
and,
true );
}
if ( object instanceof Not ) {
attachNot( this.tupleSource,
(Not) object,
this.objectSource,
binder,
column );
} else if ( object instanceof Exists ) {
attachExists( this.tupleSource,
(Exists) object,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -