// CTGglob.beh -- Glob matching and manipulation // $Id: glob.beh,v 1.8 1997/09/12 02:04:32 dougo Exp $ // modified: Binoy : 1997/11/14 ClassGlobSpec { traversal allClassNames(ClassGlobVisitor v) { to { ClassName, AnyClass }; } } ClassGlobVisitor { before { ClassName, AnyClass } (@ @) } { GlobSpec, ClassGlobSpec } { (@ boolean match(Glob glob) { GlobMatcher matcher = new GlobMatcher(glob, false); allGlobs(matcher); return matcher.get_found_one(); } @) } ClassGlobSpec { traversal allGlobs(GlobVisitor v) { to ClassGlob; } (@ /** Return true iff the globspec matches the class. */ boolean match(ClassName name) { return match(new ClassGlob(name)); } @) } GlobSpec { traversal allGlobs(GlobVisitor v) { to { ClassGlob, PartGlob, SubclassGlob, SuperclassGlob }; } (@ /** Return true iff the globspec matches the edge from source to part. */ boolean match(ClassName source, Part part) { return match(new PartGlob(source, part.get_partname(), part.get_classname())) || match(new ClassGlob(part.get_classname())); } /** Return true iff the globspec matches the edge from source to sub. */ boolean match(ClassName source, Subclass sub) { return match(new SubclassGlob(source, sub.get_classname())) || match(new ClassGlob(sub.get_classname())); } /** Return true iff the globspec matches the edge from source to sup. */ boolean match(ClassName source, Superclass sup) { return match(new SuperclassGlob(source, sup.get_classname())) || match(new ClassGlob(sup.get_classname())); } /** Return true iff the globspec matches the edge. */ boolean match(TGEdge edge) { TGEdgeGlobMaker m = new TGEdgeGlobMaker(); edge.toAll(m); return match(m.get_return_val()) || match(new ClassGlob((ClassName) edge.get_dest().get_classname())); } @) } TGEdgeGlobMaker { before -> TGVertex,classname,ClassNameI (@ cl = (ClassName) dest; @) before -> TGCEdge,name,PartNameI (@ name = (PartName) dest; @) after -> TGEdge,source,TGVertex (@ s = cl; @) after -> TGEdge,dest,TGVertex (@ d = cl; @) after TGCEdge (@ return_val = new PartGlob(s, name, d); @) after TGAEdge (@ return_val = new SubclassGlob(s, d); @) after TGIEdge (@ return_val = new SuperclassGlob(s, d); @) } GlobVisitor { before { GlobSpec, ClassGlobSpec, Glob, ClassGlob, PartGlob, SubclassGlob, SuperclassGlob } (@ @) } GlobMatcher { before ClassGlob (@ if (glob instanceof ClassGlob && host.get_name().match(((ClassGlob) glob).get_name())) found_one = true; @) before PartGlob (@ if (glob instanceof PartGlob) { PartGlob pglob = (PartGlob) glob; if (host.get_source().match(pglob.get_source()) && host.get_name().match(pglob.get_name()) && host.get_dest().match(pglob.get_dest())) found_one = true; } @) before SubclassGlob (@ if (glob instanceof SubclassGlob) { SubclassGlob sglob = (SubclassGlob) glob; if (host.get_source().match(sglob.get_source()) && host.get_dest().match(sglob.get_dest())) found_one = true; } @) before SuperclassGlob (@ if (glob instanceof SuperclassGlob) { SuperclassGlob sglob = (SuperclassGlob) glob; if (host.get_source().match(sglob.get_source()) && host.get_dest().match(sglob.get_dest())) found_one = true; } @) } SourceGlob { (@ boolean match(SourceGlob glob) { return name.match(glob.name); } @) } DestGlob { (@ boolean match(DestGlob glob) { return name.match(glob.name); } @) } ClassNameGlob { abstract boolean match(ClassNameGlob glob); } ClassNameGlob { abstract boolean match(ClassNameExact ex); } AnyClass { (@ boolean match(ClassNameGlob glob) { return true; } @) } AnyClass { (@ boolean match(ClassNameExact ex) { return true; } @) } ClassNameExact { (@ boolean match(ClassNameGlob glob) { return glob.match(this); } boolean match(ClassNameExact ex) { return classname.equals(ex.classname); } @) } PartNameGlob { abstract boolean match(PartNameGlob glob); } PartNameGlob { abstract boolean match(PartNameExact ex); } AnyPart { (@ boolean match(PartNameGlob glob) { return true; } @) } AnyPart { (@ boolean match(PartNameExact ex) { return true; } @) } PartNameExact { (@ boolean match(PartNameGlob glob) { return glob.match(this); } boolean match(PartNameExact ex) { return partname.equals(ex.partname); } @) } GlobSpec { (@ /** Return a ClassGlobSpec that matches all the classes in the GlobSpec, or null if there are none. */ ClassGlobSpec collectClassGlobs() { ClassGlobCollector c = new ClassGlobCollector(); allClassGlobs(c); return c.get_spec(); } /** Return a GlobSpec that matches all the edges in the GlobSpec, or null if there are none. */ GlobSpec collectEdgeGlobs() { EdgeGlobCollector c = new EdgeGlobCollector(); allEdgeGlobs(c); return c.get_spec(); } /** Merge two glob specs into the union of the two. */ GlobSpec union(GlobSpec spec) { if (spec == null) return this; GlobCollector coll = new GlobCollector(new GlobSet()); allGlobs(coll); spec.allGlobs(coll); return coll.get_spec(); } @) traversal allClassGlobs(GlobVisitor v) { to ClassGlob; } traversal allEdgeGlobs(GlobVisitor v) { to EdgeGlob; } } ClassGlobCollector { before ClassGlob (@ if (spec == null) spec = new ClassGlobSet(new ClassGlob_Commalist()); spec.addElement(host); @) } EdgeGlobCollector { before EdgeGlob (@ if (spec == null) spec = new GlobSet(new Glob_Commalist()); spec.addElement(host); @) } GlobCollector { before Glob (@ spec.addElement(host); @) } ClassGlobSpec { (@ /** Convert a set of classes to a set of edges outgoing from the classes. */ GlobSpec toOutgoingEdgeSpec() { OutgoingEdgeSpecConvertor c = new OutgoingEdgeSpecConvertor(new GlobSet()); allGlobs(c); return c.get_spec(); } @) } OutgoingEdgeSpecConvertor { before ClassGlob (@ spec.addElement(PartGlob.parse("-> " + host + ",*,*")); spec.addElement(SubclassGlob.parse("=> " + host + ",*,*")); spec.addElement(SuperclassGlob.parse(":> " + host + ",*,*")); @) } Glob { void addToHostSet(HostSet hostset) (@ if (isExact()) hostset.addExactHost(this); else hostset.addGlob(this); @) /** An exact glob has no wildcards. */ boolean isExact() to { AnyClass, AnyPart } { init (@ return_val = true; @) before { AnyClass, AnyPart } (@ return_val = false; @) } /** A partname glob has an exact partname and no class wildcards. */ boolean isPartNameGlob() to { ClassNameExact, PartNameExact } { (@ boolean cne, pne; @) before ClassNameExact (@ cne = true; @) before PartNameExact (@ pne = true; @) return boolean (@ pne && !cne @) } /** Get the exact partname, assuming it's a partname glob. */ PartName get_partname() to PartName { before PartName (@ return_val = host; @) } } // Repetition utility functions -- these should probably be generated // automatically. ClassGlobSet { (@ void addElement(ClassGlob glob) { globs.addElement(glob); } @) } GlobSet { (@ void addElement(Glob glob) { if (globs == null) globs = new Glob_Commalist(); globs.addElement(glob); } @) } ClassGlobSpec { abstract Enumeration elements(); } ClassGlobSet { (@ Enumeration elements() { return globs.elements(); } @) } OneClassGlob { (@ Enumeration elements() { return ClassGlobSet.parse("{" + classglob + "}").elements(); } @) } ClassGlobSet { void setadd(ClassGlobSpec spec) (@ Enumeration e = spec.elements(); while (e.hasMoreElements()) { ClassGlob glob = (ClassGlob) e.nextElement(); if (!contains(glob)) addElement(glob); } @) boolean contains(ClassGlob glob) (@ return globs.contains(glob); @) } // Constructors -- these should probably be generated automatically. ClassGlob { (@ public ClassGlob(ClassName name) { this(new ClassNameExact(name)); } @) } SourceGlob { (@ public SourceGlob(ClassName name) { this(new ClassNameExact(name)); } @) } DestGlob { (@ public DestGlob(ClassName name) { this(new ClassNameExact(name)); } @) } PartGlob { (@ public PartGlob(ClassName source, PartName name, ClassName dest) { this(new SourceGlob(source), new PartNameExact(name), new DestGlob(dest)); } @) } SubclassGlob { (@ public SubclassGlob(ClassName source, ClassName dest) { this(new SourceGlob(source), new DestGlob(dest)); } @) } SuperclassGlob { (@ public SuperclassGlob(ClassName source, ClassName dest) { this(new SourceGlob(source), new DestGlob(dest)); } @) } //some util fns: have to move this somewhere.. ClassDef { traversal toClassName(ClassNameAccessor v) { bypassing { ClassParts, ClassMethods, -> *,parameters,* } to ClassName; } } { Subclass, Superclass, Part, RepeatedPart } { traversal toClassName(ClassNameAccessor v) { bypassing { -> *,actual_parameters,* } to ClassName; } } { ClassDef, Subclass, Superclass, Part, RepeatedPart } { ClassName get_classname() = toClassName { before ClassName (@ return_val = host; @) } } HostSet { void add(Glob host) (@ if (host.isExact()) addExactHost(host); else if (host.isPartNameGlob()) addPartName(host.get_partname()); else addGlob(host); @) void addExactHost(Glob host) (@ if (exactHosts == null) exactHosts = new Hashtable(); exactHosts.put(host, host); @) void addPartName(PartName name) (@ if (partnames == null) partnames = new Hashtable(); partnames.put(name, name); @) void addGlob(Glob glob) (@ if (globs == null) globs = new GlobSet(); globs.addElement(glob); @) boolean contains(Glob glob) (@ if (exactHosts != null && exactHosts.get(glob) != null) return true; if (partnames != null && glob instanceof PartGlob && partnames.get(glob.get_partname()) != null) return true; if (globs != null && globs.match(glob)) return true; return false; @) }