blob: 5d164aa0413e10e19a507851e7fca8fdad3563c7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Willink Transformations and others.
* 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:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvtr2qvtc.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.qvtd.compiler.internal.qvtr2qvtc.QVTr2QVTcRelations;
import org.eclipse.qvtd.compiler.internal.qvtr2qvtc.QvtrToQvtcTransformation;
import org.eclipse.qvtd.compiler.internal.qvtr2qvtc.Rule;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtcore.Mapping;
import org.eclipse.qvtd.pivot.qvtcorebase.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.CoreDomain;
import org.eclipse.qvtd.pivot.qvtcorebase.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtrelation.DomainPattern;
import org.eclipse.qvtd.pivot.qvtrelation.Relation;
import org.eclipse.qvtd.pivot.qvtrelation.RelationCallExp;
import org.eclipse.qvtd.pivot.qvtrelation.RelationDomain;
import org.eclipse.qvtd.pivot.qvtrelation.RelationalTransformation;
import org.eclipse.qvtd.pivot.qvttemplate.ObjectTemplateExp;
public class InvokedRelationToMappingForEnforcement extends AbstractRule {
private static class Factory extends AbstractRule.Factory
{
public @Nullable Rule createRule(@NonNull QvtrToQvtcTransformation transformation, @NonNull EObject eo) {
Rule rule = null;
if (eo instanceof Relation) {
rule = new InvokedRelationToMappingForEnforcement(transformation, (Relation) eo);
Rule tracedRule = transformation.getRecord(rule.getRuleBindings());
if (tracedRule != null)
rule = tracedRule;
}
return rule;
}
@Override
public @Nullable Rule createRule(
@NonNull QvtrToQvtcTransformation transformation,
@NonNull List<EObject> eos) {
return null;
}
}
private class SubRecord
{
@NonNull private Relation ir;
@NonNull private RelationDomain rd;
// @NonNull private TypedModel dir;
@NonNull private String tmn;
@NonNull private List<org.eclipse.ocl.pivot.Package> up;
@NonNull private String dn;
@NonNull private List<Variable> domainVars;
@NonNull private ObjectTemplateExp te;
@NonNull private Variable tev;
@NonNull private List<RelationDomain> rOppositeDomains;
@NonNull private RelationCallExp ri;
// Core
private BottomPattern mb;
private String irn;
private Mapping m;
private CoreDomain md;
private TypedModel mdir;
private GuardPattern dg;
private BottomPattern db;
private RealizedVariable tcv;
private GuardPattern mg;
public SubRecord(@NonNull RelationCallExp ri, @NonNull Relation ir,
@NonNull String irn, @NonNull RelationDomain rd,
@NonNull TypedModel dir, @NonNull String tmn,
@NonNull String dn, @NonNull List<org.eclipse.ocl.pivot.Package> up,
@NonNull List<Variable> domainVars,
@NonNull ObjectTemplateExp te, @NonNull Variable tev,
@NonNull List<RelationDomain> rOppositeDomains) {
this.ri = ri;
this.ir = ir;
this.irn = irn;
this.rd = rd;
// this.dir = dir;
this.tmn = tmn;
this.dn = dn;
this.up = up;
this.domainVars = domainVars;
this.te = te;
this.tev = tev;
this.rOppositeDomains = rOppositeDomains;
}
}
// Relations
private static final @NonNull RuleBindings.KeySet RULE_BINDINGS = new RuleBindings.KeySet();
private static final @NonNull RuleBindings.RuleKey<Relation> RELATIONS_r = RULE_BINDINGS.createRoot((Relation)null, "r");
public Transformation mt;
public static final @NonNull Rule.Factory FACTORY = new Factory();
protected final @NonNull List<SubRecord> subRecords = new ArrayList<SubRecord>();
private String rn;
protected InvokedRelationToMappingForEnforcement(
@NonNull QvtrToQvtcTransformation transformation, Relation r) {
super(transformation);
ruleBindings.put(RELATIONS_r, r);
}
/* (non-Javadoc)
* @see org.eclipse.qvtd.build.qvtrtoqvtc.impl.AbstractRule#check()
*/
@Override
public void check() {
Relation r = ruleBindings.get(RELATIONS_r);
assert (r != null);
rn = r.getName();
if (!r.isIsTopLevel()) {
List<RelationCallExp> ris = transformation.getRelationCallExpsForRelation(r);
if (ris != null) {
for (RelationCallExp ri : ris) {
assert ri != null;
Relation ir = transformation.getInvokingRelationForRelationCallExp(ri);
assert ir != null;
String irn = ir.getName();
assert irn != null;
for (Domain d : r.getDomain()) {
RelationDomain rd = (RelationDomain) d;
DomainPattern dp = rd.getPattern().get(0);
assert dp != null;
if (rd.isIsEnforceable() && dp.getTemplateExpression() instanceof ObjectTemplateExp) {
//Mapping m = QVTcoreFactory.eINSTANCE.createMapping();
String dn = rd.getName();
assert dn != null;
TypedModel dir = rd.getTypedModel();
String tmn = dir.getName();
assert tmn != null;
List<org.eclipse.ocl.pivot.Package> up = dir.getUsedPackage();
assert up != null;
List<Variable> domainVars = dp.getBindsTo();
ObjectTemplateExp te = (ObjectTemplateExp) dp.getTemplateExpression();
Variable tev = te.getBindsTo();
assert tev != null;
List<RelationDomain> rOppositeDomains = new ArrayList<RelationDomain>();
Iterator<Domain> it = r.getDomain().iterator();
while (it.hasNext()) {
rOppositeDomains.add((RelationDomain) it.next());
}
rOppositeDomains.remove(rd);
subRecords.add(new SubRecord(ri, ir, irn, rd, dir, tmn, dn, up, domainVars, te, tev, rOppositeDomains));
}
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.qvtd.build.qvtrtoqvtc.impl.AbstractRule#instantiateOutput()
*/
@Override
public void instantiateOutput() {
Relation r = ruleBindings.get(RELATIONS_r);
assert (r != null) && (mt != null);
for (SubRecord subRecord : subRecords) {
final Transformation mt2 = mt;
if (mt2 != null) {
Mapping m = transformation.findMapping(rn+'_'+subRecord.irn+'_'+subRecord.dn, mt2);
assert m != null;
subRecord.m = m;
GuardPattern mg = transformation.findGuardPattern(m);
assert mg != null;
subRecord.mg = mg;
BottomPattern mb = transformation.findBottomPattern(m);
assert mb != null;
subRecord.mb = mb;
CoreDomain md = transformation.findCoreDomain(subRecord.dn, m);
assert md != null;
subRecord.md = md;
TypedModel mdir = null;
for (TypedModel tm : mt2.getModelParameter()) {
if (tm.getName() == subRecord.tmn) {
if (tm.getUsedPackage().equals(subRecord.up)) {
mdir = tm;
break;
}
}
}
assert mdir != null;
subRecord.mdir = mdir;
GuardPattern dg = transformation.findGuardPattern(md);
assert dg != null;
subRecord.dg = dg;
BottomPattern db = transformation.findBottomPattern(md);
assert db != null;
subRecord.db = db;
}
}
}
/* (non-Javadoc)
* @see org.eclipse.qvtd.build.qvtrtoqvtc.impl.AbstractRule#setAttributes()
*/
@Override
public void setAttributes() {
for (SubRecord subRecord : subRecords) {
BottomPattern mb = subRecord.mb;
RealizedVariable tcv = subRecord.tcv;
assert (mb != null) && (tcv != null);
mb.getRealizedVariable().add(tcv);
//mb.getVariable().addAll(mbvars);
CoreDomain md = subRecord.md;
assert (md != null);
md.setTypedModel(subRecord.mdir);
md.setIsEnforceable(true);
}
}
/* (non-Javadoc)
* @see org.eclipse.qvtd.build.qvtrtoqvtc.impl.AbstractRule#when()
*/
@Override
public boolean when() {
Relation r = ruleBindings.get(RELATIONS_r);
assert r != null;
RelationalTransformation rt = (RelationalTransformation) r.getTransformation();
assert rt != null;
// This is the same code the factory has, and IMHO its better encapsulated by the factory.
// The real issue is that the bindings needs a rule and to get a record (rule) we need a binding
//Rule whenRule = RelationalTransformationToMappingTransformation.FACTORY.createRule(transformation, rt);
RelationalTransformationToMappingTransformation whenRule = new RelationalTransformationToMappingTransformation(transformation, rt);
RuleBindings whenBindings = whenRule.getRuleBindings();
RelationalTransformationToMappingTransformation whenRuleRecord = (RelationalTransformationToMappingTransformation) transformation.getRecord(whenBindings);
if (whenRuleRecord != null && whenRuleRecord.hasExecuted()) {
mt = (Transformation) whenRuleRecord.getCore();
assert mt != null;
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.qvtd.build.qvtrtoqvtc.impl.AbstractRule#where()
*/
@Override
public void where() {
QVTr2QVTcRelations relations = new QVTr2QVTcRelations(transformation);
Relation r = ruleBindings.get(RELATIONS_r);
assert r != null;
Set<Variable> allDomainVars = relations.getAllDomainVars(r);
Set<Variable> whereVars = new HashSet<Variable>();
Set<Variable> whenVars = new HashSet<Variable>();
Set<Predicate> rpSet = new HashSet<Predicate>();
if (r.getWhen() != null) {
whenVars.addAll(r.getWhen().getBindsTo());
}
if (r.getWhere() != null) {
rpSet.addAll(relations.rejectRelationCallPredicates(r.getWhere().getPredicate()));
whereVars.addAll(r.getWhere().getBindsTo());
}
Set<Variable> sharedDomainVars = relations.getSharedDomainVars(r);
Set<Variable> unsharedWhereVars = new HashSet<Variable>(whereVars);
unsharedWhereVars.removeAll(whenVars);
unsharedWhereVars.removeAll(allDomainVars);
unsharedWhereVars.addAll(sharedDomainVars);
Set<Variable> unsharedWhenVars = new HashSet<Variable>(whenVars);
unsharedWhenVars.removeAll(allDomainVars);
for (SubRecord subRecord : subRecords) {
Set<Variable> oppositeDomainVars = new HashSet<Variable>();
for (Domain d : subRecord.rOppositeDomains) {
if (((RelationDomain)d).getPattern() != null) {
oppositeDomainVars.addAll(((RelationDomain)d).getPattern().get(0).getBindsTo());
}
}
Set<Variable> domainBottomUnSharedVars = new HashSet<Variable>(subRecord.domainVars);
domainBottomUnSharedVars.removeAll(whenVars);
domainBottomUnSharedVars.removeAll(sharedDomainVars);
domainBottomUnSharedVars.remove(subRecord.tev);
Set<Predicate> predicatesWithVarBindings = relations.filterOutPredicatesThatReferToVars(rpSet, domainBottomUnSharedVars);
Set<Predicate> predicatesWithoutVarBindings = new HashSet<Predicate>(rpSet);
predicatesWithoutVarBindings.removeAll(predicatesWithVarBindings);
Set<Variable> domainTopVars = new HashSet<Variable>(subRecord.domainVars);
domainTopVars.retainAll(whenVars);
domainTopVars.add(subRecord.tev);
Mapping m = subRecord.m;
assert m!= null;
GuardPattern mg = subRecord.mg;
assert mg != null;
BottomPattern mb = subRecord.mb;
assert mb != null;
GuardPattern dg = subRecord.dg;
assert dg != null;
BottomPattern db = subRecord.db;
assert db != null;
// Relation Calls
// T6
RealizedVariable tcv = relations.doRelationDomainToTraceClassVar(r, subRecord.rd, mb);
assert tcv != null;
subRecord.tcv = tcv;
// T5
relations.doRPredicateSetToMBPredicateSet(new ArrayList<Predicate>(predicatesWithVarBindings), mb);
relations.doRVarSetToDGVarSet(new ArrayList<Variable>(domainTopVars), dg);
//T4
relations.doRVarSetToMBVarSet(new ArrayList<Variable>(unsharedWhereVars), mb);
//T3
relations.doIROppositeDomainsToMappingForEnforcement(r, subRecord.ir, subRecord.rd, m);
relations.doRInvokerToMGuard(subRecord.ir, subRecord.ri, r, mg);
relations.doROppositeDomainVarsToTraceClassProps(r, subRecord.rd, subRecord.te, oppositeDomainVars, mb);
relations.doRWhenPatternToMGuardPattern(r, mg);
relations.doRDomainToMDBottomForEnforcement(r, subRecord.rd, subRecord.te, predicatesWithoutVarBindings, domainBottomUnSharedVars, db);
relations.doRRelImplToMBottomEnforcementOperation(r, subRecord.rd, mb);
}
}
}