/**
*
*/
package agg.ruleappl;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import agg.xt_basis.Graph;
import agg.xt_basis.GraphObject;
import agg.xt_basis.Rule;
/**
* Stores related objects of two rules:
* an output object which belongs to RHS of the first rule
* is related to
* an input object which belongs to LHS of the second rule.
*
* Having a co-match of the first rule and match of the second rule
* we can find an object of the host graph which corresponds to
* the output of the first rule and input of the second rule :
*
* graph_object = comatch.getImage(object_flow.getOutput(input)
*
* match.addMapping(input, graph_object)
*
*
* @author olga
*
*/
public class ObjectFlow {
final Hashtable<Object, Object> outputInputMap;
final Object srcOfOutput; // Graph | Rule
final Object srcOfInput; // Rule
int indxOfOutput = -1, indxOfInput = -1;
/**
* @param sourceOfOutput output object can be Graph or Rule which RHS contains output objects
* @param sourceOfInput input object is a Rule which LHS contains input objects
* @param indxOfOutput index of the output object
* @param indxOfInput index of the input object
*/
public ObjectFlow(final Object sourceOfOutput, final Object sourceOfInput,
int indxOfOutput, int indxOfInput) {
this.srcOfOutput = sourceOfOutput;
this.srcOfInput = sourceOfInput;
this.indxOfOutput = indxOfOutput;
this.indxOfInput = indxOfInput;
this.outputInputMap = new Hashtable<Object, Object>();
}
public ObjectFlow(final Object sourceOfOutput, final Object sourceOfInput,
int indxOfOutput, int indxOfInput,
final Hashtable<Object, Object> outputInputMap) {
this.srcOfOutput = sourceOfOutput;
this.srcOfInput = sourceOfInput;
this.indxOfOutput = indxOfOutput;
this.indxOfInput = indxOfInput;
this.outputInputMap = outputInputMap;
}
public boolean isGraphExtended() {
return (this.srcOfOutput instanceof Graph);
}
public Object getSourceOfOutput() {
return this.srcOfOutput;
}
public Object getSourceOfInput() {
return this.srcOfInput;
}
public int getIndexOfOutput() {
return this.indxOfOutput;
}
public int getIndexOfInput() {
return this.indxOfInput;
}
public String getNameOfOutput() {
if (this.srcOfOutput instanceof Graph)
return ((Graph) this.srcOfOutput).getName();
else if (this.srcOfOutput instanceof Rule)
return ((Rule) this.srcOfOutput).getName();
else return "";
}
public String getNameOfInput() {
if (this.srcOfInput instanceof Rule)
return ((Rule) this.srcOfInput).getName();
return "";
}
public boolean isSourceOfOutput(final Object src) {
return (src == this.srcOfOutput);
}
public boolean isSourceOfInput(final Object src) {
return (src == this.srcOfInput);
}
public void addMapping(final Object output, final Object input) {
if (output != null && input != null)
this.outputInputMap.put(output, input);
}
public void removeMapping(final Object output) {
if (output != null) {
this.outputInputMap.remove(output);
}
}
/**
*
* @return mappings
* where first object is an output
* and second object is an input
* of the object flow
*/
public Hashtable<Object, Object> getMapping() {
return this.outputInputMap;
}
public int getSizeOfInput() {
return this.outputInputMap.size();
}
/**
* Returns an output (Graph)object for the specified input (Graph)object
* if it exists, otherwise null.
* @param input (Graph)object
* @return output (Graph)object
*/
public Object getOutput(final Object input) {
if (input != null) {
Enumeration<Object> keys = this.outputInputMap.keys();
while (keys.hasMoreElements()) {
Object out = keys.nextElement();
if (this.outputInputMap.get(out) == input) {
return out;
}
}
}
return null;
}
public Object getConnectedInput(
final ObjectFlow otherObjFlow, // ObjectFlow before
final Object myInputObj) {
Object outObj = this.getOutput(myInputObj);
if (this.srcOfOutput instanceof Rule
&& outObj instanceof GraphObject) {
Enumeration<GraphObject> inv = ((Rule)this.srcOfOutput).getInverseImage((GraphObject) outObj);
if (inv.hasMoreElements()) {
return inv.nextElement();
}
}
return null;
}
public Object getConnectedOutput(
final ObjectFlow otherObjFlow, // ObjectFlow before
final Object myInputObj) {
Object outObj = this.getOutput(myInputObj);
if (this.srcOfOutput instanceof Rule
&& outObj instanceof GraphObject) {
Enumeration<GraphObject> inv = ((Rule)this.srcOfOutput).getInverseImage((GraphObject) outObj);
if (inv.hasMoreElements()) {
GraphObject otherInput = inv.nextElement();
return otherObjFlow.getOutput(otherInput);
}
}
return null;
}
public boolean isInputObject(final Object obj) {
Iterator<Object> inputs = this.outputInputMap.values().iterator();
while (inputs.hasNext()) {
if (inputs.next() == obj)
return true;
}
return false;
}
public boolean isOutputObject(final Object obj) {
Enumeration<Object> outputs = this.outputInputMap.keys();
while (outputs.hasMoreElements()) {
if (outputs.nextElement() == obj)
return true;
}
return false;
}
/**
* Returns an input (Graph)object for the specified output (Graph)object
* if exists, otherwise null.
* @param output (Graph)object
* @return input (Graph)object
*/
public Object getInput(final Object output) {
if (output != null) {
return this.outputInputMap.get(output);
}
return null;
}
public List<Object> getInputs() {
return new Vector<Object> (this.outputInputMap.values());
}
public boolean isEmpty() {
return this.outputInputMap.isEmpty();
}
public String getKey() {
return String.valueOf(this.indxOfOutput)
.concat(":")
.concat(String.valueOf(this.indxOfInput));
}
public boolean compareTo(final ObjectFlow objFlow) {
if (objFlow == null)
return false;
List<Object> keys1 = new Vector<Object>(this.outputInputMap.keySet());
List<Object> keys2 = new Vector<Object>(objFlow.getMapping().keySet());
if (keys1.size() == keys2.size()
&& keys1.containsAll(keys2)) {
for (int i=0; i<keys1.size(); i++) {
if (this.outputInputMap.get(keys1.get(i))
!= objFlow.getMapping().get(keys1.get(i))) {
return false;
}
}
} else {
return false;
}
return true;
}
}