// interface.beh -- interface method implementations. // $Id: interface.beh,v 1.14 2003/01/30 22:32:25 dougo Exp $ Strategy { public boolean isSimpleStrategy() {{ return false; }} public SimpleStrategyI toSimpleStrategy() {{ return (SimpleStrategyI) this; }} } SimpleStrategy { public boolean isSimpleStrategy() {{ return true; }} } StrategyGraph { public SimpleStrategyI toSimpleStrategy() {{ return toGraph(); }} } PathDirective { public SimpleStrategyI toSimpleStrategy() {{ return getGraph(); }} } Strategy { public boolean isStrategyCombination() {{ return false; }} public StrategyCombinationI toStrategyCombination() {{ return (StrategyCombinationI) this; }} } StrategyCombination { public boolean isStrategyCombination() {{ return true; }} } StrategyCombination { public boolean isStrategyIntersection() {{ return false; }} } Intersect { public boolean isStrategyIntersection() {{ return true; }} } StrategyCombination { {{ Strategy left, right; }} public StrategyI getLeftStrategy() {{ if (left == null) left = first; return left; }} public StrategyI getRightStrategy() {{ if (right == null) { Strategy next = rest.first.it; if (rest.first.next == null) { right = next; } else { StrategyCombination r = (StrategyCombination) clone(); r.first = next; r.rest = new Strategy_Commalist(rest.first.next); r.left = r.right = null; right = r; } } return right; }} } StrategyGraph { // SimpleStrategyI: /** The strategy graph S. */ public StrategyGraphI getStrategyGraph() {{ return this; }} /** An unmodifiable Collection of source nodes. */ public Collection getSources() {{ return Collections.unmodifiableCollection(sources); }} /** An unmodifiable Collection of target nodes. */ public Collection getTargets() {{ return Collections.unmodifiableCollection(targets); }} /** The set N(v), a collection of symbolic names (strings) corresponding to node v in the strategy graph S. */ public Collection getNames(Object v) {{ return ((GlobSpec) v).collectClassGlobs().map(nameMap); }} /** The constraint map B. Return null for B_true, in which all predicates return true. */ public ConstraintMapI getConstraintMap() {{ return this; }} // StrategyGraphI: /** An unmodifiable Collection of nodes in the strategy graph. */ public Collection getNodes() {{ return Collections.unmodifiableCollection(nodes.keySet()); }} /** An unmodifiable Collection of indices (Integers) of the edges coming into node v. Return an empty list if there are no incoming edges, null if there is no such node. */ public Collection getIncomingEdges(Object v) {{ IncidentEdges ie = (IncidentEdges) nodes.get(v); return ie == null ? null : ie.incoming; }} /** An unmodifiable Collection of indices (Integers) of the edges going out of node v. Return an empty list if there are no outgoing edges, null if there is no such node. */ public Collection getOutgoingEdges(Object v) {{ IncidentEdges ie = (IncidentEdges) nodes.get(v); return ie == null ? null : ie.outgoing; }} /** The number of edges in the strategy graph. */ public int numEdges() {{ return edgeList.size(); }} /** The source node of edge number i. */ public Object getEdgeSource(int i) {{ return ((SGEdge) edgeList.get(i)).get_source(); }} /** The target node of edge number i. */ public Object getEdgeTarget(int i) {{ return ((SGEdge) edgeList.get(i)).get_target(); }} // ConstraintMapI: /** Is the element predicate for the ith edge in the strategy graph true for the class graph node v, using name map N? */ public boolean meetsConstraint(int i, Object v, NameMapI N) {{ SGEdge sgedge = (SGEdge) edgeList.get(i); return sgedge.meetsConstraint(v, composeNameMap(N)); }} /** Is the element predicate for the ith edge in the strategy graph true for the class graph edge e, using name map N? */ public boolean meetsConstraint(int i, EdgeI e, NameMapI N) {{ SGEdge sgedge = (SGEdge) edgeList.get(i); return sgedge.meetsConstraint(e, composeNameMap(N)); }} /** Is the element predicate for the node a in the strategy graph true for the class graph node v, using name map N? */ public boolean meetsConstraint(Object a, Object v, NameMapI N) {{ return ((GlobSpec) a).match(v, composeNameMap(N)); }} /** Is the element predicate for the node a in the strategy graph true for the class graph edge e, using name map N? */ public boolean meetsConstraint(Object a, EdgeI e, NameMapI N) {{ return ((GlobSpec) a).match(e, composeNameMap(N)); }} /** Construct the composition of N and the encapsulated name map. Memoize the result. */ NameMapI composeNameMap(NameMapI N) {{ if (N != memoN) { memoN = N; if (N == null) composedN = nameMap; else if (nameMap == null) composedN = N; else composedN = NameMap.compose(N, nameMap); } return composedN; }} {{ NameMapI memoN, composedN; }} } SymbolicNameMap { /** A collection of nodes in class graph G corresponding to symbolic node name l in the strategy, or null if l is a wildcard (all nodes in the class graph). */ public Collection get(String l, ClassGraphI G) throws NoSuchClassGraphNodeException {{ ClassGlobSpec glob = get(l); if (glob == null) return Collections.singleton(G.getNode(l)); Collection strings = glob.getStrings(); if (strings == null) return null; Collection nodes = new HashSet(); Iterator i = strings.iterator(); while (i.hasNext()) { nodes.add(G.getNode((String) i.next())); } return nodes; }} /** Does symbolic node name l map to class graph node cgv? */ public boolean match(String l, Object cgv) {{ ClassGlobSpec cgNames = get(l); return cgNames == null ? String.valueOf(cgv).equals(l) : cgNames.match(cgv, null); }} /** Does symbolic edge label l map to class graph edge label cgl? */ public boolean match(String l, String cgl) {{ ClassGlobSpec cgNames = get(l); return cgNames == null ? cgl.equals(l) : cgNames.match(cgl, null); }} } Strategy { /** * An unmodifiable set of symbolic names that the source nodes in * the strategy graph map to, or null if the strategy can start at * any class graph node. */ public abstract Set getSourceNames(); /** * An unmodifiable set of symbolic names that the target nodes in * the strategy graph map to, or null if the strategy can finish at * any class graph node. */ public abstract Set getTargetNames(); } SimpleStrategy { public Set getSourceNames() {{ return getAllNames(toSimpleStrategy().getSources()); }} public Set getTargetNames() {{ return getAllNames(toSimpleStrategy().getTargets()); }} /** * An unmodifiable set of symbolic names that the given nodes in the * strategy graph map to, or null if one or more of the nodes is a * wildcard node that can map to all class graph nodes. */ public Set getAllNames(Collection nodes) {{ Set names = new LinkedHashSet(); for (Iterator it = nodes.iterator(); it.hasNext();) { Collection nodeNames = toSimpleStrategy().getNames(it.next()); if (nodeNames == null) return null; else names.addAll(nodeNames); } return Collections.unmodifiableSet(names); }} } StrategyCombination { public Set getSourceNames() {{ return combineNames(((Strategy) getLeftStrategy()).getSourceNames(), ((Strategy) getRightStrategy()).getSourceNames()); }} public Set getTargetNames() {{ return combineNames(((Strategy) getLeftStrategy()).getTargetNames(), ((Strategy) getRightStrategy()).getTargetNames()); }} public abstract Set combineNames(Set l, Set r); } Intersect { public Set combineNames(Set l, Set r) {{ if (l == null) return r; if (r == null) return l; Set combined = new LinkedHashSet(l); combined.retainAll(r); return Collections.unmodifiableSet(combined); }} } { Join, Merge } { public Set combineNames(Set l, Set r) {{ throw new RuntimeException("Join and Merge not yet implemented."); }} } StrategyReference { {{ Map env; Strategy strategy; }} Strategy deref() {{ if (strategy == null) { strategy = (Strategy) env.get(ident.toString()); if (strategy == null) throw new RuntimeException("No such strategy: " + ident); } return strategy; }} public boolean isSimpleStrategy() {{ return deref().isSimpleStrategy(); }} public SimpleStrategyI toSimpleStrategy() {{ return deref().toSimpleStrategy(); }} public boolean isStrategyCombination() {{ return deref().isStrategyCombination(); }} public StrategyCombinationI toStrategyCombination() {{ return deref().toStrategyCombination(); }} public Set getSourceNames() {{ return deref().getSourceNames(); }} public Set getTargetNames() {{ return deref().getTargetNames(); }} }