/*
* Copyright 2005 Red Hat, Inc. and/or its affiliates.
*
* 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.core.rule;
import org.drools.core.base.ValueType;
import org.drools.core.base.evaluators.AfterEvaluatorDefinition.AfterEvaluator;
import org.drools.core.base.evaluators.BeforeEvaluatorDefinition.BeforeEvaluator;
import org.drools.core.base.evaluators.MeetsEvaluatorDefinition.MeetsEvaluator;
import org.drools.core.base.evaluators.MetByEvaluatorDefinition.MetByEvaluator;
import org.drools.core.common.EventFactHandle;
import org.drools.core.common.InternalFactHandle;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.spi.Evaluator;
import org.drools.core.spi.InternalReadAccessor;
import org.drools.core.spi.Tuple;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class VariableRestriction {
private VariableRestriction() { }
public static VariableContextEntry createContextEntry(InternalReadAccessor fieldExtractor,
Declaration declaration,
Evaluator evaluator) {
ValueType coerced = evaluator.getCoercedValueType();
if ( evaluator.isTemporal() ) {
if ( evaluator instanceof BeforeEvaluator || evaluator instanceof MeetsEvaluator) {
return new LeftStartRightEndContextEntry( fieldExtractor,
declaration,
evaluator );
}
if ( evaluator instanceof AfterEvaluator || evaluator instanceof MetByEvaluator ) {
return new LeftEndRightStartContextEntry( fieldExtractor,
declaration,
evaluator );
}
// else
return new TemporalVariableContextEntry( fieldExtractor,
declaration,
evaluator );
}
if ( coerced.isBoolean() ) {
return new BooleanVariableContextEntry( fieldExtractor,
declaration,
evaluator );
} else if ( coerced.isFloatNumber() ) {
return new DoubleVariableContextEntry( fieldExtractor,
declaration,
evaluator );
} else if ( coerced.isIntegerNumber() || coerced.isEvent() ) {
return new LongVariableContextEntry( fieldExtractor,
declaration,
evaluator );
} else if ( coerced.isChar() ) {
return new CharVariableContextEntry( fieldExtractor,
declaration,
evaluator );
} else {
return new ObjectVariableContextEntry( fieldExtractor,
declaration,
evaluator );
}
}
public static abstract class VariableContextEntry
implements
ContextEntry {
public InternalReadAccessor extractor;
public Evaluator evaluator;
public Object object;
public Declaration declaration;
public Tuple tuple;
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();
tuple = (Tuple) 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( tuple );
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 InternalReadAccessor getFieldExtractor() {
return this.extractor;
}
public Object getObject() {
return this.object;
}
public Tuple getTuple() {
return this.tuple;
}
public Declaration getVariableDeclaration() {
return this.declaration;
}
public boolean isLeftNull() {
return this.leftNull;
}
public boolean isRightNull() {
return this.rightNull;
}
public void resetTuple() {
this.tuple = 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 Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ) );
this.left = this.declaration.getExtractor().getValue( workingMemory,
tuple.getObject( this.declaration ) );
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject() );
this.right = this.extractor.getValue( workingMemory,
handle.getObject() );
}
public void resetTuple() {
this.left = null;
this.tuple = 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 Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ) );
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getLongValue( workingMemory,
tuple.getObject( this.declaration ) );
} else {
this.left = 0;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject());
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getLongValue( workingMemory,
handle.getObject() );
} 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 Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ));
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getCharValue( workingMemory,
tuple.getObject( this.declaration ) );
} else {
this.left = 0;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject());
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getCharValue( workingMemory,
handle.getObject() );
} 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 Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ) );
if ( !leftNull ) {
this.left = this.declaration.getExtractor().getDoubleValue( workingMemory,
tuple.getObject( this.declaration ) );
} else {
this.left = 0;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject() );
if ( !rightNull ) { // avoid a NullPointerException
this.right = this.extractor.getDoubleValue( workingMemory,
handle.getObject() );
} 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 Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ) );
this.left = !leftNull && this.declaration.getExtractor().getBooleanValue( workingMemory, tuple.getObject( this.declaration ) );
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject() );
// avoid a NullPointerException
this.right = !rightNull && this.extractor.getBooleanValue( workingMemory, handle.getObject() );
}
}
public static abstract class TimestampedContextEntry extends VariableContextEntry {
public long timestamp;
public TimestampedContextEntry() {
}
public TimestampedContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal( in );
timestamp = in.readLong();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeLong( timestamp );
}
protected abstract long getTimestampFromTuple( Tuple tuple );
protected abstract long getTimestampFromFactHandle( InternalFactHandle handle );
@Override
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
if ( this.declaration.getExtractor().isSelfReference() ) {
this.timestamp = getTimestampFromTuple( tuple );
} else {
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ) );
if ( !leftNull ) { // avoid a NullPointerException
this.timestamp = this.declaration.getExtractor().getLongValue( workingMemory,
tuple.getObject( this.declaration ) );
} else {
this.timestamp = 0;
}
}
}
@Override
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
if ( this.extractor.isSelfReference() ) {
this.timestamp = getTimestampFromFactHandle( handle );
} else {
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject());
if ( !rightNull ) { // avoid a NullPointerException
this.timestamp = this.extractor.getLongValue( workingMemory,
handle.getObject() );
} else {
this.timestamp = 0;
}
}
}
}
public static class LeftStartRightEndContextEntry extends TimestampedContextEntry {
private static final long serialVersionUID = 510l;
public LeftStartRightEndContextEntry() {
}
public LeftStartRightEndContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
@Override
protected long getTimestampFromTuple( Tuple tuple ) {
return ((EventFactHandle) tuple.get( this.declaration )).getStartTimestamp();
}
@Override
protected long getTimestampFromFactHandle( InternalFactHandle handle ) {
return ((EventFactHandle)handle).getEndTimestamp();
}
}
public static class LeftEndRightStartContextEntry extends TimestampedContextEntry {
private static final long serialVersionUID = 510l;
public LeftEndRightStartContextEntry() {
}
public LeftEndRightStartContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
@Override
protected long getTimestampFromTuple( Tuple tuple ) {
return ((EventFactHandle) tuple.get( this.declaration )).getEndTimestamp();
}
@Override
protected long getTimestampFromFactHandle( InternalFactHandle handle ) {
return ((EventFactHandle)handle).getStartTimestamp();
}
}
public static class TemporalVariableContextEntry extends VariableContextEntry {
private static final long serialVersionUID = 510l;
public long startTS;
public long endTS;
public TemporalVariableContextEntry() {
}
public TemporalVariableContextEntry(final InternalReadAccessor extractor,
final Declaration declaration,
final Evaluator evaluator) {
super( extractor,
declaration,
evaluator );
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal( in );
startTS = in.readLong();
endTS = in.readLong();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal( out );
out.writeLong( startTS );
out.writeLong( startTS );
}
public void updateFromTuple(final InternalWorkingMemory workingMemory,
final Tuple tuple) {
this.tuple = tuple;
this.workingMemory = workingMemory;
if ( this.declaration.getExtractor().isSelfReference() ) {
EventFactHandle efh = ((EventFactHandle)tuple.get( this.declaration ));
this.startTS = efh.getStartTimestamp();
this.endTS = efh.getEndTimestamp();
} else {
this.leftNull = this.declaration.getExtractor().isNullValue( workingMemory,
tuple.getObject( this.declaration ) );
if ( !leftNull ) { // avoid a NullPointerException
this.startTS = this.declaration.getExtractor().getLongValue( workingMemory,
tuple.getObject( this.declaration ) );
} else {
this.startTS = 0;
}
endTS = startTS;
}
}
public void updateFromFactHandle(final InternalWorkingMemory workingMemory,
final InternalFactHandle handle) {
this.object = handle.getObject();
this.workingMemory = workingMemory;
if ( this.extractor.isSelfReference() ) {
this.startTS = ((EventFactHandle)handle).getStartTimestamp();
this.endTS = ((EventFactHandle)handle).getEndTimestamp();
} else {
this.rightNull = this.extractor.isNullValue( workingMemory,
handle.getObject());
if ( !rightNull ) { // avoid a NullPointerException
this.startTS = this.extractor.getLongValue( workingMemory,
handle.getObject() );
} else {
this.startTS = 0;
}
endTS = startTS;
}
}
}
}