blob: ae71189c049a89b97ba06094c19571f9c64b2355 [file] [log] [blame]
package org.eclipse.emf.henshin.multicda.cda.framework;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.henshin.model.Module;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.emf.henshin.model.Unit;
import org.eclipse.emf.henshin.model.resource.HenshinResourceSet;
import org.eclipse.emf.henshin.multicda.cda.ConflictAnalysis;
import org.eclipse.emf.henshin.multicda.cpa.CDAOptions;
import org.eclipse.emf.henshin.multicda.cpa.CpaByAGG;
import org.eclipse.emf.henshin.multicda.cpa.UnsupportedRuleException;
import org.eclipse.emf.henshin.multicda.cpa.result.CPAResult;
import org.eclipse.emf.henshin.multicda.cpa.result.Conflict;
import org.eclipse.emf.henshin.multicda.cpa.result.CriticalElement;
import org.eclipse.emf.henshin.multicda.cpa.result.CriticalPair;
import org.eclipse.emf.henshin.multicda.cpa.result.Dependency;
import org.eclipse.emf.henshin.preprocessing.NonDeletingPreparator;
import org.eclipse.emf.henshin.preprocessing.RulePreparator;
/**
* This worker provides execution, analysis and testing for CPA
* @author Jevgenij Huebert
*/
public class CpaWorker extends Worker {
private CpaByAGG cpa;
private CPAResult result;
private Options options = new Options();
public CpaWorker(String henshin, String[] rules, Options... options) {
this(henshin, rules, rules, options);
}
public CpaWorker(List<Rule> rules, Options... options) {
this(rules, rules, options);
}
/**
* All rules in the Henshin file will be analyzed with each other.
*
* @param henshin
* path to the Henshin file.
* @param options
* 1:dependency, 2:essential, 3:prepare, 4:noneDeletionSecondRule,
* 5:printHeader, 6:printResults, 7:silent
*/
public CpaWorker(String henshin, Options... options) {
this(henshin, new String[] {}, new String[] {}, options);
}
/**
* All rules from first list will be analyzed with all rules from the second
* list. The rule lists should not be empty!
*
* @param first
* the first rules as list of Rules
* @param second
* the second rules as list of Rules
* @param options
* 1:dependency, 2:essential, 3:prepare, 4:noneDeletionSecondRule,
* 5:printHeader, 6:printResults, 7:silent
*/
public CpaWorker(List<Rule> first, List<Rule> second, Options... options) {
init(first, second, false, false, options);
}
/**
* All rules from first list will be analyzed with all rules from the second
* list. If a List of rules is empty, it means all rules of the Henshin file
* will be analysed!
*
* @param henshin
* Path to the henshin file
* @param first
* the first rule as string array
* @param second
* the second rule as string array
* @param options
* 1:dependency, 2:essential, 3:prepare, 4:noneDeletionSecondRule,
* 5:printHeader, 6:printResults, 7:silent
*/
public CpaWorker(String henshin, String[] first, String[] second, Options... options) {
String r = henshin.substring(0, henshin.lastIndexOf("/") + 1);
String m = henshin.substring(henshin.lastIndexOf("/") + 1, henshin.length());
HenshinResourceSet resourceSet = new HenshinResourceSet(r);
Module module = resourceSet.getModule(m, false);
List<Rule> f = new ArrayList<Rule>();
List<Rule> s = new ArrayList<Rule>();
for (String firstRule : first) {
Rule rule = (Rule) module.getUnit(firstRule);
if (rule == null) {
System.err.println("Rule " + firstRule + " not found");
return;
}
f.add(rule);
}
for (String secondRule : second) {
Rule rule = (Rule) module.getUnit(secondRule);
if (rule == null) {
System.err.println("Rule " + secondRule + " not found");
return;
}
s.add(rule);
}
if (f.isEmpty())
f = new ArrayList<Rule>(s);
if (s.isEmpty())
s = new ArrayList<Rule>(f);
boolean firstAll = false;
boolean secondAll = false;
if (f.isEmpty()) {
firstAll = true;
for (Unit u : module.getUnits())
if (u instanceof Rule)
f.add((Rule) u);
}
if (s.isEmpty()) {
secondAll = true;
for (Unit u : module.getUnits())
if (u instanceof Rule)
s.add((Rule) u);
}
init(f, s, firstAll, secondAll, options);
}
private void init(List<Rule> first, List<Rule> second, boolean firstAll, boolean secondAll, Options... opt) {
if (opt.length != 0)
options = opt[0];
String ff = "", ss = "";
if (firstAll)
ff = "All";
else
for (Rule nameF : first)
ff += (ff.isEmpty() ? "" : ", ") + nameF.getName();
if (secondAll)
ss = "All";
else
for (Rule nameS : second)
ss += (ss.isEmpty() ? "" : ", ") + nameS.getName();
for (Rule r1 : first)
r1 = ConflictAnalysis.prepare(r1);
for (Rule r2 : second)
r2 = ConflictAnalysis.prepare(r2);
CDAOptions o = new CDAOptions();
o.essentialCP = options.is(Options.ESSENTIAL) || options.is(Options.INITIAL);
o.setReduceSameRuleAndSameMatch(false);
o.setIgnoreSameRules(false);
o.setIgnoreMultiplicities(true);
cpa = new CpaByAGG();
NAME = "CPA Tester";
try {
if (options.is(Options.PREPARE)) {
first = RulePreparator.prepareRule(first);
second = RulePreparator.prepareRule(second);
}
if (options.is(Options.NONE_DELETION_SECOND_RULE))
second = NonDeletingPreparator.prepareNoneDeletingsVersionsRules(second);
cpa.init(new HashSet<>(first), new HashSet<>(second), o);
} catch (UnsupportedRuleException e) {
System.err.println(e.getMessage());
}
PrintStream original = System.out;
if (options.is(Options.SILENT)) {
System.setOut(new NullPrintStream());
}
if (options.is(Options.DEPENDENCY))
result = cpa.runDependencyAnalysis();
else
result = cpa.runConflictAnalysis();
if (options.is(Options.SILENT))
System.setOut(original);
if (options.is(Options.PRINT_HEADER) && (!options.is(Options.PRINT_WHEN_RESULT) || !getResult().isEmpty())) {
System.out.println("\n\t\t " + ff + " --> " + ss + "\n\t\t\tCPA "
+ (options.is(Options.ESSENTIAL) ? "Essential" : ""));
print(options + "\n");
}
if (options.is(Options.PRINT_HEADER))
if (options.is(Options.PRINT_RESULT)
&& (!options.is(Options.PRINT_WHEN_RESULT) || !getResult().isEmpty())) {
printResult();
print();
System.out.println();
}
}
private void printResult() {
printCP(getResult());
}
@Override
public Set<CriticalPair> getResult() {
if (result != null)
if (options.is(Options.ESSENTIAL))
return new HashSet<>(result.getEssentialCriticalPairs());
else if (options.is(Options.INITIAL))
return new HashSet<>(result.getInitialCriticalPairs());
else
return new HashSet<>(result.getCriticalPairs());
return new HashSet<>();
}
@Override
public String toString() {
if (!options.is(Options.DEPENDENCY))
return getResult().size() + " Critical Pairs.";
else
return getResult().size() + " Dependency Critical Pairs.";
}
/**
* Print method for CPs
* @param cp to print
* @param errorOut first boolean describes, that result should be printed red. Second boolean prints the result in the consle.
* @return to be printed string
*/
public static String printCP(Set<CriticalPair> cp, boolean... errorOut) {
String result = "";
for (CriticalPair criticalPair : cp) {
criticalPair.getMinimalModel();
String criticalPairKind = "";
if (criticalPair instanceof Conflict) {
criticalPairKind = ((Conflict) criticalPair).getConflictKind().toString();
} else if (criticalPair instanceof Dependency) {
criticalPairKind = ((Dependency) criticalPair).getDependencyKind().toString();
}
String r = "";
for (CriticalElement e : criticalPair.getCriticalElements())
r += ", [" + e + "]";
result += criticalPairKind + ": " + r.substring(2) + "\n";
}
if (errorOut.length <= 1 || errorOut.length > 1 && errorOut[1])
if (errorOut.length == 0 || errorOut.length != 0 && !errorOut[0])
System.out.println(result);
else
System.err.println("\n" + result + "\n");
return result;
}
}
class NullPrintStream extends PrintStream {
public NullPrintStream() {
super(new NullByteArrayOutputStream());
}
private static class NullByteArrayOutputStream extends ByteArrayOutputStream {
@Override
public void write(int b) {
// do nothing
}
@Override
public void write(byte[] b, int off, int len) {
// do nothing
}
@Override
public void writeTo(OutputStream out) throws IOException {
// do nothing
}
}
}