package agg.xt_basis;
import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.BitSet;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
import java.util.Hashtable;
import agg.attribute.impl.ContextView;
import agg.attribute.impl.DeclTuple;
import agg.attribute.impl.DeclMember;
import agg.attribute.impl.ValueTuple;
import agg.attribute.impl.ValueMember;
import agg.attribute.impl.AttrTupleManager;
import agg.attribute.AttrType;
import agg.attribute.facade.impl.DefaultInformationFacade;
import agg.attribute.facade.InformationFacade;
import agg.attribute.handler.AttrHandler;
import agg.attribute.handler.impl.javaExpr.JexHandler;
import agg.cons.AtomConstraint;
import agg.cons.Evaluable;
import agg.cons.Formula;
import agg.cons.ConstraintLayer;
import agg.cons.ConstraintPriority;
import agg.ruleappl.ObjectFlow;
import agg.ruleappl.RuleSequence;
import agg.util.Disposable;
import agg.util.IntComparator;
import agg.util.OrderedSet;
import agg.util.XMLHelper;
import agg.util.XMLObject;
import agg.util.Pair;
import agg.xt_basis.agt.RuleScheme;
import agg.xt_basis.csp.CompletionPropertyBits;
import agg.xt_basis.csp.Completion_CSP_NoBJ;
/**
* This class provides functionality of a graph grammar, consisting of
* an arbitrary number of graphs (the "host graphs"), an arbitrary number of rules,
* an arbitrary number of match morphisms from the rules into the host graph.
* <p>
* The implementation serves as a factory to create instances of classes
* Type, Graph, Rule and Match, AtomConstraint and Formula,
*
* @author $Author: olga $
* @version $Id: GraGra.java,v 1.143 2010/12/16 17:31:39 olga Exp $
*/
public class GraGra implements Disposable, XMLObject {
final protected Vector<Graph>
itsGraphs = new Vector<Graph>();
/**
* The set of my rules. Elements are of type <code>Rule</code>.
*/
final protected Vector<Rule>
itsRules = new Vector<Rule>();
Hashtable<Integer, List<Rule>> ruleSets;
/**
* The set of my atomic graph constraints.
*/
final protected Vector<AtomConstraint>
itsAtomics = new Vector<AtomConstraint>(5);
/**
* The set of my constraints ( formulae ).
*/
final protected Vector<Formula>
itsConstraints = new Vector<Formula>(5);
/**
* The list of my transformation options (only option names)
*/
final protected Vector<String>
gratraOptions = new Vector<String>();
/**
* The set of my matches. Elements are of type <code>Match</code>.
*/
final protected Vector<Match>
itsMatches = new Vector<Match>();
protected RuleSequence itsRuleSequence;
final protected List<RuleSequence>
itsRuleSequences = new Vector<RuleSequence>(1);
/**
* The set of the used packages of the Java classes. These classes might be
* used for attributing.
* The first element of a Pair is the name of an attribute handler,
* the second - a list of class names.
*/
final protected Vector<Pair<String, List<String>>>
itsPackages = new Vector<Pair<String, List<String>>>(5);
/**
* My type set used in graphs and rules.
* It contains types of nodes and edges and evtl. a type graph.
*/
protected TypeSet typeSet;
/**
* My host graph. It can be changed.
*/
protected Graph itsGraph;
/**
* My start graph. It cannot be changed. At the beginning the start is equal
* to the host graph. It will be used to reset my host graph.
*/
protected Graph itsStartGraph;
protected String itsName;
protected String comment = "";
/**
* Match completion strategy
*/
protected MorphCompletionStrategy strategy;
protected boolean hasRuleApplCond;
/** Error message, if graph constraints have been failed */
private String consistErrMsg;
/** Error message, if multiplicity constraints have been failed */
private int multiplErrKind;
private boolean ruleChangedLayer;
private boolean ruleChangedPriority;
private boolean ruleChangedEvailability;
/**
* Directory name for saving
*/
protected String dirName;
/**
* File name for saving
*/
protected String fileName;
// private static final agg.attribute.AttrContext
// aGraphContext = agg.attribute.impl.AttrTupleManager.getDefaultManager().newContext(
// agg.attribute.AttrMapping.GRAPH_MAP);
/** Construct a new graph grammar. */
protected GraGra() {
this.dirName = "";
this.fileName = "";
this.itsName = "unnamed.gragra";
this.typeSet = new TypeSet();
this.itsGraph = BaseFactory.theFactory().createGraph(this.typeSet);
this.itsGraph.setKind(GraphKind.HOST);
this.itsGraph.setCompleteGraph(true);
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraphs.add(this.itsGraph);
initMorphismCompletionStrategy();
}
/** Construct a new graph grammar. */
public GraGra(boolean withGraph) {
this.dirName = "";
this.fileName = "";
this.itsName = "unnamed.gragra";
this.typeSet = new TypeSet();
if (withGraph) {
this.itsGraph = BaseFactory.theFactory().createGraph(this.typeSet);
this.itsGraph.setKind(GraphKind.HOST);
this.itsGraph.setCompleteGraph(true);
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraphs.add(this.itsGraph);
}
initMorphismCompletionStrategy();
}
/**
* Construct a new graph grammar with a type set
* and/or type graph specified by the TypeSet newTypeSet
*/
public GraGra(TypeSet newTypeSet) {
this.dirName = "";
this.fileName = "";
this.itsName = "unnamed.gragra";
this.typeSet = newTypeSet;
this.itsGraph = BaseFactory.theFactory().createGraph(this.typeSet, true);
this.itsGraph.setKind(GraphKind.HOST);
this.itsGraph.setCompleteGraph(true);
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraphs.add(this.itsGraph);
initMorphismCompletionStrategy();
}
/** Construct a new graph grammar. */
public GraGra(TypeSet newTypeSet, boolean withGraph) {
this.dirName = "";
this.fileName = "";
this.itsName = "unnamed.gragra";
this.typeSet = newTypeSet;
if (withGraph) {
this.itsGraph = BaseFactory.theFactory().createGraph(this.typeSet);
this.itsGraph.setKind(GraphKind.HOST);
this.itsGraph.setCompleteGraph(true);
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraphs.add(this.itsGraph);
}
initMorphismCompletionStrategy();
}
/**
* Constructs a graph grammar with the given graph as host graph.
*/
public GraGra(Graph g) {
this.dirName = "";
this.fileName = "";
this.itsName = "unnamed.gragra";
this.itsGraph = g;
this.itsGraph.setKind(GraphKind.HOST);
this.itsGraph.setCompleteGraph(true);
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraphs.add(this.itsGraph);
this.typeSet = g.getTypeSet();
initMorphismCompletionStrategy();
}
/**
* Trims the capacity of used vectors to be the vector's current
* size.
*/
public void trimToSize() {
this.typeSet.trimToSize();
this.itsGraphs.trimToSize();
for (int i = 0; i < this.itsGraphs.size(); i++) {
this.itsGraphs.get(i).trimToSize();
}
this.itsRules.trimToSize();
for (int i=0; i<this.itsRules.size(); i++) {
this.itsRules.get(i).trimToSize();
}
this.itsMatches.trimToSize();
for (int i=0; i<this.itsMatches.size(); i++) {
this.itsMatches.get(i).trimToSize();
}
this.itsAtomics.trimToSize();
for (int i=0; i<this.itsAtomics.size(); i++) {
this.itsAtomics.get(i).trimToSize();
}
this.itsConstraints.trimToSize();
for (int i=0; i<this.itsConstraints.size(); i++) {
this.itsConstraints.get(i).trimToSize();
}
((Vector<RuleSequence>)this.itsRuleSequences).trimToSize();
for (int i=0; i<this.itsRuleSequences.size(); i++) {
this.itsRuleSequences.get(i).trimToSize();
}
this.itsPackages.trimToSize();
this.gratraOptions.trimToSize();
if (this.itsStartGraph != null)
this.itsStartGraph.trimToSize();
}
public Vector<Pair<String, List<String>>> getPackages() {
return this.itsPackages;
}
public void setPackages(final Vector<Pair<String, List<String>>> n) {
this.itsPackages.clear();
this.itsPackages.addAll(n);
}
public void addPackage(final Pair<String, List<String>> p) {
if (!this.itsPackages.contains(p)) {
this.itsPackages.add(p);
}
}
public void removePackage(final Pair<String, Vector<String>> p) {
this.itsPackages.remove(p);
}
private Graph createGraph() {
final Graph g = BaseFactory.theFactory().createGraph(this.typeSet, true);
g.setKind(GraphKind.HOST);
g.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
// test: use xy position as attributes
g.xyAttr = this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE);
g.setCompleteGraph(true);
this.itsGraphs.add(g);
return g;
}
public boolean addGraph(final Graph g) {
boolean result;
if (this.itsGraphs.contains(g)) {
result = false;
} else {
g.setKind(GraphKind.HOST);
// test: use xy position as attributes
g.xyAttr = this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE);
g.setCompleteGraph(true);
this.itsGraphs.add(g);
result = true;
}
return result;
}
/**
* Remove the specified graph from my host graphs and destroy it.
* The current host graph and the specified graph have to be different.
*/
public void destroyGraph(final Graph g) {
if (this.itsGraphs.remove(g)) {
g.dispose();
}
}
/**
* Destroy all my host graphs.
*/
public void destroyAllGraphs() {
while (!this.itsGraphs.isEmpty()) {
final Graph g = this.itsGraphs.get(0);
this.itsGraphs.remove(0);
g.dispose();
}
}
/**
* Remove the specified graph from my graphs.
* Return FALSE if the specified graph does not belong to my graphs.
* The current host graph and the specified graph have to be different.
*/
public boolean removeGraph(final Graph g) {
if(this.itsGraphs.contains(g)) {
this.itsGraphs.remove(g);
if (this.itsGraph == g) {
if (this.itsGraphs.size() == 0) {
this.itsGraph = null;
}
}
return true;
}
return false;
}
/**
* Return true, if the Rule r is element of my rules otherwise - false.
*/
public boolean isElement(final Rule r) {
boolean found = false;
for (int i=0; i<this.itsRules.size(); i++) {
if (this.itsRules.get(i).equals(r)) {
found = true;
break;
}
}
return found;
}
/**
* Return true, if the specified Graph g is once of my host graphs,
* otherwise - false.
*/
public boolean isElement(final Graph g) {
return this.itsGraphs.contains(g);
}
public boolean trafoByPriority() {
return this.gratraOptions.contains(GraTraOptions.PRIORITY);
}
public boolean trafoByLayer() {
return this.gratraOptions.contains(GraTraOptions.LAYERED);
}
public boolean isLayered() {
return this.gratraOptions.contains(GraTraOptions.LAYERED);
}
public boolean trafoByRuleSequence() {
return this.gratraOptions.contains(GraTraOptions.RULE_SEQUENCE);
}
/*
* An element of the vector to return represents a rule layer number.
*/
public Vector<String> getLayers() {
final RuleLayer layers = new RuleLayer(this.itsRules);
final Map<Integer, HashSet<Rule>> invRuleLayers = layers.invertLayer();
Integer currentLayer = layers.getStartLayer();
final OrderedSet<Integer> ruleLayers = new OrderedSet<Integer>(new IntComparator<Integer>());
for (final Iterator<Integer> en = invRuleLayers.keySet().iterator(); en.hasNext();) {
ruleLayers.add(en.next());
}
int i=0;
final Vector<String> v = new Vector<String>();
while (currentLayer != null) {
v.add(currentLayer.toString());
i++;
if (i < ruleLayers.size()) {
currentLayer = ruleLayers.get(i);
}
else {
currentLayer = null;
}
}
return v;
}
public Vector<String> getEnabledLayers() {
final RuleLayer layers = new RuleLayer(this.getEnabledRules());
final Map<Integer, HashSet<Rule>> invRuleLayers = layers.invertLayer();
Integer currentLayer = layers.getStartLayer();
final OrderedSet<Integer> ruleLayers = new OrderedSet<Integer>(new IntComparator<Integer>());
for (final Iterator<Integer> en = invRuleLayers.keySet().iterator(); en.hasNext();) {
ruleLayers.add(en.next());
}
int i=0;
final Vector<String> v = new Vector<String>();
while (currentLayer != null) {
v.add(currentLayer.toString());
i++;
if (i < ruleLayers.size()) {
currentLayer = ruleLayers.get(i);
}
else {
currentLayer = null;
}
}
return v;
}
/*
* Returns a Vector with String elements. A String represents the priority
* number.
*/
public Vector<String> getPriorities() {
final RulePriority priors = new RulePriority(this.itsRules);
final Map<Integer, HashSet<Rule>> invRulePriors = priors.invertPriority();
Integer currentPrior = priors.getStartPriority();
final OrderedSet<Integer> rulePriors = new OrderedSet<Integer>(new IntComparator<Integer>());
for (final Iterator<Integer> en = invRulePriors.keySet().iterator(); en.hasNext();) {
rulePriors.add(en.next());
}
int i=0;
final Vector<String> v = new Vector<String>(5);
while (currentPrior != null) {
v.add(currentPrior.toString());
i++;
if (i < rulePriors.size()) {
currentPrior = rulePriors.get(i);
}
else {
currentPrior = null;
}
}
return v;
}
public Vector<String> getEnabledPriorities() {
final RulePriority priors = new RulePriority(this.getEnabledRules());
final Map<Integer, HashSet<Rule>> invRulePriors = priors.invertPriority();
Integer currentPrior = priors.getStartPriority();
final OrderedSet<Integer> rulePriors = new OrderedSet<Integer>(new IntComparator<Integer>());
for (final Iterator<Integer> en = invRulePriors.keySet().iterator(); en.hasNext();) {
rulePriors.add(en.next());
}
int i=0;
final Vector<String> v = new Vector<String>(1);
while (currentPrior != null) {
v.add(currentPrior.toString());
i++;
if (i < rulePriors.size()) {
currentPrior = rulePriors.get(i);
}
else {
currentPrior = null;
}
}
return v;
}
/**
* Reset my host graph by the Graph g.
* The types of the graph g have to be similar of my types.
* The given graph g will be added to my list of graphs if it is not already contained.
*/
public boolean resetGraph(final Graph g) {
if (this.typeSet == null || g.getTypeSet() == null) {
return false;
}
if (this.typeSet.compareTo(g.getTypeSet())) {
// allow to reset its graph
int indx = this.itsGraphs.indexOf(this.itsGraph);
if (!this.itsGraphs.contains(g)) {
this.itsGraphs.remove(this.itsGraph);
if (indx == -1) {
this.itsGraphs.add(g);
}
else {
this.itsGraphs.add(indx, g);
}
g.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
}
this.itsGraph = g;
this.itsGraph.graphDidChange();
return true;
}
return false;
}
/**
* Reset my host graph by the Graph g. The graph g has not to be in the list of my graphs.
* The types of the graph g have to be
* similar of my types.
*/
public boolean resetGraph(int atIndex, final Graph g) {
if (this.typeSet == null
|| g.getTypeSet() == null
|| atIndex < 0
|| atIndex >= this.itsGraphs.size()) {
return false;
}
if (this.typeSet.compareTo(g.getTypeSet())) {
int indx = this.itsGraphs.indexOf(this.itsGraph);
if (indx == atIndex) {
if (!this.itsGraphs.contains(g)) {
this.itsGraphs.remove(atIndex);
this.itsGraphs.add(atIndex, g);
g.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
g.graphDidChange();
this.itsGraph = g;
return true;
}
}
}
return false;
}
/** Reset my host graph by my start graph. */
public boolean resetGraph() {
boolean result = false;
if (this.itsGraph == null
|| this.typeSet == null
|| this.itsStartGraph == null
|| !this.typeSet.equals(this.itsStartGraph.getTypeSet())) {
result = false;
} else {
final int indx = this.itsGraphs.indexOf(this.itsGraph);
this.itsGraphs.remove(this.itsGraph);
this.itsGraph.dispose();
this.itsGraph = this.itsStartGraph.copy();
if (indx == -1) {
this.itsGraphs.add(this.itsGraph);
}
else {
this.itsGraphs.add(indx, this.itsGraph);
}
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraph.graphDidChange();
result = true;
}
return result;
}
/**
* Reset my host graph by the Graph g without type guarantee. The types of
* the graph g should be similar to my types.
*/
public boolean resetGraphWithoutGuarantee(final Graph g) {
boolean result = true;
final int indx = this.itsGraphs.indexOf(this.itsGraph);
if (indx >= 0) {
this.itsGraphs.remove(this.itsGraph);
}
this.itsGraph = g.copy(this.typeSet);
if (this.itsGraph == null) {
result = false;
} else {
if (indx == -1) {
this.itsGraphs.add(this.itsGraph);
} else {
this.itsGraphs.add(indx, this.itsGraph);
}
this.itsGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.itsGraph.graphDidChange();
}
return result;
}
/**
* Adds the specified Graph g to the current type graph if it exists or to a
* new created type graph otherwise. The Graph g is a type graph,
* g.isTypeGraph() should return true. The type graph check should be
* disabled. The new node/edge types of the Graph g are added to the current
* types. The current type graph structure and the structure of the Graph g
* are united dis-jointly. Double occurrence of the nodes/arcs are possible
* and they have to be resolved manually by the user.
*/
public boolean importTypeGraph(final Graph g, final boolean rewrite) {
boolean result = false;
if (g.isTypeGraph()) {
if (this.typeSet.getTypeGraph() == null) {
this.typeSet.createTypeGraph();
}
if (rewrite) {
this.typeSet.adaptTypes(g.getTypeSet(), false);
}
final Map<ValueTuple, ValueTuple> valueTable = storeAttrValueOfAttrTypeObserver();
if (this.typeSet.importTypeGraph(g, rewrite)) {
this.typeSet.refreshInheritanceArcs();
// extend the type graph by the node/arc types which are already used in graphs
// but are not defined in the type graph
// this.typeSet.extendTypeGraph(g.getNodesSet().iterator(), g.getArcsSet().iterator());
restoreAttrValueOfObserver(valueTable);
this.typeSet.getTypeGraph().graphDidChange();
result = true;
} else {
result = false;
}
}
return result;
}
private Map<ValueTuple, ValueTuple> storeAttrValueOfAttrTypeObserver() {
// System.out.println("###### storeAttrValueOfAttrTypeObserver......");
final Map<ValueTuple, ValueTuple> attrStore = new Hashtable<ValueTuple, ValueTuple>();
final Enumeration<Type> types = this.typeSet.getTypes();
while (types.hasMoreElements()) {
final Type t = types.nextElement();
if (t.getAttrType() != null) {
final DeclTuple dt = (DeclTuple) t.getAttrType();
final Enumeration<?>
observers = ((DeclTuple) t.getAttrType()).getObservers();
while (observers.hasMoreElements()) {
final Object obs = observers.nextElement();
if (obs instanceof ValueTuple) {
final ValueTuple valTuple = (ValueTuple) obs;
if (!valTuple.isEmpty()) {
final ValueTuple vt = new ValueTuple(
(AttrTupleManager) AttrTupleManager
.getDefaultManager(), dt,
(ContextView) valTuple.getContext());
for (int i = 0; i < valTuple.getSize(); i++) {
final ValueMember mem = valTuple.getValueMemberAt(i);
final ValueMember vm = vt.getValueMemberAt(mem.getName());
if (vm != null && mem.isSet()) {
vm.setExprAsText(mem.getExprAsText());
// System.out.println(vm.getName()+" = "+mem.getExprAsText());
}
}
attrStore.put((ValueTuple) obs, vt);
}
}
}
}
}
return attrStore;
}
private void restoreAttrValueOfObserver(final Map<ValueTuple, ValueTuple> attrStore) {
// System.out.println("###### restoreAttrValueOfAttrTypeObserver......");
final Enumeration<Type> types = this.typeSet.getTypes();
while (types.hasMoreElements()) {
final Type t = types.nextElement();
if (t.getAttrType() == null) {
continue;
}
final Enumeration<?> observers = ((DeclTuple) t.getAttrType())
.getObservers();
while (observers.hasMoreElements()) {
final Object obs = observers.nextElement();
if (obs instanceof ValueTuple) {
final ValueTuple vt = attrStore.get(obs);
if (vt != null) {
final ValueTuple valTuple = (ValueTuple) obs;
for (int i = 0; i < valTuple.getSize(); i++) {
final ValueMember mem = valTuple.getValueMemberAt(i);
final ValueMember vm = vt.getValueMemberAt(mem.getName());
if (vm != null && vm.isSet()) {
// System.out.println(vm.getName()+" = "+vm.getExprAsText());
mem.setExprAsText(vm.getExprAsText());
}
}
}
}
}
}
}
/**
* Reset my host graph by the Graph g. The types of the graph objects of the
* Graph g have to be similar to my types.
*/
public boolean importGraph(final Graph g) {
boolean importTried = false;
boolean result = false;
if ((g.getTypeSet().getTypeGraph() != null)
&& ((this.typeSet.getTypeGraph() == null)
|| (this.typeSet.getTypeGraph().isEmpty()
&& (getLevelOfTypeGraphCheck() == TypeSet.DISABLED)))) {
importTried = true;
if (importTypeGraph(g.getTypeSet().getTypeGraph(), true)) {
result = importGraph(g, false);
}
else {
result = false;
}
}
if (!importTried) {
result = importGraph(g, false);
}
return result;
}
/**
* Reset my host graph by the Graph g. If the parameter <code>adapt</code>
* is true, the types of the Graph g are tried to be adapted to my types.
* The types with the same name are equal. Otherwise, the types of the Graph
* g should be found among my types.
*/
public boolean importGraph(final Graph g, final boolean adapt) {
boolean result;
final Graph impGraph = doImportGraph(g, adapt);
if (impGraph == null) {
result = false;
}
else {
final int indx = this.itsGraphs.indexOf(this.itsGraph);
if (indx == -1) {
this.itsGraphs.add(impGraph);
} else {
this.itsGraphs.remove(this.itsGraph);
this.itsGraphs.add(indx, impGraph);
}
this.itsGraph = impGraph;
this.itsGraph.graphDidChange();
result = true;
}
return result;
}
/**
* Add a copy of the Graph g to the list of my (host) graphs. The types of
* the Graph g have to be similar to my types.
*/
public boolean addImportGraph(final Graph g) {
return addImportGraph(g, false);
}
/**
* Add a copy of the Graph g to the list of my (host) graphs. If the
* parameter <code>adapt</code> is true, the types of the Graph g are
* tried to be adapted to my types. The types with the same name are equal.
* Otherwise, the types of the Graph g should be found among my types.
*/
public boolean addImportGraph(final Graph g, final boolean adapt) {
boolean result;
final Graph impGraph = doImportGraph(g, adapt);
if (impGraph == null) {
result = false;
}
else {
this.itsGraphs.add(impGraph);
result = true;
}
return result;
}
private Graph doImportGraph(final Graph g, final boolean adapt) {
Graph impGraph = null;
if ((this.typeSet != null) && (g.getTypeSet() != null)) {
final String extStr = "_import";
if (this.typeSet.isEmpty()
&& adoptTypes(g.getTypeSet().getTypes())) {
impGraph = g.copy(this.typeSet);
} else if (this.typeSet.contains(g.getTypeSet())) {
impGraph = g.copy(this.typeSet);
} else if ((this.typeSet.getTypeGraph() == null)
|| (this.typeSet.getLevelOfTypeGraphCheck() == TypeSet.DISABLED)) {
final Vector<Type> typesToAdopt = new Vector<Type>(1);
final Enumeration<Type> other = g.getTypeSet().getTypes();
while (other.hasMoreElements()) {
final Type tOther = other.nextElement();
if (!this.typeSet.containsType(tOther)
&& g.getElementsOfType(tOther).hasMoreElements()) {
typesToAdopt.add(tOther);
}
}
if (adapt) {
this.typeSet.adaptTypes(g.getTypeSet().getTypes(), false);
impGraph = g.copyLight(this.typeSet);
} else if (adoptTypes(typesToAdopt.elements())) {
impGraph = g.copy(this.typeSet);
}
}
if (impGraph != null) {
impGraph.setName(g.getName() + extStr);
impGraph.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext()));
this.typeSet.extendTypeGraph(g.getNodesSet().iterator(), g.getArcsSet().iterator());
}
}
return impGraph;
}
/**
* Add a copy of the Rule r to the list of my rules. The types of the Rule r
* have to be similar to my types.
*/
public boolean addImportRule(final Rule r) {
return addImportRule(r, false);
}
/**
* Add a copy of the Rule r to the list of my rules. If the parameter
* <code>adapt</code> is true, the types of the Rule r are tried to be
* adapted to my types. The types with the same name are similar.
*
* Otherwise, the types of the Rule r should be found among my types.
*
*/
public boolean addImportRule(final Rule r, final boolean adapt) {
boolean result = false;
if (!this.itsRules.contains(r)) {
if (adapt) {
this.typeSet.adaptTypes(r.getTypeSet(), true);
}
final Rule impR = BaseFactory.theFactory().cloneRule(r, this.typeSet, true);
if (impR != null) {
this.itsRules.add(impR);
result = true;
Vector<Node> nodelist = new Vector<Node>(r.getLeft().getNodesSet());
nodelist.addAll(r.getRight().getNodesSet());
Vector<Arc> edgelist = new Vector<Arc>(r.getLeft().getArcsSet());
edgelist.addAll(r.getRight().getArcsSet());
for (int i=0; i<r.getNACsList().size(); i++) {
OrdinaryMorphism m = r.getNACsList().get(i);
nodelist.addAll(m.getTarget().getNodesSet());
edgelist.addAll(m.getTarget().getArcsSet());
}
for (int i=0; i<r.getPACsList().size(); i++) {
OrdinaryMorphism m = r.getPACsList().get(i);
nodelist.addAll(m.getTarget().getNodesSet());
edgelist.addAll(m.getTarget().getArcsSet());
}
this.typeSet.extendTypeGraph(nodelist.iterator(), edgelist.iterator());
}
}
return result;
}
/*
* The specified types contains elements of type Type and used to create new
* types which will be added to my types. Returns false, if at least one of
* the new types has failed, otherwise true.
*/
public boolean adoptTypes(final Enumeration<Type> types) {
boolean result = true;
while (types.hasMoreElements()) {
final Type t = types.nextElement();
if (this.typeSet.adoptType(t) == null) {
result = false;
break;
}
}
return result;
}
public void dispose() {
this.typeSet.setLevelOfTypeGraph(TypeSet.DISABLED);
if (this.itsRuleSequences != null)
this.itsRuleSequences.clear();
this.destroyAllMatches();
this.destroyAllRules();
// formulae
this.destroyAllConstraints();
this.destroyAllAtomics();
this.destroyAllGraphs();
if (this.itsStartGraph != null) {
this.itsStartGraph.dispose();
}
this.typeSet.destroyTypeGraph();
this.typeSet.dispose();
this.typeSet = null;
this.itsGraph = null;
}
public void finalize() {
}
private agg.attribute.AttrContext aGraphContext() {
agg.attribute.AttrContext
aGraphCntxt = agg.attribute.impl.AttrTupleManager.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
return aGraphCntxt;
}
/**
* After this method was called:
* - the type graph check is set to <code>DISABLED</code>
* - existent rule sequences, matches, rules, graphs, graph constraints, type set are empty
*/
private void clear() {
this.setLevelOfTypeGraphCheck(TypeSet.DISABLED);
if (this.itsRuleSequences != null) {
this.itsRuleSequences.clear();
this.itsRuleSequence = null;
}
this.destroyAllMatches();
this.destroyAllRules();
// formulae
this.destroyAllConstraints();
this.destroyAllAtomics();
this.destroyAllGraphs();
if (this.itsStartGraph != null) {
this.itsStartGraph.dispose();
}
this.typeSet.dispose();
}
public boolean addRule(final Rule r) {
boolean result = true;
if (this.itsRules.contains(r)) {
result = false;
} else {
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
r.getLeft().xyAttr = true;
r.getRight().xyAttr = true;
}
this.itsRules.add(r);
this.addMatch(r.getMatch());
}
return result;
}
public boolean addRuleAt(int indx, final Rule r) {
boolean result = true;
if (this.itsRules.contains(r)) {
result = false;
} else {
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
r.getLeft().xyAttr = true;
r.getRight().xyAttr = true;
}
this.itsRules.add(indx, r);
this.addMatch(r.getMatch());
}
return result;
}
public boolean removeRule(final Rule r) {
if (this.itsRules.remove(r)) {
this.refreshRuleSequences();
return true;
}
return false;
}
public boolean hasRuleWithApplCond() {
this.hasRuleApplCond = false;
for (int i=0; i<this.itsRules.size(); i++) {
if (this.itsRules.get(i).getNACsList().size() > 0
|| this.itsRules.get(i).getPACsList().size() > 0
|| this.itsRules.get(i).getNestedACsList().size() > 0) {
this.hasRuleApplCond = true;
break;
}
}
return this.hasRuleApplCond;
}
public void removeTypeGraph() {
this.typeSet.removeTypeGraph();
}
/** Set my name. */
public final void setName(final String n) {
this.itsName = n;
}
/** Return my name. */
public final String getName() {
return this.itsName;
}// getName
/** Set textual comments for this grammar. */
public void setTextualComment(final String text) {
this.comment = text;
}
/** Return textual comments of this grammar. */
public String getTextualComment() {
return this.comment;
}
/**
* Sets the directory name for saving the gragra
*/
public void setDirName(final String str) {
this.dirName = str;
}
/**
* Gets the directory name for saving the gragra
*/
public String getDirName() {
return this.dirName;
}
/**
* Sets the file name for saving the gragra
*/
public void setFileName(final String str) {
this.fileName = str;
}
/**
* Gets the file name for saving the gragra
*/
public String getFileName() {
return this.fileName;
}
/** Returns my current host graph. */
public final Graph getGraph() {
return this.itsGraph;
}
/** Returns the index of my current host graph. */
public int getIndexOfGraph() {
return this.itsGraphs.indexOf(this.itsGraph);
}
/** Returns a host graph with the specified name. */
public final Graph getGraph(final String name) {
Graph g = null;
for (int i = 0; i < this.itsGraphs.size(); i++) {
if (this.itsGraphs.get(i).getName().equals(name)) {
g = this.itsGraphs.get(i);
break;
}
}
return g;
}
/**
* Returns a host graph on the specified index or null.
*/
public final Graph getGraph(final int indx) {
Graph g = null;
if ((indx >= 0) && (indx < this.itsGraphs.size())) {
g = this.itsGraphs.get(indx);
}
return g;
}
/**
* Returns a collection of my host graphs.
*
* @deprecated replaced by <code>getListOfGraphs()</code>
*/
public final Enumeration<Graph> getGraphs() {
return this.itsGraphs.elements();
}
public final int getCountOfGraphs() {
return this.itsGraphs.size();
}
/**
* Returns a list of my host graphs.
*/
public final List<Graph> getListOfGraphs() {
return this.itsGraphs;
}
/**
* Returns a Vector of my host graphs.
*
* @deprecated replaced by <code>getListOfGraphs()</code>
*/
public final Vector<Graph> getGraphsVec() {
return this.itsGraphs;
}
/**
* Return my start graph. At the beginning the start graph is similar to my
* current host graph. In process the host graph will be changed, the start
* graph lieves unchanged.
*/
public final Graph getStartGraph() {
return this.itsStartGraph;
}
/**
* Sets my start graph to Graph g. The type set of the graph g has to be
* similar to my type set.<br>
* The start graph should not be confused with a host graph.
* The start graph is a copy of a (mostly first) host graph after a grammar loaded.
* A host graph is my current work graph. The start graph can be used to overwrite
* my current host graph <code>this.resetGraph()</code>.
*/
public void setStartGraph(final Graph g) {
if (g == null) {
destroyStartGraph();
}
else {
if (g.getTypeSet().equals(this.typeSet)) {
if (this.itsStartGraph != null) {
this.itsStartGraph.dispose();
}
this.itsStartGraph = g;
// this.itsStartGraph.setName("StartGraph");
}
}
}
/*
* The start graph will be destroyed. The host graph cannot be reset
* anymore.
*/
public void destroyStartGraph() {
this.itsStartGraph.dispose();
}
/**
* Returns list of my rules.
*
* @see agg.xt_basis.Rule
*/
public final List<Rule> getListOfRules() {
return this.itsRules;
}
public List<Rule> getListOfEnabledRules() {
List<Rule> list = new Vector<Rule>();
for (int i=0; i<this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
if (r.isEnabled()) {
list.add(r);
}
}
return list;
}
public void oneRuleHasChangedLayer() {
this.ruleChangedLayer = true;
}
public boolean hasRuleChangedLayer() {
return this.ruleChangedLayer;
}
public void oneRuleHasChangedPriority() {
this.ruleChangedPriority = true;
}
public boolean hasRuleChangedPriority() {
return this.ruleChangedPriority;
}
public void oneRuleHasChangedEvailability() {
this.ruleChangedEvailability = true;
}
public boolean hasRuleChangedEvailability() {
return this.ruleChangedEvailability;
}
/**
* Iterate through all of my rules.
*
* @see agg.xt_basis.Rule
*/
public final Enumeration<Rule> getRules() {
return this.itsRules.elements();
}
public final Iterator<Rule> getRuleIterator() {
return this.itsRules.iterator();
}
/**
* @deprecated replaced by <code>getListOfRules()</code>
*/
public final Vector<Rule> getRulesVec() {
return this.itsRules;
}
public Vector<Rule> getRulesForLayer(final int l) {
final Vector<Rule> v = new Vector<Rule>(5);
for (int i = 0; i < this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
if (r.getLayer() == l) {
v.add(r);
}
}
return v;
}
public void enableRuleLayer(final int l, final boolean enabled) {
for (int i = 0; i < this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
if (r.getLayer() == l) {
r.setEnabled(enabled);
}
}
}
public boolean isRuleLayerEnabled(final int l) {
boolean result = false;
for (int i = 0; i < this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
if (r.getLayer() == l && r.isEnabled()) {
result = true;
break;
}
}
return result;
}
public final Rule getRule(final int ruleIndx) {
Rule r = null;
if (ruleIndx < this.itsRules.size()) {
r = this.itsRules.get(ruleIndx);
}
return r;
}
public final Rule getRule(final String name) {
for (int i = 0; i < this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
if (r.getRuleScheme() == null) {
if (r.getName().equals(name)) {
return r;
}
} else {
r = r.getRuleScheme().getRule(name);
if (r != null) {
return r;
}
}
}
return null;
}
public final Rule getRuleByQualifiedName(final String name) {
for (int i = 0; i < this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
if (r.getRuleScheme() == null) {
if (r.getQualifiedName().equals(name)) {
return r;
}
} else {
r = r.getRuleScheme().getRuleByQualifiedName(name);
if (r != null) {
return r;
}
}
}
return null;
}
public MorphCompletionStrategy getMorphismCompletionStrategy() {
return this.strategy;
}
public final List<Evaluable> getListOfAtomicObjects() {
return getAtomicObjects();
}
/**
* Iterate through all of my atomic graph constraints.
*
* @see agg.cons.AtomConstraint
*/
public final Enumeration<AtomConstraint> getAtomics() {
return this.itsAtomics.elements();
}
public final AtomConstraint getAtomic(String name) {
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint ac = this.itsAtomics.get(i);
if (ac.getAtomicName().equals(name))
return ac;
}
return null;
}
/**
* Returns a list of my atomic graph constraints.
*
* @see agg.cons.AtomConstraint
*/
public final List<AtomConstraint> getListOfAtomics() {
return this.itsAtomics;
}
private final List<String> getAtomicNames() {
final List<String> names = new Vector<String>(this.itsAtomics.size());
for (int i = 0; i < this.itsAtomics.size(); i++) {
names.add(this.itsAtomics.get(i).getAtomicName());
}
return names;
}
private final List<Evaluable> getAtomicObjects() {
final List<Evaluable> res = new Vector<Evaluable>(this.itsAtomics.size());
for (int i = 0; i < this.itsAtomics.size(); i++) {
res.add(this.itsAtomics.get(i));
}
return res;
}
/**
* Returns a list of my constraints (formulae).
*
* @see agg.cons.Formula
*/
public final List<Formula> getListOfConstraints() {
return this.itsConstraints;
}
/**
* Iterate through all of my constraints (formulae).
*
* @see agg.cons.Formula
*/
public final Enumeration<Formula> getConstraints() {
return this.itsConstraints.elements();
}
/**
* Returns all of my constraints (formulae).
*
* @see agg.cons.Formula
* @deprecated replaced by <code>getListOfConstraints()</code>
*/
public final Vector<Formula> getConstraintsVec() {
return this.itsConstraints;
}
/**
* Returns constraints (formulae) that should be satisfied for all layers of
* a layered grammar. In case of a non-layered grammar it returns all its
* constraints. Vector elements are of type <code>Formula</code>.
*
* @see agg.cons.Formula
*/
public List<Formula> getGlobalConstraints() {
return getConstraintsForLayer(-1);
}
/**
* Returns constraints (formulae) for the specified layer. Vector elements
* are of type <code>Formula</code>.
*
* @see agg.cons.Formula
*/
public List<Formula> getConstraintsForLayer(final int l) {
final List<Formula> v = new Vector<Formula>(5);
for (int i = 0; i < this.itsConstraints.size(); i++) {
final Formula c = this.itsConstraints.get(i);
final Vector<Integer> layer = c.getLayer();
if (l == -1 && layer.isEmpty()) {
v.add(c);
} else if ((l > -1) && !layer.isEmpty()) {
for (int j = 0; j < layer.size(); j++) {
final Integer I = layer.get(j);
if (I.intValue() == l) {
v.add(c);
break;
}
}
}
}
return v;
}
/**
* Returns constraints (formulae) for the specified rule priority. If p is
* -1, returns all constraints. Vector elements are of type
* <code>Formula</code>.
*
* @see agg.cons.Formula
*/
public Vector<Formula> getConstraintsForPriority(final int p) {
Vector<Formula> v = new Vector<Formula>(5);
for (int i = 0; i < this.itsConstraints.size(); i++) {
Formula c = this.itsConstraints.get(i);
Vector<Integer> prior = c.getPriority();
if (p == -1 && prior.isEmpty()) {
v.add(c);
} else if ((p > -1) && !prior.isEmpty()) {
for (int j = 0; j < prior.size(); j++) {
Integer I = prior.get(j);
if (I.intValue() == p) {
v.add(c);
break;
}
}
}
}
return v;
}
private void refreshConstraints() {
for (int i = 0; i < this.itsConstraints.size(); i++) {
Formula c = this.itsConstraints.get(i);
c.getAsString(getAtomicObjects(), getAtomicNames());
}
}
public void refreshConstraintsForLayer() {
Vector<String> itsLayers = getLayers();
for (int i = 0; i < this.itsConstraints.size(); i++) {
Formula c = this.itsConstraints.get(i);
Vector<Integer> layer = c.getLayer();
Enumeration<Integer> e = layer.elements();
while (e.hasMoreElements()) {
Integer l = e.nextElement();
boolean found = false;
for (int j = 0; j < itsLayers.size(); j++) {
try {
Integer I = Integer.valueOf(itsLayers.get(j));
if (I.intValue() == l.intValue()) {
found = true;
break;
}
} catch (NumberFormatException ex) {}
}
if (!found) {
layer.remove(l);
e = layer.elements();
}
}
}
}
public void refreshConstraintsForPriority() {
Vector<String> itsPriors = getPriorities();
for (int i = 0; i < this.itsConstraints.size(); i++) {
Formula c = this.itsConstraints.get(i);
Vector<Integer> prior = c.getPriority();
Enumeration<Integer> e = c.getPriority().elements();
while (e.hasMoreElements()) {
Integer p = e.nextElement();
boolean found = false;
for (int j = 0; j < itsPriors.size(); j++) {
try {
Integer I = Integer.valueOf(itsPriors.get(j));
if (I.intValue() == p.intValue()) {
found = true;
break;
}
} catch (NumberFormatException ex) {}
}
if (!found) {
prior.remove(p);
e = prior.elements();
}
}
}
}
/**
* Create an empty rule.
*/
public Rule createRule() {
final Rule r = new Rule(this.typeSet);
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
r.getLeft().xyAttr = true;
r.getRight().xyAttr = true;
}
this.itsRules.add(r);
return r;
}
/**
* Create a rule scheme with an empty kernel rule and an empty list of multi rules.
* Add the new rule scheme at the end of the rule list.
* @return RuleScheme
*/
public RuleScheme createRuleScheme() {
final RuleScheme rs = new RuleScheme("RuleScheme"+String.valueOf(this.itsRules.size()), this.typeSet);
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
rs.getKernelRule().getLeft().xyAttr = true;
rs.getKernelRule().getRight().xyAttr = true;
}
this.itsRules.add(rs);
return rs;
}
/**
* Create a rule scheme with a kernel rule as a copy of the specified rule
* and an empty list of multi rules.
* Add the new rule scheme after the given rule in case it belongs to this grammar
* or at the end of the rule list.
* @return RuleScheme or null if creation failed
*/
public RuleScheme createRuleScheme(final Rule r) {
final RuleScheme rs = BaseFactory.theBaseFactory.makeRuleScheme(r);
if (rs != null) {
int indx = this.itsRules.indexOf(r);
if (indx >= 0)
this.itsRules.add(indx+1, rs);
else
this.itsRules.add(rs);
}
return rs;
}
/**
* Add the specified rule scheme to the rule list.
*/
public boolean addRuleScheme(final RuleScheme rs) {
boolean result = true;
if (this.itsRules.contains(rs)) {
result = false;
} else {
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
rs.getKernelRule().getLeft().xyAttr = true;
rs.getKernelRule().getRight().xyAttr = true;
for (Rule mr : rs.getMultiRules()) {
mr.getLeft().xyAttr = true;
mr.getRight().xyAttr = true;
}
}
this.itsRules.add(rs);
}
return result;
}
/**
* Sort rules by rule priority.
*/
public void sortRulesByPriority() {
RulePriority priority = new RulePriority(this.itsRules);
Integer startPriority = priority.getStartPriority();
Hashtable<Integer, HashSet<Rule>> invertedRulePriority = priority.invertPriority();
OrderedSet<Integer> rulePrioritySet = new OrderedSet<Integer>(new IntComparator<Integer>());
for (Enumeration<Integer> en = invertedRulePriority.keys(); en
.hasMoreElements();) {
rulePrioritySet.add(en.nextElement());
}
int i = 0;
// empty vector of rules
this.itsRules.clear();
// iterate by priority
Integer currentPriority = startPriority;
boolean nextPriorityExists = true;
while (nextPriorityExists && (currentPriority != null)) {
// set current rules
HashSet<Rule> rulesForPriority = invertedRulePriority.get(currentPriority);
Iterator<Rule> en = rulesForPriority.iterator();
while (en.hasNext()) {
Rule r = en.next();
// fill vector of rules
this.itsRules.add(r);
}
// set next priority
i++;
if (i < rulePrioritySet.size()) {
currentPriority = rulePrioritySet.get(i);
}
else {
nextPriorityExists = false;
}
}
}
/**
* Sort rules by layer.
*/
public void sortRulesByLayer() {
RuleLayer layer = new RuleLayer(this.itsRules);
Integer startLayer = layer.getStartLayer();
Map<Integer, HashSet<Rule>> invertedRuleLayer = layer.invertLayer();
OrderedSet<Integer> ruleLayer = new OrderedSet<Integer>(new IntComparator<Integer>());
for (Iterator<Integer> en = invertedRuleLayer.keySet().iterator(); en.hasNext();) {
ruleLayer.add(en.next());
}
int i = 0;
// empty vector of rules
this.itsRules.clear();
// iterate by layer
Integer currentLayer = startLayer;
boolean nextLayerExists = true;
while (nextLayerExists && (currentLayer != null)) {
// set current rules
HashSet<?> rulesForLayer = invertedRuleLayer.get(currentLayer);
Iterator<?> en = rulesForLayer.iterator();
while (en.hasNext()) {
Rule r = (Rule) en.next();
// fill vector of rules
this.itsRules.add(r);
}
// set next layer
i++;
if (i < ruleLayer.size()) {
currentLayer = ruleLayer.get(i);
}
else {
nextLayerExists = false;
}
}
}
/**
* Sort constraints (formulae) by layer.
*/
public void sortConstraintsByLayer() {
ConstraintLayer layer = new ConstraintLayer(this.itsConstraints);
Integer startLayer = layer.getStartLayer();
Map<Integer, HashSet<Object>> invLayer = layer.invertLayer();
OrderedSet<Integer> formulaLayer = new OrderedSet<Integer>(new IntComparator<Integer>());
for (Iterator<Integer> en = invLayer.keySet().iterator(); en.hasNext();) {
formulaLayer.add(en.next());
}
int i=0;
// empty vector of rules
this.itsConstraints.clear();
// iterate by layer
Integer currentLayer = startLayer;
boolean nextLayerExists = true;
while (nextLayerExists && (currentLayer != null)) {
// set current formulae
HashSet<?> constraintsForLayer = invLayer.get(currentLayer);
Iterator<?> en = constraintsForLayer.iterator();
while (en.hasNext()) {
Formula f = (Formula) en.next();
// fill vector of formulae
this.itsConstraints.add(f);
}
// set next layer
i++;
if (i < formulaLayer.size()) {
currentLayer = formulaLayer.get(i);
}
else {
nextLayerExists = false;
}
}
}
/**
* Sort constraints (formulae) by priority.
*/
public void sortConstraintsByPriority() {
ConstraintPriority cons = new ConstraintPriority(this.itsConstraints);
Integer start = cons.getStartPriority();
Map<Integer, HashSet<Object>> inverted = cons.invertPriority();
OrderedSet<Integer> set = new OrderedSet<Integer>(new IntComparator<Integer>());
for (Iterator<Integer> en = inverted.keySet().iterator(); en.hasNext();) {
set.add(en.next());
}
int i=0;
// empty vector of rules
this.itsConstraints.clear();
// iterate by layer
Integer current = start;
boolean nextExists = true;
while (nextExists && (current != null)) {
// set current formulae
HashSet<?> constraintsForLayer = inverted.get(current);
Iterator<?> en = constraintsForLayer.iterator();
while (en.hasNext()) {
Formula f = (Formula) en.next();
// fill vector of formulae
this.itsConstraints.add(f);
}
// set next layer
i++;
if (i < set.size()) {
current = set.get(i);
}
else {
nextExists = false;
}
}
}
/**
* Create a copy of my host graph.
*/
public Graph cloneGraph() {
return this.itsGraph.graphcopy();
}
/**
* Returns a copy of the Rule <code>r</code>.
*/
public Rule cloneRule(final Rule r) {
Rule aNewRule = BaseFactory.theFactory().cloneRule(r, this.typeSet, true);
this.itsRules.add(aNewRule);
return aNewRule;
}
/**
* Returns an inverse rule of the Rule <code>r</code>.
*/
public Rule reverseRule(final Rule r) {
final Pair<Pair<Rule,Boolean>, Pair<OrdinaryMorphism, OrdinaryMorphism>>
inverseRulePair = BaseFactory.theFactory().reverseRule(r);
if (inverseRulePair != null) {
Rule invRule = inverseRulePair.first.first;
r.disposeInverseConstruct();
return invRule;
}
return null;
}
/**
* Returns an inverse rule scheme of the RuleScheme <code>rs</code>.
*/
public RuleScheme reverseRuleScheme(final RuleScheme rs) {
RuleScheme invRS = BaseFactory.theFactory().reverseRuleScheme(rs);
return invRS;
}
public AtomConstraint createAtomic(final String name) {
final AtomConstraint ac = (BaseFactory.theFactory())
.createAtomic(this.typeSet, name);
ac.setMorphismCompletionStrategy(this.strategy);
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
ac.getSource().xyAttr = true;
ac.getTarget().xyAttr = true;
}
this.itsAtomics.add(ac);
return ac;
}
public boolean addAtomic(final AtomConstraint ac) {
boolean result = true;
if (this.itsAtomics.contains(ac)) {
result = false;
} else {
// test: use xy position as attributes
if (this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE)) {
ac.getSource().xyAttr = true;
ac.getTarget().xyAttr = true;
}
ac.setMorphismCompletionStrategy(this.strategy);
this.itsAtomics.add(ac);
}
return result;
}
public boolean removeAtomic(final AtomConstraint ac) {
for (int i = 0; i < this.itsConstraints.size(); i++) {
this.itsConstraints.get(i).patchOutEvaluable(ac, true);
}
return this.itsAtomics.remove(ac);
}
public Formula createConstraint(final String name) {
// clearRuleConstraints();
Formula f = new Formula(true);
f.setName(name);
this.itsConstraints.add(f);
return f;
}
public boolean addConstraint(final Formula f) {
boolean result = true;
if (this.itsConstraints.contains(f)) {
result = false;
} else {
// clearRuleConstraints();
this.itsConstraints.add(f);
}
return result;
}
/** Dispose the type graph. */
public void destroyTypeGraph() {
this.typeSet.removeTypeGraph();
}
/** Dispose the specified rule. */
public void destroyRule(final Rule rule) {
if (this.itsRules.remove(rule)) {
rule.dispose();
}
}
public void destroyAllRules() {
while (!this.itsRules.isEmpty()) {
Rule rule = this.itsRules.get(0);
this.itsRules.remove(0);
rule.dispose();
}
}
public void destroyAtomic(final AtomConstraint a) {
if (this.itsAtomics.remove(a)) {
clearRuleConstraints(a);
for (int i = 0; i < this.itsConstraints.size(); i++) {
this.itsConstraints.get(i).patchOutEvaluable(a, true);
}
a.dispose(true, true);
}
}
public void destroyAllAtomics() {
int n = this.itsAtomics.size()-1;
while(!this.itsAtomics.isEmpty()) {
AtomConstraint a = this.itsAtomics.remove(n);
clearRuleConstraints(a);
for (int i = 0; i < this.itsConstraints.size(); i++) {
this.itsConstraints.get(i).patchOutEvaluable(a, true);
}
a.dispose();
n = this.itsAtomics.size()-1;
}
}
public void destroyConstraint(final Formula f) {
if (this.itsConstraints.remove(f)) {
clearRuleConstraints(f);
}
}
public void destroyAllConstraints() {
while(!this.itsConstraints.isEmpty()) {
Formula f = this.itsConstraints.get(0);
this.itsConstraints.remove(0);
clearRuleConstraints(f);
}
}
public Vector<String> destroyGraphObjectsOfType(final Type t,
boolean fromTypeGraph) {
Vector<String> failed = new Vector<String>(5);
// delete from host graphs
for (int i = 0; i < this.itsGraphs.size(); i++) {
Graph g = this.itsGraphs.get(i);
if (!g.destroyObjectsOfType(t)) {
failed.add(g.getName());
}
}
// delete from rules
Iterator<Rule> rules = this.itsRules.iterator();
while (rules.hasNext()) {
Rule r = rules.next();
if (!r.destroyObjectsOfType(t)) {
failed.add(r.getName());
}
}
// delete from atomic graph constraints
Enumeration<AtomConstraint> atomics = getAtomics();
while (atomics.hasMoreElements()) {
AtomConstraint a = atomics.nextElement();
a.getSource().destroyObjectsOfType(t);
Enumeration<AtomConstraint> conclusions = a.getConclusions();
while (conclusions.hasMoreElements()) {
AtomConstraint c = conclusions.nextElement();
if (!c.getTarget().destroyObjectsOfType(t)) {
failed.add(c.getName());
}
}
}
// delete from type graph
if (this.typeSet.getTypeGraph() != null
&& fromTypeGraph
&& !this.typeSet.getTypeGraph().destroyObjectsOfType(t)) {
failed.add(this.typeSet.getTypeGraph().getName());
}
return failed;
}
/**
*
* @param ts
* A type set
* @param fromTypeGraph
* Is to destroy the graph objects from the Type Graph or not
* @return
* <code>null</code> if destroying was successful, otherwise - a list with failed types.
*/
public Vector<String> destroyGraphObjectsOfTypes(final Vector<Type> ts,
final boolean fromTypeGraph) {
Vector<String> failed = null;
if (this.itsStartGraph != null) {
this.itsStartGraph.destroyObjectsOfTypes(ts);
}
Vector<String> v = null;
// delete from host graph
for (int i = 0; i < this.itsGraphs.size(); i++) {
Graph g = this.itsGraphs.get(i);
v = g.destroyObjectsOfTypes(ts);
if (v != null) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
}
// delete from rules
Iterator<Rule> rules = this.itsRules.iterator();
while (rules.hasNext()) {
Rule r = rules.next();
v = r.destroyObjectsOfTypes(ts);
if (!v.isEmpty()) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
}
// delete from atomic graph constraints
Enumeration<AtomConstraint> atomics = getAtomics();
while (atomics.hasMoreElements()) {
AtomConstraint a = atomics.nextElement();
v = a.getSource().destroyObjectsOfTypes(ts);
if (v != null) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
Enumeration<AtomConstraint> conclusions = a.getConclusions();
while (conclusions.hasMoreElements()) {
AtomConstraint c = conclusions.nextElement();
v = c.getTarget().destroyObjectsOfTypes(ts);
if (v != null) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
}
}
// delete from type graph
if (this.typeSet.getTypeGraph() != null && fromTypeGraph) {
v = this.typeSet.getTypeGraph().destroyObjectsOfTypes(ts);
if (v != null) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
}
return failed;
}
/**
* @param t
* A node or an edge type
* @return
* <code>true</code> if destroying was successful, otherwise >code>false</code>
*/
public boolean destroyGraphObjectsOfTypeFromHostGraph(final Type t) {
// delete from host graph
return this.itsGraph.destroyObjectsOfType(t);
}
/**
*
* @param ts
* A type list
* @return
* <code>null</code> if destroying was successful, otherwise - a list with failed types.
*/
public Vector<String> destroyGraphObjectsOfTypesFromHostGraph(
final Vector<Type> ts) {
// delete from host graph
return this.itsGraph.destroyObjectsOfTypes(ts);
}
/**
* @param t
* A node or an edge type
* @return
* <code>empty list</code> if destroying was successful, otherwise - a list with names of failed rules.
*/
public Vector<String> destroyGraphObjectsOfTypeFromRules(final Type t) {
Vector<String> failed = new Vector<String>(5);
// delete from rules
Iterator<Rule> rules = this.itsRules.iterator();
while (rules.hasNext()) {
Rule r = rules.next();
if (!r.destroyObjectsOfType(t)) {
failed.add(r.getName());
}
}
return failed;
}
/**
* @param ts
* A list of types
* @return
* <code>empty list</code> if destroying was successful, otherwise - a list with names of failed rules.
*/
public Vector<String> destroyGraphObjectsOfTypesFromRules(final Vector<Type> ts) {
Vector<String> failed = new Vector<String>(5);
// delete from rules
Iterator<Rule> rules = this.itsRules.iterator();
while (rules.hasNext()) {
Rule r = rules.next();
Vector<String> v = r.destroyObjectsOfTypes(ts);
if (!v.isEmpty()) {
failed.addAll(v);
}
}
return failed;
}
/**
* @param t
* A node or an edge type
* @return
* <code>empty list</code> if destroying was successful, otherwise - a list with names of failed
* graph constraints.
*/
public Vector<String> destroyGraphObjectsOfTypeFromGraphConstraints(final Type t) {
Vector<String> failed = new Vector<String>(5);
// delete from atomic graph constraints
Enumeration<AtomConstraint> atomics = getAtomics();
while (atomics.hasMoreElements()) {
AtomConstraint a = atomics.nextElement();
a.getSource().destroyObjectsOfType(t);
Enumeration<AtomConstraint> conclusions = a.getConclusions();
while (conclusions.hasMoreElements()) {
AtomConstraint c = conclusions.nextElement();
if (!c.getTarget().destroyObjectsOfType(t)) {
failed.add(c.getName());
}
}
}
return failed;
}
/**
* @param ts
* A list of types
* @return
* <code>empty list</code> if destroying was successful, otherwise - a list with names of failed
* graph constraints.
*/
public Vector<String> destroyGraphObjectsOfTypesFromGraphConstraints(
final Vector<Type> ts) {
Vector<String> failed = null;
// delete from atomic graph constraints
Enumeration<AtomConstraint> atomics = getAtomics();
while (atomics.hasMoreElements()) {
AtomConstraint a = atomics.nextElement();
Vector<String> v = a.getSource().destroyObjectsOfTypes(ts);
if (v != null) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
Enumeration<AtomConstraint> conclusions = a.getConclusions();
while (conclusions.hasMoreElements()) {
AtomConstraint c = conclusions.nextElement();
v = c.getTarget().destroyObjectsOfTypes(ts);
if (v != null) {
if (failed == null)
failed = new Vector<String>(5);
failed.addAll(v);
}
}
}
return failed;
}
/**
* Iterate through all of the matches existing between the given rule and
* the start graph. Enumeration elements are of type <code>Match</code>.
*
* @see agg.xt_basis.Match
*
* @return
* Enumeration with elements of the type <code>Match</code>.
*/
public final Enumeration<Match> getMatches(Rule rule) {
Vector<Match> mtchs = new Vector<Match>();
for (int i = 0; i < this.itsMatches.size(); i++) {
Match m = this.itsMatches.get(i);
if (m.getRule().equals(rule)) {
mtchs.add(m);
}
}
return mtchs.elements();
}// getMatches
/**
* Iterate through all of the matches existing between the given rule and
* all graphs of this grammar. Returns the match for the specified rule and
* graph if such is found, otherwise null.
*/
public final Match getMatch(final Rule rule, final Graph g) {
Match m = null;
for (int i = 0; i < this.itsMatches.size(); i++) {
if (this.itsMatches.get(i).getRule() == rule
&& this.itsMatches.get(i).getTarget() == g) {
m = this.itsMatches.get(i);
}
}
return m;
}
/**
* Create an empty match morphism between the left hand side of the given rule
* and my current host graph.
* Note that this does not yield a valid match
* (unless the left hand side of the given rule is empty),
* because a match has to be a total morphism.
*/
public Match createMatch(Rule rule) {
// if (rule instanceof RuleScheme) {
// Match m = ((RuleScheme) rule).getMatch(this.itsGraph);
// rule.setMatch(m);
// this.itsMatches.add(m);
// return m;
// }
// else
{
Match m = new Match(rule, this.itsGraph);
rule.setMatch(m);
this.itsMatches.add(m);
return m;
}
}
/**
* Create an empty match morphism between the left hand side of the given rule
* and the given graph.
* Note that this does not yield a valid match
* (unless the left hand side of the given rule is empty),
* because a match has to be a total morphism.<br>
* The given Graph g is set to be the current graph of the grammar.
*/
public Match createMatch(Rule rule, Graph g) {
if (this.resetGraph(g)) {
Match m = new Match(rule, g);
rule.setMatch(m);
this.itsMatches.add(m);
return m;
}
return null;
}
public void addMatch(final Match m) {
if (m != null)
this.itsMatches.add(m);
}
/** Dispose the specified match. */
public void destroyMatch(Match match) {
if (match != null) {
if (match.getRule() != null)
match.getRule().setMatch(null);
this.itsMatches.remove(match);
match.dispose();
}
}
public void destroyMatches(Graph g) {
for (int i = 0; i < this.itsMatches.size(); i++) {
Match match = this.itsMatches.get(i);
if (match.getTarget() == g) {
this.itsMatches.remove(match);
i--;
if (match.getRule() != null)
match.getRule().setMatch(null);
match.dispose();
}
}
}
public void destroyAllMatches() {
while (!this.itsMatches.isEmpty()) {
Match match = this.itsMatches.remove(0);
if (match != null) {
if (match.getRule() != null)
match.getRule().setMatch(null);
match.dispose();
}
}
}
/*
* Replace its type set by the specified sharedTypes.
* Precondition: this GraGra has to contain at most one empty host graph
* and one empty rule. Its type set should be empty, too.
*
* @param sharedTypes the type set to share
* @return true if setting was successful, otherwise - false
*/
/*
private boolean setSharedTypes(final TypeSet sharedTypes) {
if ((this.getListOfGraphs().size() == 0
|| (this.getListOfGraphs().size() == 1
&& this.getListOfGraphs().get(0).isEmpty()))
&& (this.getListOfRules().size() == 0
|| (this.getListOfRules().size() == 1
&& this.getListOfRules().get(0).isEmptyRule()))
&& this.getListOfAtomics().size() == 0
&& this.getListOfConstraints().size() == 0) {
this.typeSet = sharedTypes;
if (this.getListOfGraphs().size() == 1) {
this.getListOfGraphs().get(0).setTypeSet(this.typeSet);
}
if (this.getListOfRules().size() == 1) {
this.getListOfRules().get(0).getLeft().setTypeSet(this.typeSet);
this.getListOfRules().get(0).getRight().setTypeSet(this.typeSet);
}
return true;
}
return false;
}
*/
/**
* Creates an empty type graph.
* If a type graph was already defined, it will be lost.
*/
public Graph createTypeGraph() {
Graph tg = this.typeSet.createTypeGraph();
// test: use XY position as attributes
tg.xyAttr = this.gratraOptions.contains(GraTraOptions.XY_POS_ATTRIBUTE);
return tg;
}
/**
* Returns the type graph or <code>null</code>,
* if no type graph was created before.
*/
public Graph getTypeGraph() {
return this.typeSet.getTypeGraph();
}
/**
* Create a new type for typing of GraphObjects.
*
* @deprecated replaced by
* <code>Type createNodeType(boolean withAttributes)</code> for node type
* and
* <code>Type createArcType(boolean withAttributes)</code> for edge type
*/
public Type createType() {
return this.typeSet.createType();
}
/*
* Create a new type for typing of GraphObjects.
*
* @deprecated replaced by
* <code>Type createNodeType(boolean withAttributes)</code> for node type
* and
* <code>Type createArcType(boolean withAttributes)</code> for edge type
*/
public Type createType(boolean withAttributes) {
return this.typeSet.createType(withAttributes);
}
/**
* Creates a new node type for typing of Node.
* @param withAttributes if true, then attribute type is also created
*/
public Type createNodeType(boolean withAttributes) {
return this.typeSet.createNodeType(withAttributes);
}
/**
* Creates a new arc type for typing of Arc.
* @param withAttributes if true, then attribute type is also created
*/
public Type createArcType(boolean withAttributes) {
return this.typeSet.createArcType(withAttributes);
}
/** Returns <code>true</code> if this gragra uses the specified type. */
public boolean isUsingType(final GraphObject t) {
boolean result = graphIsUsingType(t)
|| ruleIsUsingType(t)
|| constraintIsUsingType(t);
return result;
}
private boolean graphIsUsingType(final GraphObject t) {
boolean result = false;
for (int i = 0; i < this.itsGraphs.size(); i++) {
if (this.itsGraphs.get(i).isUsingType(t)) {
result = true;
}
}
if (this.itsStartGraph != null) {
result = result || this.itsStartGraph.isUsingType(t);
}
return result;
}
private boolean ruleIsUsingType(final GraphObject t) {
boolean result = false;
for (int i = 0; i < this.itsRules.size(); i++) {
if (this.itsRules.get(i).isUsingType(t)) {
result = true;
}
}
return result;
}
private boolean constraintIsUsingType(final GraphObject t) {
boolean result = false;
Iterator<AtomConstraint> e = this.itsAtomics.iterator();
while (!result && e.hasNext()) {
AtomConstraint atom = e.next();
if (atom.getSource().isUsingType(t)
|| atom.getTarget().isUsingType(t)) {
result = true;
}
}
return result;
}
public void refreshAttributed() {
for (int i = 0; i < this.itsGraphs.size(); i++) {
this.itsGraphs.get(i).refreshAttributed();
}
if (this.itsStartGraph != null) {
this.itsStartGraph.refreshAttributed();
}
for (int i = 0; i < this.itsRules.size(); i++) {
this.itsRules.get(i).refreshAttributed();
}
for (int i=0; i<this.itsAtomics.size(); i++) {
this.itsAtomics.get(i).refreshAttributed();
}
}
/**
* returns the type manger used in this gragra and in all its graphs.
*/
public TypeSet getTypeSet() {
return this.typeSet;
}
/**
* Iterate through all of the types that may be assigned to GraphObjects.
* Enumeration elements are of type <code>Type</code>.
*
* @see agg.xt_basis.Type
*/
public Enumeration<Type> getTypes() {
return this.typeSet.getTypes();
}
/** Dispose the specified type. */
public void destroyType(Type type) throws TypeException {
this.typeSet.destroyType(type);
}
/**
* changes the behavior of the type graph check and defines, how the type
* graph is used. The host graph must satisfies the new level, so it is
* checked first. If the host graph satisfies the constraints, an empty
* collection will be returned and a collection of
* {@link agg.xt_basis.TypeError} if there were problems during the test.
*
* @param level
* <table>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#DISABLED}</td>
* <td>The type graph will be ignored, so all graphs can contain
* objects with types undefined in the type graph. Multiplicity
* will be also ignored.</td>
* </tr>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#ENABLED}</td>
* <td>The type graph will be basicaly used, so all graphs can
* only contain objects with types defined in the type graph. But
* the multiplicity will not be checked.</td>
* </tr> } *
* <tr>
* <td>{@link agg.xt_basis.TypeSet#ENABLED_MAX}</td>
* <td>The type graph will be basicaly used, so all graphs can
* only contain objects with types defined in the type graph.
* Multiplicities in all graphs should satisfy the defined
* maximum constraints.</td>
* </tr>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#ENABLED_MAX_MIN}</td>
* <td>The type graph is defined and used, so all graphs can only
* contain objects with types defined in the type graph.
* All graphs must satisfy the defined maximum/minimum multiplicity
* constraints of node and edge types.</td>
* </tr>
* </table>
*/
public Collection<TypeError> setLevelOfTypeGraphCheck(int level) {
// System.out.println("GraGra.setLevelOfTypeGraphCheck :: "+level);
this.multiplErrKind = -1;
int oldLevel = this.typeSet.getLevelOfTypeGraphCheck();
// first check the type graph
Collection<TypeError> checkResult = this.typeSet
.setLevelOfTypeGraphCheck(level);
if (checkResult.isEmpty()) {
// save the errors of more checks
Vector<TypeError> errors = new Vector<TypeError>();
// the host graphs
Iterator<Graph> graphIt = this.itsGraphs.iterator();
while (graphIt.hasNext()) {
Graph g = graphIt.next();
if (!g.isEmpty() || level == TypeSet.ENABLED_MAX_MIN)
errors.addAll(this.typeSet.checkType(g));
}
if (level != TypeSet.DISABLED) {
// if (level == TypeSet.ENABLED_MAX){
// all rules
Iterator<Rule> ruleIt = this.itsRules.iterator();
while (ruleIt.hasNext()) {
Rule r = ruleIt.next();
if (r.getRuleScheme() == null)
errors.addAll(this.typeSet.checkType(r));
else {
errors.addAll(this.typeSet.checkType(r.getRuleScheme().getKernelRule()));
for (int i=0; i<r.getRuleScheme().getMultiRules().size(); i++) {
errors.addAll(this.typeSet.checkType(r.getRuleScheme().getMultiRules().get(i)));
}
}
}
// all atomics
Iterator<AtomConstraint> en = this.itsAtomics.iterator();
while (en.hasNext()) {
errors.addAll(this.typeSet.checkType(en.next()));
}
}
if (!errors.isEmpty()) {
if (oldLevel == level) {
oldLevel = TypeSet.ENABLED;
}
this.typeSet.setLevelOfTypeGraphCheck(oldLevel);
}
// return errors or empty list
return errors;
}
if (oldLevel == level) {
oldLevel = TypeSet.DISABLED;
}
return checkResult;
}// setLevelOfTypeGraphCheck
/**
* returns the level of type graph usage in the type set.
*
* @return <table>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#DISABLED}</td>
* <td>The type graph will be ignored, so all graphs can contain
* objects with types undefined in the type graph. Multiplicity will
* be also ignored.</td>
* </tr>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#ENABLED}</td>
* <td>The type graph will be basicaly used, so all graphs can only
* contain objects with types defined in the type graph. But the
* multiplicity will not be checked.</td>
* </tr>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#ENABLED_MAX}</td>
* <td>The type graph will be basicaly used, so all graphs can only
* contain objects with types defined in the type graph.
* Multiplicities in all graphs should satisfy the defined maximum
* constraints.</td>
* </tr>
* <tr>
* <td>{@link agg.xt_basis.TypeSet#ENABLED_MAX_MIN}</td>
* <td>The type graph will be used, so all graphs can only contain
* objects with types defined in the type graph. Multiplicities in
* all graphs must satisfy the defined maximum constraints and the
* hosting graph must</td>
* </tr>
* </table>
*/
public int getLevelOfTypeGraphCheck() {
return this.typeSet.getLevelOfTypeGraphCheck();
}// getLevelOfTypeGraphCheck
public void setMorphismCompletionStrategyOfGraphConstraints() {
// System.out.println(this.this.strategy);
// set morphism completion strategy
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint a = this.itsAtomics.get(i);
a.setMorphismCompletionStrategy(this.strategy);
}
}
private int getMultiplicityErrorKind(int currentKind, TypeError error) {
if ((currentKind != TypeError.TO_MUCH_NODES)
&& (error.getErrorNumber() == TypeError.TO_MUCH_NODES))
return error.getErrorNumber();
else if (currentKind == -1)
return error.getErrorNumber();
else
return currentKind;
}
/**
* Checks all graphs of this GraGra due to node type multiplicity
* of the specified type Node of the current type graph.
*
* @param typeNode
* @return null
* if all graphs satisfy multiplicity constraint,
* otherwise - a string with names of failed graphs
*/
public String checkNodeTypeMultiplicity(final Node typeNode) {
int errorkind = -1;
final List<String> result = new Vector<String>();
// check graphs
for (int i=0; i<this.itsGraphs.size(); i++) {
final Graph graph = this.itsGraphs.get(i);
TypeError error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
graph,
this.getLevelOfTypeGraphCheck());
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(graph.getName());
}
// else {
// error = graph.checkNodeRequiresArc();
// errorkind = getMultiplicityErrorKind(errorkind, error);
// result.add(graph.getName());
// }
}
// check graphs of rules
for (int i=0; i<this.itsRules.size(); i++) {
final Rule rule = this.itsRules.get(i);
TypeError error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
rule.getLeft(),
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(rule.getLeft().getName());
}
error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
rule.getRight(),
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(rule.getRight().getName());
}
// check NACs
final List<OrdinaryMorphism> nacs = rule.getNACsList();
for (int l=0; l<nacs.size(); l++) {
final Graph nacgraph = nacs.get(l).getTarget();
error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
nacgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(nacgraph.getName());
}
}
// check PACs
final List<OrdinaryMorphism> pacs = rule.getPACsList();
for (int l=0; l<pacs.size(); l++) {
final Graph pacgraph = pacs.get(l).getTarget();
error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
pacgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(pacgraph.getName());
}
}
}
// check atomic graph constraints
for (int i = 0; i < this.itsAtomics.size(); i++) {
final AtomConstraint a = this.itsAtomics.get(i);
final Graph pgraph = a.getConclusion(0).getSource();
TypeError error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
pgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(pgraph.getName());
}
final Enumeration<AtomConstraint> concls = a.getConclusions();
while (concls.hasMoreElements()) {
final Graph cgraph = concls.nextElement().getTarget();
error = this.typeSet.checkNodeTypeMultiplicity(
typeNode.getType(),
cgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(cgraph.getName());
}
}
}
if (!result.isEmpty()) {
this.multiplErrKind = errorkind;
}
return (result.isEmpty())? null: result.toString();
}
/**
* Checks all graphs of this GraGra due to edge type multiplicity
* of the specified type Arc of the current type graph.
*
* @param typeArc
* @return null
* if all graphs satisfy multiplicity constraint,
* otherwise - a string with names of failed graphs
*/
public String checkEdgeTypeMultiplicity(final Arc typeArc) {
int errorkind = -1;
final List<String> result = new Vector<String>();
// check graphs
for (int i=0; i<this.itsGraphs.size(); i++) {
final Graph graph = this.itsGraphs.get(i);
TypeError error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
graph,
this.getLevelOfTypeGraphCheck());
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(graph.getName());
}
}
// check graphs of rules
for (int i=0; i<this.itsRules.size(); i++) {
final Rule rule = this.itsRules.get(i);
TypeError error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
rule.getLeft(),
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(rule.getLeft().getName());
}
error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
rule.getRight(),
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(rule.getRight().getName());
}
// check NACs
final List<OrdinaryMorphism> nacs = rule.getNACsList();
for (int l=0; l<nacs.size(); l++) {
final Graph nacgraph = nacs.get(l).getTarget();
error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
nacgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(nacgraph.getName());
}
}
// check PACs
final List<OrdinaryMorphism> pacs = rule.getPACsList();
for (int l=0; l<pacs.size(); l++) {
final Graph pacgraph = pacs.get(l).getTarget();
error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
pacgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(pacgraph.getName());
}
}
}
// check atomic graph constraints
for (int i = 0; i < this.itsAtomics.size(); i++) {
final AtomConstraint a = this.itsAtomics.get(i);
final Graph pgraph = a.getConclusion(0).getSource();
TypeError error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
pgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(pgraph.getName());
}
final Enumeration<AtomConstraint> concls = a.getConclusions();
while (concls.hasMoreElements()) {
final Graph cgraph = concls.nextElement().getTarget();
error = this.typeSet.checkEdgeTypeMultiplicity(
typeArc,
cgraph,
TypeSet.ENABLED_MAX);
if (error != null) {
errorkind = getMultiplicityErrorKind(errorkind, error);
result.add(cgraph.getName());
}
}
}
if (!result.isEmpty()) {
this.multiplErrKind = errorkind;
}
return (result.isEmpty())? null: result.toString();
}
public int getMultiplicityErrorKind() {
return this.multiplErrKind;
}
/**
* This method checks if all graph constraints (formulas) are valid and then
* when parameter validity is TRUE if the host graph is consistent.
*/
public boolean checkGraphConstraints(boolean validity) {
boolean all_valid = true;
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint a = this.itsAtomics.get(i);
a.setMorphismCompletionStrategy(this.strategy);
if (!a.isValid()) {
this.consistErrMsg = this.consistErrMsg + " "
+ a.getAtomicName() + " ";
all_valid = false;
}
}
if (!all_valid) {
return false;
}
boolean all_good = true;
this.consistErrMsg = "";
Vector<Evaluable> atomics = new Vector<Evaluable>();
atomics.addAll(this.itsAtomics);
for (int i = 0; i < this.itsConstraints.size(); i++) {
Formula f = this.itsConstraints.get(i);
if (!f.isEnabled()) {
continue;
}
if (!f.isValid()) {
// String fn = f.getAsString(this.itsAtomics, getAtomicNames());
String fn = f.getAsString(atomics, getAtomicNames());
if (fn.indexOf('[') == -1) {
this.consistErrMsg = this.consistErrMsg + " " + f.getName()
+ " : " + fn.substring(1, fn.length() - 1) + " ";
} else {
this.consistErrMsg = this.consistErrMsg + " " + f.getName()
+ " : " + fn.substring(1, fn.length() - 1) + " ";
}
all_good = false;
}
if (!validity && !f.eval(this.itsGraph)) {
// String fn = f.getAsString(this.itsAtomics, getAtomicNames());
String fn = f.getAsString(atomics, getAtomicNames());
if (fn.indexOf('[') == -1) {
this.consistErrMsg = this.consistErrMsg + " "
+ f.getName() + " : "
+ fn.substring(0, fn.length()) + " ";
} else {
this.consistErrMsg = this.consistErrMsg + " "
+ f.getName() + " : "
+ fn.substring(1, fn.length() - 1) + " ";
}
all_good = false;
}
}
return all_good;
}
/**
* Returns TRUE if the graph g satisfies all graph constraints of this graph
* grammar. Pre-condition: The graph constraints have to be valid and the
* graph g is a graph of the graph set defined with this grammar.
*/
public boolean checkGraphConsistency(Graph g) {
return checkGraphConsistency(g, this.itsConstraints);
}
/**
* Returns TRUE if the graph g satisfies the specified container with graph
* constraints of this graph grammar. If the parameter constraints is null,
* all constraints of this grammar should be satisfied. Pre-condition: The
* graph constraints have to be valid and the graph g is a graph of the
* graph set defined with this grammar.
*/
public boolean checkGraphConsistency(Graph g, final List<Formula> constraints) {
// System.out.println("GraGra.checkGraphConsistency(Graph, Vector constraints");
this.consistErrMsg = "";
boolean all_valid = true;
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint a = this.itsAtomics.get(i);
a.setMorphismCompletionStrategy(this.strategy);
if (!a.isValid()) {
this.consistErrMsg = this.consistErrMsg + " "
+ a.getAtomicName() + " ";
all_valid = false;
}
}
if (!all_valid) {
return false;
}
Vector<Evaluable> atomics = new Vector<Evaluable>();
atomics.addAll(this.itsAtomics);
for (int i = 0; i < constraints.size(); i++) {
Formula f = constraints.get(i);
@SuppressWarnings("unused")
String fn = f.getAsString(atomics, getAtomicNames());
if (!f.isEnabled()) {
continue;
} else if (!f.isValid()) {
this.consistErrMsg = this.consistErrMsg + " "
+ f.getName() + " ";
return false;
} else if (!f.isEvaluable()) {
this.consistErrMsg = this.consistErrMsg + " "
+ f.getName() + " ";
return true;
} else if (!f.eval(g)) {
this.consistErrMsg = this.consistErrMsg + " "
+ f.getName() + " ";
return false;
}
}
return true;
}
public boolean checkAtomics(boolean checkAtomicValidityOnly) {
this.consistErrMsg = "";
boolean all_valid = true;
boolean all_satisfied = true;
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint a = this.itsAtomics.get(i);
a.setMorphismCompletionStrategy(this.strategy);
if (!a.isValid()) {
this.consistErrMsg = this.consistErrMsg + " "
+ a.getAtomicName() + " ";
all_valid = false;
}
if (all_valid && !checkAtomicValidityOnly && !a.eval(this.itsGraph)) {
this.consistErrMsg = this.consistErrMsg + " "
+ a.getAtomicName() + " ";
all_satisfied = false;
}
}
if (checkAtomicValidityOnly) {
return all_valid;
}
return all_satisfied;
}
public String getConsistencyErrorMsg() {
return this.consistErrMsg;
}
/**
* Converts all constraints (formulas) to post application conditions for
* all rules. Returns empty message if all atomic graph constraints are
* valid and converting for each rule was successful, otherwise - error
* message.
*/
public String convertConstraints() {
String msg = "";
if (this.itsAtomics.size() <= 0 || this.itsConstraints.size() <= 0) {
msg = "Atomics or constraints do not exist.";
return msg;
}
Vector<Rule> rs = new Vector<Rule>();
rs.addAll(this.itsRules);
for (int i = 0; i < rs.size(); i++) {
// check atomics
for (int j = 0; j < this.itsAtomics.size(); j++) {
AtomConstraint a = this.itsAtomics.get(j);
if (!a.isValid()) {
msg = "Atomic \"" + a.getAtomicName() + "\" is not valid";
return msg;
}
}
// convert
Rule r = rs.get(i);
r.clearConstraints();
r.setUsedFormulas(this.itsConstraints);
String msg0 = r.convertUsedFormulas();
if (!"".equals(msg0)) {
msg = "Rule \""
+ r.getName()
+ "\" : \n"
+ msg0
+ "\nConverting constraints to post application conditions failed.";
return msg;
}
}
return msg;
}
/**
* Clear such post application constraints of rules which contain the specified atomic graph constraint.
*/
public void clearRuleConstraints(AtomConstraint ac) {
Iterator<Rule> en = this.itsRules.iterator();
while (en.hasNext()) {
en.next().clearConstraints(ac);
}
}
/**
* Clear such post application constraints of rules which contain the specified formula.
*/
public void clearRuleConstraints(Formula f) {
Iterator<Rule> en = this.itsRules.iterator();
while (en.hasNext()) {
en.next().clearConstraints(f);
}
}
/**
* Clear all post application constraints of all rules.
*/
public void clearRuleConstraints() {
Iterator<Rule> en = this.itsRules.iterator();
while (en.hasNext()) {
en.next().clearConstraints();
}
}
/** Sets my rule layer */
public void setRuleLayer(final RuleLayer rl) {
for (Iterator<Rule> keys = this.getListOfRules().iterator(); keys.hasNext();) {
Object key = keys.next();
Integer layer = rl.getRuleLayer().get(key);
if (layer != null) {
((Rule) key).setLayer(layer.intValue());
}
}
}
public void unsetLayerTriggerRule() {
for (int i = 0; i < this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
r.setTriggerForLayer(false);
}
}
public Vector<String> getGraTraOptions() {
return this.gratraOptions;
}
public void setGraTraOptions(Vector<String> opts) {
this.gratraOptions.clear();
this.gratraOptions.addAll(opts);
}
private void initMorphismCompletionStrategy() {
this.strategy = CompletionStrategySelector.getDefault();
this.strategy.setRandomisedDomain(true);
this.gratraOptions.add(GraTraOptions.CSP);
this.gratraOptions.add(GraTraOptions.INJECTIVE);
this.gratraOptions.add(GraTraOptions.DANGLING);
this.gratraOptions.add(GraTraOptions.IDENTIFICATION);
this.gratraOptions.add(GraTraOptions.NACS);
this.gratraOptions.add(GraTraOptions.PACS);
this.gratraOptions.add(GraTraOptions.GACS);
}
/**
* set morphism completion strategy based on loaded gratra options.
*/
private void setMorphismCompletionStrategy() {
// set strategy
if (this.gratraOptions.contains(GraTraOptions.CSP)) {
this.strategy = new Completion_NAC(new Completion_InjCSP());
}
else if (this.gratraOptions.contains("CSP w/o BJ")) {
this.strategy = new Completion_NAC(new Completion_CSP_NoBJ());
}
if (this.strategy == null) {
initMorphismCompletionStrategy();
} else {
// set this.strategy properties
if (!this.gratraOptions.contains(GraTraOptions.INJECTIVE)) {
this.strategy.getProperties()
.clear(CompletionPropertyBits.INJECTIVE);
}
if (!this.gratraOptions.contains(GraTraOptions.DANGLING)) {
this.strategy.getProperties()
.clear(CompletionPropertyBits.DANGLING);
}
if (!this.gratraOptions.contains(GraTraOptions.IDENTIFICATION)) {
this.strategy.getProperties()
.clear(CompletionPropertyBits.IDENTIFICATION);
}
if (!this.gratraOptions.contains(GraTraOptions.NACS)) {
this.strategy.getProperties()
.clear(CompletionPropertyBits.NAC);
}
if (!this.gratraOptions.contains(GraTraOptions.PACS)) {
this.strategy.getProperties()
.clear(CompletionPropertyBits.PAC);
}
if (!this.gratraOptions.contains(GraTraOptions.GACS)) {
this.strategy.getProperties()
.clear(CompletionPropertyBits.GAC);
}
if (this.gratraOptions.contains(GraTraOptions.DETERMINED_CSP_DOMAIN)) {
this.strategy.setRandomisedDomain(false);
}
else if (this.gratraOptions.contains(GraTraOptions.RANDOM_CSP_DOMAIN))
this.strategy.setRandomisedDomain(true);
}
setMorphismCompletionStrategyOfGraphConstraints();
}
public void addGraTraOption(String opt) {
if (!this.gratraOptions.contains(opt)) {
this.gratraOptions.add(opt);
if (opt.equals(GraTraOptions.DETERMINED_CSP_DOMAIN))
this.strategy.setRandomisedDomain(false);
else if (opt.equals(GraTraOptions.RANDOM_CSP_DOMAIN))
this.strategy.setRandomisedDomain(true);
else
this.strategy.setProperty(opt);
// this.strategy.showProperties();
}
}
public void removeGraTraOption(String opt) {
if (this.gratraOptions.contains(opt)) {
this.gratraOptions.remove(opt);
if (opt.equals(GraTraOptions.DETERMINED_CSP_DOMAIN))
this.strategy.setRandomisedDomain(true);
else
this.strategy.removeProperty(opt);
// this.strategy.showProperties();
}
}
/**
* Set morphism completion strategy by the specified strategy.
*/
public void setMorphismCompletionStrategy(MorphCompletionStrategy strat) {
setGraTraOptions(strat);
}
/**
* Set morphism completion strategy by the specified strategy.
*/
public void setGraTraOptions(final MorphCompletionStrategy strat) {
if (strat == null) {
return;
}
this.gratraOptions.clear();
this.strategy = strat;
String stratName = CompletionStrategySelector.getName(this.strategy);
this.gratraOptions.add(stratName);
// get match conditions
BitSet activebits = this.strategy.getProperties();
for (int j = 0; j < CompletionPropertyBits.BITNAME.length; j++) {
String bitName = CompletionPropertyBits.BITNAME[j];
if (activebits.get(j)) {
this.gratraOptions.add(bitName);
}
}
if (!this.strategy.isRandomisedDomain())
this.gratraOptions.add(GraTraOptions.DETERMINED_CSP_DOMAIN);
// this.strategy.showProperties();
setMorphismCompletionStrategyOfGraphConstraints();
}
public boolean compareTo(final GraGra gragra, final boolean transOption) {
if (gragra == null) {
return false;
}
boolean checkLayer = false;
// boolean checkPriority = false;
if (transOption) {
for (int i = 0; i < this.gratraOptions.size(); i++) {
String op = this.gratraOptions.get(i);
if (!gragra.getGraTraOptions().contains(op)) {
return false;
}
// else if(op.equals("layered"))
// checkLayer = true;
// else if(op.equals("priority"))
// checkPriority = true;
}
}
if (!compareRulesTo(gragra, checkLayer)
|| !compareConstraintsTo(gragra)) {
return false;
}
return true;
}
public boolean compareTo(GraGra gragra) {
if (!getName().equals(gragra.getName())) {
return false;
}
// compare type set inclusive type graph
if (!this.getTypeSet().compareTo(gragra.getTypeSet())) {
return false;
}
// compare graph
if (!this.itsGraph.compareTo(gragra.getGraph())) {
return false;
}
// compare rules
Vector<Object> another = new Vector<Object>();
another.add(gragra.getListOfRules());
if (this.itsRules.size() != another.size()) {
return false;
}
for (int i = 0; i < this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
Rule r1 = gragra.getRule(r.getName());
if (r1 != null && r.compareTo(r1)) {
another.remove(r1);
}
}
if (!another.isEmpty()) {
return false;
}
// compare atomics
Enumeration<?> e = gragra.getAtomics();
another = new Vector<Object>();
while (e.hasMoreElements()) {
another.add(e.nextElement());
}
if (this.itsAtomics.size() != another.size()) {
return false;
}
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint a = this.itsAtomics.get(i);
for (int j = another.size() - 1; j >= 0; j--) {
AtomConstraint a1 = (AtomConstraint) another.get(j);
if (a.compareTo(a1)) {
another.remove(a1);
break;
}
}
}
if (!another.isEmpty()) {
return false;
}
// compare formulas
e = gragra.getConstraints();
another = new Vector<Object>();
while (e.hasMoreElements()) {
another.add(e.nextElement());
}
if (this.itsConstraints.size() != another.size()) {
return false;
}
for (int i = 0; i < this.itsConstraints.size(); i++) {
Formula f = this.itsConstraints.get(i);
for (int j = another.size() - 1; j >= 0; j--) {
Formula f1 = (Formula) another.get(j);
if (f.compareTo(f1)) {
another.remove(f1);
break;
}
}
}
if (!another.isEmpty()) {
return false;
}
return true;
}
public boolean compareRulesTo(GraGra gragra, boolean checkLayer) {
// compare rules
Vector<Rule> another = new Vector<Rule>();
another.addAll(gragra.getListOfRules());
if (this.itsRules.size() != another.size()) {
return false;
}
Rule r = null;
for (int i = 0; i < this.itsRules.size(); i++) {
r = this.itsRules.get(i);
Rule r1 = gragra.getRule(r.getName());
if (r1 != null) {
if (r.compareTo(r1))
another.remove(r1);
if (checkLayer && r.getLayer() != r1.getLayer()) {
return false;
}
}
}
if (!another.isEmpty() && r != null) {
return false;
}
return true;
}
public boolean compareConstraintsTo(GraGra gragra) {
// compare atomics
Vector<AtomConstraint> another = new Vector<AtomConstraint>();
Enumeration<AtomConstraint> e = gragra.getAtomics();
while (e.hasMoreElements()) {
another.add(e.nextElement());
}
if (this.itsAtomics.size() != another.size()) {
return false;
}
AtomConstraint a = null;
for (int i = 0; i < this.itsAtomics.size(); i++) {
a = this.itsAtomics.get(i);
for (int j = another.size() - 1; j >= 0; j--) {
AtomConstraint a1 = another.get(j);
if (a.compareTo(a1)) {
another.remove(a1);
break;
}
}
}
if (!another.isEmpty() && a != null) {
return false;
}
// compare formulas
Enumeration<Formula> eF = gragra.getConstraints();
Vector<Formula> anotherF = new Vector<Formula>();
while (eF.hasMoreElements()) {
anotherF.add(eF.nextElement());
}
if (this.itsConstraints.size() != anotherF.size()) {
return false;
}
Formula f = null;
for (int i = 0; i < this.itsConstraints.size(); i++) {
f = this.itsConstraints.get(i);
for (int j = anotherF.size() - 1; j >= 0; j--) {
Formula f1 = anotherF.get(j);
if (f.compareTo(f1)) {
anotherF.remove(f1);
break;
}
}
}
if (!anotherF.isEmpty() && f != null) {
return false;
}
return true;
}
public Vector<Rule> getNonInjectiveRules() {
final Vector<Rule> result = new Vector<Rule>(1);
for (int i=0; i<this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
if (r.isEnabled() && !r.isInjective()) {
result.add(r);
}
}
return result;
}
public boolean isGraphReadyForTransform() {
return this.itsGraph.isReadyForTransform();
}
/**
* Prepares info about rule:
* does rule create, delete, change something.
*/
public void prepareRuleInfo() {
for (int i=0; i<this.itsRules.size(); i++) {
this.itsRules.get(i).prepareRuleInfo();
}
}
/**
* Checks the types, rules and graph constraints of this grammar.
* Prepares infos of rules if <code>prepareRuleInfo</code> is true.
* @return Pair object or null. A Pair object contains the failed element of
* the grammar. This element is the Pair.first object which can be
* of type agg.xt_basis.Type, agg.xt_basis.Rule or
* agg.cons.AtomConstraint. The second object is a message of type
* String which is a text about failed object.
*/
public Pair<Object, String> isReadyToTransform(boolean prepareRuleInfo) {
Pair<Object, String> result = this.isReadyToTransform();
if (result == null) {
this.prepareRuleInfo();
}
return result;
}
/**
* Checks the types, rules and graph constraints of this grammar.
*
* @return Pair object or null. A Pair object contains the failed element of
* the grammar. This element is the Pair.first object which can be
* of type agg.xt_basis.Type, agg.xt_basis.Rule or
* agg.cons.AtomConstraint. The second object is a message of type
* String which is a text about failed object.
*/
public Pair<Object, String> isReadyToTransform() {
String msg = "";
// check attr. types exist
Enumeration<Type> e = this.typeSet.getTypes();
while (e.hasMoreElements()) {
Type t = e.nextElement();
if (!doesAttrTypeExist(t)) {
msg = "Not all attribute members of the type : \""
+ t.getName() + "\" are declared correctly.";
return new Pair<Object, String>(t, msg);
}
}
Pair<Object, String> p = checkInheritedAttributesValid();
if (p != null) {
return p;
}
// check graphs
for (int i=0; i<this.itsGraphs.size(); i++) {
Graph g = this.itsGraphs.get(i);
if (!g.isReadyForTransform()) {
msg = "Graph \"" + g.getName() + "\" : " + "not all attribute set"; //g.getErrorMsg();
return new Pair<Object, String>(g, msg);
}
}
// check rules
for (int i=0; i<this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
if (!r.isReadyToTransform()) {
msg = "Rule \"" + r.getName() + "\" : " + r.getErrorMsg();
return new Pair<Object, String>(r, msg);
}
}
// check atomic graph constraints
return isGraphConstraintReadyForTransform();
}
/**
* Checks atomic graph constraints.
*
* @return The first failed agg.cons.AtomConstraint object or null, if all
* graph constraints were OK.
*/
public Pair<Object, String> isGraphConstraintReadyForTransform() {
for (int i = 0; i < this.itsAtomics.size(); i++) {
AtomConstraint a = this.itsAtomics.get(i);
if (!a.isValid()) {
String msg = "Atomic graph constraint \""
+ a.getAtomicName()
+ "\" is not valid. "
+ "\nPlease check: "
+ "\n - graph morphism ( injective and total ) "
+ "\n - attribute context ( variable and condition declarations ).";
return new Pair<Object, String>(a, msg);
}
}
return null;
}
/*
* Returns a type which contains an attribute member of type does not
* exist, otherwise null.
*/
public Type doAttrTypesExist() {
// check attr. types exist
Enumeration<Type> e = this.typeSet.getTypes();
while (e.hasMoreElements()) {
Type t = e.nextElement();
if (!doesAttrTypeExist(t))
return t;
}
return null;
}
/*
* Returns false if the specified Type type contains an attribute member
* which type does not exist, otherwise true.
*/
private boolean doesAttrTypeExist(Type type) {
if (type.getAttrType() == null) {
return true;
}
boolean isClass = false;
DeclTuple declTupl = (DeclTuple) type.getAttrType();
for (int i = 0; i < declTupl.getSize(); i++) {
DeclMember decl = (DeclMember) declTupl.getMemberAt(i);
String t = decl.getTypeName();
if (isPrimitiveType(t)) {
continue;
}
try {
Class.forName(t);
isClass = true;
} catch (ClassNotFoundException ex) {}
if (isClass) {
continue;
}
// construct class name as package+class
agg.attribute.handler.AttrHandler attrHandlers[] = agg.attribute.impl.AttrTupleManager
.getDefaultManager().getHandlers();
for (int h = 0; h < attrHandlers.length; h++) {
agg.attribute.handler.AttrHandler attrh = attrHandlers[h];
Vector<String> packs = ((agg.attribute.handler.impl.javaExpr.JexHandler) attrh)
.getClassResolver().getPackages();
for (int pi = 0; pi < packs.size(); pi++) {
String pack = packs.get(pi);
// check if class exists
try {
Class.forName(pack + "." + t);
isClass = true;
break;
} catch (ClassNotFoundException ex) {}
}
if (isClass)
break;
}
}
return true;
}
private boolean isPrimitiveType(String t) {
return "int".equals(t)
|| "long".equals(t)
|| "short".equals(t)
|| "double".equals(t)
|| "float".equals(t)
|| "boolean".equals(t)
|| "char".equals(t)
|| "byte".equals(t);
}
public Pair<Object, String> checkInheritedAttributesValid() {
if (this.typeSet.getLevelOfTypeGraphCheck() <= TypeSet.DISABLED
&& this.typeSet.hasInheritance()) {
Enumeration<Type> e = this.typeSet.getTypes();
while (e.hasMoreElements()) {
Type t = e.nextElement();
// hier multiple inheritance!!!
for (int i = 0; i < t.getParents().size(); i++) {
Type p = t.getParents().get(i);
AttrType attrType = p.getAttrType();
if (attrType != null
&& attrType.getNumberOfEntries() != 0) {
String msg = "Type \""
+ t.getName()
+ "\" - inheritance conflict: inherited attributes by disabled type graph.";
return new Pair<Object, String>(t, msg);
}
}
}
}
return null;
}
/**
* Returned list contains plain rules and plain multi rules of the rule schemes.
* The plain multi rules are used for computing critical pairs of the CPA.
* This work is still in progress.
*
* @return extended list of rules
*/
public List<Rule> getRulesWithIntegratedMultiRulesOfRuleScheme() {
final List<Rule> list = new Vector<Rule>();
for (int i=0; i<this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
if (r.isEnabled()) {
if (r.getRuleScheme() == null) {
list.add(r);
} else {
final RuleScheme rs = r.getRuleScheme();
rs.propagateApplCondsOfKernelToMultiRules();
for (int j=0; j<rs.getMultiRules().size(); j++) {
final Rule mRule = rs.getMultiRules().get(j);
list.add(mRule);
}
}
}
}
return list;
}
/**
* Returned list contains plain rules and plain kernel and multi rules of the rule schemes.
* The plain kernel and multi rules are used for computing critical pairs of the CPA.
* This work is still in progress.
*
* @return extended list of rules
*/
public List<Rule> getRulesWithIntegratedRulesOfRuleScheme() {
final List<Rule> list = new Vector<Rule>();
for (int i=0; i<this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
if (r.isEnabled()) {
if (r.getRuleScheme() == null) {
list.add(r);
} else {
final RuleScheme rs = r.getRuleScheme();
rs.propagateApplCondsOfKernelToMultiRules();
list.add(rs.getKernelRule());
for (int j=0; j<rs.getMultiRules().size(); j++) {
final Rule mRule = rs.getMultiRules().get(j);
list.add(mRule);
}
}
}
}
return list;
}
public void removeShiftedApplConditionsFromMultiRules() {
for (int k=0; k<this.itsRules.size(); k++) {
final Rule r = this.itsRules.get(k);
if (r.getRuleScheme() != null) {
RuleScheme rs = r.getRuleScheme();
rs.removeShiftedApplConditionsFromMultiRules();
}
}
}
public List<Rule> getEnabledRules() {
final Vector<Rule> v = new Vector<Rule>();
for (int i = 0; i < this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
if (r.isEnabled()) {
v.add(r);
}
}
return v;
}
/**
* Returns applicable rules due to the specified morphism completion strategy
* and current host graph.
*/
public Vector<Rule> getApplicableRules(MorphCompletionStrategy aStrategy) {
return getApplicableRules(this.itsGraph, aStrategy);
}
/**
* Returns applicable rules due to the specified host graph
* and morphism completion strategy.
*/
public Vector<Rule> getApplicableRules(Graph g,
MorphCompletionStrategy aStrategy) {
final Vector<Rule> applicableRules = new Vector<Rule>();
if (!this.itsGraphs.contains(g) && !g.isReadyForTransform()) {
return applicableRules;
}
for (int i = 0; i < this.itsRules.size(); i++) {
final Rule r = this.itsRules.get(i);
// if (r.isReadyToTransform())
{
if (r.isApplicable(g, aStrategy, false)) {
r.setApplicable(true);
applicableRules.add(r);
} else {
r.setApplicable(false);
}
}
// else {
// r.setApplicable(false);
// }
}
return applicableRules;
}
/**
* Reset applicability attribute of all rules by <code>true</code>.
*/
public void dismissRuleApplicability() {
for (int i = 0; i < this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
r.setApplicable(true);
}
}
/*
* Returns TRUE if the image graph of the Match m satisfies all graph
* constraints of this grammar. Pre-condition: The graph constraints have to
* be valid and the image graph is a graph of the graph set defined with
* this grammar. The match m has to be a valid match.
*/
// private boolean checkGraphConsistency(Match m) {
// boolean result = true;
// BaseFactory bf = BaseFactory.theFactory();
// OrdinaryMorphism copy = m.getImage().isoToCopy();
// copy.getImage().setCompleteGraph(true);
// OrdinaryMorphism com = m.compose(copy);
// Match m2 = bf.makeMatch(m.getRule(), com);
// if (m2 != null) {
// m2.adaptAttrContextValues(m.getAttrContext());
// Step s = new Step();
// try {
// OrdinaryMorphism co_match = (OrdinaryMorphism) s.execute(m2,
// true);
// if (co_match != null) {
// if (checkGraphConsistency(m2.getImage()))
// result = true;
// else
// result = false;
// co_match.dispose();
// } else
// result = false;
// } catch (TypeException e) {
// result = false;
// }
// bf.destroyMatch(m2);
// m2 = null;
// } else
// result = false;
// com.dispose();
// copy.dispose(false, true);
// return result;
// }
/*
private boolean checkGraphConsistency(Match m, final List<Formula> constraints) {
// if(typeSet.hasInheritance()) return true;
boolean result = true;
BaseFactory bf = BaseFactory.theFactory();
OrdinaryMorphism copy = m.getImage().isomorphicCopy();
copy.getImage().setCompleteGraph(true);
OrdinaryMorphism com = m.compose(copy);
Match m2 = bf.makeMatch(m.getRule(), com);
if (m2 == null) {
result = false;
} else {
m2.adaptAttrContextValues(m.getAttrContext());
// TestStep s = new TestStep();
try {
OrdinaryMorphism
co_match = (OrdinaryMorphism) TestStep.execute(m2, true);
if (co_match == null) {
result = false;
} else {
if (isLayered()) {
List<Formula> commonConstraints = getConstraintsForLayer(-1);
if (checkGraphConsistency(m2.getImage(),
commonConstraints)) {
result = true;
}
else {
result = false;
}
}
if (checkGraphConsistency(m2.getImage(), constraints)) {
result = true;
}
else {
result = false;
}
co_match.dispose();
}
} catch (TypeException e) {
result = false;
}
m2.dispose();
}
com.dispose();
copy.dispose(false, true);
return result;
}
*/
public void storeUsedClassPackages() {
this.itsPackages.clear();
InformationFacade info = DefaultInformationFacade.self();
// AttrHandler javaHandler = info.getJavaHandler();
AttrHandler[] attrHandlers = info.getAttrManager().getHandlers();
for (int i = 0; i < attrHandlers.length; i++) {
AttrHandler attrHandler = attrHandlers[i];
Pair<String, List<String>> p = new Pair<String, List<String>>(
attrHandler.getName(), ((JexHandler) attrHandler)
.getClassResolver().getPackages());
addPackage(p);
}
}
public void setUsedClassPackages() {
// Get an attribute handler
InformationFacade info = DefaultInformationFacade.self();
// AttrHandler javaHandler = info.getJavaHandler();
AttrHandler[] attrHandlers = info.getAttrManager().getHandlers();
for (int i = 0; i < this.itsPackages.size(); i++) {
Pair<String, List<String>> p = this.itsPackages.get(i);
String handler = p.first;
boolean found = false;
AttrHandler attrHandler = null;
Vector<String> hPacks = new Vector<String>(0);
for (int h = 0; h < attrHandlers.length; h++) {
attrHandler = attrHandlers[h];
String hName = attrHandler.getName();
hPacks = ((JexHandler) attrHandler).getClassResolver()
.getPackages();
if (hName.equals(handler)) {
found = true;
}
}
if (found && attrHandler != null) {
List<String> packs = p.second;
for (int j = 0; j < packs.size(); j++) {
String pack = packs.get(j);
if (!hPacks.contains(pack)) {
((JexHandler) attrHandler).appendPackage(pack);
}
}
}
}
}
/**
* Set rule subsequences of the current rule sequence.
* The first Vector element of a Pair is a rule subsequence.
* The first String element of a Pair is a rule name.
* The second element of a Pair represents
* the iteration count of a rule subsequence or of an individual rule.
* The value for the iteration count may be "*" or a decimal > 0.
* The current rule sequence can be used for graph transformation.
*/
public void setSubsequencesOfCurrentRuleSequence(
final List<Pair<List<Pair<String, String>>, String>> sequences) {
this.itsRuleSequence.setSubsequenceList(sequences);
}
public void setCurrentRuleSequence(final RuleSequence seq) {
if (this.itsRuleSequences.contains(seq)) {
this.itsRuleSequence = seq;
}
}
public RuleSequence getCurrentRuleSequence() {
return this.itsRuleSequence;
}
public int getIndexOfCurrentRuleSequence() {
if (this.itsRuleSequence != null)
return this.itsRuleSequences.indexOf(this.itsRuleSequence);
return -1;
}
public void addRuleSequence(final RuleSequence seq) {
this.itsRuleSequences.add(seq);
this.itsRuleSequence = seq;
}
public void removeRuleSequence(final RuleSequence seq) {
if (this.itsRuleSequence == seq) {
this.itsRuleSequence = null;
}
this.itsRuleSequences.remove(seq);
}
/**
* If true, the ApplRuleSequencesGraTra -
* a transformation by validated rule sequence - will be started.<br>
* Precondition: the current rule sequence exists and its applicability is checked.
*
*/
public boolean trafoByApplicableRuleSequence() {
return (this.itsRuleSequence != null) && this.itsRuleSequence.isTrafoByARS();
}
public void setTrafoByApplicableRuleSequence(boolean b) {
if (this.itsRuleSequence != null)
this.itsRuleSequence.setTrafoByARS(b);
}
public boolean trafoByRuleSequenceWithObjectFlow() {
return (this.itsRuleSequence != null) && this.itsRuleSequence.isTrafoByObjFlow();
}
public void setTrafoByRuleSequenceWithObjectFlow(boolean b) {
if (this.itsRuleSequence != null)
this.itsRuleSequence.setTrafoByObjFlow(b);
}
public void clearRuleSequences() {
this.itsRuleSequences.clear();
}
public List<RuleSequence> getRuleSequences() {
return this.itsRuleSequences;
}
/**
* Returns the rule sequences.
* The first Vector element of a Pair is a rule subsequence.
* The first String element of a Pair is a rule name.
* The second element of a Pair represents
* the iteration count of a rule subsequence or of an individual rule.
* The value for the iteration count may be "*" or a decimal.
*/
public List<Pair<List<Pair<String, String>>, String>> getRuleSequenceList() {
if (this.itsRuleSequence != null) {
return this.itsRuleSequence.getSubSequenceList();
}
return null;
}
private void refreshRuleSequences() {
if (this.itsRuleSequences != null) {
for (int i = 0; i < this.itsRuleSequences.size(); i++) {
RuleSequence ruleSeq = this.itsRuleSequences.get(i);
boolean dorefresh = false;
for (int j=0; j<ruleSeq.getSubSequenceList().size(); j++) {
Pair<List<Pair<String, String>>, String> grp = ruleSeq.getSubSequenceList().get(j);
List<Pair<String, String>> grpRules = grp.first;
for (int k = 0; k < grpRules.size(); k++) {
Pair<String, String> p = grpRules.get(k);
String rulename = p.first;
if (this.getRule(rulename) == null) {
grpRules.remove(k);
k--;
dorefresh = true;
}
}
}
if (dorefresh) {
ruleSeq.refresh();
ruleSeq.uncheck();
}
}
}
}
private void updateTypeObjectsMapOfGraphs() {
for (int i = 0; i < this.itsGraphs.size(); i++) {
Graph g = this.itsGraphs.get(i);
g.updateTypeObjectsMap();
}
}
public void createAttrInstanceWhereNeeded() {
for (int i = 0; i < this.itsGraphs.size(); i++) {
this.itsGraphs.get(i).createAttrInstanceWhereNeeded();
}
for (int i=0; i<this.itsRules.size(); i++) {
this.itsRules.get(i).createAttrInstanceWhereNeeded();
}
for (int i=0; i<this.itsAtomics.size(); i++) {
this.itsAtomics.get(i).createAttrInstanceWhereNeeded();
}
this.itsStartGraph.createAttrInstanceWhereNeeded();
}
public void createAttrInstanceOfTypeWhereNeeded(final Type t) {
for (int i = 0; i < this.itsGraphs.size(); i++) {
this.itsGraphs.get(i).createAttrInstanceOfTypeWhereNeeded(t);
}
for (int i=0; i<this.itsRules.size(); i++) {
this.itsRules.get(i).createAttrInstanceOfTypeWhereNeeded(t);
}
for (int i=0; i<this.itsAtomics.size(); i++) {
this.itsAtomics.get(i).createAttrInstanceOfTypeWhereNeeded(t);
}
this.itsStartGraph.createAttrInstanceOfTypeWhereNeeded(t);
}
private void initRuleSubsets() {
if (this.ruleSets != null) {
this.ruleSets.clear();
}
this.ruleSets = new Hashtable<Integer, List<Rule>>();
Vector<Rule> set = new Vector<Rule>(this.itsRules);
this.ruleSets.put(Integer.valueOf(1), set);
}
public void removeRuleSubsets() {
if (this.ruleSets != null) {
this.ruleSets.clear();
this.ruleSets = null;
}
}
public void addRuleSubset(List<Rule> set) {
if (this.ruleSets == null) {
initRuleSubsets();
}
this.ruleSets.put(Integer.valueOf(this.ruleSets.size()), set);
}
public Hashtable<Integer, List<Rule>> getRuleSubsets() {
return this.ruleSets;
}
/**
* The specified file name is the full name of the file to save this grammar into.
* @param filename
*/
public void save(String filename) {
String ggx = ".ggx";
storeUsedClassPackages();
String outfileName = "";
if ("".equals(filename)) {
outfileName = this.itsName + "_out.ggx";
} else {
outfileName = filename;
if (outfileName.indexOf(ggx) == -1) {
outfileName = outfileName.concat(ggx);
}
}
if (outfileName.endsWith(ggx)) {
XMLHelper xmlh = new XMLHelper();
// outfileName = XMLHelper.replaceGermanSpecialCh(outfileName);
xmlh.addTopObject(this);
xmlh.save_to_xml(outfileName);
File f = new File(outfileName);
if (f.exists()) {
this.fileName = f.getName();
if (f.getParent() == null) {
this.dirName = "." + File.separator;
} else {
this.dirName = f.getParent() + File.separator;
}
}
}
}
public void save(String dirname, String filename) {
String fullname = dirname.concat(File.separator).concat(filename);
save(fullname);
}
/**
* The specified file name is the full name of the file to load a grammar from.
* @param filename
*/
public void load(String filename) throws Exception {
File f = new File(filename);
if (f.exists()) {
if (filename.endsWith(".ggx")) {
XMLHelper h = new XMLHelper();
/*
* if(XMLHelper.hasGermanSpecialCh(filename)){
* System.out.println("Read file name exception occurred! "
* +"\nMaybe the German umlaut like ä, ö, ü or ß were used. "
* +"\nPlease replace it by ae, oe, ue or ss " +"\nand try
* again."); return; }
*/
if (h.read_from_xml(filename)) {
h.getTopObject(this);
this.fileName = f.getName();
if (f.getParent() == null) {
this.dirName = "." + File.separator;
} else {
this.dirName = f.getParent() + File.separator;
}
} else {
throw new Exception("File \"" + filename
+ "\" is not an AGG file!");
}
} else {
throw new Exception("File \"" + filename
+ "\" is not a \".ggx\" file!");
}
} else {
throw new Exception("File \"" + filename
+ "\" doesn't exist!");
}
}
public void read(String filename) throws Exception {
File f = new File(filename);
if (f.exists()) {
if (filename.endsWith(".ggx")) {
XMLHelper h = new XMLHelper();
/*
* if(XMLHelper.hasGermanSpecialCh(filename)){
* System.out.println("Read file name exception occurred! "
* +"\nMaybe the German umlaut like ä, ö, ü or ß were used. "
* +"\nPlease replace it by ae, oe, ue or ss " +"\nand try
* again."); return; }
*/
if (h.read_from_xml(filename)) {
h.getTopObject(this);
this.fileName = f.getName();
if (f.getParent() != null) {
this.dirName = f.getParent() + File.separator;
}
else {
this.dirName = "." + File.separator;
}
setUsedClassPackages();
} else {
throw new Exception("File \"" + filename
+ "\" is not an AGG file!");
}
} else {
throw new Exception("File \"" + filename
+ "\" is not a \".ggx\" file!");
}
} else {
throw new Exception("File \"" + filename + "\" does not exist!");
}
}
/**
* saves the properties and values of all elements of this gragra in the
* open element of the given XMLHelper. If the gragra should also create its
* own element use XwriteObject.
*
* @param h
* an XMLHelper with an open Element for this gragra
* @see agg.xt_basis.GraGra#XwriteObject
*/
private void saveXML(XMLHelper h) {
// save packages
storeUsedClassPackages();
if ((this.itsPackages != null) && !this.itsPackages.isEmpty()) {
for (int i = 0; i < this.itsPackages.size(); i++) {
Pair<String, List<String>> p = this.itsPackages.get(i);
String attrHand = p.first;
h.openSubTag("TaggedValue");
h.addAttr("Tag", "AttrHandler");
h.addAttr("TagValue", attrHand);
List<String> v = p.second;
for (int j = 0; j < v.size(); j++) {
String n = v.get(j);
h.openSubTag("TaggedValue");
h.addAttr("Tag", "Package");
h.addAttr("TagValue", n);
h.close();
}
h.close();
}// for i
}
// save options
for (int i = 0; i < this.gratraOptions.size(); i++) {
h.openSubTag("TaggedValue");
h.addAttr("Tag", this.gratraOptions.get(i));
h.addAttr("TagValue", "true");
h.close(); // TaggedValue
}
// save types and the type graph
h.openSubTag("TaggedValue");
h.addAttr("Tag", "TypeGraphLevel");
switch (this.typeSet.getLevelOfTypeGraphCheck()) {
case TypeSet.ENABLED:
h.addAttr("TagValue", "ENABLED");
break;
case TypeSet.ENABLED_MAX:
h.addAttr("TagValue", "ENABLED_MAX");
break;
case TypeSet.ENABLED_MAX_MIN:
h.addAttr("TagValue", "ENABLED_MAX_MIN");
break;
case TypeSet.DISABLED:
default:
h.addAttr("TagValue", "DISABLED");
}
h.close(); // TaggedValue
// <Types>
h.openSubTag("Types");
// a <Type> tag for each type
h.addEnumeration("", getTypes(), true);
// a <Graph> tag for the type graph
// the types must defined here, because the XwriteObject
// method of Graph use them
h.addObject("", this.typeSet.getTypeGraph(), true);
// </Types>
h.close();
// save host graphs
for (int i=0; i<this.itsGraphs.size(); i++) {
this.itsGraphs.get(i).setKind(GraphKind.HOST);
}
h.addList("", this.itsGraphs, true);
// save graph constraints (atomics graph constraints and formulas
if (!this.itsAtomics.isEmpty()) {
h.openSubTag("Constraints");
// save atomic constraints
h.addList("", getListOfAtomics(), true);
// save formulas
if (!this.itsConstraints.isEmpty()) {
Iterator<Formula> en = this.itsConstraints.iterator();
while (en.hasNext()) {
Formula f = en.next();
List<Evaluable> atomics = new Vector<Evaluable>();
atomics.addAll(getListOfAtomicObjects());
String s = f.getAsString(atomics);
h.addObjectSub(f);
h.peekObject(f, null);
h.addAttr("f", s);
h.close();
}// while hasMoreElements
}// if hasMoreElements
h.close(); // constraints
}
// save rules
for (int i=0; i<this.itsRules.size(); i++) {
Rule r = this.itsRules.get(i);
r.getSource().setKind(GraphKind.LHS);
r.getTarget().setKind(GraphKind.RHS);
if (r instanceof RuleScheme) {
((RuleScheme)r).storeIndexOfRuleList(i);
}
}
h.addList("", this.itsRules, true);
// save matches
if (!this.itsMatches.isEmpty()) {
h.openSubTag("Matches");
for (int i = 0; i < this.itsMatches.size(); i++) {
Match m = this.itsMatches.get(i);
if (m != null
&& m.getRule() != null
&& !m.isEmpty()) {
m.setName("MatchOf_" + m.getRule().getName());
h.openSubTag("MatchOf");
h.addObject("Rule", m.getRule(), false);
h.addObject("", m, true);
h.close();
}
}
h.close();
}
// save rule sequences
if (this.itsRuleSequences != null && !this.itsRuleSequences.isEmpty()) {
h.openSubTag("RuleSequences");
for (int i = 0; i < this.itsRuleSequences.size(); i++) {
final RuleSequence seq = this.itsRuleSequences.get(i);
h.openSubTag("Sequence");
h.addAttr("name", seq.getName());
if (seq.isTrafoByARS())
h.addAttr(RuleSequence.TRAFO_BY_ARS, "true");
if (seq.isTrafoByObjFlow())
h.addAttr(RuleSequence.TRAFO_BY_OBJECT_FLOW, "true");
if (seq.getGraph() != null) {
h.openSubTag("Graph");
h.addObject("id", seq.getGraph(), false);
h.close();
}
List<Pair<List<Pair<String, String>>, String>> seqList = seq.getSubSequenceList();
for (int j = 0; j < seqList.size(); j++) {
Pair<List<Pair<String, String>>, String> pi = seqList.get(j);
h.openSubTag("Subsequence");
h.addAttr("iterations", pi.second);
List<Pair<String, String>> v = pi.first;
for (int k = 0; k < v.size(); k++) {
Pair<String, String> pj = v.get(k);
h.openSubTag("Item");
h.addAttr("rule", pj.first);
h.addAttr("iterations", pj.second);
h.close();
}
h.close();
}
// write object flow : rule1.RHS -> rule2.LHS
if (seq.isObjFlowDefined()) {
Enumeration<String> keys = seq.getObjectFlow().keys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
ObjectFlow objFlow = seq.getObjectFlow().get(key);
h.openSubTag("ObjectFlow");
h.addAttr("enabled", String.valueOf(seq.isObjFlowEnabled()));
h.addAttr("index", key);
if (objFlow.isGraphExtended() && objFlow.getIndexOfOutput() == 0) {
h.addAttr("output", ((Graph)objFlow.getSourceOfOutput()).getName());
} else {
if (((Rule)objFlow.getSourceOfOutput()).getRuleScheme() == null)
h.addAttr("output", ((Rule)objFlow.getSourceOfOutput()).getName());
else {
h.addAttr("output",
((Rule)objFlow.getSourceOfOutput()).getRuleScheme().getName()
+"."
+((Rule)objFlow.getSourceOfOutput()).getName());
}
}
if (((Rule)objFlow.getSourceOfInput()).getRuleScheme() == null)
h.addAttr("input", ((Rule)objFlow.getSourceOfInput()).getName());
else {
h.addAttr("input",
((Rule)objFlow.getSourceOfInput()).getRuleScheme().getName()
+"."
+((Rule)objFlow.getSourceOfInput()).getName());
}
Enumeration<Object> elems = objFlow.getMapping().keys();
while (elems.hasMoreElements()) {
GraphObject o = (GraphObject) elems.nextElement();
h.openSubTag("Mapping");
h.addObject("orig", o, false);
h.addObject("image", (GraphObject) objFlow.getMapping().get(o), false);
h.close();
}
h.close();
}
}
h.close();
}
h.close();
}
updateTypeObjectsMapOfGraphs();
// do copy of saved host graph
int tgl_check = this.typeSet.getLevelOfTypeGraphCheck();
if (this.typeSet.getLevelOfTypeGraphCheck() == TypeSet.ENABLED_MAX_MIN)
this.typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX);
this.itsStartGraph = cloneGraph();
this.typeSet.setLevelOfTypeGraphCheck(tgl_check);
}// saveXML
/**
* reads the properties and values of all elements of this gragra from the
* open element of the given XMLHelper. If the gragra element should be
* searched and open use XreadObject.
*
* @param h
* an XMLHelper with an open Element for this gragra
* @see agg.xt_basis.GraGra#XreadObject
*/
private void loadXML(XMLHelper h) {
// the level of type graph check
int loadedLevel = TypeSet.DISABLED;
boolean tgl_ENABLED_MAX_MIN = false;
this.gratraOptions.clear();
String v = "";
String v1 = "";
String tag = "";
boolean taggedvalue = true;
while (taggedvalue) {
if (tag.equals("AttrHandler")) {
v = h.readAttr("TagValue");
Vector<String> packs = new Vector<String>(0);
boolean isPackage = true;
while (isPackage && h.readSubTag("TaggedValue")) {
String tag1 = h.readAttr("Tag").trim();
if (tag1.equals("Package")) {
v1 = h.readAttr("TagValue");
if (!v1.isEmpty()) {
packs.add(v1.trim());
}
h.close();
} else {
isPackage = false;
}
}
packs.remove("genged.alphabet.datatypes");
packs.remove("com.objectspace.jgl");
Pair<String, List<String>>
p = new Pair<String, List<String>>(v, packs);
this.itsPackages.add(p);
h.close();
setUsedClassPackages();
}
if (h.readSubTag("TaggedValue")) {
v = null;
tag = h.readAttr("Tag").trim();
v1 = h.readAttr("TagValue");
if (!v1.isEmpty()) {
v = v1.trim();
}
if (!tag.equals("AttrHandler")) {
if (tag.equalsIgnoreCase("TypeGraphLevel")) {
if (v != null && !"".equals(v)) {
if (v.equalsIgnoreCase("ENABLED")) {
loadedLevel = TypeSet.ENABLED;
}
else if (v.equalsIgnoreCase("ENABLED_MAX")) {
loadedLevel = TypeSet.ENABLED_MAX;
}
else if (v.equalsIgnoreCase("ENABLED_MAX_MIN")) {
loadedLevel = TypeSet.ENABLED_MAX;
tgl_ENABLED_MAX_MIN = true;
} else if (v.equalsIgnoreCase("DISABLED")) {
loadedLevel = TypeSet.DISABLED;
}
} else {
loadedLevel = TypeSet.DISABLED;
}
} else {
// System.out.println(tag);
if (v != null && !"".equals(v)) {
if (v.equalsIgnoreCase("true")) {
this.gratraOptions.add(tag);
}
} else {
this.gratraOptions.add(tag);
}
}
h.close();
}
} else {
taggedvalue = false;
}
}// while
// long time0 = System.currentTimeMillis();
boolean attributed = false;
// read the <Types> tag with the types and the type graph
if (h.readSubTag("Types")) {
Type t = null;
// read all Types
// first the unspecified types (old format)
Enumeration<?> en = h.getEnumeration("", null, true, "Type");
while (en.hasMoreElements()) {
System.out.println(this.itsName+" old format Type !");
h.peekElement(en.nextElement());
t = createType();
h.loadObject(t);
h.close();
if (t.getAttrType() != null
&& t.getAttrType().getNumberOfEntries() != 0) {
attributed = true;
}
}// while hasMoreElements
// the node types
en = h.getEnumeration("", null, true, "NodeType");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
t = createNodeType(false);
h.loadObject(t);
h.close();
if (t.getAttrType() != null
&& t.getAttrType().getNumberOfEntries() != 0) {
attributed = true;
}
if (t.getAdditionalRepr().equals("")
|| t.getAdditionalRepr().indexOf("Color") == -1) {
t.setAdditionalRepr("NODE");
}
}// while hasMoreElements
// the edge type
en = h.getEnumeration("", null, true, "EdgeType");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
t = createArcType(false);
h.loadObject(t);
h.close();
if (t.getAttrType() != null
&& t.getAttrType().getNumberOfEntries() != 0) {
attributed = true;
}
if (t.getAdditionalRepr().equals("")
|| t.getAdditionalRepr().indexOf("Color") == -1) {
t.setAdditionalRepr("EDGE");
}
}// while hasMoreElements
// now construct the type graph
// the types used there must have defined before
if (h.readSubTag("Graph")) {
Graph tg = this.createTypeGraph();
h.loadObject(tg);
h.close();
// mark type graph as unused first
this.typeSet.setLevelOfTypeGraph(TypeSet.DISABLED);
this.getTypeGraph().attributed = attributed;
this.getTypeGraph().setKind(GraphKind.TG);
}// if readSubTag("Graph")
// close the <Types> tag
h.close();
this.typeSet.refreshInheritanceArcs();
}// if readSubTag("Types")
if (this.typeSet.getTypeGraph() == null) {
this.typeSet.setLevelOfTypeGraph(TypeSet.DISABLED);
}
else if (loadedLevel != TypeSet.DISABLED
&& loadedLevel != TypeSet.UNDEFINED) {
this.typeSet.setLevelOfTypeGraph(TypeSet.ENABLED);
}
// System.out.println("(Base) Grammar Types: "
// + (System.currentTimeMillis() - time0) + "ms");
// read the graphs at <Graph> tags
// time0 = System.currentTimeMillis();
this.itsGraphs.clear();
List<?> graphList = h.getList("", null, true, "Graph");
Iterator<?> graphIter = graphList.iterator();
while (graphIter.hasNext()) {
h.peekElement(graphIter.next());
Graph g = createGraph();
h.loadObject(g);
h.close();
g.attributed = attributed;
}
if (this.itsGraphs.isEmpty()) {
this.itsGraphs.add(BaseFactory.theFactory().createGraph(this.typeSet));
}
this.itsGraph = this.itsGraphs.get(0);
// System.out.println("(Base) Grammar Graphs: "
// + (System.currentTimeMillis() - time0) + "ms");
// first try to read Graphconstraint_Atomic and Formula of AGG V1.2.0b
boolean gcAtomicsLoaded = false;
// read atomic constraints
Enumeration<?> en = h.getEnumeration("", null, true,
"Graphconstraint_Atomic");
if (en.hasMoreElements()) {
gcAtomicsLoaded = true;
}
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
AtomConstraint ac = createAtomic("");
h.loadObject(ac);
h.close();
ac.getSource().setKind(GraphKind.PREMISE);
ac.getTarget().setKind(GraphKind.CONCLUSION);
}
if (gcAtomicsLoaded) {
if (h.readSubTag("Constraints")) {
// read formulas
en = h.getEnumeration("", null, true, "Formula");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
Formula f;
f = (Formula) h.loadObject(createConstraint(""));
if (f != null) {
String s = h.readAttr("f");
f.setFormula(this.getListOfAtomicObjects(), s);
s = h.readAttr("name");
f.setName(s);
}
h.close();
}
h.close();
}
} else {
// try to read Graphconstraint_Atomic and Formula of current AGG
// read constraint from <Constraints> tag
if (h.readSubTag("Constraints")) {
// read atomic constraints
en = h.getEnumeration("", null, true, "Graphconstraint_Atomic");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
AtomConstraint ac = createAtomic("");
h.loadObject(ac);
h.close();
}
this.itsAtomics.trimToSize();
// read formulas
en = h.getEnumeration("", null, true, "Formula");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
Formula f;
f = (Formula) h.loadObject(createConstraint(""));
if (f != null) {
String s = h.readAttr("f");
f.setFormula(getListOfAtomicObjects(), s);
}
h.close();
}
h.close();
}
}
// read rule from <Rule> tag
// long time0 = System.currentTimeMillis();
boolean hasGACs = false;
List<Rule> rulesWithGC = new Vector<Rule>();
this.itsRules.clear();
Enumeration<?> en1 = h.getEnumeration("", null, true, "Rule");
while (en1.hasMoreElements()) {
h.peekElement(en1.nextElement());
Rule r = createRule();
h.loadObject(r);
hasGACs = hasGACs || r.hasNestedACs();
if (!r.getUsedAtomics().isEmpty())
rulesWithGC.add(r);
h.close();
}
Enumeration<?> en2 = h.getEnumeration("", null, true, "RuleScheme");
while (en2.hasMoreElements()) {
h.peekElement(en2.nextElement());
RuleScheme rs = createRuleScheme();
h.loadObject(rs);
hasGACs = hasGACs || rs.hasNestedACs();
h.close();
if ((rs.getStoredIndexOfRuleList() >= 0)
&& (rs.getStoredIndexOfRuleList() < this.itsRules.size()-1)) {
this.itsRules.remove(rs);
this.itsRules.add(rs.getStoredIndexOfRuleList(), rs);
}
}
this.itsRules.trimToSize();
if (!hasGACs && !this.gratraOptions.contains(GraTraOptions.GACS)) {
this.gratraOptions.add(GraTraOptions.GACS);
}
// System.out.println("(Base) Grammar Rules: "
// + (System.currentTimeMillis() - time0) + "ms");
// read match from <Match> tag
this.itsMatches.clear();
if (h.readSubTag("Matches")) {
boolean nextMatch = true;
while (nextMatch) {
if (h.readSubTag("MatchOf")) {
Object obj = h.getObject("Rule", null, false);
if (obj instanceof Rule) {
Rule r = (Rule) obj;
Match m = createMatch(r);
h.getObject("Match", m, true);
if (m.getSize() > 0)
m.setPartialMorphismCompletion(true);
}
h.close();
} else {
nextMatch = false;
}
}
h.close();
}
// read rule sequences
this.itsRuleSequences.clear();
if (h.readSubTag("RuleSequences")) {
boolean newformat = false;
while (h.readSubTag("Sequence")) {
this.itsRuleSequence = new RuleSequence(this, "RuleSequence");
this.itsRuleSequences.add(this.itsRuleSequence);
String strName = h.readAttr("name");
if ("true".equals(h.readAttr(RuleSequence.TRAFO_BY_ARS))) {
this.itsRuleSequence.setTrafoByARS(true);
}
if ("true".equals(h.readAttr(RuleSequence.TRAFO_BY_OBJECT_FLOW))) {
this.itsRuleSequence.setTrafoByObjFlow(true);
}
while (h.readSubTag("Subsequence")) {
newformat = true;
Vector<Pair<String, String>> vec = new Vector<Pair<String, String>>();
String iters = h.readAttr("iterations");
while (h.readSubTag("Item")) {
String ruleName = h.readAttr("rule");
String ruleIters = h.readAttr("iterations");
vec.add(new Pair<String, String>(ruleName, ruleIters));
h.close();
}
try {
this.itsRuleSequence.getSubSequenceList().add(new Pair<List<Pair<String, String>>, String>(
vec, iters));
} catch (java.lang.NumberFormatException ex) {}
h.close();
}
if (newformat) {
if (h.readSubTag("Graph")) {
Graph g = (Graph) h.getObject("id", null, false);
if (g != null) {
this.itsRuleSequence.setGraph(g);
this.itsRuleSequence.setCheckAtGraph(true);
}
h.close();
}
if (!strName.equals(""))
this.itsRuleSequence.setName(strName);
// read object flow : rule1.RHS -> rule2.LHS
while (h.readSubTag("ObjectFlow")) {
String enabledStr = h.readAttr("enabled");
if (!"".equals(enabledStr))
this.itsRuleSequence.enableObjFlow(Boolean.valueOf(enabledStr).booleanValue());
String indxStr = h.readAttr("index");
String[] indx = indxStr.split(":");
int indx1 = -1;
try {
indx1 = Integer.valueOf(indx[0]).intValue();
} catch (java.lang.NumberFormatException ex) {}
int indx2 = -1;
try {
indx2 = Integer.valueOf(indx[1]).intValue();
} catch (java.lang.NumberFormatException ex) {}
String sourceOutputName = h.readAttr("output");
Object sourceOutput = this.getRule(sourceOutputName);
if (sourceOutput != null) {
// source of output is Rule (RHS), so indx1 != 0
if (indx1 == 0 && this.itsRuleSequence.getGraph() != null)
sourceOutput = null;
} else {
sourceOutput = this.getGraph(sourceOutputName);
// source of output is Host Graph, so indx1 = 0
if (indx1 != 0)
sourceOutput = null;
}
String sourceInputName = h.readAttr("input");
Object sourceInput = this.getRule(sourceInputName);
if (sourceInput != null) {
// source of input is Rule (LHS), so indx1 != 0
if (indx2 == 0)
sourceInput = null;
}
// System.out.println(sourceOutputName+" : "+sourceInputName+" "+indx1+" : "+indx2);
if (sourceOutput != null && sourceInput != null
&& indx1 != -1 && indx2 != -1) {
ObjectFlow objFlow = new ObjectFlow(sourceOutput, sourceInput, indx1, indx2);
while (h.readSubTag("Mapping")) {
Object o1 = h.getObject("orig", null, false);
Object o2 = h.getObject("image", null, false);
if (o1 != null && o2 != null) {
objFlow.addMapping(o1, o2);
}
h.close();
}
if (!objFlow.isEmpty()) {
this.itsRuleSequence.addObjFlow(objFlow);
}
}
h.close();
}
} else {
// old format
String iters = h.readAttr("iterations");
if (!"".equals(iters)) {
Vector<Pair<String, String>> vec = new Vector<Pair<String, String>>();
while (h.readSubTag("Item")) {
String ruleName = h.readAttr("rule");
String ruleIters = h.readAttr("iterations");
vec.add(new Pair<String, String>(ruleName, ruleIters));
h.close();
}
try {
this.itsRuleSequence.getSubSequenceList().add(new Pair<List<Pair<String, String>>, String>(
vec, iters));
} catch (java.lang.NumberFormatException ex) {}
}
this.itsRuleSequence.setGraph(this.getGraph());
this.itsRuleSequence.setCheckAtGraph(true);
}
h.close();
this.itsRuleSequence.getMatchSequence().reinit(this.itsRuleSequence);
this.itsRuleSequence.makeFlatSequence();
}
h.close();
// set current sequence
if (!this.itsRuleSequences.isEmpty()) {
this.itsRuleSequence = this.itsRuleSequences.get(0);
}
}
// set level of type graph check
if (tgl_ENABLED_MAX_MIN) {
loadedLevel = TypeSet.ENABLED_MAX_MIN;
}
if (loadedLevel == TypeSet.ENABLED_MAX
|| loadedLevel == TypeSet.ENABLED_MAX_MIN) {
setLevelOfTypeGraphCheck(loadedLevel);
}
else {
this.typeSet.setLevelOfTypeGraph(loadedLevel);
}
setMorphismCompletionStrategy();
refreshConstraints();
for (int j = 0; j < this.itsAtomics.size(); j++) {
AtomConstraint a = this.itsAtomics.get(j);
a.isValid();
}
// make post application condition of rule
for (int i=0; i<rulesWithGC.size(); i++) {
Rule r = this.itsRules.get(i);
if (!r.getUsedAtomics().isEmpty()) {
r.convertUsedFormulas();
}
}
rulesWithGC.clear();
}
/**
* Save the properties and values of all elements of this gragra in an own
* element in the XML file saved by the given XMLHelper.
*
* @param h
* an XMLHelper, without an open element for this gragra.
* @see agg.xt_basis.GraGra#saveXML
*/
public void XwriteObject(XMLHelper h) {
h.openNewElem("GraphTransformationSystem", this);
h.addAttr("name", this.itsName);
h.addAttr("directed", String.valueOf(this.typeSet.isArcDirected()));
h.addAttr("parallel", String.valueOf(this.typeSet.isArcParallel()));
if (!"".equals(this.comment)) {
h.addAttr("comment", this.comment);
}
saveXML(h);
h.close();
}
/**
* reads the properties and values of all elements of this gragra from an
* element called <CODE><GraphTransformationSystem></CODE> in the
* XML file opened by the given XMLHelper.
*
* @param h
* an XMLHelper, with an not yet opened element for this gragra.
* @see agg.xt_basis.GraGra#loadXML
*/
public void XreadObject(XMLHelper h) {
// clear eventually existent grammar elements
this.clear();
// read the grammar from filename.ggx
if (h.isTag("GraphTransformationSystem", this)) {
String str = h.readAttr("name");
setName(str.replaceAll(" ", ""));
str = h.readAttr("directed");
if (!"".equals(str)) {
this.typeSet.setArcDirected(Boolean.valueOf(str).booleanValue());
}
str = h.readAttr("parallel");
if (!"".equals(str)) {
this.typeSet.setArcParallel(Boolean.valueOf(str).booleanValue());
}
str = h.readAttr("comment");
if (!"".equals(str)) {
this.comment = str;
}
loadXML(h);
h.close();
// long time0 = System.currentTimeMillis();
this.isReadyToTransform();
// System.out.println("(Base) Grammar isReadyToTransform info check: "
// + (System.currentTimeMillis() - time0) + "ms");
return;
}
// try to read the grammar of critical pairs from CPA file ( filename.cpx )
// which should be renamed to filename.ggx before
if (h.isTag("CriticalPairs", this)) {
if (h.readSubTag("GraphTransformationSystem")) {
String str = h.readAttr("name");
setName(str.replaceAll(" ", ""));
str = h.readAttr("comment");
if (!"".equals(str)) {
this.comment = str;
}
loadXML(h);
h.close();
this.trimToSize();
this.isReadyToTransform();
}
}
}
/*
* Create and return a new subgragra. It is automatically added to my set of
* subgragras.
*
* @see agg.xt_basis.GraGra#getSubGraGras
*/
// public final SubGraGra createSubGraGra() {
// SubGraGra anSG = new SubGraGra(this);
// if (itsSubGraGras == null)
// itsSubGraGras = new Vector<SubGraGra>(5, 1);
// itsSubGraGras.add(anSG);
// return anSG;
// }
/*
* Remove a subgragra from my set of subgragras.
*
* @return <code>false</code> iff <code>sg</code> was not an element of
* my set of subgragras.
*/
// public final boolean destroySubGraGra(SubGraGra sg) {
// if (sg != null) {
// if (itsSubGraGras.remove(sg)) {
// sg.dispose();
// return true;
// }
// }
// return false;
// }
/*
* Return an Enumeration of all of my subgragras (not including myself).
* Enumeration elements are of type <code>SubGraGra</code>.
*/
// public final Enumeration<SubGraGra> getSubGraGras() {
// if (itsSubGraGras != null)
// return itsSubGraGras.elements();
// else
// return (new Vector<SubGraGra>(0)).elements();
// }
}