//Nicholas Cassie - ncassie //Matt Finkel - mfinkel // Jason Lacouture - ateamjay // Project - phase 2 // March 15, 2004 // We have completed lab exercises 1,2,6,7,8,18 // sg.beh -- behavior for creating strategy graphs // $Id: sg.beh,v 1.16 2003/01/30 02:26:04 dougo Exp $ Strategy { /** Read a strategy expression from a byte stream. */ public static Strategy readFrom(InputStream in) throws ParseException {{ return readFrom(in, new HashMap()); }} /** Read a strategy expression from a char stream. */ public static Strategy readFrom(Reader in) throws ParseException {{ return readFrom(in, new HashMap()); }} /** Convert a string to a strategy. */ public static Strategy fromString(String s) {{ return fromString(s, new HashMap()); }} /** * Read a strategy expression from a byte stream. * Strategy references are resolved by looking them up in the * provided environent. */ public static Strategy readFrom(InputStream in, Map env) throws ParseException {{ Strategy s = StrategyExpression.parse(in).get_strategy(); s.attachEnv(env); return s; }} /** * Read a strategy expression from a char stream. * Strategy references are resolved by looking them up in the * provided environent. */ public static Strategy readFrom(Reader in, Map env) throws ParseException {{ Strategy s = StrategyExpression.parse(in).get_strategy(); s.attachEnv(env); return s; }} /** * Convert a string to a strategy. * Strategy references are resolved by looking them up in the * provided environent. */ public static Strategy fromString(String in, Map env) {{ Strategy s = StrategyExpression.parse(in).get_strategy(); s.attachEnv(env); return s; }} } Strategy { void attachEnv(Map env) to StrategyReference { before StrategyReference {{ host.env = env; }} } } StrategyGraph { {{ List edgeList = new ArrayList(); class IncidentEdges { List incoming = new ArrayList(), outgoing = new ArrayList(); } Map nodes = new HashMap(); // node -> IncidentEdges Set sources = new HashSet(), targets = new HashSet(); SymbolicNameMapI nameMap = null; }} init {{ edges = new SGEdge_SList(); }} StrategyGraph toGraph() {{ if (edgeList.isEmpty()) { Enumeration e = edges.elements(); int i = 0; Set allSources = new HashSet(), allTargets = new HashSet(); while (e.hasMoreElements()) { SGEdge edge = (SGEdge) e.nextElement(); addEdge(edge, i++); allSources.add(edge.get_source()); allTargets.add(edge.get_target()); } if (sources.isEmpty()) sources = allSources; if (targets.isEmpty()) targets = allTargets; if (nameMap == null) nameMap = (parsedNameMap == null ? new NameMap() : parsedNameMap); parsedNameMap = null; } return this; }} /* Add an edge to the strategy graph. */ public void addEdge(SGEdge edge) {{ addEdge(edge, edges.size()); edges.addElement(edge); }} void addEdge(SGEdge edge, int i) {{ edgeList.add(edge); GlobSpec source = edge.get_source(); if (edge.isSource()) sources.add(source); IncidentEdges ie = (IncidentEdges) nodes.get(source); if (ie == null) nodes.put(source, ie = new IncidentEdges()); ie.outgoing.add(new Integer(i)); GlobSpec target = edge.get_target(); if (edge.isTarget()) targets.add(target); ie = (IncidentEdges) nodes.get(target); if (ie == null) nodes.put(target, ie = new IncidentEdges()); ie.incoming.add(new Integer(i)); }} } PathDirective { {{ StrategyGraph graph; }} public StrategyGraph getGraph() {{ if (graph == null) graph = toGraph(); return graph; }} } PathDirective { StrategyGraph toGraph() to { From, NegativeConstraint, PositiveConstraint, To, ToStop, NameMap } { {{ SGEdge edge; }} {{ NameMap map = new NameMap(); }} before PathDirective {{ return_val = new StrategyGraph(); return_val.nameMap = map; }} before From {{ ClassGlobSpec sourcespec = host.get_sources(); edge = new SGEdge(); edge.set_source(sourcespec.toGlobSpec()); edge.set_sourcemarker(new SourceMarker()); }} before NegativeConstraint {{ edge.set_constraint(host); }} before PositiveConstraint {{ GlobSpec glob = host.get_glob(); edge.set_target(glob); return_val.addEdge(edge); edge = new SGEdge(); edge.set_source(glob); }} before ToStop {{ // Bypass the target(s). Bypassing constraint = Bypassing.parse("bypassing " + host.get_targets()); edge.set_constraint(constraint.intersectWith(edge.get_constraint())); }} after TargetDirective {{ ClassGlobSpec targets = host.get_targets(); edge.set_target(targets.toGlobSpec()); edge.set_targetmarker(new TargetMarker()); return_val.addEdge(edge); }} before NameMap {{ return_val.nameMap = NameMap.compose(host, map); }} } } Bypassing { NegativeConstraint intersectWith(NegativeConstraint constraint) {{ if (constraint == null) return this; if (constraint instanceof OnlyThrough) return constraint; return new Bypassing(glob.union(constraint.get_glob())); }} } Translator { {{ edu.neu.ccs.demeter.aplib.cd.ClassGraph cg; edu.neu.ccs.demeter.dj.ClassGraph demCG; //constructor taking a demeter.aplib.cd.ClassGraph and a demeter.dj.ClassGraph public Translator(edu.neu.ccs.demeter.aplib.cd.ClassGraph origCD, edu.neu.ccs.demeter.dj.ClassGraph origDemCG) { cg = origCD; demCG = origDemCG; } //constructor taking a demeter.aplib.cd.ClassGraph public Translator(edu.neu.ccs.demeter.aplib.cd.ClassGraph origCD) { cg = origCD; } //constructor taking a demeter.dj.ClassGraph public Translator(edu.neu.ccs.demeter.dj.ClassGraph origCD){ demCG = origCD; } //function to create the normalized version of the user's class dictionary public String normalizeCD() { return cg.normalize().toString(); } public void printSelect(String travStrat) { edu.neu.ccs.demeter.aplib.cd.ClassGraph currCG = cg; edu.neu.ccs.demeter.aplib.sg.Strategy strat = edu.neu.ccs.demeter.aplib.sg.Strategy.fromString(travStrat); try{ edu.neu.ccs.demeter.aplib.Traversal t = edu.neu.ccs.demeter.aplib.Traversal.compute(strat, currCG); edu.neu.ccs.demeter.aplib.cd.ClassGraph tempCG = new edu.neu.ccs.demeter.aplib.cd.ClassGraph(); for(Iterator it = t.getEdgeSets().iterator(); it.hasNext(); ) tempCG.addEdge(((edu.neu.ccs.demeter.aplib.Traversal.EdgeSet) it.next()).getEdge()); System.out.println("\nThe selected version of you class dictionary is:"); System.out.println(tempCG); }catch (Exception e){ System.out.println("Exception caught in Translator.getSelect"); } } public String getStratExprString(SelectorLanguage s, GraphNodes gn) { edu.neu.ccs.demeter.dj.ClassGraph currCG = demCG; final String stratName = gn.get_strategyname().get_name().toString(); String strStrat = "from * to *"; edu.neu.ccs.demeter.dj.Visitor v = new edu.neu.ccs.demeter.dj.Visitor(){ StrategyExpression expr = new StrategyExpression(); void before(StrategyDef stratDef){ if(stratDef.get_strategyname().get_name().toString().equals(stratName)){ expr = stratDef.get_strategyexpression(); } } public Object getReturnValue(){ return expr; } }; currCG.traverse(s, strStrat, v); StrategyExpression selectedStrategy = (StrategyExpression)v.getReturnValue(); return selectedStrategy.get_strategy().toString(); } }} } SemanticChecker { {{ edu.neu.ccs.demeter.dj.Strategy id; edu.neu.ccs.demeter.dj.ClassGraph cg; boolean isChecked; SelectorLanguage s; //constructor public SemanticChecker(edu.neu.ccs.demeter.dj.ClassGraph initClassGraph, SelectorLanguage sem) { id = new edu.neu.ccs.demeter.dj.Strategy("from edu.neu.ccs.demeter.aplib.sg.SelectorLanguage to *"); cg = initClassGraph; isChecked = true; s = sem; } //call all the semantic checking functions of this class //returns true if semantics are proper, false otherwise public boolean checkSemantics() { repUndef(cg); checkDefinedStrats(cg, getDefStrats(cg)); // checkTraversal(id, cg); return isChecked; } //get each used nodes and strategies, and check for their definition void repUndef(final edu.neu.ccs.demeter.dj.ClassGraph cg){ checkDefinedNodes(cg, getDefNodes(cg)); checkDefinedStrats(cg, getDefStrats(cg)); } //create a hashSet of all the used nodeNames HashSet getDefNodes(final edu.neu.ccs.demeter.dj.ClassGraph cg) { String strategy = "from edu.neu.ccs.demeter.aplib.sg.SelectorLanguage bypassing edu.neu.ccs.demeter.aplib.sg.NodeSubsetExpression to edu.neu.ccs.demeter.aplib.sg.NodeSubsetName"; edu.neu.ccs.demeter.dj.Visitor v = new edu.neu.ccs.demeter.dj.Visitor(){ HashSet return_val = new HashSet(); void before(NodeSubsetName nsn){ return_val.add(nsn.get_name()); } public Object getReturnValue(){ return return_val; } }; cg.traverse(s, strategy, v); return (HashSet)v.getReturnValue(); } //create a hashSet of all the used Strategies HashSet getDefStrats(final edu.neu.ccs.demeter.dj.ClassGraph cg) { String strategy = "from edu.neu.ccs.demeter.aplib.sg.SelectorLanguage via edu.neu.ccs.demeter.aplib.sg.StrategyDef bypassing edu.neu.ccs.demeter.aplib.sg.StrategyExpression to edu.neu.ccs.demeter.aplib.sg.StrategyName"; edu.neu.ccs.demeter.dj.Visitor v = new edu.neu.ccs.demeter.dj.Visitor(){ HashSet return_val = new HashSet(); void before(StrategyName sn){ return_val.add(sn.get_name()); } public Object getReturnValue(){ return return_val; } }; cg.traverse(s, strategy, v); return (HashSet)v.getReturnValue(); } //check all the used NodeSubsetNames for definitions void checkDefinedNodes(final edu.neu.ccs.demeter.dj.ClassGraph cg, final HashSet classHash) { String usedThings = "from * through edu.neu.ccs.demeter.aplib.sg.NodeSubsetExpression to edu.neu.ccs.demeter.aplib.sg.NodeSubsetName"; cg.traverse(s, usedThings, new edu.neu.ccs.demeter.dj.Visitor(){ void before(NodeSubsetName nsn) { edu.neu.ccs.demeter.Ident vn = (edu.neu.ccs.demeter.Ident)cg.fetch(nsn, "from * to edu.neu.ccs.demeter.Ident"); if(!classHash.contains(vn)) { System.out.println("The object " + nsn.get_name().toString() + " is undefined."); isChecked = false; } } }); } //check all the used Strategies for definitions void checkDefinedStrats(final edu.neu.ccs.demeter.dj.ClassGraph cg, final HashSet classHash1) { String usedThings = "from edu.neu.ccs.demeter.aplib.sg.SelectorLanguage to edu.neu.ccs.demeter.aplib.sg.StrategyName"; cg.traverse(s, usedThings, new edu.neu.ccs.demeter.dj.Visitor(){ void before(StrategyName sn) { edu.neu.ccs.demeter.Ident vn = (edu.neu.ccs.demeter.Ident)cg.fetch(sn, "from * to edu.neu.ccs.demeter.Ident"); if(!classHash1.contains(vn)) { System.out.println("The object" + sn.get_name().toString() + "is undefined."); isChecked = false; } } }); } //check the traversal void checkTraversal(String travStrat, final edu.neu.ccs.demeter.aplib.cd.ClassGraph cg) { try{ edu.neu.ccs.demeter.aplib.sg.Strategy strat = edu.neu.ccs.demeter.aplib.sg.Strategy.fromString(travStrat); edu.neu.ccs.demeter.aplib.Traversal t = edu.neu.ccs.demeter.aplib.Traversal.compute(strat, cg); edu.neu.ccs.demeter.dj.ClassGraph tempCG = new edu.neu.ccs.demeter.dj.ClassGraph(); for(Iterator it = t.getEdgeSets().iterator(); it.hasNext(); ){ tempCG.addEdge(((edu.neu.ccs.demeter.aplib.Traversal.EdgeSet) it.next()).getEdge()); } edu.neu.ccs.demeter.dj.TraversalGraph tg = new edu.neu.ccs.demeter.dj.TraversalGraph(travStrat, tempCG); }catch (Exception e){ System.out.println("Exception caught in Translator.getSelect"); } } }} } Main { /** Testing stub. */ public static void main(String args[]) {{ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); SelectorLanguage s = new SelectorLanguage(); try { s = SelectorLanguage.parse(in); } catch (ParseException e) { System.err.println(e.getMessage()); } //create the classGraph using the correct package edu.neu.ccs.demeter.dj.ClassGraph cg = new edu.neu.ccs.demeter.dj.ClassGraph("edu.neu.ccs.demeter.aplib.sg", true, false); //create a new semantic check with our cg and an object rooted at a SelectorLanguage object SemanticChecker semCheck = new SemanticChecker(cg, s); //checkSemantics returns a boolean //if it returns true the semantics have passed, otherwise there is an error in the user's input if(semCheck.checkSemantics()) { //create a new visitor that gets the contents of the user's classdictionary edu.neu.ccs.demeter.dj.Visitor v = new edu.neu.ccs.demeter.dj.Visitor(){ String classes = ""; void before(ClassDict sn){ classes = classes + sn.get_text(); } public Object getReturnValue(){ return classes; } }; //get the class dictionary, store it in userCD cg.traverse(s, "from * to *", v); String userCD = (String)v.getReturnValue(); //create a new classGraph from that class dictionary edu.neu.ccs.demeter.aplib.cd.ClassGraph userCG = edu.neu.ccs.demeter.aplib.cd.ClassGraph.fromString(userCD); System.out.println("The entered class dictionary was: \n" + userCG.toString()); //translate the user's class dictionary into the two required outputs Translator cgTrans = new Translator(userCG, cg); //Normalized CD //System.out.println("\nThe normalized version of your Class Dictionary:"); //System.out.println(cgTrans.normalizeCD()); //Selected CD //create a visitor object to get all the selectorNames edu.neu.ccs.demeter.dj.Visitor selectorV = new edu.neu.ccs.demeter.dj.Visitor(){ String selector = ""; void before(SelectorName sn){ selector = selector + sn.get_ident(); } public Object getReturnValue(){ return selector; } }; //get the selectorNames cg.traverse(s, "from * to *", selectorV); final String selectorName = (String)selectorV.getReturnValue(); //create a visitor that checks each NodeSubsetSpec's for equality with our SelectorName //if you get a match, get the corresponding nodeSubsetExpression edu.neu.ccs.demeter.dj.Visitor nodeV = new edu.neu.ccs.demeter.dj.Visitor(){ NodeSubsetExpression name; void before(NodeSubsetSpec nss){ if(selectorName.equals(nss.get_nodesubsetname().get_name().toString())){ name = nss.get_nodesubsetexpression(); } } public Object getReturnValue(){ return name; } }; //get the nodeSubsetExpression cg.traverse(s, "from * to *", nodeV); String travStrat = cgTrans.getStratExprString(s, (GraphNodes)nodeV.getReturnValue()); edu.neu.ccs.demeter.aplib.sg.Strategy strat = edu.neu.ccs.demeter.aplib.sg.Strategy.fromString(travStrat); semCheck.checkTraversal(travStrat, userCG); //Normalized CD System.out.println("\nThe normalized version of your Class Dictionary:"); System.out.println(cgTrans.normalizeCD()); //get the nodeSubsetExpression we're trying to work on if there is a selector name if (nodeV.getReturnValue() != null){ cgTrans.printSelect(travStrat); } else System.out.println("No graph node found"); } else System.out.println("The input semantics are incorrect, please try again."); }} }