/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
package de.tub.tfs.henshin.analysis;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.henshin.model.ConditionalUnit;
import org.eclipse.emf.henshin.model.HenshinFactory;
import org.eclipse.emf.henshin.model.IndependentUnit;
import org.eclipse.emf.henshin.model.PriorityUnit;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.emf.henshin.model.SequentialUnit;
import org.eclipse.emf.henshin.model.Unit;
import org.eclipse.emf.henshin.model.impl.ConditionalUnitImpl;
import org.eclipse.emf.henshin.model.impl.HenshinPackageImpl;
import org.eclipse.emf.henshin.model.impl.IndependentUnitImpl;
import org.eclipse.emf.henshin.model.impl.PriorityUnitImpl;
import org.eclipse.emf.henshin.model.impl.RuleImpl;
import org.eclipse.emf.henshin.model.impl.SequentialUnitImpl;
public class ControlFlowRelation {
private abstract class ControlFlowHandler<T extends Unit>{
List<Unit> localPriorRules = new LinkedList<Unit>();
public abstract HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,T t, List<Unit> globalPriorRules);
}
private Unit emfUnit;
private static HashMap<Class,ControlFlowHandler> handler = new HashMap<Class, ControlFlowRelation.ControlFlowHandler>();
private List<String> errors = new LinkedList<String>();
private List<Unit> priorRules = new LinkedList<Unit>();
private HashSet<Pair<Unit,Unit>> cfr = new HashSet<Pair<Unit,Unit>>();
private void initHandler() {
if (!handler.isEmpty())
return;
handler.put(RuleImpl.class, new ControlFlowHandler<Rule>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,Rule t, List<Unit> globalPriorRules) {
localPriorRules.clear();
HashSet<Pair<Unit,Unit>> cfr = new HashSet<Pair<Unit,Unit>>();
List<Unit> l = globalPriorRules;
for (Unit prior : l){
cfr.add(new Pair<Unit,Unit>(prior, t));
}
localPriorRules.add(t);
globalPriorRules.add(t);
return cfr;
}
});
handler.put(IndependentUnitImpl.class, new ControlFlowHandler<IndependentUnit>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,IndependentUnit t, List<Unit> globalPriorRules) {
localPriorRules.clear();
HashSet<Pair<Unit,Unit>> cfr = new HashSet<Pair<Unit,Unit>>();
EList<Unit> subUnits = t.getSubUnits();
List<List<Unit>> priorUnits = new LinkedList<List<Unit>>();
for (Unit unit : subUnits) {
cfr.addAll( ControlFlowRelation.handler.get(unit.getClass()).handle(r, unit, new LinkedList<Unit>( globalPriorRules) ) );
priorUnits.add(new LinkedList<Unit>( ControlFlowRelation.handler.get(unit.getClass()).localPriorRules));
//localPriorRules.addAll(ControlFlowRelation.handler.get(unit.getClass()).localPriorRules);
}
for (List<Unit> list : priorUnits) {
cfr.addAll(merge(localPriorRules,list,true));
localPriorRules.addAll(list);
}
globalPriorRules.addAll(localPriorRules);
return cfr;
}
});
handler.put(SequentialUnitImpl.class, new ControlFlowHandler<SequentialUnit>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,SequentialUnit t, List<Unit> globalPriorRules) {
localPriorRules.clear();
HashSet<Pair<Unit,Unit>> cfr = new HashSet<Pair<Unit,Unit>>();
List<Unit> subUnits = t.getSubUnits();
for (Unit sub : subUnits) {
cfr.addAll(r.handler.get(sub.getClass()).handle(r, sub, globalPriorRules));
localPriorRules.addAll(r.handler.get(sub.getClass()).localPriorRules);
globalPriorRules.addAll(r.handler.get(t.getClass()).localPriorRules);
}
return cfr;
}
});
handler.put(PriorityUnitImpl.class, new ControlFlowHandler<PriorityUnit>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,PriorityUnit t, List<Unit> globalPriorRules) {
throw new UnsupportedOperationException();
}
});
/* handler.put(AmalgamationUnitImpl.class, new ControlFlowHandler<AmalgamationUnit>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,AmalgamationUnit t, List<Unit> globalPriorRules) {
throw new UnsupportedOperationException();
}
});
handler.put(CountedUnitImpl.class, new ControlFlowHandler<CountedUnit>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,CountedUnit t, List<Unit> globalPriorRules) {
throw new UnsupportedOperationException();
}
});
*/
handler.put(ConditionalUnitImpl.class, new ControlFlowHandler<ConditionalUnit>() {
@Override
public HashSet<Pair<Unit,Unit>> handle(ControlFlowRelation r,ConditionalUnit t, List<Unit> globalPriorRules) {
throw new UnsupportedOperationException();
}
});
}
public ControlFlowRelation(Unit tu) {
this.initHandler();
this.emfUnit = tu;
this.cfr.addAll( handler.get(tu.getClass()).handle(this,tu, priorRules));
}
/**
* @param args
*/
public static void main(String[] args) {
HenshinPackageImpl.init();
IndependentUnit u1 = HenshinFactory.eINSTANCE.createIndependentUnit();
SequentialUnit s1 = HenshinFactory.eINSTANCE.createSequentialUnit();
Unit u2 = HenshinFactory.eINSTANCE.createRule();
u2.setName("r1");
Unit u3 = HenshinFactory.eINSTANCE.createRule();
u3.setName("r2");
Unit u4 = HenshinFactory.eINSTANCE.createRule();
u4.setName("r3");
Unit u5 = HenshinFactory.eINSTANCE.createRule();
u5.setName("r4");
u1.getSubUnits().add(u2);
u1.getSubUnits().add(u3);
s1.getSubUnits().add(u4);
s1.getSubUnits().add(u1);
s1.getSubUnits().add(u5);
ControlFlowRelation r1 = new ControlFlowRelation(s1);
System.out.println(Arrays.deepToString(r1.cfr.toArray()));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static LinkedList<Object> flatten(int exclude, List<?> obj){
LinkedList<Object> list = new LinkedList<Object>();
int count = 0;
for (Object object : obj) {
if (count++ == exclude)
continue;
if (object instanceof Collection){
list.addAll((Collection) object);
} else {
list.add(object);
}
}
return list;
}
private static HashSet<Pair<Unit, Unit>> merge(
Collection<Unit> mainPrior,
Collection<Unit> subPrior,
boolean bidirectional) {
HashSet<Pair<Unit, Unit>> subCFR = new HashSet<Pair<Unit,Unit>>();
for (Unit r2 : subPrior) {
for (Unit r1 : mainPrior) {
subCFR.add(new Pair<Unit,Unit>(r1,r2));
if (bidirectional)
subCFR.add(new Pair<Unit,Unit>(r2,r1));
}
}
return subCFR;
}
}