/*******************************************************************************
* 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.tgg.interpreter.impl;
import java.util.HashMap;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.henshin.interpreter.matching.constraints.DomainSlot;
import org.eclipse.emf.henshin.interpreter.matching.constraints.UnaryConstraint;
import org.eclipse.emf.henshin.model.Attribute;
import org.eclipse.emf.henshin.model.Node;
import org.eclipse.emf.henshin.model.Rule;
import de.tub.tfs.henshin.tgg.TAttribute;
import de.tub.tfs.henshin.tgg.TNode;
import de.tub.tfs.henshin.tgg.interpreter.util.RuleUtil;
/**
* This class is for checking the correct mapping in a execution cycle of FTRules.
* It is given to the {@link EmfEngine} of henshin.
* @see ExecuteFTRulesCommand
* @see EmfEngine#registerUserConstraint(Class, Object...)
*/
public class OpRuleAttributeConstraintEMF implements UnaryConstraint {
/**
* Hashmap with the attribute markers that is updated during the execution of the operational rules
*/
private HashMap<EObject, HashMap<EAttribute,Boolean>> isTranslatedAttributeMap;
/**
* Hashmap with the node markers that is updated during the execution of the operational rules
*/
private HashMap<EObject, Boolean> isTranslatedNodeMap;
/**
* The node which can be mapped to another node in the graph (see
* {@link FTRuleConstraint#check(Node graphNode)}). The node could be a node in
* a {@link Rule} or in a nac.
*/
private TNode ruleTNode;
private String ruleNodeMarker;
protected TAttribute ruleAttr;
private String ruleAttrMarker;
protected EAttribute eAttribute;
protected Boolean nullValueMatching;
/**
* the constructor
* @param ruleTNode see {@link FTRuleConstraint#ruleTNode}
* @param isTranslatedMap see {@link FTRuleConstraint#isTranslatedMap}
*/
public OpRuleAttributeConstraintEMF(Attribute attr,
HashMap<EObject, Boolean> isTranslatedMap,
HashMap<EObject,HashMap<EAttribute, Boolean>> isTranslatedAttributeMap) {
this((TAttribute)attr,isTranslatedMap,isTranslatedAttributeMap,true);
}
/**
* the constructor
* @param ruleTNode see {@link FTRuleConstraint#ruleTNode}
* @param isTranslatedMap see {@link FTRuleConstraint#isTranslatedMap}
*/
public OpRuleAttributeConstraintEMF(Attribute attr,
HashMap<EObject, Boolean> isTranslatedMap,
HashMap<EObject,HashMap<EAttribute, Boolean>> isTranslatedAttributeMap,
boolean nullValueMatching) {
this.ruleTNode = (TNode)attr.getNode();
this.ruleNodeMarker=ruleTNode.getMarkerType();
this.ruleAttr = (TAttribute)attr;
ruleAttrMarker = ruleAttr.getMarkerType();
this.isTranslatedNodeMap = isTranslatedMap;
this.isTranslatedAttributeMap = isTranslatedAttributeMap;
this.eAttribute = attr.getType();
this.nullValueMatching=nullValueMatching;
}
/**
* Checks if the mapping in a {@link TRule}.
* @see org.eclipse.emf.henshin.interpreter.matching.constraints.HenshinUserConstraint#check(org.eclipse.emf.henshin.model.Node)
*/
@Override
public boolean check(DomainSlot slot) {
EObject graphNode = slot.getValue();
// handle case, when attribute value is null
if (graphNode.eGet(eAttribute) == null) {
// rule explicitly requires null value
if ("null".equals(ruleAttr.getValue()))
return true;
// inconsistent, if
// matching does not allow null values
if (nullValueMatching == false)
return false;
}
if (ruleAttrMarker == null || RuleUtil.TR_UNSPECIFIED.equals(ruleAttrMarker))
// attribute is not marked or marked with wild card - no marker restriction - only component restriction
return true;
// attribute is marked with [tr] or [!tr]
if (isMarkedNode(graphNode)) {
// case: node is in marked component
if (RuleUtil.Not_Translated_Graph.equals(ruleNodeMarker))
// case: node is to be translated ([!tr])
// then: the node marker check ensures already that the
// attribute marker fits, i.e., nothing to do
return true;
else
// cases:
// A. node is context node ([tr])
// B. node is marked with unspecified marker ([tr?])
// check the attribute marker
return (checkAttribute(graphNode));
}
// case: node is not in marked component, nothing to check
return true;
}
/**
* Checks if a graphnode is a source node.
* @param graphNode
* @return true if it is a source node, else false
*/
private boolean isMarkedNode(EObject graphNode) {
return isTranslatedNodeMap.containsKey(graphNode);
}
private boolean checkAttribute(EObject graphNode) {
// graph node is in translated map
// rule attribute is marked with [tr] or [!tr], thus check the marker
HashMap<EAttribute, Boolean> graphNodeMap = isTranslatedAttributeMap.get(graphNode);
if(graphNodeMap == null)
// no attribute markers for graph node available in graph
return false;
Boolean graphAttrMarker = graphNodeMap.get(eAttribute);
if(graphAttrMarker == null)
// no marker for this attribute available in graph
return false;
// attribute marker is available in graph, thus check it
if (RuleUtil.Translated_Graph.equals(ruleAttrMarker)) {
// attribute is only in context but not to be translated, thus it is already translated
return (Boolean.TRUE.equals(graphAttrMarker));
}
if (RuleUtil.Not_Translated_Graph.equals(ruleAttrMarker)) {
// attribute is to be translated, thus it is not yet translated
return (Boolean.FALSE.equals(graphAttrMarker));
}
// unknown case: should not occur
System.out.println("ERROR: during matching - checking of attribute markers failed.");
return false;
}
}