From c680c10ad9057106e23b149246abdd84b41775ee Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Sat, 25 Jun 2016 23:08:49 +0200 Subject: [PATCH] Code formatting and cleanup. --- .gitignore | 3 +- javainspect.iml | 15 + pom.xml | 199 +++-- .../inspector/java/methods/Annotation.java | 36 +- .../java/methods/ClassReference.java | 60 +- .../inspector/java/methods/Clazz.java | 120 +-- .../java/methods/EnumerationBuffer.java | 50 +- .../inspector/java/methods/Import.java | 4 +- .../inspector/java/methods/JavaFile.java | 267 +++--- .../inspector/java/methods/Modifiers.java | 137 ++- .../inspector/java/methods/Package.java | 2 +- .../inspector/java/methods/Project.java | 2 +- .../java/methods/ProjectScanner.java | 100 +-- .../inspector/java/methods/package-info.java | 5 +- .../java/structure/ClassDescriptor.java | 800 +++++++++--------- .../inspector/java/structure/ClassGraph.java | 364 ++++---- .../java/structure/FieldDescriptor.java | 258 +++--- .../java/structure/GraphElement.java | 8 +- .../java/structure/MethodDescriptor.java | 305 +++---- .../inspector/java/structure/Utils.java | 255 +++--- .../structure/example/RenderDemoClasses.java | 8 +- .../structure/example/RenderJavaInspect.java | 72 +- .../example/structure/SampleClass.java | 8 +- .../example/structure/SampleEnum.java | 2 +- .../example/structure/SampleInterface.java | 2 +- .../example/structure/SampleSuperClass.java | 8 +- 26 files changed, 1546 insertions(+), 1544 deletions(-) create mode 100644 javainspect.iml diff --git a/.gitignore b/.gitignore index fa26886..d8ed27d 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.settings/ /.project /.classpath -target/ +/target/ +/.idea/ diff --git a/javainspect.iml b/javainspect.iml new file mode 100644 index 0000000..2f97aee --- /dev/null +++ b/javainspect.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index d5bcd99..68beb58 100644 --- a/pom.xml +++ b/pom.xml @@ -1,118 +1,109 @@ - - 4.0.0 - eu.svjatoslav - javainspect - 1.5-SNAPSHOT - jar - Java inspect - Utility to visualize Java code + + 4.0.0 + eu.svjatoslav + javainspect + 1.5-SNAPSHOT + jar + Java inspect + Utility to visualize Java code - - svjatoslav.eu - http://svjatoslav.eu - + + svjatoslav.eu + http://svjatoslav.eu + - - UTF-8 - UTF-8 - + + UTF-8 + UTF-8 + - - - - - org.codehaus.mojo - findbugs-maven-plugin - 2.5.3 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - UTF-8 - - + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + UTF-8 + + - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar - - - - + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9 - - - attach-javadocs - - jar - - - - - - + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + + attach-javadocs + + jar + + + + - - - org.apache.maven.wagon - wagon-ssh-external - 2.6 - - - + - - - eu.svjatoslav - svjatoslavcommons - 1.5-SNAPSHOT - - + + + org.apache.maven.wagon + wagon-ssh-external + 2.6 + + + - - - svjatoslav.eu - svjatoslav.eu - scpexe://svjatoslav.eu/var/www/svjatoslav.eu/maven - - - svjatoslav.eu - svjatoslav.eu - scpexe://svjatoslav.eu/var/www/svjatoslav.eu/maven - - + + + eu.svjatoslav + svjatoslavcommons + 1.5-SNAPSHOT + + - - - svjatoslav.eu - Svjatoslav repository - http://www2.svjatoslav.eu/maven/ - - + + + svjatoslav.eu + svjatoslav.eu + scpexe://svjatoslav.eu/var/www/svjatoslav.eu/maven + + + svjatoslav.eu + svjatoslav.eu + scpexe://svjatoslav.eu/var/www/svjatoslav.eu/maven + + + + + svjatoslav.eu + Svjatoslav repository + http://www2.svjatoslav.eu/maven/ + + - - scm:git:ssh://git@svjatoslav.eu/home/git/repositories/javainspect.git - scm:git:ssh://git@svjatoslav.eu/home/git/repositories/javainspect.git - + + + scm:git:ssh://git@svjatoslav.eu/home/git/repositories/javainspect.git + scm:git:ssh://git@svjatoslav.eu/home/git/repositories/javainspect.git + \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/Annotation.java b/src/main/java/eu/svjatoslav/inspector/java/methods/Annotation.java index da60061..d4581b0 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/Annotation.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/Annotation.java @@ -15,32 +15,32 @@ import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch; public class Annotation { - private String name; + private String name; - public Annotation(final Tokenizer tokenizer) throws InvalidSyntaxException { + public Annotation(final Tokenizer tokenizer) throws InvalidSyntaxException { - name = tokenizer.getNextToken().token; + name = tokenizer.getNextToken().token; - if (!tokenizer.probeNextToken("(")) - return; + if (!tokenizer.probeNextToken("(")) + return; - int depth = 1; + int depth = 1; - while (true) { - final TokenizerMatch token = tokenizer.getNextToken(); + while (true) { + final TokenizerMatch token = tokenizer.getNextToken(); - if (token == null) - return; + if (token == null) + return; - if ("(".equals(token.token)) - depth++; - if (")".equals(token.token)) - depth--; + if ("(".equals(token.token)) + depth++; + if (")".equals(token.token)) + depth--; - if (depth == 0) - return; - } + if (depth == 0) + return; + } - } + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/ClassReference.java b/src/main/java/eu/svjatoslav/inspector/java/methods/ClassReference.java index 4643d86..12216ab 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/ClassReference.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/ClassReference.java @@ -9,49 +9,49 @@ package eu.svjatoslav.inspector.java.methods; -import java.util.ArrayList; -import java.util.List; - import eu.svjatoslav.commons.string.tokenizer.InvalidSyntaxException; import eu.svjatoslav.commons.string.tokenizer.Tokenizer; +import java.util.ArrayList; +import java.util.List; + public class ClassReference { - public String name; + public String name; - List typeParameters = new ArrayList(); + List typeParameters = new ArrayList(); - public ClassReference(final Tokenizer tokenizer) - throws InvalidSyntaxException { - name = tokenizer.getNextToken().token; + public ClassReference(final Tokenizer tokenizer) + throws InvalidSyntaxException { + name = tokenizer.getNextToken().token; - if (!tokenizer.probeNextToken("<")) - return; + if (!tokenizer.probeNextToken("<")) + return; - while (true) { - final ClassReference parameterType = new ClassReference(tokenizer); - typeParameters.add(parameterType); + while (true) { + final ClassReference parameterType = new ClassReference(tokenizer); + typeParameters.add(parameterType); - if (!tokenizer.probeNextToken(",")) - break; - } + if (!tokenizer.probeNextToken(",")) + break; + } - tokenizer.expectNextToken(">"); - } + tokenizer.expectNextToken(">"); + } - @Override - public String toString() { - final EnumerationBuffer result = new EnumerationBuffer(); + @Override + public String toString() { + final EnumerationBuffer result = new EnumerationBuffer(); - result.append(name); + result.append(name); - if (typeParameters.size() > 0) { - result.append("<"); - for (final ClassReference classReference : typeParameters) - result.appendEnumeration(classReference.toString()); - result.append(">"); - } + if (typeParameters.size() > 0) { + result.append("<"); + for (final ClassReference classReference : typeParameters) + result.appendEnumeration(classReference.toString()); + result.append(">"); + } - return result.toString(); - } + return result.toString(); + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/Clazz.java b/src/main/java/eu/svjatoslav/inspector/java/methods/Clazz.java index 2825e3f..425098f 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/Clazz.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/Clazz.java @@ -9,89 +9,89 @@ package eu.svjatoslav.inspector.java.methods; -import java.util.ArrayList; -import java.util.List; - import eu.svjatoslav.commons.string.tokenizer.InvalidSyntaxException; import eu.svjatoslav.commons.string.tokenizer.Tokenizer; import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch; +import java.util.ArrayList; +import java.util.List; + public class Clazz { - private final String packageName; - private final String className; - private final boolean isInterface; + private final String packageName; + private final String className; + private final boolean isInterface; - public ClassReference superClass; - public List implementedInterfaces = new ArrayList(); + public ClassReference superClass; + public List implementedInterfaces = new ArrayList(); - public Clazz(final String packageName, final String className, - final Tokenizer tokenizer, final boolean isInterface) - throws InvalidSyntaxException { + public Clazz(final String packageName, final String className, + final Tokenizer tokenizer, final boolean isInterface) + throws InvalidSyntaxException { - this.packageName = packageName; - this.className = className; - this.isInterface = isInterface; + this.packageName = packageName; + this.className = className; + this.isInterface = isInterface; - while (true) { - final TokenizerMatch match = tokenizer.getNextToken(); + while (true) { + final TokenizerMatch match = tokenizer.getNextToken(); - if ("extends".equals(match.token)) { - superClass = new ClassReference(tokenizer); - continue; - } + if ("extends".equals(match.token)) { + superClass = new ClassReference(tokenizer); + continue; + } - if ("implements".equals(match.token)) { - while (true) { - implementedInterfaces.add(new ClassReference(tokenizer)); + if ("implements".equals(match.token)) { + while (true) { + implementedInterfaces.add(new ClassReference(tokenizer)); - if (tokenizer.probeNextToken(",")) - continue; + if (tokenizer.probeNextToken(",")) + continue; - break; - } - continue; - } + break; + } + continue; + } - if ("{".equals(match.token)) { - parseClassBody(tokenizer); - break; - } + if ("{".equals(match.token)) { + parseClassBody(tokenizer); + break; + } - } - } + } + } - public String getFullName() { - return packageName + "." + className; - } + public String getFullName() { + return packageName + "." + className; + } - public void parseClassBody(final Tokenizer tokenizer) { - tokenizer.skipUntilDataEnd(); - } + public void parseClassBody(final Tokenizer tokenizer) { + tokenizer.skipUntilDataEnd(); + } - @Override - public String toString() { - final EnumerationBuffer result = new EnumerationBuffer(); + @Override + public String toString() { + final EnumerationBuffer result = new EnumerationBuffer(); - result.append(packageName + " -> " + className + " "); + result.append(packageName + " -> " + className + " "); - if (isInterface) - result.append("(interface)"); - else - result.append("(class)"); - result.append("\n"); + if (isInterface) + result.append("(interface)"); + else + result.append("(class)"); + result.append("\n"); - if (superClass != null) - result.append(" super: " + superClass.toString() + "\n"); + if (superClass != null) + result.append(" super: " + superClass.toString() + "\n"); - if (implementedInterfaces.size() > 0) { - result.append(" implements: "); - for (final ClassReference classReference : implementedInterfaces) - result.appendEnumeration(classReference.toString()); - result.append("\n"); - } + if (implementedInterfaces.size() > 0) { + result.append(" implements: "); + for (final ClassReference classReference : implementedInterfaces) + result.appendEnumeration(classReference.toString()); + result.append("\n"); + } - return result.toString(); - } + return result.toString(); + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/EnumerationBuffer.java b/src/main/java/eu/svjatoslav/inspector/java/methods/EnumerationBuffer.java index ec7bfcc..15d2266 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/EnumerationBuffer.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/EnumerationBuffer.java @@ -11,39 +11,39 @@ package eu.svjatoslav.inspector.java.methods; public class EnumerationBuffer { - private final String enumerationDelimiter; + private final String enumerationDelimiter; - private final StringBuffer buffer = new StringBuffer(); + private final StringBuffer buffer = new StringBuffer(); - public int enumeratedEntitiesCount = 0; + public int enumeratedEntitiesCount = 0; - public EnumerationBuffer() { - this(", "); - } + public EnumerationBuffer() { + this(", "); + } - public EnumerationBuffer(final String enumerationDelimiter) { - this.enumerationDelimiter = enumerationDelimiter; - } + public EnumerationBuffer(final String enumerationDelimiter) { + this.enumerationDelimiter = enumerationDelimiter; + } - public void append(final String value) { - buffer.append(value); - } + public void append(final String value) { + buffer.append(value); + } - public void appendEnumeration(final String value) { - if (enumeratedEntitiesCount > 0) - buffer.append(enumerationDelimiter); + public void appendEnumeration(final String value) { + if (enumeratedEntitiesCount > 0) + buffer.append(enumerationDelimiter); - buffer.append(value); - enumeratedEntitiesCount++; - } + buffer.append(value); + enumeratedEntitiesCount++; + } - public void resetEnumeration() { - enumeratedEntitiesCount = 0; - } + public void resetEnumeration() { + enumeratedEntitiesCount = 0; + } - @Override - public String toString() { - return buffer.toString(); - } + @Override + public String toString() { + return buffer.toString(); + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/Import.java b/src/main/java/eu/svjatoslav/inspector/java/methods/Import.java index dc2443b..33ac196 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/Import.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/Import.java @@ -11,7 +11,7 @@ package eu.svjatoslav.inspector.java.methods; public class Import { - String path; - boolean isStatic = false; + String path; + boolean isStatic = false; } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/JavaFile.java b/src/main/java/eu/svjatoslav/inspector/java/methods/JavaFile.java index e8cbe6b..29f1a1c 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/JavaFile.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/JavaFile.java @@ -9,184 +9,177 @@ package eu.svjatoslav.inspector.java.methods; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - import eu.svjatoslav.commons.string.tokenizer.InvalidSyntaxException; import eu.svjatoslav.commons.string.tokenizer.Tokenizer; import eu.svjatoslav.commons.string.tokenizer.TokenizerMatch; -public class JavaFile { - - private final List imports = new ArrayList(); - - private String packageName; - - private final File file; - - StringBuffer contents = new StringBuffer(); - - public List classes = new ArrayList(); - - public JavaFile(final File file) throws IOException, InvalidSyntaxException { - this.file = file; - parse(); - } - - public void parse() throws IOException, InvalidSyntaxException { - System.out.println("java file: " + file); - - readFile(); +import java.io.*; +import java.util.ArrayList; +import java.util.List; - final Tokenizer tokenizer = new Tokenizer(contents.toString()); +public class JavaFile { - // empty space - tokenizer.addTerminator(" ", true); - tokenizer.addTerminator("\t", true); - tokenizer.addTerminator("\n", true); + public static final String UTF_8 = "UTF-8"; + private final List imports = new ArrayList(); + private final File file; + public List classes = new ArrayList(); + StringBuffer contents = new StringBuffer(); + private String packageName; + + public JavaFile(final File file) throws IOException, InvalidSyntaxException { + this.file = file; + parse(); + } + + public void parse() throws IOException, InvalidSyntaxException { + System.out.println("java file: " + file); + + readFile(); - tokenizer.addTerminator(";", false); - tokenizer.addTerminator("{", false); - tokenizer.addTerminator("}", false); - tokenizer.addTerminator("(", false); - tokenizer.addTerminator(")", false); - tokenizer.addTerminator("[", false); - tokenizer.addTerminator("]", false); - tokenizer.addTerminator("<", false); - tokenizer.addTerminator(">", false); - tokenizer.addTerminator(",", false); - tokenizer.addTerminator("@", false); + final Tokenizer tokenizer = new Tokenizer(contents.toString()); + + // empty space + tokenizer.addTerminator(" ", true); + tokenizer.addTerminator("\t", true); + tokenizer.addTerminator("\n", true); + + tokenizer.addTerminator(";", false); + tokenizer.addTerminator("{", false); + tokenizer.addTerminator("}", false); + tokenizer.addTerminator("(", false); + tokenizer.addTerminator(")", false); + tokenizer.addTerminator("[", false); + tokenizer.addTerminator("]", false); + tokenizer.addTerminator("<", false); + tokenizer.addTerminator(">", false); + tokenizer.addTerminator(",", false); + tokenizer.addTerminator("@", false); - // comments - tokenizer.addTerminator("//", "\n", true); - tokenizer.addTerminator("/*", "*/", true); + // comments + tokenizer.addTerminator("//", "\n", true); + tokenizer.addTerminator("/*", "*/", true); - final Modifiers modifiers = new Modifiers(); + final Modifiers modifiers = new Modifiers(); - while (true) { - final TokenizerMatch match = tokenizer.getNextToken(); - if (match == null) - break; + while (true) { + final TokenizerMatch match = tokenizer.getNextToken(); + if (match == null) + break; - if (match.token.equals("package")) { - parsePackage(tokenizer); - continue; - } + if (match.token.equals("package")) { + parsePackage(tokenizer); + continue; + } - if (match.token.equals("import")) { - parseImport(tokenizer); - continue; - } + if (match.token.equals("import")) { + parseImport(tokenizer); + continue; + } - final boolean wasModifier = modifiers.parseModifier(match.token); - if (wasModifier) - continue; + final boolean wasModifier = modifiers.parseModifier(match.token); + if (wasModifier) + continue; - if ("class".equals(match.token)) { - parseClass(tokenizer); - continue; - } + if ("class".equals(match.token)) { + parseClass(tokenizer); + continue; + } - if ("interface".equals(match.token)) { - parseInterface(tokenizer); - continue; - } + if ("interface".equals(match.token)) { + parseInterface(tokenizer); + continue; + } - if ("@".equals(match.token)) { - final Annotation annotation = new Annotation(tokenizer); - continue; - } + if ("@".equals(match.token)) { + new Annotation(tokenizer); + continue; + } - System.out.println(" " + modifiers.toString() + " " - + match.token); - modifiers.reset(); - skipUntilSemicolon(tokenizer); - } + System.out.println(" " + modifiers.toString() + " " + + match.token); + modifiers.reset(); + skipUntilSemicolon(tokenizer); + } - } + } - private void parseClass(final Tokenizer tokenizer) - throws InvalidSyntaxException { + private void parseClass(final Tokenizer tokenizer) + throws InvalidSyntaxException { - final TokenizerMatch match = tokenizer.getNextToken(); - final Clazz clazz = new Clazz(packageName, match.token, tokenizer, - false); - // System.out.println(clazz.toString()); - classes.add(clazz); + final TokenizerMatch match = tokenizer.getNextToken(); + final Clazz clazz = new Clazz(packageName, match.token, tokenizer, + false); + // System.out.println(clazz.toString()); + classes.add(clazz); - } + } - private void parseImport(final Tokenizer tokenizer) - throws InvalidSyntaxException { + private void parseImport(final Tokenizer tokenizer) + throws InvalidSyntaxException { - final Import imp = new Import(); + final Import imp = new Import(); - final TokenizerMatch match = tokenizer.getNextToken(); + final TokenizerMatch match = tokenizer.getNextToken(); - if (match.token.equals("static")) { - imp.isStatic = true; - imp.path = tokenizer.getNextToken().token; - } else - imp.path = match.token; + if (match.token.equals("static")) { + imp.isStatic = true; + imp.path = tokenizer.getNextToken().token; + } else + imp.path = match.token; - imports.add(imp); + imports.add(imp); - tokenizer.expectNextToken(";"); - } + tokenizer.expectNextToken(";"); + } - private void parseInterface(final Tokenizer tokenizer) - throws InvalidSyntaxException { + private void parseInterface(final Tokenizer tokenizer) + throws InvalidSyntaxException { - final TokenizerMatch match = tokenizer.getNextToken(); - final Clazz clazz = new Clazz(packageName, match.token, tokenizer, true); - // System.out.println(clazz.toString()); - classes.add(clazz); - } + final TokenizerMatch match = tokenizer.getNextToken(); + final Clazz clazz = new Clazz(packageName, match.token, tokenizer, true); + // System.out.println(clazz.toString()); + classes.add(clazz); + } - private void parsePackage(final Tokenizer tokenizer) - throws InvalidSyntaxException { + private void parsePackage(final Tokenizer tokenizer) + throws InvalidSyntaxException { - final TokenizerMatch match = tokenizer.getNextToken(); + final TokenizerMatch match = tokenizer.getNextToken(); - packageName = match.token; + packageName = match.token; - tokenizer.expectNextToken(";"); - } + tokenizer.expectNextToken(";"); + } - private void readFile() throws FileNotFoundException, IOException { - final FileReader fileReader = new FileReader(file); + private void readFile() throws IOException { + InputStreamReader inputStream = new InputStreamReader(new FileInputStream(file), UTF_8); - final BufferedReader bufferedReader = new BufferedReader(fileReader); + final BufferedReader bufferedReader = new BufferedReader(inputStream); - while (true) { - final String line = bufferedReader.readLine(); + while (true) { + final String line = bufferedReader.readLine(); - if (line == null) - break; + if (line == null) + break; - contents.append(line); - contents.append("\n"); - } + contents.append(line); + contents.append("\n"); + } - bufferedReader.close(); - fileReader.close(); - } + bufferedReader.close(); + inputStream.close(); + } - public void skipUntilSemicolon(final Tokenizer tokenizer) { - while (true) { - final TokenizerMatch token = tokenizer.getNextToken(); + public void skipUntilSemicolon(final Tokenizer tokenizer) { + while (true) { + final TokenizerMatch token = tokenizer.getNextToken(); - if (token == null) - return; + if (token == null) + return; - if (token.token.equals(";")) - return; - } - } + if (token.token.equals(";")) + return; + } + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/Modifiers.java b/src/main/java/eu/svjatoslav/inspector/java/methods/Modifiers.java index 1417d90..a062383 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/Modifiers.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/Modifiers.java @@ -11,74 +11,71 @@ package eu.svjatoslav.inspector.java.methods; public class Modifiers { - public enum Access { - PUBLIC("public"), PROTECTED("protected"), DEFAULT(""), PRIVATE( - "private"); - - public final String name; - - Access(final String name) { - this.name = name; - }; - } - - Access access = Access.DEFAULT; - - boolean isStatic = false;; - - boolean isFinal = false; - - boolean isAbstract = false; - - public boolean parseModifier(final String string) { - for (final Access access : Access.values()) - if (access.name.equals(string)) { - this.access = access; - return true; - } - - if ("static".equals(string)) { - isStatic = true; - return true; - } - - if ("final".equals(string)) { - isFinal = true; - return true; - } - - if ("abstract".equals(string)) { - isAbstract = true; - return true; - } - - return false; - } - - public void reset() { - isStatic = false; - isFinal = false; - access = Access.DEFAULT; - } - - @Override - public String toString() { - final StringBuffer result = new StringBuffer(); - - result.append(access.name); - - if (isStatic) { - if (result.length() > 0) - result.append(" "); - result.append("static"); - } - - if (isFinal) { - if (result.length() > 0) - result.append(" "); - result.append("final"); - } - - return result.toString(); - } + Access access = Access.DEFAULT; + boolean isStatic = false; + boolean isFinal = false; + boolean isAbstract = false; + + public boolean parseModifier(final String string) { + for (final Access access : Access.values()) + if (access.name.equals(string)) { + this.access = access; + return true; + } + + if ("static".equals(string)) { + isStatic = true; + return true; + } + + if ("final".equals(string)) { + isFinal = true; + return true; + } + + if ("abstract".equals(string)) { + isAbstract = true; + return true; + } + + return false; + } + + public void reset() { + isStatic = false; + isFinal = false; + access = Access.DEFAULT; + } + + @Override + public String toString() { + final StringBuffer result = new StringBuffer(); + + result.append(access.name); + + if (isStatic) { + if (result.length() > 0) + result.append(" "); + result.append("static"); + } + + if (isFinal) { + if (result.length() > 0) + result.append(" "); + result.append("final"); + } + + return result.toString(); + } + + public enum Access { + PUBLIC("public"), PROTECTED("protected"), DEFAULT(""), PRIVATE( + "private"); + + public final String name; + + Access(final String name) { + this.name = name; + } + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/Package.java b/src/main/java/eu/svjatoslav/inspector/java/methods/Package.java index ecb9884..98e7cec 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/Package.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/Package.java @@ -14,6 +14,6 @@ import java.util.Map; public class Package { - Map classes = new HashMap(); + Map classes = new HashMap(); } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/Project.java b/src/main/java/eu/svjatoslav/inspector/java/methods/Project.java index 76270bc..ba6c0ee 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/Project.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/Project.java @@ -14,6 +14,6 @@ import java.util.Map; public class Project { - Map packages = new HashMap(); + Map packages = new HashMap(); } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/ProjectScanner.java b/src/main/java/eu/svjatoslav/inspector/java/methods/ProjectScanner.java index 2674d86..78a5e9c 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/ProjectScanner.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/ProjectScanner.java @@ -9,6 +9,9 @@ package eu.svjatoslav.inspector.java.methods; +import eu.svjatoslav.commons.file.FilePathParser; +import eu.svjatoslav.commons.string.tokenizer.InvalidSyntaxException; + import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -16,71 +19,70 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import eu.svjatoslav.commons.file.FilePathParser; -import eu.svjatoslav.commons.string.tokenizer.InvalidSyntaxException; - public class ProjectScanner { - private final File scanPath; + private final File scanPath; + public List javaFiles = new ArrayList(); + Map projects = new HashMap(); - Map projects = new HashMap(); - public List javaFiles = new ArrayList(); + public ProjectScanner(final File projectPath) { + scanPath = projectPath; + parse(); + } - public ProjectScanner(final File projectPath) { - scanPath = projectPath; - parse(); - } + public List getAllClasses() { + final List result = new ArrayList(); - public List getAllClasses() { - final List result = new ArrayList(); + for (final JavaFile file : javaFiles) + for (final Clazz clazz : file.classes) + result.add(clazz); - for (final JavaFile file : javaFiles) - for (final Clazz clazz : file.classes) - result.add(clazz); + return result; + } - return result; - } + public void parse() { - public void parse() { + if (!scanPath.exists()) + System.out.println("Path not found: " + scanPath); - if (!scanPath.exists()) - System.out.println("Path not found: " + scanPath); + if (!scanPath.canRead()) + System.out.println("Cannot read path: " + scanPath); - if (!scanPath.canRead()) - System.out.println("Cannot read path: " + scanPath); + if (scanPath.isDirectory()) + parseDirectory(scanPath); - if (scanPath.isDirectory()) - parseDirectory(scanPath); + if (scanPath.isFile()) + parseFile(scanPath); + } - if (scanPath.isFile()) - parseFile(scanPath); - } + public void parseDirectory(final File file) { - public void parseDirectory(final File file) { + File[] filesList = file.listFiles(); + if (filesList == null) throw new RuntimeException("Cannot scan directory: " + file); - for (final File subFile : file.listFiles()) { + for (final File subFile : filesList) { - if (subFile.isFile()) - parseFile(subFile); + if (subFile.isFile()) + parseFile(subFile); - if (subFile.isDirectory()) - parseDirectory(subFile); - } - } + if (subFile.isDirectory()) + parseDirectory(subFile); + } + } - public void parseFile(final File file) { - final String fileExtension = FilePathParser.getFileExtension(file); - if ("java".equalsIgnoreCase(fileExtension)) - try { - final JavaFile javaFile = new JavaFile(file); - javaFiles.add(javaFile); - } catch (final IOException e) { - System.out.println("Error parsing file: " + file.toString() - + ": " + e.toString()); - } catch (final InvalidSyntaxException e) { - System.out.println("Syntax error occured while parsing file: " - + file.toString() + ": " + e.toString()); - } - } + public void parseFile(final File file) { + final String fileExtension = FilePathParser.getFileExtension(file); + if ("java".equalsIgnoreCase(fileExtension)) + try { + final JavaFile javaFile = new JavaFile(file); + javaFiles.add(javaFile); + } catch (final IOException e) { + System.out.println("Error parsing file: " + file.toString() + + ": " + e.toString()); + } catch (final InvalidSyntaxException e) { + System.out.println("Syntax error occured while parsing file: " + + file.toString() + ": " + e.toString()); + } + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/methods/package-info.java b/src/main/java/eu/svjatoslav/inspector/java/methods/package-info.java index 2bc2e95..3897205 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/methods/package-info.java +++ b/src/main/java/eu/svjatoslav/inspector/java/methods/package-info.java @@ -13,10 +13,9 @@ package eu.svjatoslav.inspector.java.methods; * This package contains quickly hacked together Java language parser. * Goal is to start visualizing method call references and other things * which are not easily readable at runtime via reflection. - * + *

* Work in progress... - * + *

* Currently in is useful just for detecting class names and packages. - * */ diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java index 2494966..c21761c 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassDescriptor.java @@ -11,502 +11,500 @@ package eu.svjatoslav.inspector.java.structure; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeMap; -import java.util.TreeSet; +import java.util.*; /** * Describes single class instance */ -public class ClassDescriptor implements GraphElement { +public class ClassDescriptor implements GraphElement, Comparable { + + private static final int MAX_REFERECNES_COUNT = 10; + private final Map nameToFieldMap = new TreeMap(); + private final SortedSet methods = new TreeSet(); + private final ClassGraph classGraph; + boolean isEnum; + boolean isInterface; + boolean isArray; + List interfaces = new ArrayList(); + ClassDescriptor superClass; + private String fullyQualifiedName; + /** + * Incoming arrows will have this color. + */ + private String distinctiveReferenceColor; + private String interfaceColor; + private String superClassColor; + private boolean isShown = true; + /** + * Amount of field and method references pointing to this class. + */ + private int referencesCount = 0; + + // for interface, counts amount of found implementations + private int implementationsCount = 0; + + // counts amount of times this class is extended + private int extensionsCount = 0; + + private ClassDescriptor arrayComponent; + + public ClassDescriptor(final ClassGraph classGraph) { + this.classGraph = classGraph; + } + + protected void analyzeClass(final Class clazz) { + + fullyQualifiedName = clazz.getName(); + + isArray = clazz.isArray(); + + if (isArray) { + final Class componentType = clazz.getComponentType(); + arrayComponent = getClassGraph().getOrCreateClassDescriptor( + componentType); + } + + // System.out.println("class: " + fullyQualifiedName); + + isEnum = clazz.isEnum(); + + isInterface = clazz.isInterface(); + + if (!isVisible()) + return; + + indexFields(clazz.getDeclaredFields()); + indexFields(clazz.getFields()); + + indexMethods(clazz); + + for (final Class interfaceClass : clazz.getInterfaces()) { + final ClassDescriptor interfaceClassDescriptor = getClassGraph() + .getOrCreateClassDescriptor(interfaceClass); + interfaceClassDescriptor.registerImplementation(); + interfaces.add(interfaceClassDescriptor); + } + + superClass = getClassGraph().getOrCreateClassDescriptor( + clazz.getSuperclass()); + if (superClass != null) + superClass.registerExtension(); + + } + + protected boolean areReferencesShown() { + return referencesCount <= MAX_REFERECNES_COUNT; + } + + private void enlistFieldReferences(final StringBuffer result) { + if (nameToFieldMap.isEmpty()) + return; + + result.append("\n"); + result.append(" // field references to other classes\n"); + for (final Map.Entry entry : nameToFieldMap + .entrySet()) + result.append(entry.getValue().getDot()); + } + + private void enlistFields(final StringBuffer result) { + if (nameToFieldMap.isEmpty()) + return; + + result.append("\n"); + result.append(" // fields:\n"); + + // enlist fields + for (final Map.Entry entry : nameToFieldMap + .entrySet()) + result.append(entry.getValue().getEmbeddedDot()); + } + + private void enlistImplementedInterfaces(final StringBuffer result) { + if (interfaces.isEmpty()) + return; - private static final int MAX_REFERECNES_COUNT = 10; + result.append("\n"); + result.append(" // interfaces implemented by class: " + + fullyQualifiedName + "\n"); - private String fullyQualifiedName; + for (final ClassDescriptor interfaceDescriptor : interfaces) { + if (!interfaceDescriptor.isVisible()) + continue; - private final Map nameToFieldMap = new TreeMap(); + if (!interfaceDescriptor.areReferencesShown()) + continue; - private final SortedSet methods = new TreeSet(); + result.append(" " + interfaceDescriptor.getGraphId() + " -> " + + getGraphId() + "[style=\"dotted\", color=\"" + + interfaceDescriptor.getInterfaceColor() + + "\", penwidth=10, dir=\"forward\"];\n"); + } + } - /** - * Incoming arrows will have this color. - */ - private String distinctiveReferenceColor; + private void enlistMethodReferences(final StringBuffer result) { + if (methods.isEmpty()) + return; - private String interfaceColor; + result.append("\n"); + result.append(" // method references to other classes\n"); + for (final MethodDescriptor methodDescriptor : methods) + result.append(methodDescriptor.getDot()); + } - private String superClassColor; + private void enlistMethods(final StringBuffer result) { + if (methods.isEmpty()) + return; + + result.append("\n"); + result.append(" // methods:\n"); + + // enlist methods + for (final MethodDescriptor methodDescriptor : methods) + result.append(methodDescriptor.getEmbeddedDot()); + } + + private void enlistSuperClass(final StringBuffer result) { + if (superClass == null) + return; + + if (!superClass.isVisible()) + return; + + if (!superClass.areReferencesShown()) + return; + + result.append("\n"); + result.append(" // super class for: " + fullyQualifiedName + "\n"); + + result.append(" " + superClass.getGraphId() + " -> " + getGraphId() + + "[ color=\"" + superClass.getSuperClassColor() + + "\", penwidth=10, dir=\"forward\"];\n"); + } - boolean isEnum; + private void generateDotHeader(final StringBuffer result) { + result.append("\n"); + result.append("// Class: " + fullyQualifiedName + "\n"); - boolean isInterface; + result.append(" " + getGraphId() + "[label=<\n"); - boolean isArray; + result.append("\n"); + result.append(" // class descriptor header\n"); + result.append(" \n"); + } - List interfaces = new ArrayList(); + private String getBackgroundColor() { + String bgColor = ""; - ClassDescriptor superClass; + if (isEnum) + bgColor = "bgcolor=\"navajowhite2\""; - /** - * Amount of field and method references pointing to this class. - */ - private int referencesCount = 0; + if (isInterface) + bgColor = "bgcolor=\"darkslategray1\""; - // for interface, counts amount of found implementations - private int implementationsCount = 0; + return bgColor; + } - // counts amount of times this class is extended - private int extensionsCount = 0; + private String getBorderWidth() { - private ClassDescriptor arrayComponent; + if (!areReferencesShown()) + return "4"; + return "1"; + } - public ClassDescriptor(final ClassGraph classGraph) { - this.classGraph = classGraph; - } + protected ClassGraph getClassGraph() { + return classGraph; + } - protected void analyzeClass(final Class clazz) { + protected String getClassName(final boolean differentiateArray) { + // this is needed for nested classes + final String actualClassName = fullyQualifiedName.replace('$', '.'); - fullyQualifiedName = clazz.getName(); + String result; + if (isArray) { + // for arrays use array component instead of array class name + result = arrayComponent.fullyQualifiedName; + if (result.contains(".")) { + final int i = result.lastIndexOf('.'); + result = result.substring(i + 1); + } + } else { + final int i = actualClassName.lastIndexOf('.'); + result = actualClassName.substring(i + 1); + } - isArray = clazz.isArray(); + if (differentiateArray) + if (isArray) + result += " []"; - if (isArray) { - final Class componentType = clazz.getComponentType(); - arrayComponent = getClassGraph().getOrCreateClassDescriptor( - componentType); - } + // this is needed for nested classes + // result = result.replace('$', '.'); + return result; + } - // System.out.println("class: " + fullyQualifiedName); + protected String getColor() { + if (distinctiveReferenceColor == null) + distinctiveReferenceColor = Utils.getNextDarkColor(); - isEnum = clazz.isEnum(); + return distinctiveReferenceColor; + } - isInterface = clazz.isInterface(); + @Override + public String getDot() { + if (!isVisible()) + return ""; - if (!isVisible()) - return; + if (isArray) + return ""; - indexFields(clazz.getDeclaredFields()); - indexFields(clazz.getFields()); + final StringBuffer result = new StringBuffer(); - indexMethods(clazz); + generateDotHeader(result); - for (final Class interfaceClass : clazz.getInterfaces()) { - final ClassDescriptor interfaceClassDescriptor = getClassGraph() - .getOrCreateClassDescriptor(interfaceClass); - interfaceClassDescriptor.registerImplementation(); - interfaces.add(interfaceClassDescriptor); - } + enlistFields(result); - superClass = getClassGraph().getOrCreateClassDescriptor( - clazz.getSuperclass()); - if (superClass != null) - superClass.registerExtension(); + enlistMethods(result); - }; + result.append("
" + + "" + getPackageName() + + "
"); - private boolean isShown = true; + final String parentClassesName = getParentClassesName(); + if (parentClassesName.length() > 0) + result.append("" + parentClassesName + + "
\n"); - private final ClassGraph classGraph; + result.append("" + getClassName(false) + + "" + "
>, shape=\"none\"];\n"); - protected boolean areReferencesShown() { - return referencesCount <= MAX_REFERECNES_COUNT; - } + enlistFieldReferences(result); - private void enlistFieldReferences(final StringBuffer result) { - if (nameToFieldMap.isEmpty()) - return; + enlistMethodReferences(result); - result.append("\n"); - result.append(" // field references to other classes\n"); - for (final Map.Entry entry : nameToFieldMap - .entrySet()) - result.append(entry.getValue().getDot()); - } + enlistImplementedInterfaces(result); - private void enlistFields(final StringBuffer result) { - if (nameToFieldMap.isEmpty()) - return; + enlistSuperClass(result); - result.append("\n"); - result.append(" // fields:\n"); + return result.toString(); + } - // enlist fields - for (final Map.Entry entry : nameToFieldMap - .entrySet()) - result.append(entry.getValue().getEmbeddedDot()); - } + @Override + public String getEmbeddedDot() { + return null; + } - private void enlistImplementedInterfaces(final StringBuffer result) { - if (interfaces.isEmpty()) - return; + /** + * Returns field with given name (case is ignored). Or null if + * field is not found. + * + * @param fieldToSearch field name (case is ignored) + * @return field matching given name + */ + protected FieldDescriptor getFieldIgnoreCase(final String fieldToSearch) { - result.append("\n"); - result.append(" // interfaces implemented by class: " - + fullyQualifiedName + "\n"); + for (final String fieldName : nameToFieldMap.keySet()) + if (fieldToSearch.equalsIgnoreCase(fieldName)) + return nameToFieldMap.get(fieldName); - for (final ClassDescriptor interfaceDescriptor : interfaces) { - if (!interfaceDescriptor.isVisible()) - continue; + return null; + } - if (!interfaceDescriptor.areReferencesShown()) - continue; + protected String getFullyQualifiedName() { + return fullyQualifiedName; + } - result.append(" " + interfaceDescriptor.getGraphId() + " -> " - + getGraphId() + "[style=\"dotted\", color=\"" - + interfaceDescriptor.getInterfaceColor() - + "\", penwidth=10, dir=\"forward\"];\n"); - } - } + @Override + public String getGraphId() { + final String result = "class_" + + fullyQualifiedName.replace('.', '_').replace(";", "") + .replace("[L", "").replace('$', '_'); + return result; + } - private void enlistMethodReferences(final StringBuffer result) { - if (methods.isEmpty()) - return; + private String getInterfaceColor() { + if (interfaceColor == null) + interfaceColor = Utils.getNextDarkColor(); - result.append("\n"); - result.append(" // method references to other classes\n"); - for (final MethodDescriptor methodDescriptor : methods) - result.append(methodDescriptor.getDot()); - } + return interfaceColor; + } - private void enlistMethods(final StringBuffer result) { - if (methods.isEmpty()) - return; - - result.append("\n"); - result.append(" // methods:\n"); - - // enlist methods - for (final MethodDescriptor methodDescriptor : methods) - result.append(methodDescriptor.getEmbeddedDot()); - } - - private void enlistSuperClass(final StringBuffer result) { - if (superClass == null) - return; - - if (!superClass.isVisible()) - return; - - if (!superClass.areReferencesShown()) - return; - - result.append("\n"); - result.append(" // super class for: " + fullyQualifiedName + "\n"); - - result.append(" " + superClass.getGraphId() + " -> " + getGraphId() - + "[ color=\"" + superClass.getSuperClassColor() - + "\", penwidth=10, dir=\"forward\"];\n"); - } + private FieldDescriptor getOrCreateFieldDescriptor(final Field field) { - private void generateDotHeader(final StringBuffer result) { - result.append("\n"); - result.append("// Class: " + fullyQualifiedName + "\n"); + final String fieldName = field.getName(); - result.append(" " + getGraphId() + "[label=<\n"); + if (nameToFieldMap.containsKey(fieldName)) + return nameToFieldMap.get(fieldName); - result.append("\n"); - result.append(" // class descriptor header\n"); - result.append(" \n"); - } + return newFieldDescriptor; + } - private String getBackgroundColor() { - String bgColor = ""; + private int getOutgoingReferencesCount() { + int result = 0; - if (isEnum) - bgColor = "bgcolor=\"navajowhite2\""; + // count method references + for (final MethodDescriptor methodDescriptor : methods) + result += methodDescriptor.getOutsideVisibleReferencesCount(); - if (isInterface) - bgColor = "bgcolor=\"darkslategray1\""; + // count field references + for (final FieldDescriptor fieldDescriptor : nameToFieldMap.values()) + result += fieldDescriptor.getOutsideVisibleReferencesCount(); - return bgColor; - } + // count implemented interfaces + for (final ClassDescriptor classDescriptor : interfaces) + if (classDescriptor.isVisible()) + result++; - private String getBorderWidth() { + // count superclass + if (superClass != null) + if (superClass.isVisible()) + result++; - if (!areReferencesShown()) - return "4"; - return "1"; - } + return result; + } - protected ClassGraph getClassGraph() { - return classGraph; - } + private String getPackageName() { - protected String getClassName(final boolean differentiateArray) { - // this is needed for nested classes - final String actualClassName = fullyQualifiedName.replace('$', '.'); + final int i = fullyQualifiedName.lastIndexOf('.'); - String result; - if (isArray) { - // for arrays use array component instead of array class name - result = arrayComponent.fullyQualifiedName; - if (result.contains(".")) { - final int i = result.lastIndexOf('.'); - result = result.substring(i + 1); - } - } else { - final int i = actualClassName.lastIndexOf('.'); - result = actualClassName.substring(i + 1); - } + if (i == -1) + return ""; - if (differentiateArray) - if (isArray) - result += " []"; + return fullyQualifiedName.substring(0, i).replace("[L", ""); + } - // this is needed for nested classes - // result = result.replace('$', '.'); - return result; - } + private String getParentClassesName() { + int i = fullyQualifiedName.lastIndexOf('.'); + final String fullClassName = fullyQualifiedName.substring(i + 1); - protected String getColor() { - if (distinctiveReferenceColor == null) - distinctiveReferenceColor = Utils.getNextDarkColor(); + i = fullClassName.lastIndexOf('$'); + if (i == -1) + return ""; + final String parentClassesName = fullClassName.substring(0, i); + return parentClassesName.replace('$', '.'); + } - return distinctiveReferenceColor; - } + private String getSuperClassColor() { + if (superClassColor == null) + superClassColor = Utils.getNextLightColor(); - @Override - public String getDot() { - if (!isVisible()) - return ""; + return superClassColor; + } - if (isArray) - return ""; + /** + * Checks if class has field with given name (case is ignored). Returns + * true if such field is found. + * + * @param fieldToSearch field to search for (case is ignored) + * @return true if field is found. + */ + protected boolean hasFieldIgnoreCase(final String fieldToSearch) { - final StringBuffer result = new StringBuffer(); + for (final String fieldName : nameToFieldMap.keySet()) + if (fieldToSearch.equalsIgnoreCase(fieldName)) + return true; - generateDotHeader(result); + return false; + } - enlistFields(result); + private void hide() { + isShown = false; + } - enlistMethods(result); + protected void hideClassIfNoReferences() { + if (!isVisible()) + return; - result.append("
" - + "" + getPackageName() - + "
"); + final FieldDescriptor newFieldDescriptor = new FieldDescriptor(this); + nameToFieldMap.put(fieldName, newFieldDescriptor); - final String parentClassesName = getParentClassesName(); - if (parentClassesName.length() > 0) - result.append("" + parentClassesName - + "
\n"); + newFieldDescriptor.analyzeField(field); - result.append("" + getClassName(false) - + "" + "
>, shape=\"none\"];\n"); + final int totalReferencesCount = getOutgoingReferencesCount() + + referencesCount + extensionsCount + implementationsCount; - enlistFieldReferences(result); + if (totalReferencesCount == 0) { + hide(); + return; + } - enlistMethodReferences(result); + return; + } - enlistImplementedInterfaces(result); + private void indexFields(final Field[] fields) { + for (final Field field : fields) + getOrCreateFieldDescriptor(field); + } - enlistSuperClass(result); + private void indexMethods(final Class clazz) { + for (final Method method : clazz.getMethods()) { + final MethodDescriptor methodDescriptor = new MethodDescriptor( + this, method.getName()); - return result.toString(); - } + methods.add(methodDescriptor); - @Override - public String getEmbeddedDot() { - return null; - } + methodDescriptor.analyze(method); + } - /** - * Returns field with given name (case is ignored). Or null if - * field is not found. - * - * @param fieldToSearch - * field name (case is ignored) - * @return field matching given name - */ - protected FieldDescriptor getFieldIgnoreCase(final String fieldToSearch) { + } - for (final String fieldName : nameToFieldMap.keySet()) - if (fieldToSearch.equalsIgnoreCase(fieldName)) - return nameToFieldMap.get(fieldName); + @Override + public boolean isVisible() { - return null; - } + if (Utils.isSystemDataType(fullyQualifiedName)) + return false; - protected String getFullyQualifiedName() { - return fullyQualifiedName; - } + if (Utils.isSystemPackage(fullyQualifiedName)) + return false; - @Override - public String getGraphId() { - final String result = "class_" - + fullyQualifiedName.replace('.', '_').replace(";", "") - .replace("[L", "").replace('$', '_'); - return result; - } + if (!getClassGraph().isClassShown(fullyQualifiedName)) + return false; - private String getInterfaceColor() { - if (interfaceColor == null) - interfaceColor = Utils.getNextDarkColor(); + if (isArray) + if (arrayComponent != null) + if (Utils.isSystemDataType(arrayComponent.fullyQualifiedName)) + // Do not show references to primitive data types in arrays. + // That is: there is no point to show reference to byte when + // we have class with byte array field. + return false; - return interfaceColor; - } + return isShown; + } - private FieldDescriptor getOrCreateFieldDescriptor(final Field field) { + /** + * Register event when another class is extending this one. + */ + protected void registerExtension() { + extensionsCount++; + } - final String fieldName = field.getName(); + protected void registerImplementation() { + implementationsCount++; + } - if (nameToFieldMap.containsKey(fieldName)) - return nameToFieldMap.get(fieldName); + protected void registerReference() { + referencesCount++; + } - final FieldDescriptor newFieldDescriptor = new FieldDescriptor(this); - nameToFieldMap.put(fieldName, newFieldDescriptor); + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ClassDescriptor)) return false; - newFieldDescriptor.analyzeField(field); + ClassDescriptor that = (ClassDescriptor) o; - return newFieldDescriptor; - } + return getFullyQualifiedName().equals(that.getFullyQualifiedName()); - private int getOutgoingReferencesCount() { - int result = 0; + } - // count method references - for (final MethodDescriptor methodDescriptor : methods) - result += methodDescriptor.getOutsideVisibleReferencesCount(); - - // count field references - for (final FieldDescriptor fieldDescriptor : nameToFieldMap.values()) - result += fieldDescriptor.getOutsideVisibleReferencesCount(); - - // count implemented interfaces - for (final ClassDescriptor classDescriptor : interfaces) - if (classDescriptor.isVisible()) - result++; - - // count superclass - if (superClass != null) - if (superClass.isVisible()) - result++; - - return result; - } - - private String getPackageName() { - - final int i = fullyQualifiedName.lastIndexOf('.'); - - if (i == -1) - return ""; - - return fullyQualifiedName.substring(0, i).replace("[L", ""); - } - - private String getParentClassesName() { - int i = fullyQualifiedName.lastIndexOf('.'); - final String fullClassName = fullyQualifiedName.substring(i + 1); - - i = fullClassName.lastIndexOf('$'); - if (i == -1) - return ""; - final String parentClassesName = fullClassName.substring(0, i); - return parentClassesName.replace('$', '.'); - } - - private String getSuperClassColor() { - if (superClassColor == null) - superClassColor = Utils.getNextLightColor(); - - return superClassColor; - } - - /** - * Checks if class has field with given name (case is ignored). Returns - * true if such field is found. - * - * @param fieldToSearch - * field to search for (case is ignored) - * - * @return true if field is found. - */ - protected boolean hasFieldIgnoreCase(final String fieldToSearch) { - - for (final String fieldName : nameToFieldMap.keySet()) - if (fieldToSearch.equalsIgnoreCase(fieldName)) - return true; - - return false; - } - - private void hide() { - isShown = false; - } - - protected void hideClassIfNoReferences() { - if (!isVisible()) - return; - - final int totalReferencesCount = getOutgoingReferencesCount() - + referencesCount + extensionsCount + implementationsCount; - - if (totalReferencesCount == 0) { - hide(); - return; - } - - return; - } - - private void indexFields(final Field[] fields) { - for (final Field field : fields) - getOrCreateFieldDescriptor(field); - } - - private void indexMethods(final Class clazz) { - for (final Method method : clazz.getMethods()) { - final MethodDescriptor methodDescriptor = new MethodDescriptor( - this, method.getName()); - - methods.add(methodDescriptor); - - methodDescriptor.analyze(method); - } - - } - - @Override - public boolean isVisible() { - - if (Utils.isSystemDataType(fullyQualifiedName)) - return false; - - if (Utils.isSystemPackage(fullyQualifiedName)) - return false; - - if (!getClassGraph().isClassShown(fullyQualifiedName)) - return false; - - if (isArray) - if (arrayComponent != null) - if (Utils.isSystemDataType(arrayComponent.fullyQualifiedName)) - // Do not show references to primitive data types in arrays. - // That is: there is no point to show reference to byte when - // we have class with byte array field. - return false; - - return isShown; - } - - /** - * Register event when another class is extending this one. - */ - protected void registerExtension() { - extensionsCount++; - } - - protected void registerImplementation() { - implementationsCount++; - } - - protected void registerReference() { - referencesCount++; - } + @Override + public int hashCode() { + return getFullyQualifiedName().hashCode(); + } + @Override + public int compareTo(ClassDescriptor o) { + return fullyQualifiedName.compareTo(o.fullyQualifiedName); + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java index c8de18b..1488b1c 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/ClassGraph.java @@ -9,6 +9,11 @@ package eu.svjatoslav.inspector.java.structure; +import eu.svjatoslav.commons.file.CommonPathResolver; +import eu.svjatoslav.commons.string.WildCardMatcher; +import eu.svjatoslav.inspector.java.methods.Clazz; +import eu.svjatoslav.inspector.java.methods.ProjectScanner; + import java.io.File; import java.io.IOException; import java.io.PrintWriter; @@ -17,204 +22,193 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import eu.svjatoslav.commons.file.CommonPathResolver; -import eu.svjatoslav.commons.string.WildCardMatcher; -import eu.svjatoslav.inspector.java.methods.Clazz; -import eu.svjatoslav.inspector.java.methods.ProjectScanner; +import static eu.svjatoslav.inspector.java.methods.JavaFile.UTF_8; public class ClassGraph { - /** - * Maps class fully qualified names to class descriptors. - */ - private final Map fullyQualifiedNameToClassMap = new HashMap(); - - private final List blacklistClassPatterns = new ArrayList(); - - private final List whitelistClassPatterns = new ArrayList(); - - private String targetDirectory = CommonPathResolver.getDesktopDirectory() - .getAbsolutePath() + "/"; - - private boolean keepDotFile; - - public ClassGraph() { - } - - /** - * @param objects - * objects that shall be added to graph - * - * @return this {@link ClassGraph} - */ - public ClassGraph add(final Object... objects) { - - if (objects != null) - for (final Object object : objects) - addObject(object); - - return this; - } - - private void addObject(final Object object) { - if (object instanceof Class) - getOrCreateClassDescriptor((Class) object); - else - getOrCreateClassDescriptor(object.getClass()); - } - - /** - * @param path - * path to recursively scan for java source code could be - * relative to current project or absolute - */ - public void addProject(final String path) { - final ProjectScanner projectScanner = new ProjectScanner(new File(path)); - for (final Clazz clazz : projectScanner.getAllClasses()) - try { - System.out.println("Class full name: " + clazz.getFullName()); - final Class c = this.getClass().forName(clazz.getFullName()); - addObject(c); - } catch (final Exception exception) { - System.out.println("cannot add class: " - + exception.getMessage()); - } - } - - public void blacklistClassPattern(final String pattern) { - blacklistClassPatterns.add(pattern); - } - - /** - * @param resultFileName - * file name for the generated graph. File extension will be - * added automatically. Existing file with the same name will be - * overwritten. - * - */ - - public void generateGraph(final String resultFileName) { - - final String dotFilePath = targetDirectory + resultFileName + ".dot"; - final String imageFilePath = targetDirectory + resultFileName + ".png"; - - System.out.println("Dot file path:" + dotFilePath); - - try { - // write DOT file to disk - final PrintWriter out = new PrintWriter(dotFilePath); - out.write(getDot()); - out.close(); - - // execute GraphViz to visualize graph - try { - Runtime.getRuntime() - .exec(new String[] { "dot", "-Tpng", dotFilePath, "-o", - imageFilePath }).waitFor(); - } catch (final InterruptedException e) { - } finally { - } - - if (!keepDotFile) - // delete dot file - new File(dotFilePath).delete(); - } catch (final IOException e) { - System.err.println(e); - } - - } - - private String getDot() { - final StringBuffer result = new StringBuffer(); - - result.append("digraph Java {\n"); - result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n"); - - for (final Map.Entry entry : fullyQualifiedNameToClassMap - .entrySet()) - result.append(entry.getValue().getDot()); - - result.append("}\n"); - - final String resultStr = result.toString(); - return resultStr; - } - - /** - * @param clazz - * class that shall be added to graph - * - * @return {@link ClassDescriptor} corresponding to given {@link Class} - */ - protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) { - - if (clazz == null) - return null; - - final String classFullyQualifiedName = clazz.getName(); - - // reuse existing instance if possible - if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName)) - return fullyQualifiedNameToClassMap.get(classFullyQualifiedName); - - // create new class descriptor - final ClassDescriptor newClassDescriptor = new ClassDescriptor(this); - fullyQualifiedNameToClassMap.put(classFullyQualifiedName, - newClassDescriptor); - - newClassDescriptor.analyzeClass(clazz); - - return newClassDescriptor; - } - - /** - * Hide orphaned class that have no references - * - * @return this {@link ClassGraph} - */ - public ClassGraph hideOrphanedClasses() { - - for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap - .values()) - classDescriptor.hideClassIfNoReferences(); + /** + * Maps class fully qualified names to class descriptors. + */ + private final Map fullyQualifiedNameToClassMap = new HashMap(); + + private final List blacklistClassPatterns = new ArrayList(); + + private final List whitelistClassPatterns = new ArrayList(); + + private String targetDirectory = CommonPathResolver.getDesktopDirectory() + .getAbsolutePath() + "/"; + + private boolean keepDotFile; + + public ClassGraph() { + } + + /** + * @param objects objects that shall be added to graph + * @return this {@link ClassGraph} + */ + public ClassGraph add(final Object... objects) { + + if (objects != null) + for (final Object object : objects) + addObject(object); + + return this; + } + + private void addObject(final Object object) { + if (object instanceof Class) + getOrCreateClassDescriptor((Class) object); + else + getOrCreateClassDescriptor(object.getClass()); + } + + /** + * @param path path to recursively scan for java source code could be + * relative to current project or absolute + */ + public void addProject(final String path) { + final ProjectScanner projectScanner = new ProjectScanner(new File(path)); + for (final Clazz clazz : projectScanner.getAllClasses()) + try { + System.out.println("Class full name: " + clazz.getFullName()); + final Class c = this.getClass().forName(clazz.getFullName()); + addObject(c); + } catch (final Exception exception) { + System.out.println("cannot add class: " + + exception.getMessage()); + } + } + + public void blacklistClassPattern(final String pattern) { + blacklistClassPatterns.add(pattern); + } + + /** + * @param resultFileName file name for the generated graph. File extension will be + * added automatically. Existing file with the same name will be + * overwritten. + */ + + public void generateGraph(final String resultFileName) { + + final String dotFilePath = targetDirectory + resultFileName + ".dot"; + final String imageFilePath = targetDirectory + resultFileName + ".png"; + + System.out.println("Dot file path:" + dotFilePath); + + try { + // write DOT file to disk + final PrintWriter out = new PrintWriter(dotFilePath, UTF_8); + out.write(getDot()); + out.close(); + + // execute GraphViz to visualize graph + try { + Runtime.getRuntime() + .exec(new String[]{"dot", "-Tpng", dotFilePath, "-o", + imageFilePath}).waitFor(); + } catch (final InterruptedException ignored) { + } + + if (!keepDotFile) + // delete dot file + if (!new File(dotFilePath).delete()) throw new RuntimeException("Cannot delete file: " + dotFilePath); + } catch (final IOException e) { + System.err.println(e); + } + + } + + private String getDot() { + final StringBuffer result = new StringBuffer(); + + result.append("digraph Java {\n"); + result.append("graph [rankdir=LR, overlap = false, concentrate=true];\n"); + + for (final Map.Entry entry : fullyQualifiedNameToClassMap + .entrySet()) + result.append(entry.getValue().getDot()); + + result.append("}\n"); + + final String resultStr = result.toString(); + return resultStr; + } + + /** + * @param clazz class that shall be added to graph + * @return {@link ClassDescriptor} corresponding to given {@link Class} + */ + protected ClassDescriptor getOrCreateClassDescriptor(final Class clazz) { + + if (clazz == null) + return null; + + final String classFullyQualifiedName = clazz.getName(); + + // reuse existing instance if possible + if (fullyQualifiedNameToClassMap.containsKey(classFullyQualifiedName)) + return fullyQualifiedNameToClassMap.get(classFullyQualifiedName); + + // create new class descriptor + final ClassDescriptor newClassDescriptor = new ClassDescriptor(this); + fullyQualifiedNameToClassMap.put(classFullyQualifiedName, + newClassDescriptor); + + newClassDescriptor.analyzeClass(clazz); + + return newClassDescriptor; + } + + /** + * Hide orphaned class that have no references + * + * @return this {@link ClassGraph} + */ + public ClassGraph hideOrphanedClasses() { + + for (final ClassDescriptor classDescriptor : fullyQualifiedNameToClassMap + .values()) + classDescriptor.hideClassIfNoReferences(); - return this; - } + return this; + } - protected boolean isClassShown(final String className) { - for (final String pattern : blacklistClassPatterns) - if (WildCardMatcher.match(className, pattern)) - return false; + protected boolean isClassShown(final String className) { + for (final String pattern : blacklistClassPatterns) + if (WildCardMatcher.match(className, pattern)) + return false; - if (!whitelistClassPatterns.isEmpty()) { - for (final String pattern : whitelistClassPatterns) - if (WildCardMatcher.match(className, pattern)) - return true; - return false; - } + if (!whitelistClassPatterns.isEmpty()) { + for (final String pattern : whitelistClassPatterns) + if (WildCardMatcher.match(className, pattern)) + return true; + return false; + } - return true; - } + return true; + } - public ClassGraph setKeepDotFile(final boolean keepDotFile) { - this.keepDotFile = keepDotFile; + public ClassGraph setKeepDotFile(final boolean keepDotFile) { + this.keepDotFile = keepDotFile; - return this; - } + return this; + } - public ClassGraph setTargetDirectory(String directoryPath) { - if (!directoryPath.endsWith("/")) - directoryPath += "/"; + public ClassGraph setTargetDirectory(String directoryPath) { + if (!directoryPath.endsWith("/")) + directoryPath += "/"; - targetDirectory = directoryPath; + targetDirectory = directoryPath; - return this; - } + return this; + } - public ClassGraph whitelistClassPattern(final String pattern) { - whitelistClassPatterns.add(pattern); + public ClassGraph whitelistClassPattern(final String pattern) { + whitelistClassPatterns.add(pattern); - return this; - } + return this; + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java b/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java index 7128c4e..59f93fc 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/FieldDescriptor.java @@ -21,136 +21,134 @@ import java.util.List; public class FieldDescriptor implements GraphElement { - private String name; - private ClassDescriptor type; - private final ClassDescriptor parentClass; - private final List typeArguments = new ArrayList(); - private boolean isInherited; - - public FieldDescriptor(final ClassDescriptor parent) { - parentClass = parent; - } - - public void analyzeField(final Field field) { - - if (!field.getDeclaringClass().getName() - .equals(parentClass.getFullyQualifiedName())) - isInherited = true; - - name = field.getName(); - type = parentClass.getClassGraph().getOrCreateClassDescriptor( - field.getType()); - type.registerReference(); - - final Type genericType = field.getGenericType(); - if (genericType instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) genericType; - for (final Type t : pt.getActualTypeArguments()) - if (t instanceof Class) { - final Class cl = (Class) t; - final ClassDescriptor genericTypeDescriptor = parentClass - .getClassGraph().getOrCreateClassDescriptor(cl); - genericTypeDescriptor.registerReference(); - typeArguments.add(genericTypeDescriptor); - } - - } - } - - @Override - public String getDot() { - - if (!isVisible()) - return ""; - - final StringBuffer result = new StringBuffer(); - - // describe associated types - for (final ClassDescriptor classDescriptor : typeArguments) - if (classDescriptor.isVisible()) - if (classDescriptor.areReferencesShown()) - result.append(" " + getGraphId() + " -> " - + classDescriptor.getGraphId() + "[label=\"" + name - + "\", color=\"" + classDescriptor.getColor() - + "\", style=\"bold\"];\n"); - - if (!type.isVisible()) - return result.toString(); - - // main type - boolean showLink = type.areReferencesShown(); - - if (type == parentClass) - showLink = false; - - if (parentClass.isEnum) - showLink = false; - - if (showLink) - result.append(" " + getGraphId() + " -> " + type.getGraphId() - + "[label=\"" + name + "\"," + " color=\"" - + type.getColor() + "\", style=\"bold\"];\n"); - - return result.toString(); - } - - @Override - public String getEmbeddedDot() { - - if (!isVisible()) - return ""; - - final StringBuffer result = new StringBuffer(); - - result.append(" // " + name + "\n"); - if (parentClass.isEnum && (type == parentClass)) { - result.append(" "); - result.append(name + "\n"); - } else { - result.append(" "); - result.append(""); - result.append(type.getClassName(true) + ""); - result.append(""); - result.append(name + "\n"); - } - return result.toString(); - } - - @Override - public String getGraphId() { - return parentClass.getGraphId() + ":" + name; - } - - protected int getOutsideVisibleReferencesCount() { - - if (!isVisible()) - return 0; - - if (type != null) - if (type.isVisible()) - return 1; - - return 0; - } - - protected ClassDescriptor getType() { - return type; - } - - @Override - public boolean isVisible() { - if (isInherited) - return false; - - if (name.contains("$")) - return false; - - if (name.equals("serialVersionUID")) - return false; + private final ClassDescriptor parentClass; + private final List typeArguments = new ArrayList(); + private String name; + private ClassDescriptor type; + private boolean isInherited; + + public FieldDescriptor(final ClassDescriptor parent) { + parentClass = parent; + } + + public void analyzeField(final Field field) { + + if (!field.getDeclaringClass().getName() + .equals(parentClass.getFullyQualifiedName())) + isInherited = true; + + name = field.getName(); + type = parentClass.getClassGraph().getOrCreateClassDescriptor( + field.getType()); + type.registerReference(); + + final Type genericType = field.getGenericType(); + if (genericType instanceof ParameterizedType) { + final ParameterizedType pt = (ParameterizedType) genericType; + for (final Type t : pt.getActualTypeArguments()) + if (t instanceof Class) { + final Class cl = (Class) t; + final ClassDescriptor genericTypeDescriptor = parentClass + .getClassGraph().getOrCreateClassDescriptor(cl); + genericTypeDescriptor.registerReference(); + typeArguments.add(genericTypeDescriptor); + } + + } + } + + @Override + public String getDot() { + + if (!isVisible()) + return ""; + + final StringBuffer result = new StringBuffer(); + + // describe associated types + for (final ClassDescriptor classDescriptor : typeArguments) + if (classDescriptor.isVisible()) + if (classDescriptor.areReferencesShown()) + result.append(" " + getGraphId() + " -> " + + classDescriptor.getGraphId() + "[label=\"" + name + + "\", color=\"" + classDescriptor.getColor() + + "\", style=\"bold\"];\n"); + + if (!type.isVisible()) + return result.toString(); + + // main type + boolean showLink = type.areReferencesShown(); + + if (type == parentClass) + showLink = false; + + if (parentClass.isEnum) + showLink = false; + + if (showLink) + result.append(" " + getGraphId() + " -> " + type.getGraphId() + + "[label=\"" + name + "\"," + " color=\"" + + type.getColor() + "\", style=\"bold\"];\n"); + + return result.toString(); + } + + @Override + public String getEmbeddedDot() { + + if (!isVisible()) + return ""; + + final StringBuffer result = new StringBuffer(); + + result.append(" // " + name + "\n"); + if (parentClass.isEnum && (type == parentClass)) { + result.append(" "); + result.append(name + "\n"); + } else { + result.append(" "); + result.append(""); + result.append(type.getClassName(true) + ""); + result.append(""); + result.append(name + "\n"); + } + return result.toString(); + } + + @Override + public String getGraphId() { + return parentClass.getGraphId() + ":" + name; + } + + protected int getOutsideVisibleReferencesCount() { + + if (!isVisible()) + return 0; + + if (type != null) + if (type.isVisible()) + return 1; + + return 0; + } + + protected ClassDescriptor getType() { + return type; + } + + @Override + public boolean isVisible() { + if (isInherited) + return false; + + if (name.contains("$")) + return false; + + return !name.equals("serialVersionUID"); - return true; - } + } } \ No newline at end of file diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java b/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java index 98212d2..1e88dba 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/GraphElement.java @@ -11,12 +11,12 @@ package eu.svjatoslav.inspector.java.structure; public interface GraphElement { - public String getDot(); + String getDot(); - public String getEmbeddedDot(); + String getEmbeddedDot(); - public String getGraphId(); + String getGraphId(); - public boolean isVisible(); + boolean isVisible(); } diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java b/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java index 173ddc3..d411cb0 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/MethodDescriptor.java @@ -19,157 +19,178 @@ import java.util.List; * This class corresponds to single method within a java class. */ public class MethodDescriptor implements GraphElement, - Comparable { - - private final String methodName; - private ClassDescriptor returnType; - private final ClassDescriptor parentClass; - private final List argumentTypes = new ArrayList(); - private boolean isInherited; - - public MethodDescriptor(final ClassDescriptor parent, - final String methodName) { - parentClass = parent; - this.methodName = methodName; - } - - public void analyze(final Method method) { - - if (!method.getDeclaringClass().getName() - .equals(parentClass.getFullyQualifiedName())) - isInherited = true; - - returnType = parentClass.getClassGraph().getOrCreateClassDescriptor( - method.getReturnType()); - returnType.registerReference(); - - final Type genericType = method.getGenericReturnType(); - if (genericType instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) genericType; - for (final Type t : pt.getActualTypeArguments()) - if (t instanceof Class) { - final Class cl = (Class) t; - final ClassDescriptor classDescriptor = parentClass - .getClassGraph().getOrCreateClassDescriptor(cl); - classDescriptor.registerReference(); - argumentTypes.add(classDescriptor); - } - - } - } - - @Override - public int compareTo(final MethodDescriptor o) { - - final int nameComparisonResult = methodName.compareTo(o.methodName); - if (nameComparisonResult != 0) - return nameComparisonResult; - - return toString().compareTo(o.toString()); - } - - @Override - public String getDot() { - - if (!isVisible()) - return ""; - - final StringBuffer result = new StringBuffer(); - - // describe associated types - for (final ClassDescriptor classDescriptor : argumentTypes) - if (classDescriptor.isVisible()) - if (classDescriptor.areReferencesShown()) - result.append(" " + getGraphId() + " -> " - + classDescriptor.getGraphId() + "[label=\"" - + methodName + "\", color=\"" - + classDescriptor.getColor() - + "\", style=\"dotted, bold\"];\n"); - - if (!returnType.isVisible()) - return result.toString(); - - // main type - if (returnType.areReferencesShown()) - result.append(" " + getGraphId() + " -> " - + returnType.getGraphId() + "[label=\"" + methodName - + "\"," + " color=\"" + returnType.getColor() - + "\", style=\"dotted, bold\"];\n"); - - return result.toString(); - } - - @Override - public String getEmbeddedDot() { - if (!isVisible()) - return ""; - - final StringBuffer result = new StringBuffer(); - - result.append(" // " + methodName + "\n"); - - result.append(" " - + "" + returnType.getClassName(true) - + "" + "" - + getMethodLabel() + "\n"); - - return result.toString(); - } - - @Override - public String getGraphId() { - return parentClass.getGraphId() + ":" + methodName; - } - - private String getMethodLabel() { - return methodName; - } + Comparable { + + private final String methodName; + private final ClassDescriptor parentClass; + private final List argumentTypes = new ArrayList(); + private ClassDescriptor returnType; + private boolean isInherited; + + public MethodDescriptor(final ClassDescriptor parent, + final String methodName) { + parentClass = parent; + this.methodName = methodName; + } + + public void analyze(final Method method) { + + if (!method.getDeclaringClass().getName() + .equals(parentClass.getFullyQualifiedName())) + isInherited = true; + + returnType = parentClass.getClassGraph().getOrCreateClassDescriptor( + method.getReturnType()); + returnType.registerReference(); + + final Type genericType = method.getGenericReturnType(); + if (genericType instanceof ParameterizedType) { + final ParameterizedType pt = (ParameterizedType) genericType; + for (final Type t : pt.getActualTypeArguments()) + if (t instanceof Class) { + final Class cl = (Class) t; + final ClassDescriptor classDescriptor = parentClass + .getClassGraph().getOrCreateClassDescriptor(cl); + classDescriptor.registerReference(); + argumentTypes.add(classDescriptor); + } + + } + } - protected int getOutsideVisibleReferencesCount() { - int result = 0; - - if (returnType.isVisible()) - result++; + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MethodDescriptor)) return false; + + MethodDescriptor that = (MethodDescriptor) o; + + if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) return false; + if (parentClass != null ? !parentClass.equals(that.parentClass) : that.parentClass != null) return false; + return argumentTypes != null ? argumentTypes.equals(that.argumentTypes) : that.argumentTypes == null; + + } + + + @Override + public int hashCode() { + int result = methodName != null ? methodName.hashCode() : 0; + result = 31 * result + (parentClass != null ? parentClass.hashCode() : 0); + result = 31 * result + (argumentTypes != null ? argumentTypes.hashCode() : 0); + return result; + } + + @Override + public String getDot() { + + if (!isVisible()) + return ""; + + final StringBuffer result = new StringBuffer(); + + // describe associated types + for (final ClassDescriptor classDescriptor : argumentTypes) + if (classDescriptor.isVisible()) + if (classDescriptor.areReferencesShown()) + result.append(" " + getGraphId() + " -> " + + classDescriptor.getGraphId() + "[label=\"" + + methodName + "\", color=\"" + + classDescriptor.getColor() + + "\", style=\"dotted, bold\"];\n"); + + if (!returnType.isVisible()) + return result.toString(); + + // main type + if (returnType.areReferencesShown()) + result.append(" " + getGraphId() + " -> " + + returnType.getGraphId() + "[label=\"" + methodName + + "\"," + " color=\"" + returnType.getColor() + + "\", style=\"dotted, bold\"];\n"); + + return result.toString(); + } + + @Override + public String getEmbeddedDot() { + if (!isVisible()) + return ""; + + final StringBuffer result = new StringBuffer(); + + result.append(" // " + methodName + "\n"); + + result.append(" " + + "" + returnType.getClassName(true) + + "" + "" + + getMethodLabel() + "\n"); + + return result.toString(); + } + + @Override + public String getGraphId() { + return parentClass.getGraphId() + ":" + methodName; + } + + private String getMethodLabel() { + return methodName; + } + + protected int getOutsideVisibleReferencesCount() { + int result = 0; + + if (returnType.isVisible()) + result++; + + for (final ClassDescriptor classDescriptor : argumentTypes) + if (classDescriptor.isVisible()) + result++; - for (final ClassDescriptor classDescriptor : argumentTypes) - if (classDescriptor.isVisible()) - result++; - - return result; - } + return result; + } - @Override - public boolean isVisible() { + @Override + public boolean isVisible() { - // hide inherited methods - if (isInherited) - return false; + // hide inherited methods + if (isInherited) + return false; - // hide common object methods - if (Utils.isCommonObjectMethod(methodName)) - return false; + // hide common object methods + if (Utils.isCommonObjectMethod(methodName)) + return false; - // hide common Enumeration methods - if (parentClass.isEnum && Utils.isEnumMethod(methodName)) - return false; + // hide common Enumeration methods + if (parentClass.isEnum && Utils.isEnumMethod(methodName)) + return false; - // hide get/set methods for the field of the same name - if (methodName.startsWith("get") || methodName.startsWith("set")) - if (parentClass.hasFieldIgnoreCase(methodName.substring(3))) - return false; + // hide get/set methods for the field of the same name + if (methodName.startsWith("get") || methodName.startsWith("set")) + if (parentClass.hasFieldIgnoreCase(methodName.substring(3))) + return false; - // hide is methods for the boolean field of the same name - if (methodName.startsWith("is")) { - final FieldDescriptor field = parentClass - .getFieldIgnoreCase(methodName.substring(2)); - if (field != null) - if ("boolean".equals(field.getType().getFullyQualifiedName())) - return false; - } + // hide is methods for the boolean field of the same name + if (methodName.startsWith("is")) { + final FieldDescriptor field = parentClass + .getFieldIgnoreCase(methodName.substring(2)); + if (field != null) + if ("boolean".equals(field.getType().getFullyQualifiedName())) + return false; + } - return true; + return true; - } + } + @Override + public int compareTo(MethodDescriptor that) { + if (this == that) return 0; + + int comparisonResult = methodName.compareTo(that.methodName); + if (comparisonResult != 0) return comparisonResult; + + return parentClass.compareTo(that.parentClass); + } } diff --git a/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java b/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java index 6f599ef..41dc633 100755 --- a/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java +++ b/src/main/java/eu/svjatoslav/inspector/java/structure/Utils.java @@ -14,136 +14,129 @@ import java.util.List; public class Utils { - /** - * retrieves colors from predefined palette - * - * @return next available dark color name - */ - protected static String getNextDarkColor() { - lastChosenDarkColor++; - if (lastChosenDarkColor >= darkColors.size()) - lastChosenDarkColor = 0; - - return darkColors.get(lastChosenDarkColor); - } - - /** - * retrieves colors from predefined palette - * - * @return next available light color name - */ - protected static String getNextLightColor() { - lastChosenLightColor++; - if (lastChosenLightColor >= lightColors.size()) - lastChosenLightColor = 0; - - return lightColors.get(lastChosenLightColor); - } - - private static void initCommonObjectMethods() { - commonObjectMethods.add("wait"); - commonObjectMethods.add("equals"); - commonObjectMethods.add("toString"); - commonObjectMethods.add("hashCode"); - commonObjectMethods.add("notify"); - commonObjectMethods.add("notifyAll"); - commonObjectMethods.add("getClass"); - } - - protected static void initDarkColors() { - darkColors.add("antiquewhite4"); - darkColors.add("blueviolet"); - darkColors.add("brown4"); - darkColors.add("chartreuse4"); - darkColors.add("cyan4"); - darkColors.add("deeppink1"); - darkColors.add("deepskyblue3"); - darkColors.add("firebrick1"); - darkColors.add("goldenrod3"); - darkColors.add("gray0"); - } - - private static void initEnumMethods() { - enumMethods.add("values"); - enumMethods.add("valueOf"); - enumMethods.add("name"); - enumMethods.add("compareTo"); - enumMethods.add("valueOf"); - enumMethods.add("getDeclaringClass"); - enumMethods.add("ordinal"); - } - - private static void initLightColors() { - lightColors.add("olivedrab2"); - lightColors.add("peachpuff2"); - lightColors.add("seagreen1"); - lightColors.add("violet"); - lightColors.add("aqua"); - lightColors.add("orange"); - } - - private static void initSystemDataTypes() { - systemDataTypes.add("void"); - systemDataTypes.add("int"); - systemDataTypes.add("long"); - systemDataTypes.add("float"); - systemDataTypes.add("double"); - systemDataTypes.add("boolean"); - systemDataTypes.add("char"); - systemDataTypes.add("short"); - systemDataTypes.add("byte"); - } - - private static void initSystemPackages() { - systemPackages.add("java."); - systemPackages.add("javax."); - systemPackages.add("sun."); - } - - protected static boolean isCommonObjectMethod(final String name) { - return commonObjectMethods.contains(name); - } - - protected static boolean isEnumMethod(final String name) { - return enumMethods.contains(name); - } - - protected static boolean isSystemDataType(final String name) { - return systemDataTypes.contains(name); - } - - protected static boolean isSystemPackage(final String name) { - - for (final String packagePrefix : systemPackages) - if (name.startsWith(packagePrefix)) - return true; - - return false; - } - - private static final List systemDataTypes = new ArrayList(); - - private static final List commonObjectMethods = new ArrayList(); - - private static final List systemPackages = new ArrayList(); - - private static final List darkColors = new ArrayList(); - - private static final List lightColors = new ArrayList(); - - private static final List enumMethods = new ArrayList(); - - private static int lastChosenDarkColor = -1; - - private static int lastChosenLightColor = -1; - - static { - initEnumMethods(); - initSystemDataTypes(); - initDarkColors(); - initLightColors(); - initCommonObjectMethods(); - initSystemPackages(); - } + private static final List systemDataTypes = new ArrayList(); + private static final List commonObjectMethods = new ArrayList(); + private static final List systemPackages = new ArrayList(); + private static final List darkColors = new ArrayList(); + private static final List lightColors = new ArrayList(); + private static final List enumMethods = new ArrayList(); + private static int lastChosenDarkColor = -1; + private static int lastChosenLightColor = -1; + + static { + initEnumMethods(); + initSystemDataTypes(); + initDarkColors(); + initLightColors(); + initCommonObjectMethods(); + initSystemPackages(); + } + + /** + * retrieves colors from predefined palette + * + * @return next available dark color name + */ + protected static String getNextDarkColor() { + lastChosenDarkColor++; + if (lastChosenDarkColor >= darkColors.size()) + lastChosenDarkColor = 0; + + return darkColors.get(lastChosenDarkColor); + } + + /** + * retrieves colors from predefined palette + * + * @return next available light color name + */ + protected static String getNextLightColor() { + lastChosenLightColor++; + if (lastChosenLightColor >= lightColors.size()) + lastChosenLightColor = 0; + + return lightColors.get(lastChosenLightColor); + } + + private static void initCommonObjectMethods() { + commonObjectMethods.add("wait"); + commonObjectMethods.add("equals"); + commonObjectMethods.add("toString"); + commonObjectMethods.add("hashCode"); + commonObjectMethods.add("notify"); + commonObjectMethods.add("notifyAll"); + commonObjectMethods.add("getClass"); + } + + protected static void initDarkColors() { + darkColors.add("antiquewhite4"); + darkColors.add("blueviolet"); + darkColors.add("brown4"); + darkColors.add("chartreuse4"); + darkColors.add("cyan4"); + darkColors.add("deeppink1"); + darkColors.add("deepskyblue3"); + darkColors.add("firebrick1"); + darkColors.add("goldenrod3"); + darkColors.add("gray0"); + } + + private static void initEnumMethods() { + enumMethods.add("values"); + enumMethods.add("valueOf"); + enumMethods.add("name"); + enumMethods.add("compareTo"); + enumMethods.add("valueOf"); + enumMethods.add("getDeclaringClass"); + enumMethods.add("ordinal"); + } + + private static void initLightColors() { + lightColors.add("olivedrab2"); + lightColors.add("peachpuff2"); + lightColors.add("seagreen1"); + lightColors.add("violet"); + lightColors.add("aqua"); + lightColors.add("orange"); + } + + private static void initSystemDataTypes() { + systemDataTypes.add("void"); + systemDataTypes.add("int"); + systemDataTypes.add("long"); + systemDataTypes.add("float"); + systemDataTypes.add("double"); + systemDataTypes.add("boolean"); + systemDataTypes.add("char"); + systemDataTypes.add("short"); + systemDataTypes.add("byte"); + } + + private static void initSystemPackages() { + systemPackages.add("java."); + systemPackages.add("javax."); + systemPackages.add("sun."); + } + + protected static boolean isCommonObjectMethod(final String name) { + return commonObjectMethods.contains(name); + } + + protected static boolean isEnumMethod(final String name) { + return enumMethods.contains(name); + } + + protected static boolean isSystemDataType(final String name) { + return systemDataTypes.contains(name); + } + + protected static boolean isSystemPackage(final String name) { + + for (final String packagePrefix : systemPackages) + if (name.startsWith(packagePrefix)) + return true; + + return false; + } } diff --git a/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderDemoClasses.java b/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderDemoClasses.java index a3f83ec..90aa480 100755 --- a/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderDemoClasses.java +++ b/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderDemoClasses.java @@ -15,10 +15,10 @@ import eu.svjatoslav.inspector.java.structure.example.structure.SampleClass2; public class RenderDemoClasses { - public static void main(final String[] args) { + public static void main(final String[] args) { - new ClassGraph().add(SampleClass.class, SampleClass2.class) - .generateGraph("example"); - } + new ClassGraph().add(SampleClass.class, SampleClass2.class) + .generateGraph("example"); + } } diff --git a/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderJavaInspect.java b/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderJavaInspect.java index 132276a..1f38883 100755 --- a/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderJavaInspect.java +++ b/src/test/java/eu/svjatoslav/inspector/java/structure/example/RenderJavaInspect.java @@ -9,61 +9,61 @@ package eu.svjatoslav.inspector.java.structure.example; -import java.io.FileNotFoundException; - import eu.svjatoslav.inspector.java.structure.ClassGraph; import eu.svjatoslav.inspector.java.structure.Utils; +import java.io.FileNotFoundException; + public class RenderJavaInspect { - private static void fullProjectExample() { - // Create graph - final ClassGraph graph = new ClassGraph(); + private static void fullProjectExample() { + // Create graph + final ClassGraph graph = new ClassGraph(); - // Recursively scan current directory for Java source code and attempt - // to detect class names from there to be added to the graph. - graph.addProject("."); + // Recursively scan current directory for Java source code and attempt + // to detect class names from there to be added to the graph. + graph.addProject("."); - // Blacklist example classes from being shown on the graph - graph.blacklistClassPattern("eu.svjatoslav.inspector.java.structure.example.*"); + // Blacklist example classes from being shown on the graph + graph.blacklistClassPattern("eu.svjatoslav.inspector.java.structure.example.*"); - // do not show single classes with no relationships on the graph - graph.hideOrphanedClasses(); + // do not show single classes with no relationships on the graph + graph.hideOrphanedClasses(); - // Produce bitmap image titled "JavaInspect full project.png" to the - // user Desktop directory. - graph.generateGraph("JavaInspect full project"); - } + // Produce bitmap image titled "JavaInspect full project.png" to the + // user Desktop directory. + graph.generateGraph("JavaInspect full project"); + } - private static void handpickClassesExample() { - /* - * This example demonstrates generating of class graph from hand picked + private static void handpickClassesExample() { + /* + * This example demonstrates generating of class graph from hand picked * classes and visualizing GraphViz itself. */ - // Create graph - final ClassGraph graph = new ClassGraph(); + // Create graph + final ClassGraph graph = new ClassGraph(); - // Add some random object to the graph. GraphViz will detect Class from - // the object. - graph.add(graph); + // Add some random object to the graph. GraphViz will detect Class from + // the object. + graph.add(graph); - // Also add some random class to the graph. - graph.add(Utils.class); + // Also add some random class to the graph. + graph.add(Utils.class); - // Keep intermediary GraphViz DOT file for reference. - graph.setKeepDotFile(true); + // Keep intermediary GraphViz DOT file for reference. + graph.setKeepDotFile(true); - // Produce bitmap image titled "JavaInspect.png" to the user Desktop - // directory - graph.generateGraph("JavaInspect"); - } + // Produce bitmap image titled "JavaInspect.png" to the user Desktop + // directory + graph.generateGraph("JavaInspect"); + } - public static void main(final String[] args) throws FileNotFoundException { + public static void main(final String[] args) throws FileNotFoundException { - handpickClassesExample(); + handpickClassesExample(); - fullProjectExample(); + fullProjectExample(); - } + } } diff --git a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleClass.java b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleClass.java index 3e496c4..9336717 100755 --- a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleClass.java +++ b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleClass.java @@ -2,10 +2,10 @@ package eu.svjatoslav.inspector.java.structure.example.structure; public class SampleClass extends SampleSuperClass { - ObjectVisibleAsClassField sampleClassField; + ObjectVisibleAsClassField sampleClassField; - public ObjectReturnedByMethod sampleMethod() { - return new ObjectReturnedByMethod(); - } + public ObjectReturnedByMethod sampleMethod() { + return new ObjectReturnedByMethod(); + } } diff --git a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleEnum.java b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleEnum.java index dfb6ea2..05a3f80 100755 --- a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleEnum.java +++ b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleEnum.java @@ -2,6 +2,6 @@ package eu.svjatoslav.inspector.java.structure.example.structure; public enum SampleEnum { - ONE, TWO, THREE, FOUR + ONE, TWO, THREE, FOUR } diff --git a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleInterface.java b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleInterface.java index 136bfde..e9d6bc5 100755 --- a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleInterface.java +++ b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleInterface.java @@ -1,5 +1,5 @@ package eu.svjatoslav.inspector.java.structure.example.structure; public interface SampleInterface { - public SampleEnum getSomeValue(); + SampleEnum getSomeValue(); } diff --git a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleSuperClass.java b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleSuperClass.java index 96edce2..10de17e 100755 --- a/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleSuperClass.java +++ b/src/test/java/eu/svjatoslav/inspector/java/structure/example/structure/SampleSuperClass.java @@ -2,9 +2,9 @@ package eu.svjatoslav.inspector.java.structure.example.structure; public class SampleSuperClass implements SampleInterface { - @Override - public SampleEnum getSomeValue() { - return SampleEnum.ONE; - } + @Override + public SampleEnum getSomeValue() { + return SampleEnum.ONE; + } } -- 2.20.1