Skip to content

Commit

Permalink
finished HtmlOutputGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
siom79 committed Mar 4, 2024
1 parent 33654be commit d6c22ee
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 146 deletions.
2 changes: 1 addition & 1 deletion japicmp/src/main/java/japicmp/JApiCmp.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static void main(String[] args) {
}
} catch (Exception e) {
LOGGER.log(Level.FINE, CAUGHT_EXCEPTION + e.getLocalizedMessage(), e);
System.err.println(String.format("Execution of %s failed: %s", JApiCmp.class.getSimpleName(), e.getMessage()));
System.err.printf("Execution of %s failed: %s%n", JApiCmp.class.getSimpleName(), e.getMessage());
e.printStackTrace();
systemExit.exit(1);
}
Expand Down
24 changes: 21 additions & 3 deletions japicmp/src/main/java/japicmp/cli/JApiCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
import japicmp.config.Options;
import japicmp.exception.JApiCmpException;
import japicmp.model.JApiClass;
import japicmp.output.html.HtmlOutput;
import japicmp.output.html.HtmlOutputGenerator;
import japicmp.output.html.HtmlOutputGeneratorOptions;
import japicmp.output.incompatible.IncompatibleErrorOutput;
import japicmp.output.semver.SemverOut;
import japicmp.output.stdout.StdoutOutputGenerator;
import japicmp.output.xml.XmlOutput;
import japicmp.output.xml.XmlOutputGenerator;
import japicmp.output.xml.XmlOutputGeneratorOptions;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class JApiCli {
Expand Down Expand Up @@ -39,18 +46,29 @@ private void generateOutput(Options options, List<JApiClass> jApiClasses, JarArc
System.out.println(output);
return;
}
if (options.getXmlOutputFile().isPresent() || options.getHtmlOutputFile().isPresent()) {
SemverOut semverOut = new SemverOut(options, jApiClasses);
SemverOut semverOut = new SemverOut(options, jApiClasses);
if (options.getXmlOutputFile().isPresent()) {
XmlOutputGeneratorOptions xmlOutputGeneratorOptions = new XmlOutputGeneratorOptions();
xmlOutputGeneratorOptions.setCreateSchemaFile(true);
xmlOutputGeneratorOptions.setSemanticVersioningInformation(semverOut.generate());
XmlOutputGenerator xmlGenerator = new XmlOutputGenerator(jApiClasses, options, xmlOutputGeneratorOptions);
try (XmlOutput xmlOutput = xmlGenerator.generate()) {
XmlOutputGenerator.writeToFiles(options, xmlOutput);
} catch (Exception e) {
throw new JApiCmpException(JApiCmpException.Reason.IoException, "Could not close output streams: " + e.getMessage(), e);
throw new JApiCmpException(JApiCmpException.Reason.IoException, "Could not write XML file: " + e.getMessage(), e);
}
}
if (options.getHtmlOutputFile().isPresent()) {
HtmlOutputGeneratorOptions htmlOutputGeneratorOptions = new HtmlOutputGeneratorOptions();
htmlOutputGeneratorOptions.setSemanticVersioningInformation(semverOut.generate());
HtmlOutputGenerator outputGenerator = new HtmlOutputGenerator(jApiClasses, options, htmlOutputGeneratorOptions);
HtmlOutput htmlOutput = outputGenerator.generate();
try {
Files.write(Paths.get(options.getHtmlOutputFile().get()), htmlOutput.getHtml().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
throw new JApiCmpException(JApiCmpException.Reason.IoException, "Could not write HTML file: " + e.getMessage(), e);
}
}
StdoutOutputGenerator stdoutOutputGenerator = new StdoutOutputGenerator(options, jApiClasses);
String output = stdoutOutputGenerator.generate();
System.out.println(output);
Expand Down
101 changes: 69 additions & 32 deletions japicmp/src/main/java/japicmp/output/html/HtmlOutputGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;

import static japicmp.util.StringHelper.filtersAsString;
Expand Down Expand Up @@ -57,22 +54,70 @@ private void classes(StringBuilder sb) {
.map(jApiClass -> loadAndFillTemplate("/html/class-entry.html", mapOf(
"fullyQualifiedName", jApiClass.getFullyQualifiedName(),
"outputChangeStatus", outputChangeStatus(jApiClass),
"javaObjectSerializationCompatibleClass", javaObjectSerializationCompatibleClass(jApiClass),
"javaObjectSerializationCompatible", javaObjectSerializationCompatible(jApiClass),
"modifiers", modifiers(jApiClass),
"classType", classType(jApiClass),
"compatibilityChanges", compatibilityChanges(jApiClass),
"compatibilityChanges", compatibilityChanges(jApiClass, false),
"classFileFormatVersion", classFileFormatVersion(jApiClass),
"genericTemplates", genericTemplates(jApiClass),
"superclass", superclass(jApiClass),
"interfaces", interfaces(jApiClass),
"serialVersionUid", serialVersionUid(jApiClass),
"fields", fields(jApiClass),
"constructors", constructors(jApiClass)
"constructors", constructors(jApiClass),
"methods", methods(jApiClass),
"annotations", annotations(jApiClass.getAnnotations())
)))
.collect(Collectors.joining()));
}

private String methods(JApiClass jApiClass) {
if (!jApiClass.getMethods().isEmpty()) {
return loadAndFillTemplate("/html/methods.html", mapOf(
"tbody", methodsTBody(jApiClass.getMethods())
));
}
return "";
}

private String methodsTBody(List<JApiMethod> methods) {
return methods.stream()
.sorted(Comparator.comparing(JApiMethod::getName))
.map(method -> "<tr>\n" +
"<td>" + outputChangeStatus(method) + "</td>\n" +
"<td>" + modifiers(method) + "</td>\n" +
"<td>" + genericTemplates(method) + "</td>\n" +
"<td>" + returnType(method) + "</td>\n" +
"<td>" + method.getName() + "(" + parameters(method) + ")" + annotations(method.getAnnotations()) + "</td>\n" +
"<td>" + exceptions(method) + "</td>\n" +
"<td>" + compatibilityChanges(method, true) + "</td>\n" +
"<td>" +
loadAndFillTemplate("/html/line-numbers.html", mapOf(
"oldLineNumber", method.getOldLineNumberAsString(),
"newLineNumber", method.getNewLineNumberAsString())) + "</td>\n" +
"</tr>\n")
.collect(Collectors.joining());
}

private String returnType(JApiMethod method) {
return "<span class=\"method_return_type " + method.getReturnType().getChangeStatus().name().toLowerCase() + "\">" +
returnTypeValue(method.getReturnType()) +
"</span>";
}

private String returnTypeValue(JApiReturnType returnType) {
switch (returnType.getChangeStatus()) {
case NEW:
case UNCHANGED:
return returnType.getNewReturnType() + genericParameterTypes(returnType);
case REMOVED:
return returnType.getOldReturnType() + genericParameterTypes(returnType);
case MODIFIED:
return returnType.getNewReturnType() + "&#160;(&lt;-&#160;" + returnType.getOldReturnType() + genericParameterTypes(returnType);
}
return "";
}

private String constructors(JApiClass jApiClass) {
if (!jApiClass.getConstructors().isEmpty()) {
return loadAndFillTemplate("/html/constructors.html", mapOf(
Expand All @@ -90,7 +135,7 @@ private String constructors(List<JApiConstructor> constructors) {
"<td>" + genericTemplates(constructor) + "</td>\n" +
"<td>" + constructor.getName() + "(" + parameters(constructor) + ")" + annotations(constructor.getAnnotations()) + "</td>\n" +
"<td>" + exceptions(constructor) + "</td>\n" +
"<td>" + compatibilityChanges(constructor) + "</td>\n" +
"<td>" + compatibilityChanges(constructor, true) + "</td>\n" +
"<td>" +
loadAndFillTemplate("/html/line-numbers.html", mapOf(
"oldLineNumber", constructor.getOldLineNumberAsString(),
Expand All @@ -99,10 +144,10 @@ private String constructors(List<JApiConstructor> constructors) {
.collect(Collectors.joining());
}

private String exceptions(JApiConstructor constructor) {
if (!constructor.getExceptions().isEmpty()) {
private String exceptions(JApiBehavior jApiBehavior) {
if (!jApiBehavior.getExceptions().isEmpty()) {
return loadAndFillTemplate("/html/exceptions.html", mapOf(
"tbody", exceptionsTBody(constructor.getExceptions())
"tbody", exceptionsTBody(jApiBehavior.getExceptions())
));
}
return "";
Expand All @@ -117,8 +162,8 @@ private String exceptionsTBody(List<JApiException> exceptions) {
.collect(Collectors.joining());
}

private String parameters(JApiConstructor constructor) {
return constructor.getParameters().stream()
private String parameters(JApiBehavior jApiBehavior) {
return jApiBehavior.getParameters().stream()
.map(parameter -> "<span class=\"method_parameter " + parameter.getChangeStatus().name().toLowerCase() + "\">" +
parameter.getType() +
genericParameterTypes(parameter) +
Expand All @@ -138,12 +183,13 @@ private String fields(JApiClass jApiClass) {

private String fields(List<JApiField> fields) {
return fields.stream()
.sorted(Comparator.comparing(JApiField::getName))
.map(field -> "<tr>\n" +
"<td>" + outputChangeStatus(field) + "</td>\n" +
"<td>" + modifiers(field) + "</td>\n" +
"<td>" + type(field) + "</td>\n" +
"<td>" + field.getName() + annotations(field.getAnnotations()) + "</td>\n" +
"<td>" + compatibilityChanges(field) + "</td>\n" +
"<td>" + compatibilityChanges(field, true) + "</td>\n" +
"</tr>\n")
.collect(Collectors.joining());
}
Expand Down Expand Up @@ -179,6 +225,7 @@ private String annotations(List<JApiAnnotation> annotations) {

private String annotationsTBody(List<JApiAnnotation> annotations) {
return annotations.stream()
.sorted(Comparator.comparing(JApiAnnotation::getFullyQualifiedName))
.map(annotation -> "<tr>\n" +
"<td>" + outputChangeStatus(annotation) + "</td>\n" +
"<td>" + annotation.getFullyQualifiedName() + "</td>\n" +
Expand All @@ -204,11 +251,11 @@ private String annotationElements(List<JApiAnnotationElement> elements) {
"<td>" + element.getName() + "</td>\n" +
"<td>" + element.getOldElementValues().stream()
.map(this::valueToString)
.collect(Collectors.joining()) +
.collect(Collectors.joining(",<wbr/>")) +
"</td>\n" +
"<td>" + element.getNewElementValues().stream()
.map(this::valueToString)
.collect(Collectors.joining()) +
.collect(Collectors.joining(",<wbr/>")) +
"</td>\n" +
"</tr>\n")
.collect(Collectors.joining());
Expand Down Expand Up @@ -271,7 +318,7 @@ private String interfacesTBody(List<JApiImplementedInterface> interfaces) {
.map(interfaze -> "<tr>\n" +
"<td>" + outputChangeStatus(interfaze) + "</td>\n" +
"<td>" + interfaze.getFullyQualifiedName() + "</td>\n" +
"<td>" + compatibilityChanges(interfaze) + "</td>\n" +
"<td>" + compatibilityChanges(interfaze, true) + "</td>\n" +
"</tr>\n")
.collect(Collectors.joining());
}
Expand All @@ -296,7 +343,7 @@ private String superclassTBody(JApiSuperclass superclass) {
return "<tr>\n" +
"<td>" + outputChangeStatus(superclass) + "</td>\n" +
"<td>" + superclassName(superclass) + "</td>\n" +
"<td>" + compatibilityChanges(superclass) + "</td>\n" +
"<td>" + compatibilityChanges(superclass, true) + "</td>\n" +
"</tr>\n";
}

Expand Down Expand Up @@ -424,15 +471,15 @@ private String classFileFormatVersionString(int majorVersion, int minorVersion)
return "n.a.";
}

private String compatibilityChanges(JApiCompatibility jApiClass) {
private String compatibilityChanges(JApiCompatibility jApiClass, boolean withNA) {
if (!jApiClass.getCompatibilityChanges().isEmpty()) {
return loadAndFillTemplate("/html/compatibility-changes.html", mapOf(
"tbody", jApiClass.getCompatibilityChanges().stream()
.map(this::compatibilityChange)
.collect(Collectors.joining())
));
}
return "";
return withNA ? "n.a." : "";
}

private String compatibilityChange(JApiCompatibilityChange jApiCompatibilityChange) {
Expand Down Expand Up @@ -483,23 +530,13 @@ private String modifier(JApiModifier<? extends Enum<? extends Enum<?>>> jApiModi
return "";
}

private String javaObjectSerializationCompatibleClass(JApiClass jApiClass) {
if (jApiClass.getJavaObjectSerializationCompatible() == JApiJavaObjectSerializationCompatibility.JApiJavaObjectSerializationChangeStatus.NOT_SERIALIZABLE) {
return "";
} else if (jApiClass.getJavaObjectSerializationCompatible() == JApiJavaObjectSerializationCompatibility.JApiJavaObjectSerializationChangeStatus.SERIALIZABLE_COMPATIBLE) {
return "new";
} else {
return "removed";
}
}

private String javaObjectSerializationCompatible(JApiClass jApiClass) {
if (jApiClass.getJavaObjectSerializationCompatible() == JApiJavaObjectSerializationCompatibility.JApiJavaObjectSerializationChangeStatus.NOT_SERIALIZABLE) {
return "";
} else if (jApiClass.getJavaObjectSerializationCompatible() == JApiJavaObjectSerializationCompatibility.JApiJavaObjectSerializationChangeStatus.SERIALIZABLE_COMPATIBLE) {
return "&#160;(Serializable compatible)&#160;";
return "<span class=\"new\">&#160;(Serializable compatible)&#160;</span>";
} else {
return "&#160;(Serializable incompatible(!): " + jApiClass.getJavaObjectSerializationCompatibleAsString() + ")&#160;";
return "<span class=\"removed\">&#160;(Serializable incompatible(!): " + jApiClass.getJavaObjectSerializationCompatibleAsString() + ")&#160;</span>";
}
}

Expand Down
Loading

0 comments on commit d6c22ee

Please sign in to comment.