/**
* <copyright>
* </copyright>
*
* $Id$
*/
package tefkat.engine.runtime.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.EDataTypeUniqueEList;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.EObjectContainmentWithInverseEList;
import org.eclipse.emf.ecore.util.InternalEList;
import tefkat.config.TefkatConfig.TefkatConfigFactory;
import tefkat.engine.runtime.NamespaceDeclaration;
import tefkat.engine.runtime.PatternDefn;
import tefkat.engine.runtime.RuntimePackage;
import tefkat.engine.runtime.StratificationException;
import tefkat.engine.runtime.TRule;
import tefkat.engine.runtime.TefkatException;
import tefkat.engine.runtime.Term;
import tefkat.engine.runtime.Transformation;
import tefkat.engine.runtime.VarScope;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Transformation</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link tefkat.engine.runtime.impl.TransformationImpl#getTRule <em>TRule</em>}</li>
* <li>{@link tefkat.engine.runtime.impl.TransformationImpl#getImportedPackages <em>Imported Packages</em>}</li>
* <li>{@link tefkat.engine.runtime.impl.TransformationImpl#getNamespaceDeclarations <em>Namespace Declarations</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class TransformationImpl extends PatternScopeImpl implements Transformation {
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final String copyright = "Copyright michael lawley 2004";
final private Map sourceTermsMap = new HashMap();
final private Map targetTermsMap = new HashMap();
final private Map overrideTermsMap = new HashMap();
/**
* The cached value of the '{@link #getTRule() <em>TRule</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTRule()
* @generated
* @ordered
*/
protected EList tRule = null;
/**
* The cached value of the '{@link #getImportedPackages() <em>Imported Packages</em>}' attribute list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getImportedPackages()
* @generated
* @ordered
*/
protected EList importedPackages = null;
/**
* The cached value of the '{@link #getNamespaceDeclarations() <em>Namespace Declarations</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getNamespaceDeclarations()
* @generated
* @ordered
*/
protected EList namespaceDeclarations = null;
/**
* Maps from a TRule to a Collection of the TRules that supersede it
* with respect to <em>this</em> Transformation.
*/
private Map invertedSupersedesMap = new HashMap();
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected TransformationImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected EClass eStaticClass() {
return RuntimePackage.Literals.TRANSFORMATION;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList getTRule() {
if (tRule == null) {
tRule = new EObjectContainmentWithInverseEList(TRule.class, this, RuntimePackage.TRANSFORMATION__TRULE, RuntimePackage.TRULE__TRANSFORMATION);
}
return tRule;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList getImportedPackages() {
if (importedPackages == null) {
importedPackages = new EDataTypeUniqueEList(String.class, this, RuntimePackage.TRANSFORMATION__IMPORTED_PACKAGES);
}
return importedPackages;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList getNamespaceDeclarations() {
if (namespaceDeclarations == null) {
namespaceDeclarations = new EObjectContainmentEList(NamespaceDeclaration.class, this, RuntimePackage.TRANSFORMATION__NAMESPACE_DECLARATIONS);
}
return namespaceDeclarations;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public List[] getStrata() throws TefkatException {
// FIXME handle inheritance of tracking classes
Collection rules = getTRule();
Collection patterns = getPatternDefn();
final IntMap levelMapping = new IntMap(2 * (rules.size() + patterns.size()) + 1);
final Stratifier stratifier = new Stratifier();
for (final Iterator ruleItr = rules.iterator(); ruleItr.hasNext(); ) {
TRule rule = (TRule) ruleItr.next();
Collection goal = rule.getGoal();
levelMapping.putInt(rule, 0);
for (final Iterator termItr = goal.iterator(); termItr.hasNext(); ) {
Term term = (Term) termItr.next();
stratifier.check(rule, term);
}
}
for (final Iterator patternItr = patterns.iterator(); patternItr.hasNext(); ) {
PatternDefn pattern = (PatternDefn) patternItr.next();
levelMapping.putInt(pattern, 0);
stratifier.check(pattern, pattern.getTerm());
}
List less = new ArrayList();
List lesseq = new ArrayList();
// fireInfo(" finding dependencies...");
// FIXME - handle subtyping and stratification
for (final Iterator itr = stratifier.readers.entrySet().iterator(); itr.hasNext(); ) {
Map.Entry entry = (Map.Entry) itr.next();
Object tc = entry.getKey();
Set set = (Set) entry.getValue();
for (final Iterator sItr = set.iterator(); sItr.hasNext(); ) {
Object scope = sItr.next();
lesseq.add(new Object[] {tc, scope});
// System.out.println("PR: " + tc + " <= " + scope);
}
}
for (final Iterator itr = stratifier.writers.entrySet().iterator(); itr.hasNext(); ) {
Map.Entry entry = (Map.Entry) itr.next();
Object tc = entry.getKey();
Set set = (Set) entry.getValue();
for (final Iterator sItr = set.iterator(); sItr.hasNext(); ) {
Object scope = sItr.next();
lesseq.add(new Object[] {scope, tc});
// System.out.println("PW: " + scope + " <= " + tc);
}
}
for (final Iterator itr = stratifier.neg_readers.entrySet().iterator(); itr.hasNext(); ) {
Map.Entry entry = (Map.Entry) itr.next();
Object tc = entry.getKey();
Set set = (Set) entry.getValue();
for (final Iterator sItr = set.iterator(); sItr.hasNext(); ) {
Object scope = sItr.next();
less.add(new Object[] {tc, scope});
// System.out.println("NR: " + tc + " < " + scope);
}
}
for (final Iterator itr = stratifier.neg_writers.entrySet().iterator(); itr.hasNext(); ) {
Map.Entry entry = (Map.Entry) itr.next();
Object tc = entry.getKey();
Set set = (Set) entry.getValue();
for (final Iterator sItr = set.iterator(); sItr.hasNext(); ) {
Object scope = sItr.next();
less.add(new Object[] {tc, scope});
// System.out.println("NW: " + tc + " < " + scope);
}
}
// fireInfo(" populating strata...");
boolean done = false;
int maxLevel = 0;
for (boolean acyclic = true; !done && acyclic && maxLevel <= levelMapping.size(); ) {
done = true;
acyclic = false;
for (final Iterator lItr = less.iterator(); lItr.hasNext(); ) {
Object[] pair = (Object[]) lItr.next();
// System.err.println(pair);
// System.err.println(pair[0]);
// System.err.println(pair[1]);
int lidx = levelMapping.getInt(pair[0]);
int gidx = levelMapping.getInt(pair[1]);
if (lidx >= gidx) {
// System.out.println("fix " + getName(pair[0]) + " >= " + getName(pair[1]) + ": " + lidx + " " + gidx + " -> " + (lidx + 1));
levelMapping.putInt(pair[1], lidx + 1);
if (lidx >= maxLevel) {
maxLevel = lidx + 1;
}
// levelMapping.put(pair[1], maxLevel);
done = false;
}
acyclic |= (0 == lidx);
}
for (final Iterator lItr = lesseq.iterator(); lItr.hasNext(); ) {
Object[] pair = (Object[]) lItr.next();
int lidx = levelMapping.getInt(pair[0]);
int gidx = levelMapping.getInt(pair[1]);
if (lidx > gidx) {
// System.out.println("fix " + getName(pair[0]) + " > " + getName(pair[1]) + ": " + lidx + " " + gidx + " -> " + lidx);
levelMapping.putInt(pair[1], lidx);
if (lidx > maxLevel) {
maxLevel = lidx;
}
// levelMapping.put(pair[1], maxLevel);
done = false;
}
acyclic |= (0 == lidx);
}
}
List[] strata = new List[maxLevel + 1];
for (int level = 0; level < strata.length; level++) {
strata[level] = new ArrayList();
}
for (final Iterator itr = rules.iterator(); itr.hasNext(); ) {
Object scope = itr.next();
int level = levelMapping.getInt(scope);
// System.out.println(level + ": " + scope);
strata[level].add(scope);
}
for (final Iterator itr = patterns.iterator(); itr.hasNext(); ) {
Object scope = itr.next();
int level = levelMapping.getInt(scope);
// System.out.println(level + ": " + scope);
strata[level].add(scope);
}
if (!done) {
String s = orderString(maxLevel, levelMapping, less, lesseq);
throw new StratificationException(strata, "Rules are not stratifiable: " + s);
}
return strata;
}
private String orderString(int maxLevel, IntMap levelMapping, List less, List lesseq) {
StringBuffer sb = new StringBuffer();
for (final Iterator lItr = less.iterator(); lItr.hasNext(); ) {
Object[] pair = (Object[]) lItr.next();
int lidx = levelMapping.getInt(pair[0]);
int gidx = levelMapping.getInt(pair[1]);
if (maxLevel == lidx && maxLevel == gidx) {
sb.append(", ");
sb.append(getName(pair[0]));
sb.append(" < ");
sb.append(getName(pair[1]));
}
}
for (final Iterator lItr = lesseq.iterator(); lItr.hasNext(); ) {
Object[] pair = (Object[]) lItr.next();
int lidx = levelMapping.getInt(pair[0]);
int gidx = levelMapping.getInt(pair[1]);
if (maxLevel == lidx && maxLevel == gidx) {
sb.append(", ");
sb.append(getName(pair[0]));
sb.append(" <= ");
sb.append(getName(pair[1]));
}
}
return sb.toString();
}
private String getName(Object obj) {
if (obj instanceof EClass) {
return ((EClass) obj).getName();
} else if (obj instanceof VarScope) {
return ((VarScope) obj).getName();
} else {
return String.valueOf(obj);
}
}
static class IntMap extends HashMap {
private static final long serialVersionUID = -935093331755581828L;
public IntMap(int size) {
super(size);
}
public void putInt(Object key, int value) {
put(key, Integer.valueOf(value));
}
int getInt(Object key) {
final Integer value = ((Integer) get(key));
if (null != value) {
return value.intValue();
} else {
return 0; // default value
}
}
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public void addSupersedes(TRule superseder, TRule superseded) {
Collection supersedingRules = getSupersedingRules(superseded);
supersedingRules.add(superseder);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public void removeSupersedes(TRule superseder, TRule superseded) {
Collection supersedingRules = (Collection) invertedSupersedesMap.get(superseded);
if (null == supersedingRules) {
throw new Error("invertedSupersedesMap should contain entry for " + superseded);
}
supersedingRules.remove(superseder);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public Collection getSupersedingRules(TRule superseded) {
Collection supersedingRules = (Collection) invertedSupersedesMap.get(superseded);
if (null == supersedingRules) {
supersedingRules = new ArrayList();
invertedSupersedesMap.put(superseded, supersedingRules);
}
return supersedingRules;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case RuntimePackage.TRANSFORMATION__TRULE:
return ((InternalEList)getTRule()).basicAdd(otherEnd, msgs);
}
return super.eInverseAdd(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case RuntimePackage.TRANSFORMATION__TRULE:
return ((InternalEList)getTRule()).basicRemove(otherEnd, msgs);
case RuntimePackage.TRANSFORMATION__NAMESPACE_DECLARATIONS:
return ((InternalEList)getNamespaceDeclarations()).basicRemove(otherEnd, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case RuntimePackage.TRANSFORMATION__TRULE:
return getTRule();
case RuntimePackage.TRANSFORMATION__IMPORTED_PACKAGES:
return getImportedPackages();
case RuntimePackage.TRANSFORMATION__NAMESPACE_DECLARATIONS:
return getNamespaceDeclarations();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case RuntimePackage.TRANSFORMATION__TRULE:
getTRule().clear();
getTRule().addAll((Collection)newValue);
return;
case RuntimePackage.TRANSFORMATION__IMPORTED_PACKAGES:
getImportedPackages().clear();
getImportedPackages().addAll((Collection)newValue);
return;
case RuntimePackage.TRANSFORMATION__NAMESPACE_DECLARATIONS:
getNamespaceDeclarations().clear();
getNamespaceDeclarations().addAll((Collection)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void eUnset(int featureID) {
switch (featureID) {
case RuntimePackage.TRANSFORMATION__TRULE:
getTRule().clear();
return;
case RuntimePackage.TRANSFORMATION__IMPORTED_PACKAGES:
getImportedPackages().clear();
return;
case RuntimePackage.TRANSFORMATION__NAMESPACE_DECLARATIONS:
getNamespaceDeclarations().clear();
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean eIsSet(int featureID) {
switch (featureID) {
case RuntimePackage.TRANSFORMATION__TRULE:
return tRule != null && !tRule.isEmpty();
case RuntimePackage.TRANSFORMATION__IMPORTED_PACKAGES:
return importedPackages != null && !importedPackages.isEmpty();
case RuntimePackage.TRANSFORMATION__NAMESPACE_DECLARATIONS:
return namespaceDeclarations != null && !namespaceDeclarations.isEmpty();
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public String toString() {
return "TRANSFORMATION " + getName();
}
Map getSourceTermsMap() {
return sourceTermsMap;
}
Map getTargetTermsMap() {
return targetTermsMap;
}
Map getOverrideTermsMap() {
return overrideTermsMap;
}
} //TransformationImpl