mirror of https://github.com/dspinellis/UMLGraph
Introduced explicit enums for relation types and relation directions, added an option to specify the direction and type of relations included in the context (basically, a tool to build a map from relation type to direction), fixed a test that still contained the old -inferassoc intestead of -inferrel
This commit is contained in:
parent
afa290cca5
commit
14b80c0eab
|
|
@ -20,8 +20,9 @@
|
|||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class's dot-comaptible alias name (for fully qualified class names)
|
||||
|
|
@ -42,7 +43,7 @@ class ClassInfo {
|
|||
* all the classes linked with a bi-directional relation , and the ones
|
||||
* referred by a directed relation
|
||||
*/
|
||||
Set<String> relatedClasses = new HashSet<String>();
|
||||
Map<String, RelationPattern> relatedClasses = new HashMap<String, RelationPattern>();
|
||||
|
||||
ClassInfo(boolean p, boolean h) {
|
||||
nodePrinted = p;
|
||||
|
|
@ -51,12 +52,17 @@ class ClassInfo {
|
|||
classNumber++;
|
||||
}
|
||||
|
||||
public void addRelation(String dest) {
|
||||
relatedClasses.add(dest);
|
||||
public void addRelation(String dest, RelationType rt, RelationDirection d) {
|
||||
RelationPattern ri = relatedClasses.get(dest);
|
||||
if(ri == null) {
|
||||
ri = new RelationPattern(RelationDirection.NONE);
|
||||
relatedClasses.put(dest, ri);
|
||||
}
|
||||
ri.addRelation(rt, d);
|
||||
}
|
||||
|
||||
public boolean isRelated(String dest) {
|
||||
return relatedClasses.contains(dest);
|
||||
public RelationPattern getRelation(String dest) {
|
||||
return relatedClasses.get(dest);
|
||||
}
|
||||
|
||||
/** Start numbering from zero. */
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ import com.sun.javadoc.RootDoc;
|
|||
|
||||
/**
|
||||
* Matches classes that are directly connected to one of the classes matched by
|
||||
* the regual expression specified. The context center is computed by regex lookup.
|
||||
* Depending on the specified Options, inferred relations and dependencies will
|
||||
* be used as well.
|
||||
* the regual expression specified. The context center is computed by regex
|
||||
* lookup. Depending on the specified Options, inferred relations and
|
||||
* dependencies will be used as well.
|
||||
* <p>
|
||||
* This class needs to perform quite a bit of computations in order to gather
|
||||
* the network of class releationships, so you are allowed to reuse it should
|
||||
* you
|
||||
* you
|
||||
* @author wolf
|
||||
*
|
||||
* @depend - - - DevNullWriter
|
||||
|
|
@ -61,6 +61,10 @@ public class ContextMatcher implements ClassMatcher {
|
|||
* @param keepParentHide If true, parent option hide patterns will be
|
||||
* preserved, so that classes hidden by the options won't
|
||||
* be shown in the context
|
||||
* @param fullContext If true, all the classes related to the context
|
||||
* center will be included, otherwise it will match only
|
||||
* the classes referred with an outgoing relation from
|
||||
* the context center
|
||||
* @throws IOException
|
||||
*/
|
||||
public ContextMatcher(RootDoc root, Pattern pattern, Options options, boolean keepParentHide) throws IOException {
|
||||
|
|
@ -68,14 +72,14 @@ public class ContextMatcher implements ClassMatcher {
|
|||
this.root = root;
|
||||
this.keepParentHide = keepParentHide;
|
||||
opt = (Options) options.clone();
|
||||
opt.setOption(new String[] {"-!hide"});
|
||||
opt.setOption(new String[] {"-!attributes"});
|
||||
opt.setOption(new String[] {"-!operations"});
|
||||
opt.setOption(new String[] { "-!hide" });
|
||||
opt.setOption(new String[] { "-!attributes" });
|
||||
opt.setOption(new String[] { "-!operations" });
|
||||
this.cg = new ClassGraphHack(root, opt);
|
||||
|
||||
setContextCenter(pattern);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Can be used to setup a different pattern for this context matcher.
|
||||
* <p>
|
||||
|
|
@ -103,11 +107,12 @@ public class ContextMatcher implements ClassMatcher {
|
|||
* @param cd
|
||||
*/
|
||||
private void addToGraph(ClassDoc cd) {
|
||||
// avoid adding twice the same class, but don't rely on cg.getClassInfo since there
|
||||
// avoid adding twice the same class, but don't rely on cg.getClassInfo
|
||||
// since there
|
||||
// are other ways to add a classInfor than printing the class
|
||||
if(visited.contains(cd.toString()))
|
||||
if (visited.contains(cd.toString()))
|
||||
return;
|
||||
|
||||
|
||||
visited.add(cd.toString());
|
||||
cg.printClass(cd, false);
|
||||
cg.printRelations(cd);
|
||||
|
|
@ -146,10 +151,8 @@ public class ContextMatcher implements ClassMatcher {
|
|||
for (ClassDoc mcd : matched) {
|
||||
String mcName = mcd.toString();
|
||||
ClassInfo ciMatched = cg.getClassInfo(mcName);
|
||||
if (ciMatched != null && ciMatched.isRelated(name))
|
||||
return true;
|
||||
ClassInfo ci = cg.getClassInfo(name);
|
||||
if (ci != null && ci.isRelated(mcName))
|
||||
RelationPattern rp = ciMatched.getRelation(name);
|
||||
if (ciMatched != null && rp != null && opt.contextRelationPattern.matchesOne(rp))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -109,11 +109,12 @@ public class Options implements Cloneable, OptionProvider {
|
|||
String guilClose = "»"; // "\u00bb";
|
||||
boolean inferRelationships;
|
||||
boolean inferDependencies;
|
||||
RelationPattern contextRelationPattern;
|
||||
boolean useImports;
|
||||
Visibility inferDendencyVisibility;
|
||||
boolean inferDepInPackage;
|
||||
boolean verbose2;
|
||||
String inferRelationshipType;
|
||||
RelationType inferRelationshipType;
|
||||
private Vector<Pattern> collPackages;
|
||||
boolean compact;
|
||||
// internal option, used by UMLDoc to generate relative links between classes
|
||||
|
|
@ -161,12 +162,13 @@ public class Options implements Cloneable, OptionProvider {
|
|||
useGuillemot = true;
|
||||
findViews = false;
|
||||
viewName = null;
|
||||
contextRelationPattern = new RelationPattern(RelationDirection.BOTH);
|
||||
inferRelationships = false;
|
||||
inferDependencies = false;
|
||||
inferDendencyVisibility = Visibility.PRIVATE;
|
||||
inferDepInPackage = false;
|
||||
useImports = false;
|
||||
inferRelationshipType = "navassoc";
|
||||
inferRelationshipType = RelationType.NAVASSOC;
|
||||
collPackages = new Vector<Pattern>();
|
||||
compact = false;
|
||||
relativeLinksForSourcePackages = false;
|
||||
|
|
@ -220,6 +222,7 @@ public class Options implements Cloneable, OptionProvider {
|
|||
option.equals("-useimports") ||
|
||||
option.equals("-inferdep") ||
|
||||
option.equals("-inferdepinpackage") ||
|
||||
option.equals("-fullContext") ||
|
||||
option.equals("-verbose2") ||
|
||||
option.equals("-compact"))
|
||||
|
||||
|
|
@ -251,9 +254,10 @@ public class Options implements Cloneable, OptionProvider {
|
|||
option.equals("-inferreltype") ||
|
||||
option.equals("-inferdepvis") ||
|
||||
option.equals("-collpackages") ||
|
||||
option.equals("-link")
|
||||
)
|
||||
option.equals("-link"))
|
||||
return 2;
|
||||
else if(option.equals("-contextPattern"))
|
||||
return 3;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -423,22 +427,23 @@ public class Options implements Cloneable, OptionProvider {
|
|||
} else if(opt[0].equals("-!inferrel")) {
|
||||
inferRelationships = false;
|
||||
} else if(opt[0].equals("-inferreltype")) {
|
||||
if(ClassGraph.associationMap.containsKey(opt[1])) {
|
||||
inferRelationshipType = opt[1];
|
||||
} else {
|
||||
System.err.println("Unknown association type " + opt[1]);
|
||||
}
|
||||
try {
|
||||
inferRelationshipType = RelationType.valueOf(opt[1].toUpperCase());
|
||||
} catch(IllegalArgumentException e) {
|
||||
System.err.println("Unknown association type " + opt[1]);
|
||||
}
|
||||
} else if(opt[0].equals("-!inferreltype")) {
|
||||
inferRelationshipType = "navassoc";
|
||||
inferRelationshipType = RelationType.NAVASSOC;
|
||||
} else if(opt[0].equals("-inferdepvis")) {
|
||||
Visibility vis = Visibility.parseVisibility(opt[1]);
|
||||
if(vis == null)
|
||||
System.err.println("Ignoring invalid visibility specification for dependency inference" + vis);
|
||||
inferDendencyVisibility = Visibility.PRIVATE;
|
||||
try {
|
||||
Visibility vis = Visibility.valueOf(opt[1].toUpperCase());
|
||||
inferDendencyVisibility = vis;
|
||||
} catch(IllegalArgumentException e) {
|
||||
System.err.println("Ignoring invalid visibility specification for " +
|
||||
"dependency inference: " + opt[1]);
|
||||
}
|
||||
} else if(opt[0].equals("-!inferdepvis")) {
|
||||
inferDendencyVisibility = Visibility.PRIVATE;
|
||||
} else if(opt[0].equals("-!inferreltype")) {
|
||||
inferRelationshipType = "navassoc";
|
||||
} else if(opt[0].equals("-inferdep")) {
|
||||
inferDependencies = true;
|
||||
} else if(opt[0].equals("-!inferdep")) {
|
||||
|
|
@ -469,6 +474,20 @@ public class Options implements Cloneable, OptionProvider {
|
|||
postfixPackage = false;
|
||||
} else if (opt[0].equals("-link")) {
|
||||
addApiDocRoots(opt[1]);
|
||||
} else if(opt[0].equals("-contextPattern")) {
|
||||
RelationDirection d; RelationType rt;
|
||||
try {
|
||||
d = RelationDirection.valueOf(opt[2].toUpperCase());
|
||||
if(opt[1].equalsIgnoreCase("all")) {
|
||||
contextRelationPattern = new RelationPattern(d);
|
||||
} else {
|
||||
rt = RelationType.valueOf(opt[1].toUpperCase());
|
||||
contextRelationPattern.addRelation(rt, d);
|
||||
}
|
||||
} catch(IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
; // Do nothing, javadoc will handle the option or complain, if
|
||||
// needed.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* The possibile directions of a relation given a reference class (used in
|
||||
* context diagrams)
|
||||
*/
|
||||
public enum RelationDirection {
|
||||
NONE, IN, OUT, BOTH;
|
||||
|
||||
/**
|
||||
* Adds the current direction
|
||||
* @param d
|
||||
* @return
|
||||
*/
|
||||
public RelationDirection sum(RelationDirection d) {
|
||||
if (this == NONE)
|
||||
return d;
|
||||
|
||||
if ((this == IN && d == OUT) || (this == OUT && d == IN) || this == BOTH || d == BOTH)
|
||||
return BOTH;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this direction "contains" the specified one, that is,
|
||||
* either it's equal to it, or this direction is {@link #BOTH}
|
||||
* @param d
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(RelationDirection d) {
|
||||
if (this == BOTH)
|
||||
return true;
|
||||
else
|
||||
return d == this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the direction of the relation. Turns IN into OUT and vice-versa, NONE and BOTH
|
||||
* are not changed
|
||||
* @return
|
||||
*/
|
||||
public RelationDirection inverse() {
|
||||
if (this == IN)
|
||||
return OUT;
|
||||
else if (this == OUT)
|
||||
return IN;
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* A map from relation types to directions
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class RelationPattern {
|
||||
/**
|
||||
* A map from RelationType (indexes) to Direction objects
|
||||
*/
|
||||
RelationDirection[] directions;
|
||||
|
||||
/**
|
||||
* Creates a new pattern using the same direction for every relation kind
|
||||
* @param defaultDirection The direction used to initialize this pattern
|
||||
*/
|
||||
public RelationPattern(RelationDirection defaultDirection) {
|
||||
directions = new RelationDirection[RelationType.values().length];
|
||||
for (int i = 0; i < directions.length; i++) {
|
||||
directions[i] = defaultDirection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds, eventually merging, a direction for the specified relation type
|
||||
* @param relationType
|
||||
* @param direction
|
||||
*/
|
||||
public void addRelation(RelationType relationType, RelationDirection direction) {
|
||||
int idx = relationType.ordinal();
|
||||
directions[idx] = directions[idx].sum(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this patterns matches at least the direction of one
|
||||
* of the relations in the other relation patterns. Matching is defined
|
||||
* by {@linkplain RelationDirection#contains(RelationDirection)}
|
||||
* @param relationPattern
|
||||
* @return
|
||||
*/
|
||||
public boolean matchesOne(RelationPattern relationPattern) {
|
||||
for (int i = 0; i < directions.length; i++) {
|
||||
if (directions[i].contains(relationPattern.directions[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* The type of relation that links two entities
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public enum RelationType {
|
||||
ASSOC, NAVASSOC, HAS, COMPOSED, DEPEND, EXTENDS, IMPLEMENTS;
|
||||
}
|
||||
|
|
@ -97,6 +97,9 @@ public class View implements OptionProvider {
|
|||
} else if (strings[0].equals("context")) {
|
||||
return new ContextMatcher(root, Pattern.compile(strings[1]), getGlobalOptions(),
|
||||
false);
|
||||
} else if (strings[0].equals("outgoingContext")) {
|
||||
return new ContextMatcher(root, Pattern.compile(strings[1]), getGlobalOptions(),
|
||||
false);
|
||||
} else if (strings[0].equals("interface")) {
|
||||
return new InterfaceMatcher(root, Pattern.compile(strings[1]));
|
||||
} else if (strings[0].equals("subclass")) {
|
||||
|
|
|
|||
|
|
@ -28,13 +28,7 @@ import com.sun.javadoc.ProgramElementDoc;
|
|||
*
|
||||
*/
|
||||
public enum Visibility {
|
||||
PRIVATE("private"), PACKAGE("package"), PROTECTED("protected"), PUBLIC("public");
|
||||
|
||||
private String name;
|
||||
|
||||
private Visibility(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
PRIVATE, PACKAGE, PROTECTED, PUBLIC;
|
||||
|
||||
public static Visibility get(ProgramElementDoc doc) {
|
||||
if (doc.isPrivate())
|
||||
|
|
@ -47,12 +41,4 @@ public enum Visibility {
|
|||
return PUBLIC;
|
||||
|
||||
}
|
||||
|
||||
public static Visibility parseVisibility(String vis) {
|
||||
for (Visibility v : Visibility.values()) {
|
||||
if (v.name.equalsIgnoreCase(vis))
|
||||
return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,9 @@
|
|||
|
||||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class's dot-comaptible alias name (for fully qualified class names)
|
||||
|
|
@ -42,7 +43,7 @@ class ClassInfo {
|
|||
* all the classes linked with a bi-directional relation , and the ones
|
||||
* referred by a directed relation
|
||||
*/
|
||||
Set<String> relatedClasses = new HashSet<String>();
|
||||
Map<String, RelationPattern> relatedClasses = new HashMap<String, RelationPattern>();
|
||||
|
||||
ClassInfo(boolean p, boolean h) {
|
||||
nodePrinted = p;
|
||||
|
|
@ -51,12 +52,17 @@ class ClassInfo {
|
|||
classNumber++;
|
||||
}
|
||||
|
||||
public void addRelation(String dest) {
|
||||
relatedClasses.add(dest);
|
||||
public void addRelation(String dest, RelationType rt, RelationDirection d) {
|
||||
RelationPattern ri = relatedClasses.get(dest);
|
||||
if(ri == null) {
|
||||
ri = new RelationPattern(RelationDirection.NONE);
|
||||
relatedClasses.put(dest, ri);
|
||||
}
|
||||
ri.addRelation(rt, d);
|
||||
}
|
||||
|
||||
public boolean isRelated(String dest) {
|
||||
return relatedClasses.contains(dest);
|
||||
public RelationPattern getRelation(String dest) {
|
||||
return relatedClasses.get(dest);
|
||||
}
|
||||
|
||||
/** Start numbering from zero. */
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ import com.sun.javadoc.RootDoc;
|
|||
|
||||
/**
|
||||
* Matches classes that are directly connected to one of the classes matched by
|
||||
* the regual expression specified. The context center is computed by regex lookup.
|
||||
* Depending on the specified Options, inferred relations and dependencies will
|
||||
* be used as well.
|
||||
* the regual expression specified. The context center is computed by regex
|
||||
* lookup. Depending on the specified Options, inferred relations and
|
||||
* dependencies will be used as well.
|
||||
* <p>
|
||||
* This class needs to perform quite a bit of computations in order to gather
|
||||
* the network of class releationships, so you are allowed to reuse it should
|
||||
* you
|
||||
* you
|
||||
* @author wolf
|
||||
*
|
||||
* @depend - - - DevNullWriter
|
||||
|
|
@ -61,6 +61,10 @@ public class ContextMatcher implements ClassMatcher {
|
|||
* @param keepParentHide If true, parent option hide patterns will be
|
||||
* preserved, so that classes hidden by the options won't
|
||||
* be shown in the context
|
||||
* @param fullContext If true, all the classes related to the context
|
||||
* center will be included, otherwise it will match only
|
||||
* the classes referred with an outgoing relation from
|
||||
* the context center
|
||||
* @throws IOException
|
||||
*/
|
||||
public ContextMatcher(RootDoc root, Pattern pattern, Options options, boolean keepParentHide) throws IOException {
|
||||
|
|
@ -68,14 +72,14 @@ public class ContextMatcher implements ClassMatcher {
|
|||
this.root = root;
|
||||
this.keepParentHide = keepParentHide;
|
||||
opt = (Options) options.clone();
|
||||
opt.setOption(new String[] {"-!hide"});
|
||||
opt.setOption(new String[] {"-!attributes"});
|
||||
opt.setOption(new String[] {"-!operations"});
|
||||
opt.setOption(new String[] { "-!hide" });
|
||||
opt.setOption(new String[] { "-!attributes" });
|
||||
opt.setOption(new String[] { "-!operations" });
|
||||
this.cg = new ClassGraphHack(root, opt);
|
||||
|
||||
setContextCenter(pattern);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Can be used to setup a different pattern for this context matcher.
|
||||
* <p>
|
||||
|
|
@ -103,11 +107,12 @@ public class ContextMatcher implements ClassMatcher {
|
|||
* @param cd
|
||||
*/
|
||||
private void addToGraph(ClassDoc cd) {
|
||||
// avoid adding twice the same class, but don't rely on cg.getClassInfo since there
|
||||
// avoid adding twice the same class, but don't rely on cg.getClassInfo
|
||||
// since there
|
||||
// are other ways to add a classInfor than printing the class
|
||||
if(visited.contains(cd.toString()))
|
||||
if (visited.contains(cd.toString()))
|
||||
return;
|
||||
|
||||
|
||||
visited.add(cd.toString());
|
||||
cg.printClass(cd, false);
|
||||
cg.printRelations(cd);
|
||||
|
|
@ -146,10 +151,8 @@ public class ContextMatcher implements ClassMatcher {
|
|||
for (ClassDoc mcd : matched) {
|
||||
String mcName = mcd.toString();
|
||||
ClassInfo ciMatched = cg.getClassInfo(mcName);
|
||||
if (ciMatched != null && ciMatched.isRelated(name))
|
||||
return true;
|
||||
ClassInfo ci = cg.getClassInfo(name);
|
||||
if (ci != null && ci.isRelated(mcName))
|
||||
RelationPattern rp = ciMatched.getRelation(name);
|
||||
if (ciMatched != null && rp != null && opt.contextRelationPattern.matchesOne(rp))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -109,11 +109,12 @@ public class Options implements Cloneable, OptionProvider {
|
|||
String guilClose = "»"; // "\u00bb";
|
||||
boolean inferRelationships;
|
||||
boolean inferDependencies;
|
||||
RelationPattern contextRelationPattern;
|
||||
boolean useImports;
|
||||
Visibility inferDendencyVisibility;
|
||||
boolean inferDepInPackage;
|
||||
boolean verbose2;
|
||||
String inferRelationshipType;
|
||||
RelationType inferRelationshipType;
|
||||
private Vector<Pattern> collPackages;
|
||||
boolean compact;
|
||||
// internal option, used by UMLDoc to generate relative links between classes
|
||||
|
|
@ -161,12 +162,13 @@ public class Options implements Cloneable, OptionProvider {
|
|||
useGuillemot = true;
|
||||
findViews = false;
|
||||
viewName = null;
|
||||
contextRelationPattern = new RelationPattern(RelationDirection.BOTH);
|
||||
inferRelationships = false;
|
||||
inferDependencies = false;
|
||||
inferDendencyVisibility = Visibility.PRIVATE;
|
||||
inferDepInPackage = false;
|
||||
useImports = false;
|
||||
inferRelationshipType = "navassoc";
|
||||
inferRelationshipType = RelationType.NAVASSOC;
|
||||
collPackages = new Vector<Pattern>();
|
||||
compact = false;
|
||||
relativeLinksForSourcePackages = false;
|
||||
|
|
@ -220,6 +222,7 @@ public class Options implements Cloneable, OptionProvider {
|
|||
option.equals("-useimports") ||
|
||||
option.equals("-inferdep") ||
|
||||
option.equals("-inferdepinpackage") ||
|
||||
option.equals("-fullContext") ||
|
||||
option.equals("-verbose2") ||
|
||||
option.equals("-compact"))
|
||||
|
||||
|
|
@ -251,9 +254,10 @@ public class Options implements Cloneable, OptionProvider {
|
|||
option.equals("-inferreltype") ||
|
||||
option.equals("-inferdepvis") ||
|
||||
option.equals("-collpackages") ||
|
||||
option.equals("-link")
|
||||
)
|
||||
option.equals("-link"))
|
||||
return 2;
|
||||
else if(option.equals("-contextPattern"))
|
||||
return 3;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -423,22 +427,23 @@ public class Options implements Cloneable, OptionProvider {
|
|||
} else if(opt[0].equals("-!inferrel")) {
|
||||
inferRelationships = false;
|
||||
} else if(opt[0].equals("-inferreltype")) {
|
||||
if(ClassGraph.associationMap.containsKey(opt[1])) {
|
||||
inferRelationshipType = opt[1];
|
||||
} else {
|
||||
System.err.println("Unknown association type " + opt[1]);
|
||||
}
|
||||
try {
|
||||
inferRelationshipType = RelationType.valueOf(opt[1].toUpperCase());
|
||||
} catch(IllegalArgumentException e) {
|
||||
System.err.println("Unknown association type " + opt[1]);
|
||||
}
|
||||
} else if(opt[0].equals("-!inferreltype")) {
|
||||
inferRelationshipType = "navassoc";
|
||||
inferRelationshipType = RelationType.NAVASSOC;
|
||||
} else if(opt[0].equals("-inferdepvis")) {
|
||||
Visibility vis = Visibility.parseVisibility(opt[1]);
|
||||
if(vis == null)
|
||||
System.err.println("Ignoring invalid visibility specification for dependency inference" + vis);
|
||||
inferDendencyVisibility = Visibility.PRIVATE;
|
||||
try {
|
||||
Visibility vis = Visibility.valueOf(opt[1].toUpperCase());
|
||||
inferDendencyVisibility = vis;
|
||||
} catch(IllegalArgumentException e) {
|
||||
System.err.println("Ignoring invalid visibility specification for " +
|
||||
"dependency inference: " + opt[1]);
|
||||
}
|
||||
} else if(opt[0].equals("-!inferdepvis")) {
|
||||
inferDendencyVisibility = Visibility.PRIVATE;
|
||||
} else if(opt[0].equals("-!inferreltype")) {
|
||||
inferRelationshipType = "navassoc";
|
||||
} else if(opt[0].equals("-inferdep")) {
|
||||
inferDependencies = true;
|
||||
} else if(opt[0].equals("-!inferdep")) {
|
||||
|
|
@ -469,6 +474,20 @@ public class Options implements Cloneable, OptionProvider {
|
|||
postfixPackage = false;
|
||||
} else if (opt[0].equals("-link")) {
|
||||
addApiDocRoots(opt[1]);
|
||||
} else if(opt[0].equals("-contextPattern")) {
|
||||
RelationDirection d; RelationType rt;
|
||||
try {
|
||||
d = RelationDirection.valueOf(opt[2].toUpperCase());
|
||||
if(opt[1].equalsIgnoreCase("all")) {
|
||||
contextRelationPattern = new RelationPattern(d);
|
||||
} else {
|
||||
rt = RelationType.valueOf(opt[1].toUpperCase());
|
||||
contextRelationPattern.addRelation(rt, d);
|
||||
}
|
||||
} catch(IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
; // Do nothing, javadoc will handle the option or complain, if
|
||||
// needed.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* The possibile directions of a relation given a reference class (used in
|
||||
* context diagrams)
|
||||
*/
|
||||
public enum RelationDirection {
|
||||
NONE, IN, OUT, BOTH;
|
||||
|
||||
/**
|
||||
* Adds the current direction
|
||||
* @param d
|
||||
* @return
|
||||
*/
|
||||
public RelationDirection sum(RelationDirection d) {
|
||||
if (this == NONE)
|
||||
return d;
|
||||
|
||||
if ((this == IN && d == OUT) || (this == OUT && d == IN) || this == BOTH || d == BOTH)
|
||||
return BOTH;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this direction "contains" the specified one, that is,
|
||||
* either it's equal to it, or this direction is {@link #BOTH}
|
||||
* @param d
|
||||
* @return
|
||||
*/
|
||||
public boolean contains(RelationDirection d) {
|
||||
if (this == BOTH)
|
||||
return true;
|
||||
else
|
||||
return d == this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the direction of the relation. Turns IN into OUT and vice-versa, NONE and BOTH
|
||||
* are not changed
|
||||
* @return
|
||||
*/
|
||||
public RelationDirection inverse() {
|
||||
if (this == IN)
|
||||
return OUT;
|
||||
else if (this == OUT)
|
||||
return IN;
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* A map from relation types to directions
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public class RelationPattern {
|
||||
/**
|
||||
* A map from RelationType (indexes) to Direction objects
|
||||
*/
|
||||
RelationDirection[] directions;
|
||||
|
||||
/**
|
||||
* Creates a new pattern using the same direction for every relation kind
|
||||
* @param defaultDirection The direction used to initialize this pattern
|
||||
*/
|
||||
public RelationPattern(RelationDirection defaultDirection) {
|
||||
directions = new RelationDirection[RelationType.values().length];
|
||||
for (int i = 0; i < directions.length; i++) {
|
||||
directions[i] = defaultDirection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds, eventually merging, a direction for the specified relation type
|
||||
* @param relationType
|
||||
* @param direction
|
||||
*/
|
||||
public void addRelation(RelationType relationType, RelationDirection direction) {
|
||||
int idx = relationType.ordinal();
|
||||
directions[idx] = directions[idx].sum(direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this patterns matches at least the direction of one
|
||||
* of the relations in the other relation patterns. Matching is defined
|
||||
* by {@linkplain RelationDirection#contains(RelationDirection)}
|
||||
* @param relationPattern
|
||||
* @return
|
||||
*/
|
||||
public boolean matchesOne(RelationPattern relationPattern) {
|
||||
for (int i = 0; i < directions.length; i++) {
|
||||
if (directions[i].contains(relationPattern.directions[i]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package gr.spinellis.umlgraph.doclet;
|
||||
|
||||
/**
|
||||
* The type of relation that links two entities
|
||||
* @author wolf
|
||||
*
|
||||
*/
|
||||
public enum RelationType {
|
||||
ASSOC, NAVASSOC, HAS, COMPOSED, DEPEND, EXTENDS, IMPLEMENTS;
|
||||
}
|
||||
|
|
@ -97,6 +97,9 @@ public class View implements OptionProvider {
|
|||
} else if (strings[0].equals("context")) {
|
||||
return new ContextMatcher(root, Pattern.compile(strings[1]), getGlobalOptions(),
|
||||
false);
|
||||
} else if (strings[0].equals("outgoingContext")) {
|
||||
return new ContextMatcher(root, Pattern.compile(strings[1]), getGlobalOptions(),
|
||||
false);
|
||||
} else if (strings[0].equals("interface")) {
|
||||
return new InterfaceMatcher(root, Pattern.compile(strings[1]));
|
||||
} else if (strings[0].equals("subclass")) {
|
||||
|
|
|
|||
|
|
@ -28,13 +28,7 @@ import com.sun.javadoc.ProgramElementDoc;
|
|||
*
|
||||
*/
|
||||
public enum Visibility {
|
||||
PRIVATE("private"), PACKAGE("package"), PROTECTED("protected"), PUBLIC("public");
|
||||
|
||||
private String name;
|
||||
|
||||
private Visibility(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
PRIVATE, PACKAGE, PROTECTED, PUBLIC;
|
||||
|
||||
public static Visibility get(ProgramElementDoc doc) {
|
||||
if (doc.isPrivate())
|
||||
|
|
@ -47,12 +41,4 @@ public enum Visibility {
|
|||
return PUBLIC;
|
||||
|
||||
}
|
||||
|
||||
public static Visibility parseVisibility(String vis) {
|
||||
for (Visibility v : Visibility.values()) {
|
||||
if (v.name.equalsIgnoreCase(vis))
|
||||
return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/local/bin/dot
|
||||
#
|
||||
# Class diagram
|
||||
# Generated by UmlGraph version 4.1 (http://www.spinellis.gr/sw/umlgraph)
|
||||
# Generated by UmlGraph version 4.4 (http://www.spinellis.gr/sw/umlgraph)
|
||||
#
|
||||
|
||||
digraph G {
|
||||
|
|
@ -23,27 +23,29 @@ digraph G {
|
|||
c72:p -> c69:p [dir=back,arrowtail=empty];
|
||||
//MyList extends MyFunnyList<A, B>
|
||||
c69:p -> c70:p [dir=back,arrowtail=empty];
|
||||
// A depend C
|
||||
c66:p -> c68:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// A depend B
|
||||
c66:p -> c67:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// B depend C
|
||||
c67:p -> c68:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// B depend A
|
||||
// A HAS B
|
||||
c66:p -> c67:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond];
|
||||
// A HAS B
|
||||
c66:p -> c67:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond];
|
||||
// A HAS C
|
||||
c66:p -> c68:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond];
|
||||
// C NAVASSOC A
|
||||
c68:p -> c66:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open];
|
||||
// C NAVASSOC B
|
||||
c68:p -> c67:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open];
|
||||
// C NAVASSOC D
|
||||
c68:p -> c71:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open];
|
||||
// C NAVASSOC C
|
||||
c68:p -> c68:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open];
|
||||
// C NAVASSOC java.util.List<E>
|
||||
c68:p -> c73:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open];
|
||||
// D NAVASSOC MyList
|
||||
c71:p -> c70:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open];
|
||||
// B DEPEND A
|
||||
c67:p -> c66:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// C depend java.util.Map<K, V>
|
||||
c68:p -> c73:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// C depend java.util.List<E>
|
||||
c68:p -> c74:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// C depend java.util.ArrayList<E>
|
||||
c68:p -> c72:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// D depend MyList
|
||||
c71:p -> c70:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed];
|
||||
// java.util.Map<K, V>
|
||||
c73 [label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="2" port="p" href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Map.html"><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td> «interface» </td></tr><tr><td> Map<K, V> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> size() : int </td></tr><tr><td align="left"> isEmpty() : boolean </td></tr><tr><td align="left"> containsKey(arg0 : Object) : boolean </td></tr><tr><td align="left"> containsValue(arg0 : Object) : boolean </td></tr><tr><td align="left"> get(arg0 : Object) : V </td></tr><tr><td align="left"> put(arg0 : K, arg1 : V) : V </td></tr><tr><td align="left"> remove(arg0 : Object) : V </td></tr><tr><td align="left"> putAll(arg0 : Map<?, ?>) </td></tr><tr><td align="left"> clear() </td></tr><tr><td align="left"> keySet() : Set<K> </td></tr><tr><td align="left"> values() : Collection<V> </td></tr><tr><td align="left"> entrySet() : Set<Map.Entry<K, V>> </td></tr><tr><td align="left"> equals(arg0 : Object) : boolean </td></tr><tr><td align="left"> hashCode() : int </td></tr></table></td></tr></table>>, fontname="Helvetica", fontcolor="black", fontsize=10.0];
|
||||
// java.util.ArrayList<E>
|
||||
c72 [label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="2" port="p" href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ArrayList.html"><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td> ArrayList<E> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> serialVersionUID : long </td></tr><tr><td align="left"> elementData : E[] </td></tr><tr><td align="left"> size : int </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> trimToSize() </td></tr><tr><td align="left"> ensureCapacity(arg0 : int) </td></tr><tr><td align="left"> size() : int </td></tr><tr><td align="left"> isEmpty() : boolean </td></tr><tr><td align="left"> contains(arg0 : Object) : boolean </td></tr><tr><td align="left"> indexOf(arg0 : Object) : int </td></tr><tr><td align="left"> lastIndexOf(arg0 : Object) : int </td></tr><tr><td align="left"> clone() : Object </td></tr><tr><td align="left"> toArray() : Object[] </td></tr><tr><td align="left"> toArray(arg0 : T[]) : T[] </td></tr><tr><td align="left"> get(arg0 : int) : E </td></tr><tr><td align="left"> set(arg0 : int, arg1 : E) : E </td></tr><tr><td align="left"> add(arg0 : E) : boolean </td></tr><tr><td align="left"> add(arg0 : int, arg1 : E) </td></tr><tr><td align="left"> remove(arg0 : int) : E </td></tr><tr><td align="left"> remove(arg0 : Object) : boolean </td></tr><tr><td align="left"> fastRemove(arg0 : int) </td></tr><tr><td align="left"> clear() </td></tr><tr><td align="left"> addAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> addAll(arg0 : int, arg1 : Collection<?>) : boolean </td></tr><tr><td align="left"> removeRange(arg0 : int, arg1 : int) </td></tr><tr><td align="left"> RangeCheck(arg0 : int) </td></tr><tr><td align="left"> writeObject(arg0 : ObjectOutputStream) </td></tr><tr><td align="left"> readObject(arg0 : ObjectInputStream) </td></tr></table></td></tr></table>>, fontname="Helvetica", fontcolor="black", fontsize=10.0];
|
||||
// java.util.List<E>
|
||||
c74 [label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="2" port="p" href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html"><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td> «interface» </td></tr><tr><td> List<E> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> size() : int </td></tr><tr><td align="left"> isEmpty() : boolean </td></tr><tr><td align="left"> contains(arg0 : Object) : boolean </td></tr><tr><td align="left"> iterator() : Iterator<E> </td></tr><tr><td align="left"> toArray() : Object[] </td></tr><tr><td align="left"> toArray(arg0 : T[]) : T[] </td></tr><tr><td align="left"> add(arg0 : E) : boolean </td></tr><tr><td align="left"> remove(arg0 : Object) : boolean </td></tr><tr><td align="left"> containsAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> addAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> addAll(arg0 : int, arg1 : Collection<?>) : boolean </td></tr><tr><td align="left"> removeAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> retainAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> clear() </td></tr><tr><td align="left"> equals(arg0 : Object) : boolean </td></tr><tr><td align="left"> hashCode() : int </td></tr><tr><td align="left"> get(arg0 : int) : E </td></tr><tr><td align="left"> set(arg0 : int, arg1 : E) : E </td></tr><tr><td align="left"> add(arg0 : int, arg1 : E) </td></tr><tr><td align="left"> remove(arg0 : int) : E </td></tr><tr><td align="left"> indexOf(arg0 : Object) : int </td></tr><tr><td align="left"> lastIndexOf(arg0 : Object) : int </td></tr><tr><td align="left"> listIterator() : ListIterator<E> </td></tr><tr><td align="left"> listIterator(arg0 : int) : ListIterator<E> </td></tr><tr><td align="left"> subList(arg0 : int, arg1 : int) : List<E> </td></tr></table></td></tr></table>>, fontname="Helvetica", fontcolor="black", fontsize=10.0];
|
||||
c73 [label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="2" port="p" href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html"><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td> «interface» </td></tr><tr><td> List<E> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> </td></tr></table></td></tr><tr><td><table border="0" cellspacing="0" cellpadding="1"><tr><td align="left"> size() : int </td></tr><tr><td align="left"> isEmpty() : boolean </td></tr><tr><td align="left"> contains(arg0 : Object) : boolean </td></tr><tr><td align="left"> iterator() : Iterator<E> </td></tr><tr><td align="left"> toArray() : Object[] </td></tr><tr><td align="left"> toArray(arg0 : T[]) : T[] </td></tr><tr><td align="left"> add(arg0 : E) : boolean </td></tr><tr><td align="left"> remove(arg0 : Object) : boolean </td></tr><tr><td align="left"> containsAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> addAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> addAll(arg0 : int, arg1 : Collection<?>) : boolean </td></tr><tr><td align="left"> removeAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> retainAll(arg0 : Collection<?>) : boolean </td></tr><tr><td align="left"> clear() </td></tr><tr><td align="left"> equals(arg0 : Object) : boolean </td></tr><tr><td align="left"> hashCode() : int </td></tr><tr><td align="left"> get(arg0 : int) : E </td></tr><tr><td align="left"> set(arg0 : int, arg1 : E) : E </td></tr><tr><td align="left"> add(arg0 : int, arg1 : E) </td></tr><tr><td align="left"> remove(arg0 : int) : E </td></tr><tr><td align="left"> indexOf(arg0 : Object) : int </td></tr><tr><td align="left"> lastIndexOf(arg0 : Object) : int </td></tr><tr><td align="left"> listIterator() : ListIterator<E> </td></tr><tr><td align="left"> listIterator(arg0 : int) : ListIterator<E> </td></tr><tr><td align="left"> subList(arg0 : int, arg1 : int) : List<E> </td></tr></table></td></tr></table>>, fontname="Helvetica", fontcolor="black", fontsize=10.0];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import java.util.ArrayList;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @opt inferassoc
|
||||
* @opt inferrel
|
||||
* @opt inferdep
|
||||
* @opt inferdepinpackage
|
||||
* @opt attributes
|
||||
|
|
@ -17,7 +17,7 @@ import java.util.Map;
|
|||
class UMLOptions {}
|
||||
|
||||
/**
|
||||
* @opt inferassoctype has
|
||||
* @opt inferreltype has
|
||||
*/
|
||||
class A {
|
||||
B first;
|
||||
|
|
|
|||
Loading…
Reference in New Issue