/**
* 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.
*/
package org.drools.rule;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Arrays;
import org.drools.base.ValueType;
import org.drools.common.InternalFactHandle;
import org.drools.common.InternalWorkingMemory;
import org.drools.reteoo.LeftTuple;
import org.drools.spi.AcceptsReadAccessor;
import org.drools.spi.Evaluator;
import org.drools.spi.InternalReadAccessor;
import org.drools.spi.ReadAccessor;
import org.drools.spi.Restriction;
import org.drools.time.Interval;
public class VariableRestriction
implements
AcceptsReadAccessor,
Restriction {
private static final long serialVersionUID = 510l;
private Declaration declaration;
private Declaration[] requiredDeclarations;
private Evaluator evaluator;
private InternalReadAccessor readAccessor;
public VariableRestriction() {
}
public VariableRestriction(final InternalReadAccessor fieldExtractor,
final Declaration declaration,
final Evaluator evaluator) {
this.declaration = declaration;
this.requiredDeclarations = new Declaration[]{declaration};
this.evaluator = evaluator;
this.readAccessor = fieldExtractor;
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject( declaration );
out.writeObject( requiredDeclarations );
out.writeObject( evaluator );
out.writeObject( readAccessor );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
declaration = (Declaration) in.readObject();
requiredDeclarations = (Declaration[]) in.readObject();
evaluator = (Evaluator) in.readObject();
readAccessor = (InternalReadAccessor) in.readObject();
}
public void setReadAccessor(InternalReadAccessor readAccessor) {
this.readAccessor = readAccessor;
}
public Declaration[] getRequiredDeclarations() {
return this.requiredDeclarations;
}
public void replaceDeclaration(Declaration oldDecl,
Declaration newDecl) {
if ( this.declaration.equals( oldDecl ) ) {
this.declaration = newDecl;
this.requiredDeclarations[0] = newDecl;
}
}
public Evaluator getEvaluator() {
return this.evaluator;
}
public boolean isAllowed(final InternalReadAccessor extractor,
final InternalFactHandle handle,
final InternalWorkingMemory workingMemory,
final ContextEntry context) {
return this.evaluator.evaluate( workingMemory,
this.readAccessor,
this.evaluator.prepareLeftObject( handle ),
this.declaration.getExtractor(),
this.evaluator.prepareRightObject( handle ) );
}
public boolean isAllowedCachedLeft(final ContextEntry context,
final InternalFactHandle handle) {
return this.evaluator.evaluateCachedLeft( ((VariableContextEntry) context).workingMemory,
(VariableContextEntry) context,
this.evaluator.prepareRightObject( handle ) );
}
public boolean isAllowedCachedRight(final LeftTuple tuple,
final ContextEntry context) {
return this.evaluator.evaluateCachedRight( ((VariableContextEntry) context).workingMemory,
(VariableContextEntry) context,
this.evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
}
public boolean isTemporal() {
return this.evaluator.isTemporal();
}
public Interval getInterval() {
return this.evaluator.getInterval();
}
public String toString() {
return this.evaluator + " " + this.declaration;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((this.declaration == null) ? 0 : this.declaration.hashCode());
result = PRIME * result + ((this.evaluator == null) ? 0 : this.evaluator.hashCode());
result = PRIME * result + this.requiredDeclarations[0].hashCode();
return result;
}
public boolean equals(final Object object) {
if ( this == object ) {
return true;
}
if ( object == null || getClass() != object.getClass() ) {
return false;
}
final VariableRestriction other = (VariableRestriction) object;
return this.declaration.equals( other.declaration ) && this.evaluator.equals( other.evaluator ) && Arrays.equals( this.requiredDeclarations,
other.requiredDeclarations );
}
private final VariableContextEntry createContextEntry(final Evaluator eval,
final InternalReadAccessor fieldExtractor) {
ValueType coerced = eval.getCoercedValueType();
if ( coerced.isBoolean() ) {
return new BooleanVariableContextEntry( fieldExtractor,
this.declaration,
this.evaluator );
} else if ( coerced.isFloatNumber() ) {
return new DoubleVariableContextEntry( fieldExtractor,
this.declaration,
this.evaluator );
} else if ( coerced.isIntegerNumber() || coerced.isEvent() ) {
return new LongVariableContextEntry( fieldExtractor,
this.declaration,
this.evaluator );
} else if ( coerced.isChar() ) {
return new CharVariableContextEntry( fieldExtractor,
this.declaration,
this.evaluator );
} else {
return new ObjectVariableContextEntry( fieldExtractor,
this.declaration,
this.evaluator );
}
}
public ContextEntry createContextEntry() {
return this.createContextEntry( this.evaluator,
this.readAccessor );
}
public Object clone() {
return new VariableRestriction( this.readAccessor,
(Declaration) this.declaration.clone(),
this.evaluator );
}
public static abstract class VariableContextEntry
implements
ContextEntry {
public InternalReadAccessor extractor;
public Evaluator evaluator;
public Object object;
public Declaration declaration;
public LeftTuple reteTuple;
public ContextEntry entry;
public boolean leftNull;
public boolean rightNull;
public InternalWorkingMemory workingMemory;
public VariableContextEntry() {
}
public VariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
this.extractor = extractor;
this.declaration = declaration;
this.evaluator = evaluator;
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
workingMemory = (InternalWorkingMemory) in.readObject();
extractor = (InternalReadAccessor) in.readObject();
evaluator = (Evaluator) in.readObject();
object = in.readObject();
declaration = (Declaration) in.readObject();
reteTuple = (LeftTuple) in.readObject();
entry = (ContextEntry) in.readObject();
leftNull = in.readBoolean();
rightNull = in.readBoolean();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject( workingMemory );
out.writeObject( extractor );
out.writeObject( evaluator );
out.writeObject( object );
out.writeObject( declaration );
out.writeObject( reteTuple );
out.writeObject( entry );
out.writeBoolean( leftNull );
out.writeBoolean( rightNull );
}
public ContextEntry getNext() {
return this.entry;
}
public void setNext(final ContextEntry entry) {
this.entry = entry;
}
public ReadAccessor getFieldExtractor() {
return this.extractor;
}
public Object getObject() {
return this.object;
}
public LeftTuple getTuple() {
return this.reteTuple;
}
public Declaration getVariableDeclaration() {
return this.declaration;
}
public boolean isLeftNull() {
return this.leftNull;
}
public boolean isRightNull() {
return this.rightNull;
}
public void resetTuple() {
this.reteTuple = null;
}
public void resetFactHandle() {
this.object = null;
}
}
public static class ObjectVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public Object left;
public Object right;
public ObjectVariableContextEntry() {
}
public ObjectVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal( in );
left = in.readObject();
right = in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeObject( left );
out.writeObject( right );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final LeftTuple tuple) {
this.reteTuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
this.left = this.declaration.getExtractor().getValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = evaluator.prepareLeftObject( handle );
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
evaluator.prepareRightObject( handle ) );
this.right = this.extractor.getValue( workingMemory,
evaluator.prepareRightObject( handle ) );
}
public void resetTuple() {
this.left = null;
this.reteTuple = null;
}
public void resetFactHandle() {
this.right = null;
this.object = null;
}
}
public static class PrimitiveArrayVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public Object left;
public Object right;
public PrimitiveArrayVariableContextEntry() {
}
public PrimitiveArrayVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal( in );
left = in.readObject();
right = in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeObject( left );
out.writeObject( right );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final LeftTuple tuple) {
this.reteTuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
this.left = this.declaration.getExtractor().getValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = evaluator.prepareLeftObject( handle );
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
evaluator.prepareRightObject( handle ) );
this.right = this.extractor.getValue( workingMemory,
evaluator.prepareRightObject( handle ) );
}
public void resetTuple() {
this.left = null;
this.reteTuple = null;
}
public void resetFactHandle() {
this.right = null;
this.object = null;
}
}
public static class LongVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public long left;
public long right;
public LongVariableContextEntry() {
}
public LongVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal( in );
left = in.readLong();
right = in.readLong();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeLong( left );
out.writeLong( right );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final LeftTuple tuple) {
this.reteTuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getLongValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
} else {
this.left = 0;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = evaluator.prepareLeftObject( handle );
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
evaluator.prepareRightObject( handle ) );
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getLongValue( workingMemory,
evaluator.prepareRightObject( handle ) );
} else {
this.right = 0;
}
}
}
public static class CharVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public char left;
public char right;
public CharVariableContextEntry() {
}
public CharVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal( in );
left = in.readChar();
right = in.readChar();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeChar( left );
out.writeChar( right );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final LeftTuple tuple) {
this.reteTuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getCharValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
} else {
this.left = 0;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = evaluator.prepareLeftObject( handle );
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
evaluator.prepareRightObject( handle ) );
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getCharValue( workingMemory,
evaluator.prepareRightObject( handle ) );
} else {
this.right = 0;
}
}
}
public static class DoubleVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public double left;
public double right;
public DoubleVariableContextEntry() {
}
public DoubleVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal( in );
left = in.readDouble();
right = in.readDouble();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeDouble( left );
out.writeDouble( right );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final LeftTuple tuple) {
this.reteTuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getDoubleValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
} else {
this.left = 0;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = evaluator.prepareLeftObject( handle );
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
evaluator.prepareRightObject( handle ) );
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getDoubleValue( workingMemory,
evaluator.prepareRightObject( handle ) );
} else {
this.right = 0;
}
}
}
public static class BooleanVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public boolean left;
public boolean right;
public BooleanVariableContextEntry() {
}
public BooleanVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal( in );
left = in.readBoolean();
right = in.readBoolean();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeBoolean( left );
out.writeBoolean( right );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final LeftTuple tuple) {
this.reteTuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getBooleanValue( workingMemory,
evaluator.prepareLeftObject( tuple.get( this.declaration ) ) );
} else {
this.left = false;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = evaluator.prepareLeftObject( handle );
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
evaluator.prepareRightObject( handle ) );
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getBooleanValue( workingMemory,
evaluator.prepareRightObject( handle ) );
} else {
this.right = false;
}
}
}
}