/*
* 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.reteoo;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Arrays;
import org.drools.core.RuleBaseConfiguration;
import org.drools.core.common.InternalFactHandle;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.Memory;
import org.drools.core.common.MemoryFactory;
import org.drools.core.common.UpdateContext;
import org.drools.core.reteoo.builder.BuildContext;
import org.drools.core.rule.Declaration;
import org.drools.core.spi.PropagationContext;
import org.drools.core.time.impl.Timer;
import org.drools.core.util.AbstractBaseLinkedListNode;
import org.drools.core.util.index.TupleList;
public class TimerNode extends LeftTupleSource
implements
LeftTupleSinkNode,
MemoryFactory<TimerNode.TimerNodeMemory> {
private static final long serialVersionUID = 510l;
private Timer timer;
private String[] calendarNames;
private boolean tupleMemoryEnabled;
private Declaration[][] declarations;
private LeftTupleSinkNode previousTupleSinkNode;
private LeftTupleSinkNode nextTupleSinkNode;
// ------------------------------------------------------------
// Constructors
// ------------------------------------------------------------
public TimerNode() {
}
public TimerNode(final int id,
final LeftTupleSource tupleSource,
final Timer timer,
final String[] calendarNames,
final Declaration[][] declarations,
final BuildContext context) {
super(id, context);
setLeftTupleSource(tupleSource);
this.timer = timer;
this.calendarNames = calendarNames;
this.declarations = declarations;
this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
initMasks(context, tupleSource);
hashcode = calculateHashCode();
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
super.readExternal(in);
timer = (Timer) in.readObject();
calendarNames = (String[]) in.readObject();
tupleMemoryEnabled = in.readBoolean();
declarations = ( Declaration[][] ) in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeObject(timer);
out.writeObject( calendarNames );
out.writeBoolean(tupleMemoryEnabled);
out.writeObject( declarations );
}
public void attach(BuildContext context) {
this.leftInput.addTupleSink(this, context);
}
public void networkUpdated(UpdateContext updateContext) {
this.leftInput.networkUpdated(updateContext);
}
public Timer getTimer() {
return this.timer;
}
public String[] getCalendarNames() {
return this.calendarNames;
}
public Declaration[][] getDeclarations() {
return this.declarations;
}
/**
* Produce a debug string.
*
* @return The debug string.
*/
public String toString() {
return "[TimerNode(" + this.id + "): cond=" + this.timer + " calendars=" + ((calendarNames == null) ? "null" : Arrays.asList(calendarNames)) + "]";
}
private int calculateHashCode() {
int hash = this.leftInput.hashCode() ^ this.timer.hashCode();
if (calendarNames != null) {
for ( String calendarName : calendarNames ) {
hash = hash ^ calendarName.hashCode();
}
}
return hash;
}
public boolean equals(final Object object) {
return this == object ||
( internalEquals( object ) && this.leftInput.thisNodeEquals(((TimerNode)object).leftInput) );
}
@Override
protected boolean internalEquals( Object object ) {
if ( object == null || !(object instanceof TimerNode) || this.hashCode() != object.hashCode() ) {
return false;
}
TimerNode other = (TimerNode) object;
if (calendarNames != null) {
if (other.getCalendarNames() == null || other.getCalendarNames().length != calendarNames.length) {
return false;
}
for (int i = 0; i < calendarNames.length; i++) {
if (!other.getCalendarNames()[i].equals(calendarNames[i])) {
return false;
}
}
}
return Arrays.deepEquals( declarations, other.declarations ) &&
this.timer.equals(other.timer);
}
public TimerNodeMemory createMemory(final RuleBaseConfiguration config, InternalWorkingMemory wm) {
return new TimerNodeMemory();
}
@Override
public LeftTuple createPeer(LeftTuple original) {
EvalNodeLeftTuple peer = new EvalNodeLeftTuple();
peer.initPeer((BaseLeftTuple) original, this);
original.setPeer(peer);
return peer;
}
protected boolean doRemove(final RuleRemovalContext context,
final ReteooBuilder builder,
final InternalWorkingMemory[] workingMemories) {
if (!this.isInUse()) {
getLeftTupleSource().removeTupleSink(this);
return true;
}
return false;
}
public boolean isLeftTupleMemoryEnabled() {
return tupleMemoryEnabled;
}
public void setLeftTupleMemoryEnabled(boolean tupleMemoryEnabled) {
this.tupleMemoryEnabled = tupleMemoryEnabled;
}
/**
* Returns the next node
*
* @return The next TupleSinkNode
*/
public LeftTupleSinkNode getNextLeftTupleSinkNode() {
return this.nextTupleSinkNode;
}
/**
* Sets the next node
*
* @param next The next TupleSinkNode
*/
public void setNextLeftTupleSinkNode(final LeftTupleSinkNode next) {
this.nextTupleSinkNode = next;
}
/**
* Returns the previous node
*
* @return The previous TupleSinkNode
*/
public LeftTupleSinkNode getPreviousLeftTupleSinkNode() {
return this.previousTupleSinkNode;
}
/**
* Sets the previous node
*
* @param previous The previous TupleSinkNode
*/
public void setPreviousLeftTupleSinkNode(final LeftTupleSinkNode previous) {
this.previousTupleSinkNode = previous;
}
public short getType() {
return NodeTypeEnums.TimerConditionNode;
}
public LeftTuple createLeftTuple(InternalFactHandle factHandle,
Sink sink,
boolean leftTupleMemoryEnabled) {
return new EvalNodeLeftTuple(factHandle, sink, leftTupleMemoryEnabled);
}
public LeftTuple createLeftTuple(final InternalFactHandle factHandle,
final LeftTuple leftTuple,
final Sink sink) {
return new EvalNodeLeftTuple(factHandle, leftTuple, sink);
}
public LeftTuple createLeftTuple(LeftTuple leftTuple,
Sink sink,
PropagationContext pctx, boolean leftTupleMemoryEnabled) {
return new EvalNodeLeftTuple(leftTuple, sink, pctx, leftTupleMemoryEnabled);
}
public LeftTuple createLeftTuple(LeftTuple leftTuple,
RightTuple rightTuple,
Sink sink) {
return new EvalNodeLeftTuple(leftTuple, rightTuple, sink);
}
public LeftTuple createLeftTuple(LeftTuple leftTuple,
RightTuple rightTuple,
LeftTuple currentLeftChild,
LeftTuple currentRightChild,
Sink sink,
boolean leftTupleMemoryEnabled) {
return new EvalNodeLeftTuple(leftTuple, rightTuple, currentLeftChild, currentRightChild, sink, leftTupleMemoryEnabled);
}
@Override
public ObjectTypeNode getObjectTypeNode() {
return leftInput.getObjectTypeNode();
}
public static class TimerNodeMemory extends AbstractBaseLinkedListNode<Memory>
implements
SegmentNodeMemory {
private static final long serialVersionUID = 510l;
private TupleList insertOrUpdateLeftTuples;
private TupleList deleteLeftTuples;
private SegmentMemory memory;
private long nodePosMaskBit;
public TimerNodeMemory() {
this.insertOrUpdateLeftTuples = new TupleList();
this.deleteLeftTuples = new TupleList();
}
public TupleList getInsertOrUpdateLeftTuples() {
return this.insertOrUpdateLeftTuples;
}
public TupleList getDeleteLeftTuples() {
return this.deleteLeftTuples;
}
public short getNodeType() {
return NodeTypeEnums.TimerConditionNode;
}
public SegmentMemory getSegmentMemory() {
return this.memory;
}
public void setSegmentMemory(SegmentMemory smem) {
this.memory = smem;
}
public long getNodePosMaskBit() {
return nodePosMaskBit;
}
public void setNodePosMaskBit(long segmentPos) {
this.nodePosMaskBit = segmentPos;
}
public void setNodeDirtyWithoutNotify() {
memory.updateDirtyNodeMask( nodePosMaskBit );
}
public void setNodeCleanWithoutNotify() {
memory.updateCleanNodeMask( nodePosMaskBit );
}
public void reset() {
insertOrUpdateLeftTuples.clear();
deleteLeftTuples.clear();
}
}
@Override
public void assertLeftTuple(final LeftTuple leftTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
throw new UnsupportedOperationException();
}
@Override
public void retractLeftTuple(final LeftTuple leftTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
throw new UnsupportedOperationException();
}
}