package agg.xt_basis.csp;
/**
* Title:
* Description:
* Copyright: Copyright (c) 2000
* Company:
* @author
* @version 1.0
*/
import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Dictionary;
import agg.attribute.AttrContext;
import agg.attribute.impl.VarMember;
import agg.attribute.impl.VarTuple;
import agg.attribute.impl.ValueTuple;
import agg.attribute.impl.ValueMember;
import agg.util.csp.SolutionStrategy;
import agg.util.csp.Solution_Backjump;
import agg.util.csp.Variable;
import agg.util.Pair;
import agg.xt_basis.Arc;
import agg.xt_basis.BadMappingException;
import agg.xt_basis.Graph;
import agg.xt_basis.GraphObject;
import agg.xt_basis.Match;
import agg.xt_basis.MorphCompletionStrategy;
import agg.xt_basis.Morphism;
import agg.xt_basis.Node;
import agg.xt_basis.OrdinaryMorphism;
import agg.xt_basis.Type;
/**
* An implementation of morphism completion as a Constraint Satisfaction Problem
* (CSP).
*
* Please note: This class is only for internal use of the
* critical pair analysis for grammars with node type inheritance.
* Do not use it for any kind of implementations.
*/
public class Completion_InheritCSP extends MorphCompletionStrategy {
private ALR_InheritCSP itsCSP;
private Morphism itsMorph;
private Dictionary<Object, Variable> relatedVarMap;
// private boolean allowRestrictedDomain;
private HashMap<String, String>
mapInputParameter = new HashMap<String, String>(1);
private String errorMsg;
private static final BitSet itsSupportedProperties = new BitSet(6);
static {
itsSupportedProperties.set(CompletionPropertyBits.INJECTIVE);
itsSupportedProperties.set(CompletionPropertyBits.DANGLING);
itsSupportedProperties.set(CompletionPropertyBits.IDENTIFICATION);
}
public Completion_InheritCSP() {
super(itsSupportedProperties);
this.randomDomain = true;
super.itsName = "CSP NTI"; // Node Type Inheritance
}
public void dispose() {
super.dispose();
itsSupportedProperties.clear();
this.mapInputParameter.clear();
this.relatedVarMap = null;
this.itsMorph = null;
this.itsCSP = null;
}
public void setProperties(MorphCompletionStrategy fromStrategy) {
initialize(itsSupportedProperties,
(BitSet) fromStrategy.getProperties().clone());
}
/**
* Initialize the CSP by the specified morphism. The CSP variables are
* created for each node and edge of the source graph of this morphism.
*/
public final void initialize(OrdinaryMorphism morph)
throws BadMappingException {
this.itsMorph = morph;
AttrContext aContext = initializeAttrContext(morph);
// create CSP
this.itsCSP = new ALR_InheritCSP(morph.getOriginal(), aContext);
if (morph.getImage().getTypeObjectsMap().isEmpty())
morph.getImage().fillTypeObjectsMap();
this.itsCSP.setRequester(morph);
this.itsCSP.setDomain(morph.getImage());
}
private AttrContext initializeAttrContext(OrdinaryMorphism morph) {
if (morph instanceof Match) {
return morph.getAttrManager().newContext(
agg.attribute.AttrMapping.MATCH_MAP,
((Match) morph).getRule().getAttrContext());
}
return morph.getAttrManager().newContext(
agg.attribute.AttrMapping.PLAIN_MAP);
}
/*
private void unsetUsedVariable(GraphObject go, OrdinaryMorphism morph) {
if (go.getAttribute() == null)
return;
Vector<String> attrVars = ((ValueTuple) go.getAttribute())
.getAllVariableNames();
VarTuple varTup = (VarTuple) morph.getAttrContext().getVariables();
for (int i = 0; i < attrVars.size(); i++) {
String name = attrVars.elementAt(i);
VarMember vm = varTup.getVarMemberAt(name);
if (vm != null)
vm.setExpr(null);
}
}
*/
/**
* Template method to enable creation of CSPs with varying solution
* strategies by subclasses.
*/
protected SolutionStrategy createSolutionStrategy() {
return new Solution_Backjump(getProperties().get(CompletionPropertyBits.INJECTIVE));
}
public final void reset() {
if (this.itsCSP != null)
this.itsCSP.reset();
}
public void resetSolverQuery_Type() {
if (this.itsCSP != null)
this.itsCSP.resetQuery_Type();
}
public void enableParallelSearch(boolean b) {
this.parallel = b;
if (this.itsCSP != null)
this.itsCSP.getSolutionSolver().enableParallelSearch(b);
}
public void setStartParallelSearchByFirst(boolean b) {
this.startParallelMatchByFirstCSPVar = b;
if (this.itsCSP != null) {
this.itsCSP.getSolutionSolver().setStartParallelSearchByFirst(b);
}
}
public AttrContext getAttrContext() {
return (this.itsCSP != null)? this.itsCSP.getAttrContext(): null;
}
public void resetSolver(boolean doUpdateQueries) {
if (this.itsCSP != null)
this.itsCSP.resetSolver(doUpdateQueries);
}
public void reinitializeSolver(boolean doUpdateQueries) {
if (this.itsCSP != null)
this.itsCSP.reinitializeSolver(doUpdateQueries);
}
public void resetSolverVariables() {
if (this.itsCSP != null)
this.itsCSP.resetSolverVariables();
}
public boolean isDomainOfTypeEmpty(Type t) {
return this.itsCSP.isDomainOfTypeEmpty(t);
}
public boolean isDomainOfTypeEmpty(Type t, Type src, Type tar) {
return this.itsCSP.isDomainOfTypeEmpty(t, src, tar);
}
public void setRelatedInstanceVarMap(
Dictionary<Object, Variable> relVarMap) {
this.relatedVarMap = relVarMap;
}
public boolean hasRelatedInstanceVarMap() {
if (this.relatedVarMap != null)
return true;
return false;
}
public Dictionary<Object, Variable> getInstanceVarMap() {
if (this.itsCSP != null)
return this.itsCSP.getInstanceVarMap();
return null;
}
public void resetTypeMap(Hashtable<String, HashSet<GraphObject>> typeMap) {
if (this.itsCSP != null)
this.itsCSP.resetTypeMap(typeMap);
}
public void resetTypeMap(Graph g) {
if (this.itsCSP != null)
this.itsCSP.resetTypeMap(g);
}
public void resetVariableDomain(boolean initInstanceByNull) {
if (this.itsCSP != null) {
this.itsCSP.resetVariableDomain(initInstanceByNull);
}
}
public void resetVariableDomain(GraphObject go) {
if (this.itsCSP != null)
this.itsCSP.resetVariableDomain(go);
}
protected void unsetAttrContextVariable() {
this.itsCSP.unsetAttrContextVariable();
}
public final boolean next(OrdinaryMorphism morph) {
if (morph != this.itsMorph) {
try {
initialize(morph);
} catch (BadMappingException ex) {
return false;
}
}
return doNext((OrdinaryMorphism) this.itsMorph);
}
private boolean doNext(OrdinaryMorphism morph) {
this.itsCSP.setRelatedInstanceVarMap(this.relatedVarMap);
boolean flag = false;
this.errorMsg = "";
if (morph.getAttrContext() != null) {
((VarTuple) morph.getAttrContext().getVariables())
.unsetNotInputVariables();
}
while (this.itsCSP.nextSolution()) {
flag = true;
this.errorMsg = "";
// try add morph. mapping after CSP success
GraphObject anOrig, anImage;
Iterator<Node> anNodeIter = morph.getOriginal().getNodesSet().iterator();
while (flag && anNodeIter.hasNext()) {
anOrig = anNodeIter.next();
Variable lhsVariable = this.itsCSP.getVariable(anOrig);
if (lhsVariable != null) {
anImage = (GraphObject) lhsVariable.getInstance();
if (anImage != null) {
try {
morph.addChild2ParentMapping(anOrig, anImage);
if (morph.getImage(anOrig) == null) {
flag = false;
}
} catch (BadMappingException ex) {
flag = false;
}
}
}
}
Iterator<Arc> anArcIter = morph.getOriginal().getArcsSet().iterator();
while (flag && anArcIter.hasNext()) {
anOrig = anArcIter.next();
Variable lhsVariable = this.itsCSP.getVariable(anOrig);
if (lhsVariable != null) {
anImage = (GraphObject) lhsVariable.getInstance();
if (anImage != null) {
try {
morph.addChild2ParentMapping(anOrig, anImage);
if (morph.getImage(anOrig) == null) {
flag = false;
}
} catch (BadMappingException ex) {
flag = false;
}
}
}
}
if (!flag)
continue;
if (morph.getAttrContext() != null) {
flag = flag && checkObjectsWithSameVariable(morph);
}
if (flag) {
break;
}
morph.setErrorMsg(this.errorMsg);
}
return flag;
}
private boolean checkObjectsWithSameVariable(OrdinaryMorphism morph) {
VarTuple variables = (VarTuple) morph.getAttrContext().getVariables();
for (int i = 0; i < variables.getSize(); i++) {
VarMember var = variables.getVarMemberAt(i);
Vector<Pair<GraphObject, String>> v = new Vector<Pair<GraphObject, String>>();
Iterator<?> iter = morph.getOriginal().getNodesSet().iterator();
while (iter.hasNext()) {
GraphObject orig = (GraphObject) iter.next();
if (orig.getAttribute() == null)
continue;
ValueTuple origVal = (ValueTuple) orig.getAttribute();
for (int k = 0; k < origVal.getSize(); k++) {
ValueMember mem = origVal.getValueMemberAt(k);
if (mem.isSet()
&& mem.getExpr().isVariable()
&& mem.getExprAsText().equals(var.getName())
&& mem.getDeclaration().getTypeName().equals(
var.getDeclaration().getTypeName())) {
v.add(new Pair<GraphObject, String>(
orig, mem.getName()));
}
}
}
iter = morph.getOriginal().getArcsSet().iterator();
while (iter.hasNext()) {
GraphObject orig = (GraphObject) iter.next();
if (orig.getAttribute() == null)
continue;
ValueTuple origVal = (ValueTuple) orig.getAttribute();
for (int k = 0; k < origVal.getSize(); k++) {
ValueMember mem = origVal.getValueMemberAt(k);
if (mem.isSet()
&& mem.getExpr().isVariable()
&& mem.getExprAsText().equals(var.getName())
&& mem.getDeclaration().getTypeName().equals(
var.getDeclaration().getTypeName())) {
v.add(new Pair<GraphObject, String>(
orig, mem.getName()));
}
}
}
if (v.size() > 1) {
Pair<GraphObject, String> p = v.elementAt(0);
GraphObject img = morph.getImage(p.first);
// if (img == null) {
// System.out.println(img+" "+p.first.getType().getName());
// }
ValueTuple val = (ValueTuple) img.getAttribute();
ValueMember mem = val.getValueMemberAt(p.second);
for (int j = 1; j < v.size(); j++) {
Pair<GraphObject, String> pj = v.elementAt(j);
GraphObject imgj = morph.getImage(pj.first);
ValueTuple valj = (ValueTuple) imgj.getAttribute();
ValueMember memj = valj.getValueMemberAt(pj.second);
if (mem.isSet() && memj.isSet()) {
if (mem.getExpr().isConstant()
&& memj.getExpr().isConstant()) {
if (!mem.getExprAsText().equals(memj.getExprAsText())) {
this.errorMsg = "Attribute check: equal value by equal variable - failed!.";
return false;
}
} else if (mem.getExpr().isVariable()
&& memj.getExpr().isVariable()) {
if (!mem.getExprAsText().equals(
memj.getExprAsText())) {
this.errorMsg = "Attribute check: equal value by equal variable - failed!.";
return false;
}
} else {
this.errorMsg = "Attribute check: equal value by equal variable - failed!";
return false;
}
}
}
}
}
return true;
}
/**
* An additional object name constraint will be added for the CSP variable
* of the given GraphObject anObj. This constraint requires equality of the object names.<br>
*/
public void addObjectNameConstraint(GraphObject anObj) {
this.itsCSP.addObjectNameConstraint(anObj);
}
/**
* Removes the object name constraint for the CSP variable
* of the given GraphObject anObj.
*/
public void removeObjectNameConstraint(GraphObject anObj) {
this.itsCSP.removeObjectNameConstraint(anObj);
}
}