package agg.attribute.impl; import java.util.HashMap; import agg.attribute.AttrContext; import agg.attribute.AttrException; import agg.attribute.AttrInstance; import agg.attribute.AttrManager; import agg.attribute.AttrMapping; import agg.attribute.AttrType; import agg.attribute.handler.AttrHandler; import agg.attribute.handler.AvailableHandlers; import agg.attribute.view.AttrViewSetting; import agg.attribute.view.impl.OpenViewSetting; /** * Attribute Tuple Manager - Factory of attribute management; Provides creating * services needed by graphical components. * * @author $Author: olga $ * @version $Id: AttrTupleManager.java,v 1.21 2010/11/28 22:11:36 olga Exp $ */ @SuppressWarnings("serial") public class AttrTupleManager extends AttrObject implements agg.attribute.AttrManager { public HashMap<String,Boolean> classNameLookupMap; protected AttrHandler handlers[] = AvailableHandlers.newInstances(); protected AttrViewSetting defaultOpenView; protected AttrViewSetting defaultMaskedView; protected AttrViewSetting fixedViewSetting; protected ContextView defaultContext; protected boolean isCorrectInputEnforced = false; private String errorMsg = ""; private boolean variableContext = false; protected static AttrTupleManager myDefaultInstance = new AttrTupleManager(); /** * Returns the default instance of AttrManager. Called e.g. by facades. */ public static AttrManager getDefaultManager() { return myDefaultInstance; } /** Public constructor. */ public AttrTupleManager() { new AttrSession(); setDebug(true); this.classNameLookupMap = new HashMap<String,Boolean>(); this.defaultOpenView = new OpenViewSetting(this); this.defaultMaskedView = this.defaultOpenView.getMaskedView(); this.fixedViewSetting = new OpenViewSetting(this); this.defaultContext = makeDefaultContext(); } private ContextView makeDefaultContext() { ContextView c = new ContextView(this, AttrMapping.PLAIN_MAP); c.setAllowVarDeclarations(false); c.setAllowComplexExpr(false); c.setAllowEmptyValues(false); c.setAllowInitialExpr(true); return c; } // /////////////////////////////////////////////// // Begin of AttrManager interface implementation. // /////////////////// // Context for variables and parameters: public AttrContext newContext(int mapStyle) { ContextView c = new ContextView(this, mapStyle, null); c.setVariableContext(this.variableContext); return c; } /** * Creating a new attribute context which extends an existing one. In Graph * Transformation, the setting of variables by matching corresponding * graphical objects requires such a construction. It allows for keeping * more that one rule match at a given time; * * @param mapStyle * The kind of mapping that is allowed within this context; it is * one of: - AttrMapping.PLAIN_MAP: In Graph Transformation: rule * mapping - AttrMapping.MATCH_MAP: In Graph Transformation: * matching * @param parent * The context to extend * @return The new attribute context child * @see AttrContext * @see AttrMapping */ public AttrContext newContext(int mapStyle, AttrContext parent) { ContextView c = new ContextView(this, mapStyle, parent); c.setVariableContext(this.variableContext); return c; } /* public AttrContext makeCopyOf(AttrContext context) { ContextView c = new ContextView(this, ((ContextView) context).getMapStyle()); c.copyAttrContext(context); return c; } */ /** * Creating a full view on an existing attribute context; Through a "full * view" on a context, variables can be declared and values can be assigned * to them by the editor of attribute instances. In Graph Transformation, it * is used for the left-hand-side of a rule. * * @param context * The context to generate the view on * @return The new attribute context view * @see AttrContext */ public AttrContext newLeftContext(AttrContext context) { ContextView c = new ContextView(this, context, true); c.setVariableContext(this.variableContext); return c; } /** * Creating a view on an existing attribute context, through which variables * can not be declared; they only can be assigned values; In Graph * Transformation, it is used for the right-hand-side of a rule. * * @param context * The context to generate the view on * @return The new attribute context view * @see AttrContext */ public AttrContext newRightContext(AttrContext context) { ContextView c = new ContextView(this, context, false); c.setVariableContext(this.variableContext); return c; } /** * A variable context mins that mainly variables will be used as values of * the graph objects of a graph, so if a rule / match attribute context has * an attribute condition, it cannot be evaluated and will get TRUE as * result. This feature is mainly used for critical pair analysis, where the * attribute conditions will be handled especially. Do not use this setting * for common transformation. */ public void setVariableContext(boolean b) { this.variableContext = b; } /** * @see agg.attribute.impl#setVariableContext(boolean b) */ public boolean isVariableContext() { return this.variableContext; } /** * Getting an attribute handler by name. * * @return The attribute handler with the specified name or 'null'. */ public AttrHandler getHandler(String name) { for (int i = 0; i < this.handlers.length; i++) { if (this.handlers[i].getName().equals(name)) { return this.handlers[i]; } } return null; } /** * Creating a new attribute type. * * @return The new attribute type */ public AttrType newType() { return new DeclTuple(this); } // /////////////////// // Instance: /** * Creating a new attribute instance of the required type, without a * context. Note that for such attributes, expressions cannot contain * variables. In Graph Transformation, it is used for creating a new * attribute in the host graph. * * @param type * The type to use * @return The new attribute instance */ public AttrInstance newInstance(AttrType type) { return newInstance(type, null); } /** * Creating a new attribute instance of the required type and in the given * context or a context view. In Graph Transformation, it is used for * creating a new attribute in a rule. * * @param type * The type to use * @param context * The context to use * @return The new attribute instance */ public AttrInstance newInstance(AttrType type, AttrContext context) { if (type == null) return null; if (context == null) { return new ValueTuple(this, (DeclTuple) type, this.defaultContext); // return new ValueTuple(this, (DeclTuple) type, makeDefaultContext()); } return new ValueTuple(this, (DeclTuple) type, (ContextView) context); } /** * Returns an error message if something gone wrong, otherwise - empty * message. */ public String getErrorMsg() { return this.errorMsg; } public void clearErrorMsg() { this.errorMsg = ""; } // /////////////////// // Pre-Match Check /** * Checking if matching can be performed with respect to a given rule * context. If the rule context in question is without inconsistencies, this * method remains 'silent'. Otherwise, it throws an exception whose message * text describes the reason. */ public void checkIfReadyToMatch(AttrContext ruleContext) throws AttrException { if (ruleContext == null) { throw new AttrException("Null context supplied."); } ContextView context = (ContextView) ruleContext; String text = ""; /* * if( ruleContext.getConditions().isFalse() ) { text = "Application * condition [ "+((CondTuple) * ruleContext.getConditions()).getFailedConditionAsString()+" ] * failed."; } */ CondTuple conds = (CondTuple) context.getConditions(); for (int k = 0; k < conds.getSize(); k++) { CondMember cm = conds.getCondMemberAt(k); // System.out.println("AttrTupleManager.checkIfReadyToMatch:: // condMember: "+cm); if ( // (cm.getMark() != CondMember.NAC) // && (cm.getMark() != CondMember.NAC_LHS) // && (cm.getMark() != CondMember.PAC) // && (cm.getMark() != CondMember.PAC_LHS) // && (cm.getMark() != CondMember.NAC_PAC) // && (cm.getMark() != CondMember.NAC_PAC_LHS) cm.isEnabled() && (cm.getMark() == CondMember.LHS) && cm.isFalse()) { text = "Condition: " + cm.getExprAsText() + " failed!"; } // System.out.println("AttrTupleManager.checkIfReadyToMatch: error: "+text); } if (text.length() > 0) { this.errorMsg = text; throw new AttrException(text); } } // /////////////////// // Mapping: /** * Mapping between two attribute instances; The mapping is done according to * the context mapping property (total/partial) and is integrated into the * context; * * @param mappingContext * The context to include the mapping in * @param source * Mapping source attribute * @param target * Mapping target attribute * @return A handle to the mapping; it can be used to undo the mapping * (remove()) or to proceed to the next possible one (next()) * @see agg.attribute.AttrMapping#remove() * @see agg.attribute.AttrMapping#next() */ public AttrMapping newMapping(AttrContext mappingContext, AttrInstance source, AttrInstance target) throws AttrException { this.errorMsg = ""; try { return new TupleMapping((ContextView) mappingContext, (ValueTuple) source, (ValueTuple) target); } catch (AttrImplException ex1) { this.errorMsg = "Attributes don't match."; throw new AttrException(this.errorMsg); } } public AttrMapping newMappingChild2Parent(AttrContext mappingContext, AttrInstance source, AttrInstance target) throws AttrException { this.errorMsg = ""; try { return new TupleMapping((ContextView) mappingContext, (ValueTuple) source, (ValueTuple) target); } catch (AttrImplException ex1) { this.errorMsg = "Attributes don't match."; throw new AttrException(this.errorMsg); } } // /////////////////// // Transformation Check /** * Checking if an attributed graph transformation can be performed with * respect to a given context: variables and attribute conditions. If the given * match context is complete and without inconsistencies, this * method remains 'silent'. Otherwise, it throws an exception whose message * text describes the reason. */ public void checkIfReadyToTransform(AttrContext matchContext) throws AttrException { if (matchContext == null) { this.errorMsg = "Null context supplied."; throw new AttrException(this.errorMsg); } this.errorMsg = ""; VarTuple vars = (VarTuple) matchContext.getVariables(); for (int k = 0; k < vars.getSize(); k++) { VarMember vm = vars.getVarMemberAt(k); if (vm.isEnabled() && (vm.getMark() != VarMember.PAC) && (vm.getMark() != VarMember.NAC) && (vm.getMark() != VarMember.GAC) && !vm.isDefinite()) { this.errorMsg = "Variable: " + vm.getName() + " is not definite!"; } } CondTuple conds = (CondTuple) matchContext.getConditions(); for (int k = 0; k < conds.getSize(); k++) { CondMember cm = conds.getCondMemberAt(k); if (cm.isEnabled() && (cm.getMark() == CondMember.LHS) && !cm.isTrue()) { this.errorMsg = "Condition: " + cm.getExprAsText() + " is not satisfied!"; } } if (this.errorMsg.length() > 0) { throw new AttrException(this.errorMsg); } } /** * Checking if an attributed graph transformation can be performed with * respect to a given context: if checkVariablesOnly is TRUE then only do check * variables, otherwise - variables and attribute conditions. If the given * match context is complete and without inconsistencies, this * method remains 'silent'. Otherwise, it throws an exception whose message * text describes the reason. */ public void checkIfReadyToTransform(AttrContext matchContext, boolean checkVariablesOnly) throws AttrException { if (!checkVariablesOnly) { try { checkIfReadyToTransform(matchContext); } catch (AttrException ex) { this.errorMsg = ex.getMessage(); } } else { this.errorMsg = ""; if (matchContext == null) { this.errorMsg = "Null context supplied."; throw new AttrException(this.errorMsg); } VarTuple vars = (VarTuple) matchContext.getVariables(); for (int k = 0; k < vars.getSize(); k++) { VarMember vm = vars.getVarMemberAt(k); if (vm.isEnabled() && (vm.getMark() != VarMember.PAC) && (vm.getMark() != VarMember.NAC) && (vm.getMark() != VarMember.GAC) && !vm.isDefinite()) { this.errorMsg = "Variable: " + vm.getName() + " is not definite!"; } } if (this.errorMsg.length() > 0) { throw new AttrException(this.errorMsg); } } } // /////////////////// // View Context: /** * Creating a new view instance for loose coupling of attribute objects * with their visual representation. */ public AttrViewSetting newViewSetting() { return new OpenViewSetting(this); } public AttrViewSetting getDefaultOpenView() { return this.defaultOpenView; } public AttrViewSetting getDefaultMaskedView() { return this.defaultMaskedView; } // End of AttrManager interface implementation. // /////////////////////////////////////////////// public AttrViewSetting getFixedViewSetting() { return this.fixedViewSetting; } public void setDebug(boolean b) { VerboseControl.setDebug(b); } public AttrHandler[] getHandlers() { AttrHandler handlersCopy[] = new AttrHandler[this.handlers.length]; System.arraycopy(this.handlers, 0, handlersCopy, 0, this.handlers.length); return handlersCopy; } public boolean isCorrectInputEnforced() { return this.isCorrectInputEnforced; } public void setCorrectInputEnforced(boolean b) { this.isCorrectInputEnforced = b; } /** * Returns the class name if the specified name is a class name, * otherwise - null. */ public String isClassName(String name) { // System.out.println("AttrTupleManager.isClassName:: "+name); String result = null; boolean isClass = false; try { // Class<?> c = Class.forName(name); result = name; isClass = true; } catch (ClassNotFoundException ex) { } if (!isClass) { // 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]; java.util.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<?> c = Class.forName(pack + "." + name); result = pack + "." + name; isClass = true; break; } catch (ClassNotFoundException ex) { } } if (isClass) break; } } // System.out.println("AttrTupleManager.isClassName:: result: "+result); return result; } public String getStaticMethodCall(String aValue) { // check the form: $package.class$.static_method if (aValue.indexOf("$") == 0) { int ind = aValue.substring(1).indexOf("$"); if (ind > 0) { String clstr = aValue.substring(1, ind + 1); try { Class.forName(clstr); String tst = clstr.substring(clstr.indexOf(".") + 1); while (tst.indexOf(".") != -1) { clstr = tst.concat(""); tst = clstr.substring(clstr.indexOf(".") + 1); } clstr = tst.concat(""); String result = clstr + aValue.substring(ind + 2); return result; } catch (ClassNotFoundException ex) {} } } else { 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]; java.util.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); String tst = aValue; String pname = null; String tmp = ""; while (tst.indexOf(".") != -1) { String next = tst.substring(0, tst.indexOf(".")); String p = tmp + next; if (p.equals(pack)) { pname = pack; break; } else tmp = tmp + next; tmp = tmp + "."; tst = tst.substring(tst.indexOf(".") + 1, tst.length()); } if (pname != null) { // cut package name String result = aValue.replaceFirst(pname + ".", ""); // cut method name String clstr = result.substring(0, result.indexOf(".")); try { Class.forName(pname + "." + clstr); return result; } catch (ClassNotFoundException ex) { } } } } } return aValue; } } /* * $Log: AttrTupleManager.java,v $ * Revision 1.21 2010/11/28 22:11:36 olga * new method * * Revision 1.20 2010/08/23 07:30:49 olga * tuning * * Revision 1.19 2010/06/09 11:08:43 olga * tuning * * Revision 1.18 2010/03/31 21:08:13 olga * tuning * * Revision 1.17 2010/03/08 15:37:22 olga * code optimizing * * Revision 1.16 2009/03/12 10:57:44 olga * some changes in CPA of managing names of the attribute variables. * * Revision 1.15 2008/10/07 07:44:45 olga * Bug fixed: usage static methods of user own classes in attribute condition * * Revision 1.14 2008/05/19 09:19:32 olga * Applicability of Rule Sequence - reworking * * Revision 1.13 2007/12/10 08:42:58 olga * CPA of grammar with node type inheritance for attributed graphs - bug fixed * * Revision 1.12 2007/11/29 08:48:40 olga * apply match nextCompletion on to already total match, attr mapping part - bug fixed * * Revision 1.11 2007/11/28 08:31:42 olga * Match next completion : error message tuning * * Revision 1.10 2007/11/05 09:18:17 olga * code tuning * * Revision 1.9 2007/09/24 09:42:33 olga * AGG transformation engine tuning * * Revision 1.8 2007/09/10 13:05:19 olga * In this update: * - package xerces2.5.0 is not used anymore; * - class com.objectspace.jgl.Pair is replaced by the agg own generic class agg.util.Pair; * - bugs fixed in: usage of PACs in rules; match completion; * usage of static method calls in attr. conditions * - graph editing: added some new features * Revision 1.7 2007/06/13 08:33:09 olga Update: * V161 * * Revision 1.6 2007/05/07 07:59:30 olga CSP: extentions of CSP variables * concept * * Revision 1.5 2006/12/13 13:32:58 enrico reimplemented code * * Revision 1.4 2006/11/01 11:17:29 olga Optimized agg sources of CSP algorithm, * match usability, graph isomorphic copy, node/edge type multiplicity check for * injective rule and match * * Revision 1.3 2006/01/16 09:36:43 olga Extended attr. setting * * Revision 1.2 2005/10/24 09:04:49 olga GUI tuning * * Revision 1.1 2005/08/25 11:56:57 enrico *** empty log message *** * * Revision 1.2 2005/06/20 13:37:03 olga Up to now the version 1.2.8 will be * prepared. * * Revision 1.1 2005/05/30 12:58:04 olga Version with Eclipse * * Revision 1.12 2004/10/25 14:24:37 olga Fehlerbehandlung bei CPs und * Aenderungen im zusammenhang mit termination-Modul in AGG * * Revision 1.11 2004/06/28 08:09:55 olga Folgefehler Besetigung nach der * Anpassung der Attributekomponente fuer CPs * * Revision 1.10 2004/06/23 08:26:56 olga CPs sind endlich OK. * * Revision 1.9 2004/06/14 12:34:19 olga CP Analyse and Transformation * * Revision 1.8 2004/06/09 11:32:53 olga Attribute-Eingebe/Bedingungen : NAC * kann jetzt eigene Variablen und Bedingungen haben. CP Berechnung korregiert. * * Revision 1.7 2004/05/06 17:23:26 olga graph matching OK * * Revision 1.6 2004/04/15 10:49:47 olga Kommentare * * Revision 1.5 2004/01/07 09:37:14 olga test * * Revision 1.4 2003/12/18 16:25:48 olga Tests. * * Revision 1.3 2003/03/05 18:24:22 komm sorted/optimized import statements * * Revision 1.2 2003/02/03 17:46:30 olga new method : compareTo(AttrInstance a) * * Revision 1.1.1.1 2002/07/11 12:17:01 olga Imported sources * * Revision 1.14 2001/05/16 12:25:53 olga In checkIfReadyToMatch ist jetzt die * pruefung auf AttrMapping.PLAIN_MAP abgeschaltet. So kann man diese Methode * auch schon beim Matchen benutzen um die Attribute Condition zu testen. * * Revision 1.13 2001/05/14 12:10:42 olga Aenderungen wegen GenGEd: Match * Variable auf Variable - als Ergebnis nach Termersaetzung erscheint die * Variable in Klemmern: (x). Nur im Fall mit nur eine Variable werden die * Klammern weggelassen. Andere Aenderungen: Tests. * * Revision 1.12 2000/06/05 14:07:36 shultzke Debugausgaben fuer V1.0.0b * geloescht * * Revision 1.11 2000/05/24 10:02:28 olga Nur Testausgaben eingebaut bei der * Suche nach dem Fehler in DISAGG : Match Konstante auf Konstante * * Revision 1.10 2000/04/05 12:09:00 shultzke serialVersionUID aus V1.0.0 * generiert * */