glob.beh.html

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);
  @)
	boolean isExact()to{ AnyClass, AnyPart }{
		init (@ return_val = true; @)
		before{ AnyClass, AnyPart }(@ return_val = false; @)
	}
	boolean isPartNameGlob()to{ ClassNameExact, PartNameExact }{
		(@ boolean cne, pne; @)
		before ClassNameExact (@ cne = true; @)
		before PartNameExact (@ pne = true; @)
		return boolean (@ pne && !cne @)
	}
	PartName get_partname()to PartName{
		before PartName (@ return_val = host; @)
	}
}

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); @)
}

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));
    }
  @)
}