/*
* Copyright (c) 2005- michael lawley and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation
* which accompanies this distribution, and is available by writing to
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Contributors:
* michael lawley
*
*
*
*/
package tefkat.engine;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import tefkat.model.TRule;
import tefkat.model.Transformation;
import tefkat.model.impl.TermImpl;
/**
* By re-writing all the rules taking in to account the extends and supersedes
* relationships we can construct a single goal (with asserts) that can be
* evaluated to perform the transformation.
*
* Note that this requires us to be smart during evaluation and to re-expand the
* tree after asserts have been performed. This will also include the tricky
* case of negation-as-failure having to be undone!
*
* For R1: T1 <- S1, R2: T2 <- S2, R3: T3 <- S3 where R2 extends R1 and R3
* supersedes R1, construct:
*
* <pre>
*
* sourceXMap{R1 => [S1], R2 => [S2, S1], R3 => [S3]}
* sourceSMap{R1 => [sourceXMap(R1), ˜sourceXMap(R3)],
* R2 => [sourceXMap(R2)],
* R3 => [sourceXMap(R3)]}
* targetMap{R1 => [T1], R2 => [T2, T1], R3 => [T3]}
*
* </pre>
*
* Note, we need to include T1 in the targetMap for R2 since R1 might be
* abstract, so we can't rely on T1 having already been established.
*/
public class TransformationEvaluator {
private Map sourceXMap = new HashMap();
private Map sourceSMap = new HashMap();
private Map targetMap = new HashMap();
public TransformationEvaluator() {
}
public void evaluate(Transformation transformation, Binding context) {
buildSourceGoals(transformation);
buildTargetGoals(transformation);
// RTTerm goal = buildTransformationGoal(transformation);
// resolve(goal, context);
}
/**
* For each TRule that extends a TRule, accumulate its source terms
*/
private void buildSourceGoals(Transformation transformation) {
for (Iterator ruleItr = transformation.getTRule().iterator(); ruleItr
.hasNext();) {
TRule rule = (TRule) ruleItr.next();
collectSourceXTerms(rule);
}
for (Iterator ruleItr = transformation.getTRule().iterator(); ruleItr
.hasNext();) {
TRule rule = (TRule) ruleItr.next();
collectSourceSTerms(rule);
}
}
/**
* Construct a composite list of source terms from this rule and all of the
* rules it extends.
*
* TODO Handle TRuleVar extension (maybe we can avoid this by just using
* direct references from the VarUses and relaxing the scope rules?)
*/
private void collectSourceXTerms(TRule rule) {
if (!sourceXMap.containsKey(rule)) {
List terms = new ArrayList();
terms.add(rule.getSrc());
for (Iterator itr = rule.getExtended().iterator(); itr.hasNext();) {
TRule extRule = (TRule) itr.next();
collectSourceXTerms(extRule);
terms.addAll((List) sourceXMap.get(extRule));
}
sourceXMap.put(rule, terms);
}
}
/**
* Construct a composite list of source terms from this rule and all of the
* rules it supersedes.
*
* TODO Handle TRuleVar extension (maybe we can avoid this by just using
* direct references from the VarUses and relaxing the scope rules?)
*
* TODO FIXME check transitive superseding semantics
*/
private void collectSourceSTerms(TRule rule) {
if (!sourceSMap.containsKey(rule)) {
List terms = new ArrayList();
terms.addAll((List) sourceXMap.get(rule));
// for (Iterator itr = rule.getSuperseder().iterator(); itr.hasNext();) {
// TRule supRule = (TRule) itr.next();
// RTTerm rtNotTerm = new RTNotTerm();
// rtNotTerm.getTerms().addAll((List) sourceXMap.get(supRule));
// terms.add(rtNotTerm);
// }
sourceSMap.put(rule, terms);
} else {
// should not get here
}
}
private void buildTargetGoals(Transformation transformation) {
for (Iterator ruleItr = transformation.getTRule().iterator(); ruleItr
.hasNext();) {
TRule rule = (TRule) ruleItr.next();
collectTargetTerms(rule);
}
}
/**
* Construct a composite list of target terms from this rule and all of the
* rules it extends.
*
* TODO Handle TRuleVar extension (maybe we can avoid this by just using
* direct references from the VarUses and relaxing the scope rules?)
*/
private void collectTargetTerms(TRule rule) {
if (!targetMap.containsKey(rule)) {
RTTerm rtAssertTerm = new RTAssertTerm();
List terms = rtAssertTerm.getTerms();
terms.addAll(rule.getTgt());
for (Iterator itr = rule.getExtended().iterator(); itr.hasNext();) {
TRule extRule = (TRule) itr.next();
collectTargetTerms(extRule);
terms.addAll(((RTTerm) targetMap.get(extRule)).getTerms());
}
targetMap.put(rule, rtAssertTerm);
}
}
// private RTTerm buildTransformationGoal(Transformation transformation) {
// RTTerm rtGoal = new RTOrTerm();
// List goalTerms = rtGoal.getTerms();
// for (Iterator ruleItr = transformation.getTRule().iterator(); ruleItr
// .hasNext();) {
// TRule rule = (TRule) ruleItr.next();
// if (true/* !rule.isAbstract() */) { // TODO add abstract flag to model
// RTTerm rtRule = new RTAndTerm();
// List ruleTerms = rtRule.getTerms();
// ruleTerms.addAll((List) sourceSMap.get(rule));
// ruleTerms.add(targetMap.get(rule));
// goalTerms.add(rtRule);
// }
// }
//
// return rtGoal;
// }
}
abstract class RTTerm extends TermImpl {
private List terms = null;
public List getTerms() {
if (null == terms) {
terms = new ArrayList();
}
return terms;
}
}
class RTOrTerm extends RTTerm {
}
class RTAndTerm extends RTTerm {
}
/**
* Represents the negation of the conjunction of contained terms.
*/
class RTNotTerm extends RTTerm {
}
/**
* Represents the assertion of the contained term.
*/
class RTAssertTerm extends RTTerm {
}