blob: 8570fa7afc6c7ac31c16a958d1e4d1701e63416c [file] [log] [blame]
package org.eclipse.emf.henshin.sam.invcheck.filter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.henshin.sam.invcheck.InvariantCheckerPlugin;
import org.eclipse.emf.henshin.sam.model.samannotation.Annotation;
import org.eclipse.emf.henshin.sam.model.samgraph.Graph;
import org.eclipse.emf.henshin.sam.model.samgraphcondition.GraphCondition;
import org.eclipse.emf.henshin.sam.model.samgraphcondition.LogicalGCCoupling;
import org.eclipse.emf.henshin.sam.model.samgraphcondition.NegatedCondition;
import org.eclipse.emf.henshin.sam.model.samgraphcondition.Quantification;
import org.eclipse.emf.henshin.sam.model.samgraphcondition.SamgraphconditionPackage;
import org.eclipse.emf.henshin.sam.model.samrules.GTS;
import org.eclipse.emf.henshin.sam.model.samrules.GraphRule;
import org.eclipse.emf.henshin.sam.model.samrules.SamrulesPackage;
import org.eclipse.emf.henshin.sam.model.samtypegraph.TypeGraphCondition;
import org.eclipse.emf.henshin.sam.paf.AbstractProducer;
import org.eclipse.emf.henshin.sam.paf.FilterDispatcher;
import org.eclipse.emf.henshin.sam.paf.IPipe;
import org.eclipse.emf.henshin.sam.paf.annotation.ResultDictEntry;
public class CombinationProducer extends AbstractProducer<CombinationProducer.Pair<Graph, GraphRule>> {
private final static String name = "CombinationProducer";
private boolean printDebug;
private boolean alive = true;
@ResultDictEntry(entryName = "generatedPairs")
private int producedItems = 0;
private Map<String, IPipe<Pair<Graph, GraphRule>>> outputPipes;
public static class Pair<T, S> {
public T first;
public S second;
public Pair(T f, S sec) {
this.first = f;
this.second = sec;
}
}
private Graph[] properties;
private GraphRule[] rules;
private FilterDispatcher filterDispatcher;
public CombinationProducer() {
}
public Graph[] getProperties() {
return properties;
}
public void setProperties(Graph[] properties) {
this.properties = properties;
}
public GraphRule[] getRules() {
return rules;
}
public void setRules(GraphRule[] rules) {
this.rules = rules;
}
public Map<String, IPipe<Pair<Graph, GraphRule>>> getOutputPipes() {
if (this.outputPipes == null) {
this.outputPipes = new HashMap<String, IPipe<Pair<Graph, GraphRule>>>();
}
return this.outputPipes;
}
protected void initData() {
this.printDebug = this.getOption("printDebug");
Assert.isNotNull(this.getFilterDispatcher());
Assert.isNotNull(this.getFilterDispatcher().getFilterInput());
final EObject theEObject = this.getFilterDispatcher().getFilterInput();
Assert.isTrue(theEObject.eClass() == SamrulesPackage.eINSTANCE.getGTS());
final GTS theGTS = (GTS) theEObject;
List<Graph> forbidden = new BasicEList<Graph>();
for (TypeGraphCondition g : theGTS.getTypes().get(0).getConditions()) {
if (g.eClass() == SamgraphconditionPackage.eINSTANCE.getNegatedCondition()
&& (isAssumedProperty((GraphCondition) g) == false)) {
NegatedCondition nc = (NegatedCondition) g;
if (nc.getOperand().eClass() == SamgraphconditionPackage.eINSTANCE.getQuantification()) {
Quantification q = (Quantification) nc.getOperand();
forbidden.add(q.getContext());
}
} else if (g.eClass() == SamgraphconditionPackage.eINSTANCE.getLogicalGCCoupling()) {
LogicalGCCoupling lgc = (LogicalGCCoupling) g;
for (GraphCondition gc : lgc.getOperands()) {
if (gc.eClass() == SamgraphconditionPackage.eINSTANCE.getNegatedCondition()
&& (isAssumedProperty(gc) == false)) {
NegatedCondition neg = (NegatedCondition) gc;
if (neg.getOperand().eClass() == SamgraphconditionPackage.eINSTANCE.getQuantification()) {
Quantification q = (Quantification) neg.getOperand();
forbidden.add(q.getContext());
}
}
}
}
}
this.properties = forbidden.toArray(new Graph[forbidden.size()]);
this.rules = theGTS.getRules().toArray(new GraphRule[theGTS.getRules().size()]);
}
/**
* Tests whether a given {@link GraphCondition} is a so called <emph>Assumed
* Property</emph><br />
* Technically a <code>GraphCondition</code> is considered as an assumed
* property if it owns an {@link Annotation}, whose <code>source</code>
* property is set to the value of
* {@link InvariantCheckerPlugin#ASSUMED_GUARANTEE_ANNOTATION_SOURCE}
*
* @param cond
* the <code>GraphCondition</code> to test
* @return <code>true</code> if the <code>GraphCondition</code> is a assumed
* property, <code>false<code> otherwise.
*/
private boolean isAssumedProperty(GraphCondition cond) {
boolean result = false;
if (cond != null && !cond.getAnnotations().isEmpty()) {
for (Annotation anno : cond.getAnnotations()) {
if (InvariantCheckerPlugin.ASSUMED_GUARANTEE_ANNOTATION_SOURCE.equals(anno.getSource())) {
result = true;
break;
}
}
}
return result;
}
public String getName() {
return CombinationProducer.name;
}
public void produce() {
try {
// Arrays.sort(this.rules, new GraphRuleComparator());
for (int i = 0; i < this.properties.length; i++) {
for (int j = 0; j < this.rules.length; j++) {
Pair<Graph, GraphRule> pair = new Pair<Graph, GraphRule>(this.properties[i], this.rules[j]);
producedItems++;
if (printDebug) {
this.println(">>> DEBUG >>> CombinationProducer >>> produced pair: (" + this.properties[i] + ";"
+ this.rules[j] + ")");
}
for (Iterator<IPipe<Pair<Graph, GraphRule>>> iter = this.getOutputPipes().values().iterator(); iter
.hasNext();) {
// TODO: Avoid blocking when enquing in completely
// filled IPipe
IPipe<Pair<Graph, GraphRule>> nextPipe = iter.next();
nextPipe.queue(pair);
// check if we have to stop
if (!this.filterDispatcher.isContinueComputation())
return;
}
}
}
} catch (InterruptedException ie) {
} finally {
// close all connected outputpipes before leaving this method!!
for (Iterator<IPipe<Pair<Graph, GraphRule>>> iter = this.getOutputPipes().values().iterator(); iter
.hasNext();) {
iter.next().close();
}
}
}
public void run() {
initData();
produce();
System.err.println(Thread.currentThread().getName() + " produced " + producedItems + " items");
}
public FilterDispatcher getFilterDispatcher() {
return this.filterDispatcher;
}
public void reset() {
// TODO Auto-generated method stub
}
public boolean setFilterDispatcher(FilterDispatcher value) {
boolean changed = false;
if (this.filterDispatcher != value) {
FilterDispatcher oldValue = this.filterDispatcher;
this.filterDispatcher = null;
if (oldValue != null) {
oldValue.removeFromIDispatchable(this);
}
this.filterDispatcher = value;
changed = true;
if (value != null) {
value.addToIDispatchable(this);
}
}
return changed;
}
public boolean stillAlive() {
return this.alive;
}
}