package jadex.rules.rulesystem.rete.nodes;
import jadex.rules.rulesystem.AbstractAgenda;
import jadex.rules.rulesystem.rete.Tuple;
import jadex.rules.rulesystem.rete.extractors.AttributeSet;
import jadex.rules.state.IOAVState;
import jadex.rules.state.OAVAttributeType;
import java.util.Collection;
import java.util.Collections;
/**
* Dummy fact node for not conditions, which are no joins.
*/
public class InitialFactNode extends AbstractNode implements ITupleSourceNode, IObjectConsumerNode
{
//-------- constants -------
/** The initial fact. */
// Todo: should be in state?
public static final String INITIAL_FACT = "initial-fact";
//-------- attributes --------
/** The tuple consumers. */
protected ITupleConsumerNode[] tconsumers;
/** The object source. */
protected IObjectSourceNode osource;
/** The set of relevant attributes. */
protected AttributeSet relevants;
/** The initial fact tuple. */
protected Tuple initial_fact_tuple;
/** The initial fact memory. */
protected Collection initial_fact_mem;
//-------- methods --------
/**
* Create a new node.
*/
public InitialFactNode(int nodeid)
{
super(nodeid);
}
/**
* Initialize the pattern matcher.
* Called before the agenda is accessed
* to perform any initialization, if necessary.
*/
public void init(IOAVState state, ReteMemory mem, AbstractAgenda agenda)
{
this.initial_fact_tuple = new Tuple(state, null, INITIAL_FACT);
this.initial_fact_mem = Collections.singletonList(initial_fact_tuple);
ITupleConsumerNode[] tcon = tconsumers;
for(int i=0; tcon!=null && i<tcon.length; i++)
tcon[i].addTuple(initial_fact_tuple, state, mem, agenda);
}
//-------- object consumer interface --------
/**
* Send a new object to this node.
* @param object The object.
*/
public void addObject(Object object, IOAVState state, ReteMemory mem, AbstractAgenda agenda)
{
//System.out.println("Add object called: "+this+" "+object);
// Todo: support propagation of initial fact with reset?
}
/**
* Send a removed object to this node.
* @param object The object.
*/
public void removeObject(Object object, IOAVState state, ReteMemory mem, AbstractAgenda agenda)
{
//System.out.println("Remove object called: "+this+" "+object);
// Todo: support retraction of initial fact with reset?
}
/**
* Propagate an object change to this node.
* @param object The new object.
*/
public void modifyObject(Object object, OAVAttributeType type, Object oldvalue, Object newvalue, IOAVState state, ReteMemory mem, AbstractAgenda agenda)
{
// Nothing to do...
}
/**
* Propagate an indirect object change to this node.
* @param object The changed object.
*/
public void modifyIndirectObject(Object object, OAVAttributeType type, Object oldvalue, Object newvalue, IOAVState state, ReteMemory mem, AbstractAgenda agenda)
{
// Should never be called.
throw new UnsupportedOperationException("Unsupported method.");
}
/**
* Set the object source of this node.
* @param node The object source node.
*/
public void setObjectSource(IObjectSourceNode node)
{
this.osource = node;
}
/**
* Get the object source of this node.
* @return The object source node.
*/
public IObjectSourceNode getObjectSource()
{
return osource;
}
//-------- tuple source interface --------
/**
* Add an tuple consumer node.
* @param node A new consumer node.
*/
public void addTupleConsumer(ITupleConsumerNode node)
{
if(tconsumers==null)
{
tconsumers = new ITupleConsumerNode[]{node};
}
else
{
ITupleConsumerNode[] tmp = new ITupleConsumerNode[tconsumers.length+1];
System.arraycopy(tconsumers, 0, tmp, 0, tconsumers.length);
tmp[tconsumers.length] = node;
tconsumers = tmp;
}
}
/**
* Remove an tuple consumer.
* @param node The consumer node.
*/
public void removeTupleConsumer(ITupleConsumerNode node)
{
if(tconsumers!=null)
{
for(int i=0; i<tconsumers.length; i++)
{
if(tconsumers[i].equals(node))
{
if(tconsumers.length==1)
{
tconsumers = null;
}
else
{
ITupleConsumerNode[] tmp = new ITupleConsumerNode[tconsumers.length-1];
if(i>0)
System.arraycopy(tconsumers, 0, tmp, 0, i);
if(i<tconsumers.length-1)
System.arraycopy(tconsumers, i+1, tmp, i, tconsumers.length-1-i);
tconsumers = tmp;
}
break;
}
}
}
}
/**
* Get all tuple consumer nodes.
* @return All tuple consumer nodes.
*/
public ITupleConsumerNode[] getTupleConsumers()
{
return tconsumers;
}
/**
* Get the memory for this node.
* @return The memory.
*/
public Collection getNodeMemory(ReteMemory mem)
{
return initial_fact_mem;
}
//-------- INode methods --------
/**
* Create the node memory.
* @param state The state.
* @return The node memory.
*/
public Object createNodeMemory(IOAVState state)
{
return null;
}
/**
* Get the set of relevant attribute types.
*/
public AttributeSet getRelevantAttributes()
{
if(relevants==null)
{
synchronized(this)
{
if(relevants==null)
{
relevants = new AttributeSet();
for(int i=0; tconsumers!=null && i<tconsumers.length; i++)
{
relevants.addAll(tconsumers[i].getRelevantAttributes());
}
}
}
}
return relevants;
}
/**
* Get the set of indirect attribute types.
* I.e. attributes of objects, which are not part of an object conditions
* (e.g. for chained extractors)
* @return The relevant attribute types.
*/
public AttributeSet getIndirectAttributes()
{
return AttributeSet.EMPTY_ATTRIBUTESET;
}
//-------- cloneable --------
/**
* Do clone makes a deep clone without regarding cycles.
* Method is overridden by subclasses to actually incorporate their attributes.
* @param theclone The clone.
*/
protected void doClone(Object theclone)
{
InitialFactNode clone = (InitialFactNode)theclone;
// Deep clone tuple consumers
clone.tconsumers = new ITupleConsumerNode[tconsumers.length];
for(int i=0; i<tconsumers.length; i++)
clone.tconsumers[i] = (ITupleConsumerNode)tconsumers[i].clone();
// Set the source
clone.osource = (IObjectSourceNode)osource.clone();
}
}