From e265667f253e6a15e61b11ac31453fac76170165 Mon Sep 17 00:00:00 2001 From: Andreas Penski <18-andreas.penski@users.noreply.projekte.kosit.org> Date: Mon, 10 Aug 2020 06:38:20 +0000 Subject: [PATCH] Resolve "Validator new feature: Pruefbericht Gesamtuebersicht bei Batch Verarbeitung" --- .idea/encodings.xml | 1 + CHANGELOG.md | 8 +- docs/api.md | 2 +- pom.xml | 14 +- .../api/CheckConfiguration.java | 2 +- .../cmd/CommandLineApplication.java | 16 +- .../cmd/DefaultNamingStrategy.java | 2 +- .../validationtool/cmd/InternalCheck.java | 73 +++- .../validationtool/cmd/PrintReportAction.java | 8 +- .../validationtool/cmd/report/Format.java | 84 +++++ .../kosit/validationtool/cmd/report/Grid.java | 320 ++++++++++++++++++ .../validationtool/cmd/report/Justify.java | 35 ++ .../kosit/validationtool/cmd/report/Line.java | 106 ++++++ .../kosit/validationtool/cmd/report/Text.java | 63 ++++ .../validationtool/daemon/CheckHandler.java | 1 + .../validationtool/daemon/GuiHandler.java | 19 +- .../validationtool/daemon/HealthHandler.java | 8 +- .../validationtool/daemon/RoutingHandler.java | 14 +- .../impl/ClassPathResourceResolver.java | 3 +- .../impl/CollectingErrorEventHandler.java | 11 +- .../impl/ContentRepository.java | 2 +- .../impl/ConversionService.java | 2 +- .../impl/input/SourceInput.java | 12 +- .../impl/input/StreamHelper.java | 4 + .../validationtool/impl/model/BaseOutput.java | 6 +- .../impl/model/BaseXMLSyntaxError.java | 24 -- .../impl/tasks/SchemaValidationAction.java | 2 + .../xml/StrictRelativeResolvingStrategy.java | 11 +- .../validationtool/daemon/CheckHandlerIT.java | 34 +- .../validationtool/impl/DefaultCheckTest.java | 9 +- .../impl/SimpleScenarioCheckTest.java | 5 +- 31 files changed, 791 insertions(+), 110 deletions(-) create mode 100644 src/main/java/de/kosit/validationtool/cmd/report/Format.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/report/Grid.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/report/Justify.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/report/Line.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/report/Text.java diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 63fc954..893896a 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -5,6 +5,7 @@ + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d5e7c79..0c80cb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - `getFailedAsserts()` and `isSchematronValid()` in [DefaultResult.java](https://github.com/itplr-kosit/validator/blob/master/src/main/java/de/kosit/validationtool/impl/DefaultResult.java) do not reflect actual schematron validation result -- Processing aborts on schematron execution errors (e.g. errors within schematron logic). The validator now generates a report in such cases. +- processing aborts on schematron execution errors (e.g. errors within schematron logic). The validator now generates a report in such cases. - exception while resolving when using XSLT's `unparsed-text()` function within report generation +### Added +- [CLI] add summary report + ### Changed - engine info contains version number of the validator (configurations can output this in the report for maintainance puposes) -- Options to customize serialized report file names (cmdline only) via `--report-prefix` and `--report-postfix` +- options to customize serialized report file names (cmdline only) via `--report-prefix` and `--report-postfix` +- remove unused dependency Apache Commons HTTP ## 1.3.0 diff --git a/docs/api.md b/docs/api.md index e2bed19..7999743 100644 --- a/docs/api.md +++ b/docs/api.md @@ -41,7 +41,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import de.kosit.validationtool.api.Check; -import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.api.Result; diff --git a/pom.xml b/pom.xml index 0c7b6d3..e60b16a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - + 4.0.0 KoSIT XML Prüftool Implementierung @@ -76,6 +76,12 @@ 1.4 true + + org.fusesource.jansi + jansi + 1.18 + true + org.slf4j slf4j-simple @@ -129,12 +135,6 @@ 1.0.0 test - -org.apache.httpcomponents -httpclient - 4.5.8 - - diff --git a/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java b/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java index 10b3d56..dddf41a 100644 --- a/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java +++ b/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java @@ -36,7 +36,7 @@ import de.kosit.validationtool.impl.Scenario; * Zentrale Konfigration einer Prüf-Instanz. * * @author Andreas Penski - * @deprecated since 2.0 use {@link Configuration} instead + * @deprecated since 1.3.0 use {@link Configuration} instead */ @Getter @Setter diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java index 9705028..5421f71 100644 --- a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java +++ b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java @@ -28,7 +28,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -45,6 +48,7 @@ import lombok.extern.slf4j.Slf4j; import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.api.Result; import de.kosit.validationtool.cmd.assertions.Assertions; import de.kosit.validationtool.config.ConfigurationLoader; import de.kosit.validationtool.daemon.Daemon; @@ -58,6 +62,7 @@ import net.sf.saxon.s9api.Processor; * @author Andreas Penski */ @Slf4j +@SuppressWarnings("squid:S3725") // performance is not a problem here public class CommandLineApplication { private static final Option HELP = Option.builder("?").longOpt("help").argName("Help").desc("Displays this help").build(); @@ -247,16 +252,17 @@ public class CommandLineApplication { final Collection targets = determineTestTargets(cmd); start = System.currentTimeMillis(); + final Map results = new HashMap<>(); for (final Path p : targets) { final Input input = InputFactory.read(p); - check.checkInput(input); + results.put(p, check.checkInput(input)); } - final boolean result = check.printAndEvaluate(); + final boolean result = check.printAndEvaluate(results); log.info("Processing {} object(s) completed in {}ms", targets.size(), System.currentTimeMillis() - start); return result ? 0 : 1; } catch (final Exception e) { - e.printStackTrace(); + e.printStackTrace();// NOSONAR if (cmd.hasOption(DEBUG.getOpt())) { log.error(e.getMessage(), e); } else { @@ -327,8 +333,8 @@ public class CommandLineApplication { } private static Collection listDirectoryTargets(final Path d) { - try { - return Files.list(d).filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList()); + try ( final Stream stream = Files.list(d) ) { + return stream.filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList()); } catch (final IOException e) { throw new IllegalStateException("IOException while list directory content. Can not determine test targets.", e); } diff --git a/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java b/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java index b4ceeba..0debe17 100644 --- a/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java +++ b/src/main/java/de/kosit/validationtool/cmd/DefaultNamingStrategy.java @@ -25,7 +25,7 @@ public class DefaultNamingStrategy implements NamingStrategy { if (StringUtils.isEmpty(base)) { throw new IllegalArgumentException("Can not generate name based on null input"); } - final int index = base.lastIndexOf("."); + final int index = base.lastIndexOf('.'); final StringBuilder result = new StringBuilder(); if (isNotEmpty(this.prefix)) { result.append(this.prefix).append("-"); diff --git a/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java b/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java index 2a2c007..4933fdf 100644 --- a/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java +++ b/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java @@ -19,14 +19,28 @@ package de.kosit.validationtool.cmd; +import java.io.PrintWriter; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.Map; +import java.util.stream.Collectors; + +import org.fusesource.jansi.AnsiRenderer.Code; + import lombok.extern.slf4j.Slf4j; import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.Result; +import de.kosit.validationtool.api.XmlError; +import de.kosit.validationtool.cmd.report.Grid; +import de.kosit.validationtool.cmd.report.Grid.ColumnDefinition; +import de.kosit.validationtool.cmd.report.Justify; +import de.kosit.validationtool.cmd.report.Line; import de.kosit.validationtool.impl.DefaultCheck; import de.kosit.validationtool.impl.tasks.CheckAction; + /** * Simple Erweiterung der Klasse {@link DefaultCheck} um das Ergebnis der Assertion-Prüfung auszwerten und auszugeben. * Diese Klasse stellt keine fachlicher Erweiterung des eigentlichen Prüfvorganges dar! @@ -66,7 +80,11 @@ class InternalCheck extends DefaultCheck { return result; } - boolean printAndEvaluate() { + boolean printAndEvaluate(final Map results) { + final PrintWriter writer = new PrintWriter(System.out);// NOSONAR + writer.write(createResultGrid(results).render()); + writer.write(createStatusLine(results)); + writer.flush(); if (this.failedAssertions > 0) { log.error("Assertion check failed.\n\nAssertions run: {}, Assertions failed: {}\n", this.checkAssertions, this.failedAssertions); @@ -74,7 +92,58 @@ class InternalCheck extends DefaultCheck { log.info("Assertion check successful.\n\nAssertions run: {}, Assertions failed: {}\n", this.checkAssertions, this.failedAssertions); } - return this.failedAssertions == 0; + return this.failedAssertions == 0 && results.entrySet().stream().allMatch(e -> e.getValue().isAcceptable()); + } + + private static String createStatusLine(final Map results) { + final long acceptable = results.entrySet().stream().filter(e -> e.getValue().isAcceptable()).count(); + final long rejected = results.entrySet().stream().filter(e -> !e.getValue().isAcceptable()).count(); + final long errors = results.entrySet().stream().filter(e -> !e.getValue().isProcessingSuccessful()).count(); + final Line line = new Line(); + line.add(String.format("Validation of %s objects finished. ", results.size())); + line.add("Acceptable: ").add(acceptable, Code.GREEN); + line.add(" Rejected: ").add(rejected, Code.RED); + if (errors > 0) { + line.add(" Processing errors: ").add(errors, Code.RED); + } + return line.render(); + } + + private static Grid createResultGrid(final Map results) { + final Grid grid = new Grid( + //@formatter:off + new ColumnDefinition("filename", 60, 10, 1), + new ColumnDefinition("Schema", 7).justify(Justify.CENTER), + new ColumnDefinition("Schematron", 10).justify(Justify.CENTER), + new ColumnDefinition("Acceptance", 10, 5).justify(Justify.CENTER), + new ColumnDefinition("Error/Description", 60,20,3) + ); + //@formatter:on + results.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey().getFileName())).forEach(e -> { + final Result value = e.getValue(); + + final Code textcolor = value.isAcceptable() ? Code.GREEN : Code.RED; + grid.addCell(e.getKey().getFileName(), textcolor); + grid.addCell(value.isSchemaValid() ? "Y" : "N", textcolor); + grid.addCell(value.isSchematronValid() ? "Y" : "N", textcolor); + grid.addCell(value.getAcceptRecommendation(), textcolor); + grid.addCell(joinErrors(value)); + }); + return grid; + } + + private static String joinErrors(final Result value) { + final StringBuilder b = new StringBuilder(); + b.append(String.join(";", value.getProcessingErrors())); + if (value.getSchemaViolations() != null && !value.getSchemaViolations().isEmpty()) { + b.append(b.length() > 0 ? ";" : ""); + b.append(value.getSchemaViolations().stream().map(XmlError::getMessage).collect(Collectors.joining(";"))); + } + if (value.getSchematronResult() != null && !value.getSchematronResult().isEmpty()) { + b.append(b.length() > 0 ? ";" : ""); + b.append(value.getSchematronResult().stream().flatMap(e -> e.getMessages().stream()).collect(Collectors.joining(";"))); + } + return b.toString(); } } diff --git a/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java b/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java index 0659397..ba7c25b 100644 --- a/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java +++ b/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java @@ -42,13 +42,13 @@ class PrintReportAction implements CheckAction { private final Processor processor; @Override - public void check(Bag results) { + public void check(final Bag results) { try { final StringWriter writer = new StringWriter(); - final Serializer serializer = processor.newSerializer(writer); + final Serializer serializer = this.processor.newSerializer(writer); serializer.serializeNode(results.getReport()); - System.out.print(writer.toString()); - } catch (SaxonApiException e) { + System.out.print(writer.toString()); // NOSONAR + } catch (final SaxonApiException e) { log.error("Error while printing result to stdout", e); } } diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Format.java b/src/main/java/de/kosit/validationtool/cmd/report/Format.java new file mode 100644 index 0000000..58b3dfa --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/report/Format.java @@ -0,0 +1,84 @@ +package de.kosit.validationtool.cmd.report; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.fusesource.jansi.AnsiRenderer.Code; + +import lombok.Getter; + +/** + * Simple value holder for ansi formatting codes. + * + * @author Andreas Penski + */ +@Getter +public class Format { + + private Code textColor; + + private Code background; + + @Getter + private final Set codes = new HashSet<>(); + + public Code[] mergeCodes(final Collection newCodes) { + return mergeCodes(newCodes.toArray(new Code[newCodes.size()])); + } + + public Code[] mergeCodes(final Code... newCodes) { + final Code[] allCodes = ArrayUtils.addAll(ArrayUtils.addAll(this.codes.toArray(new Code[0]), newCodes), this.textColor, + this.background); + + final Optional color = Arrays.stream(allCodes).filter(Objects::nonNull).filter(Code::isColor).findFirst(); + final Optional bg = Arrays.stream(allCodes).filter(Objects::nonNull).filter(Code::isBackground).findFirst(); + final List attributes = Arrays.stream(allCodes).filter(Objects::nonNull).filter(Code::isBackground).filter(Code::isColor) + .collect(Collectors.toList()); + attributes.add(color.orElse(this.textColor)); + attributes.add(bg.orElse(this.background)); + return attributes.stream().filter(Objects::nonNull).toArray(Code[]::new); + } + + /** + * Sets explicit text color. + * + * @param textColor the color. + * + * @return this {@link Format} + */ + public Format color(final Code textColor) { + this.textColor = textColor; + return this; + } + + /** + * Sets explicit background color. + * + * @param color the color. + * + * @return this {@link Format} + */ + public Format background(final Code color) { + this.background = color; + return this; + } + + /** + * Fügt weitere Formatierungscodes hinzu. + * + * @param codes die Codes + * + * @return this {@link Format} + */ + public Format addCodes(final Code... codes) { + this.codes.addAll(Arrays.asList(codes)); + return this; + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Grid.java b/src/main/java/de/kosit/validationtool/cmd/report/Grid.java new file mode 100644 index 0000000..f96b7ef --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/report/Grid.java @@ -0,0 +1,320 @@ +package de.kosit.validationtool.cmd.report; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.apache.commons.lang3.StringUtils; +import org.fusesource.jansi.AnsiRenderer.Code; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * An text based grid for cli based programs. + * + * @author Andreas Penski + */ +public class Grid { + + /** + * A definition / configuration for a column with a result table. + */ + @Getter + public static class ColumnDefinition { + + private static final int MAX_LENGTH = 80; + + private final String name; + + private int length = 0; + + private final int maxLength; + + private final int minLength; + + private final int maxLines; + + private Justify justify = Justify.LEFT; + + /** + * Constructor. + * + * @param name the name of the column + */ + public ColumnDefinition(final String name) { + this(name, -1, -1, 1); + } + + /** + * Constructor. + * + * @param name the name of the column + * @param maxLength the max length of the column + */ + public ColumnDefinition(final String name, final int maxLength) { + this(name, maxLength, -1, 1); + } + + /** + * Constructor. + * + * @param name the name of the column + * @param maxLength the max length of the column + */ + public ColumnDefinition(final String name, final int maxLength, final int minLength) { + this(name, maxLength, minLength, 1); + } + + /** + * Constructor. + * + * @param name the name of the column + * @param minLength the max length of the column + * @param maxLines the max lines per cell + */ + public ColumnDefinition(final String name, final int maxLength, final int minLength, final int maxLines) { + this.name = name; + this.maxLength = maxLength; + this.minLength = minLength; + this.maxLines = maxLines; + } + + /** + * Returns the actual max length of the column + * + * @return max length + */ + public int getLength() { + if (this.minLength > 0 && this.minLength > this.length) { + return this.minLength; + } + if (this.maxLength > 0 && this.length > this.maxLength) { + return this.maxLength; + } + return this.length; + } + + /** + * Sets a calculated length for the column. + * + * @param length the length + */ + public void setLength(final int length) { + if (length > this.length) { + this.length = length; + } + if (length > MAX_LENGTH) { + this.length = MAX_LENGTH; + } + } + + public ColumnDefinition justify(final Justify justify) { + this.justify = justify; + return this; + } + } + + @RequiredArgsConstructor + @Getter + private static class Cell { + + private final Format format = DEFAULT_FORMAT; + + private final List text; + + public Cell(final Text txt) { + this.text = new ArrayList<>(); + this.text.add(txt); + } + + public Cell(final Object object, final Code... codes) { + this(new Text(object, codes)); + } + + protected Line getFormattedLine(final int lineNumber, final ColumnDefinition def) { + final Line line = new Line(); + int startSubstring = lineNumber * def.getLength(); + int currentVisibleLength = 0; + for (final Text t : this.text) { + final String part = t.getVisibleText(startSubstring, def.getLength()); + currentVisibleLength += part.length(); + if (StringUtils.isNotBlank(part)) { + line.add(part, t.getFormat()); + if (currentVisibleLength >= def.getLength()) { + break; + } + startSubstring = 0; + } else { + startSubstring = startSubstring - t.getLength(); + } + } + return line; + } + + protected List getFormattedLines(final ColumnDefinition def) { + int count = 0; + Line line; + final List lines = new ArrayList<>(); + while ((line = getFormattedLine(count++, def)).isNotEmpty()) { + lines.add(line); + } + return lines; + } + + public String render(final int row, final ColumnDefinition def) { + final List test = getFormattedLines(def); + final Line line = test.size() > row ? test.get(row) : null; + if (line != null) { + return def.getJustify().apply(line.render(false, row == def.getMaxLines() - 1 && test.size() > def.getMaxLines()), + def.getLength() + (line.getLength() - line.getVisibleLength())); + } + return def.getJustify().apply("", def.getLength()); + + } + + public Cell add(final Object object, final Code... codes) { + this.text.add(new Text(object, codes)); + return this; + } + + + + } + + private static final Format DEFAULT_FORMAT = new Format(); + + /** + * A grid / table for printing results. + */ + + private final List definitions = new ArrayList<>(); + + private final List values = new ArrayList<>(); + + /** + * Constructor. + * + * @param def {@link ColumnDefinition}s + */ + public Grid(final ColumnDefinition... def) { + Stream.of(def).forEach(this::addColumn); + } + + private String generateGridStart() { + return IntStream.range(0, getLineLength() + this.definitions.size()).mapToObj(i -> "-").collect(Collectors.joining("")) + "\n"; + } + + private String generateGridEnd() { + return IntStream.range(0, getLineLength() + this.definitions.size()).mapToObj(i -> "-").collect(Collectors.joining("")) + "\n"; + } + + private String generateHeader() { + return "|" + this.definitions.stream().map(d -> StringUtils.rightPad(d.getName(), d.getLength())).collect(Collectors.joining("|")) + + "|\n"; + } + + /** + * Adds new a column definition. + * + * @param def definitions + * @return this grid + */ + public Grid addColumn(final ColumnDefinition def) { + this.definitions.add(def); + return this; + } + + private void calculateLength() { + IntStream.range(0, this.definitions.size()).forEach(i -> { + final ColumnDefinition def = this.definitions.get(i); + final List column = getColumn(i); + final int maxLength = column.stream().mapToInt(cell -> cell.getText().stream().mapToInt(Text::getLength).sum()).max().orElse(0); + def.setLength(Math.max(maxLength, def.getName().length())); + + }); + } + + public List getColumn(final int index) { + + return IntStream.range(0, this.values.size()).filter(n -> n % this.definitions.size() == index).mapToObj(this.values::get) + .collect(Collectors.toList()); + } + + public Grid addCell(final Cell cell) { + this.values.add(cell); + return this; + } + + public Grid addCell(final Text... text) { + return addCell(new Cell(Arrays.asList(text))); + } + + public Grid addCell(final Object cell, final Code... codes) { + final Format f = new Format(); + f.addCodes(codes); + final Text t = new Text(cell, f); + return addCell(new Cell(t)); + } + + public Grid addCell(final Object cell) { + return addCell(cell, DEFAULT_FORMAT.getTextColor()); + } + + private Collection> prepareLines() { + final AtomicInteger counter = new AtomicInteger(); + final int chunkSize = this.definitions.size(); + return this.values.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values(); + } + + public String render() { + final StringBuilder b = new StringBuilder(); + calculateLength(); + b.append(generateGridStart()); + b.append(generateHeader()); + prepareLines().forEach(line -> b.append(printLine(line))); + + b.append(generateGridEnd()); + return b.toString(); + } + + private String printLine(final List line) { + final StringBuilder b = new StringBuilder(); + int virtualLine = 0; + while (true) { + final StringBuilder current = new StringBuilder(); + final int bound = this.definitions.size(); + for (int i = 0; i < bound; i++) { + final ColumnDefinition def = this.definitions.get(i); + current.append("|"); + current.append(line.get(i).render(virtualLine, def)); + } + current.append("|"); + if (isEmpty(current) || virtualLine >= getMaxVirtualLine()) { + break; + } + b.append(current.toString()); + virtualLine++; + b.append("\n"); + } + return b.toString(); + + } + + private static boolean isEmpty(final StringBuilder current) { + return current.toString().replaceAll("\\|", "").trim().length() == 0; + } + + private int getMaxVirtualLine() { + return this.definitions.stream().mapToInt(ColumnDefinition::getMaxLines).max().orElseThrow(IllegalAccessError::new); + } + + private int getLineLength() { + return this.definitions.stream().map(ColumnDefinition::getLength).reduce(0, Integer::sum); + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Justify.java b/src/main/java/de/kosit/validationtool/cmd/report/Justify.java new file mode 100644 index 0000000..8a238be --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/report/Justify.java @@ -0,0 +1,35 @@ +package de.kosit.validationtool.cmd.report; + +import org.apache.commons.lang3.StringUtils; + +/** + * Justification modes for the text in grid columns. + * + * @author Andreas Penski + */ +public enum Justify { + + LEFT { + + @Override + public String apply(final String string, final int length) { + return StringUtils.rightPad(string, length); + } + }, + CENTER { + + @Override + public String apply(final String string, final int length) { + return StringUtils.center(string, length); + } + }, + RIGHT { + + @Override + public String apply(final String string, final int length) { + return StringUtils.leftPad(string, length); + } + }; + + public abstract String apply(String string, int length); +} diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Line.java b/src/main/java/de/kosit/validationtool/cmd/report/Line.java new file mode 100644 index 0000000..9cf0fa3 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/report/Line.java @@ -0,0 +1,106 @@ +package de.kosit.validationtool.cmd.report; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.fusesource.jansi.AnsiRenderer.Code; + +import lombok.NoArgsConstructor; + +/** + * Helper for printing a colored lines (with newline at the end) to the console. + */ +@NoArgsConstructor +public class Line { + + private final List texts = new ArrayList<>(); + + private Format baseFormat = new Format(); + + /** + * Constructor. + * + * @param format the configured base format + */ + public Line(final Format format) { + this.baseFormat = format; + } + + /** + * Constructor. + * + * @param codes Ansi escape codes for formatting + */ + public Line(final Code... codes) { + this(new Format().addCodes(codes)); + } + + /** + * Add some text to the line. + * + * @param text the text + * @return this line + */ + public Line add(final Text text) { + this.texts.add(text); + return this; + } + + public Line add(final Object t) { + return add(new Text(t)); + } + + public Line add(final Object text, final Code... codes) { + return add(new Text(text, codes)); + } + + public Line add(final Object text, final Format format) { + return add(new Text(text, format)); + } + + public String render() { + return render(true, false); + } + + String render(final boolean newLine, final boolean dotted) { + final List joins = new ArrayList<>(); + final List reversed = new ArrayList<>(this.texts); + int replace = 0; + Collections.reverse(reversed); + if (dotted && getVisibleLength() > replace) { + replace = 3; + } + for (final Text t : reversed) { + if (replace > 0) { + final String render = t.render(t.getVisibleText(0, t.getVisibleLength() - replace), this.baseFormat); + if (StringUtils.isNotEmpty(render)) { + joins.add(render); + } + replace = replace - t.getVisibleLength(); + } else { + joins.add(t.render(this.baseFormat)); + } + + } + Collections.reverse(joins); + return String.join(" ", joins) + (dotted ? "..." : "") + (newLine ? "\n" : ""); + } + + public int getLength() { + return this.texts.stream().mapToInt(Text::getLength).sum(); + } + + public static String render(final String text, final Code... codes) { + return new Line().add(text, codes).render(); + } + + public boolean isNotEmpty() { + return !this.texts.isEmpty(); + } + + public int getVisibleLength() { + return this.texts.stream().mapToInt(Text::getVisibleLength).sum(); + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/report/Text.java b/src/main/java/de/kosit/validationtool/cmd/report/Text.java new file mode 100644 index 0000000..4456c8d --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/report/Text.java @@ -0,0 +1,63 @@ +package de.kosit.validationtool.cmd.report; + +import java.util.Arrays; + +import org.fusesource.jansi.AnsiRenderer; +import org.fusesource.jansi.AnsiRenderer.Code; + +import lombok.Getter; + +/** + * Ansi formatted text for outputting to the console. + * + * @author Andreas Penski + */ +@Getter +public class Text { + + private final String value; + + private Format format; + + public Text(final Object value) { + this.value = value != null ? value.toString() : ""; + this.format = new Format(); + } + + public Text(final Object value, final Format format) { + this(value); + this.format = format; + } + + public Text(final Object value, final Code... codes) { + this(value, new Format().addCodes(codes)); + } + + public String getVisibleText(final int startIndex, final int length) { + if (startIndex < 0) { + return "Wrong cell text index"; + } + if (startIndex > this.value.length()) { + return ""; + } + final String substring = this.value.substring(startIndex); + return substring.length() > length ? substring.substring(0, length) : substring; + } + + public String render(final String text, final Format baseformat) { + return AnsiRenderer.render(text, + Arrays.stream(this.format.mergeCodes(baseformat.getCodes())).map(Code::name).toArray(String[]::new)); + } + + public int getLength() { + return render(this.format).length(); + } + + public String render(final Format baseFormat) { + return render(getValue(), baseFormat); + } + + public int getVisibleLength() { + return this.value.length(); + } +} diff --git a/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java b/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java index 1476d8c..29e0d62 100644 --- a/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java +++ b/src/main/java/de/kosit/validationtool/daemon/CheckHandler.java @@ -44,6 +44,7 @@ class CheckHandler extends BaseHandler { try { log.debug("Incoming request"); final String requestMethod = httpExchange.getRequestMethod(); + // check neccessary, since gui can be disabled if (requestMethod.equals("POST")) { final InputStream inputStream = httpExchange.getRequestBody(); if (inputStream.available() > 0) { diff --git a/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java b/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java index 972daf8..8dce9fe 100644 --- a/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java +++ b/src/main/java/de/kosit/validationtool/daemon/GuiHandler.java @@ -1,15 +1,17 @@ package de.kosit.validationtool.daemon; -import com.sun.net.httpserver.HttpExchange; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.apache.commons.io.IOUtils; - import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.util.Arrays; +import org.apache.commons.io.IOUtils; + +import com.sun.net.httpserver.HttpExchange; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + public class GuiHandler extends BaseHandler { private static final URL INDEX_HTML = GuiHandler.class.getClassLoader().getResource("gui/index.html"); @@ -21,7 +23,7 @@ public class GuiHandler extends BaseHandler { } @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(final HttpExchange exchange) throws IOException { assert INDEX_HTML != null; final String path = exchange.getRequestURI().toASCIIString(); if (path.equals("/")) { @@ -29,7 +31,8 @@ public class GuiHandler extends BaseHandler { } else{ final URL resource = GuiHandler.class.getClassLoader().getResource("gui" + path); if (resource != null) { - write(exchange,IOUtils.toString(resource, Charset.defaultCharset()).getBytes(), Mediatype.resolveBySuffix(resource.getPath()).getMimeType());; + write(exchange, IOUtils.toString(resource, Charset.defaultCharset()).getBytes(), + Mediatype.resolveBySuffix(resource.getPath()).getMimeType()); }else { error(exchange,404,"not found"); } @@ -45,7 +48,7 @@ public class GuiHandler extends BaseHandler { CSS("text/css"); private final String mimeType; - static Mediatype resolveBySuffix(String path){ + static Mediatype resolveBySuffix(final String path) { return Arrays.stream(values()).filter(e->path.toUpperCase().endsWith("."+e.name())).findFirst().orElse(Mediatype.MD); } } diff --git a/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java b/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java index de7e40f..3ca8ca6 100644 --- a/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java +++ b/src/main/java/de/kosit/validationtool/daemon/HealthHandler.java @@ -4,13 +4,13 @@ import java.io.IOException; import com.sun.net.httpserver.HttpExchange; -import de.kosit.validationtool.impl.EngineInformation; -import de.kosit.validationtool.model.daemon.ApplicationType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.impl.ConversionService; +import de.kosit.validationtool.impl.EngineInformation; +import de.kosit.validationtool.model.daemon.ApplicationType; import de.kosit.validationtool.model.daemon.HealthType; import de.kosit.validationtool.model.daemon.MemoryType; @@ -39,7 +39,7 @@ class HealthHandler extends BaseHandler { final HealthType h = new HealthType(); h.setMemory(createMemory()); h.setApplication(createApplication()); - h.setStatus(scenarios.getScenarios().size() > 0 ? "UP" : "DOWN"); + h.setStatus(!this.scenarios.getScenarios().isEmpty() ? "UP" : "DOWN"); return h; } @@ -53,7 +53,7 @@ class HealthHandler extends BaseHandler { } private static ApplicationType createApplication() { - ApplicationType a = new ApplicationType(); + final ApplicationType a = new ApplicationType(); a.setBuild(EngineInformation.getBuild()); a.setName(EngineInformation.getName()); a.setVersion(EngineInformation.getVersion()); diff --git a/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java b/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java index d15a39c..6a79457 100644 --- a/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java +++ b/src/main/java/de/kosit/validationtool/daemon/RoutingHandler.java @@ -1,11 +1,11 @@ package de.kosit.validationtool.daemon; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import lombok.RequiredArgsConstructor; - import java.io.IOException; +import com.sun.net.httpserver.HttpExchange; + +import lombok.RequiredArgsConstructor; + /** * A simple handler which routes between the {@link CheckHandler} and the {@link GuiHandler} depending on the request. */ @@ -17,12 +17,12 @@ class RoutingHandler extends BaseHandler { private final GuiHandler guiHandler; @Override - public void handle(HttpExchange exchange) throws IOException { + public void handle(final HttpExchange exchange) throws IOException { final String requestMethod = exchange.getRequestMethod(); if (requestMethod.equals("POST")) { - checkHandler.handle(exchange); + this.checkHandler.handle(exchange); } else if (requestMethod.equals("GET")) { - guiHandler.handle(exchange); + this.guiHandler.handle(exchange); } else { error(exchange, 405, String.format("Method % not supported", requestMethod)); } diff --git a/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java b/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java index 46ff31f..f97bbc8 100644 --- a/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java +++ b/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java @@ -114,8 +114,9 @@ class ClassPathResourceResolver implements LSResourceResolver { try { final URL resource = resolved.isAbsolute() ? resolved.toURL() : ClassPathResourceResolver.class.getResource(resolved.toASCIIString()); - final InputStream in = resource.openStream(); final LSInputImpl input = new LSInputImpl(publicId, systemId, resolved.toASCIIString()); + // intentionally not closed, since xml stack wants it open upon return + final InputStream in = resource.openStream(); input.setByteStream(in); return input; diff --git a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java index b1daca8..af02d6d 100644 --- a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java +++ b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java @@ -51,9 +51,9 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro private static final int DEFAULT_ABORT_COUNT = 50; - private final Collection errors = new ArrayList<>(); + private static final int stopProcessCount = DEFAULT_ABORT_COUNT; - private final int stopProcessCount = DEFAULT_ABORT_COUNT; + private final Collection errors = new ArrayList<>(); private static XMLSyntaxError createError(final XMLSyntaxErrorSeverity severity, final String message) { final XMLSyntaxError e = new XMLSyntaxError(); @@ -97,7 +97,7 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro e.setColumnNumber(event.getLocator().getColumnNumber()); e.setRowNumber(event.getLocator().getLineNumber()); this.errors.add(e); - return this.stopProcessCount != this.errors.size(); + return stopProcessCount != this.errors.size(); } /** @@ -161,9 +161,8 @@ public class CollectingErrorEventHandler implements ValidationEventHandler, Erro public String getErrorDescription() { final StringJoiner joiner = new StringJoiner("\n"); - this.errors.forEach(e -> joiner - .add(e.getSeverityCode().value() + " " + e.getMessage() + " At row " + e.getRowNumber() + " at pos " - + e.getColumnNumber())); + this.errors.forEach(e -> joiner.add( + e.getSeverityCode().value() + " " + e.getMessage() + " At row " + e.getRowNumber() + " at pos " + e.getColumnNumber())); return joiner.toString(); } } \ No newline at end of file diff --git a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java index 33a8388..84cd418 100644 --- a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java +++ b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java @@ -101,7 +101,7 @@ public class ContentRepository { this.schemaFactory = this.resolvingConfigurationStrategy.createSchemaFactory(); } - @SuppressWarnings("java:S2095") + @SuppressWarnings("squid:S2095") private static Source resolve(final URL resource) { try { return new StreamSource(resource.openStream(), resource.toURI().getRawPath()); diff --git a/src/main/java/de/kosit/validationtool/impl/ConversionService.java b/src/main/java/de/kosit/validationtool/impl/ConversionService.java index 0fc6cd0..5a362bf 100644 --- a/src/main/java/de/kosit/validationtool/impl/ConversionService.java +++ b/src/main/java/de/kosit/validationtool/impl/ConversionService.java @@ -131,7 +131,7 @@ public class ConversionService { public void initialize(final Collection context) { final String[] packages = context != null ? context.stream().map(Package::getName).toArray(String[]::new) : new String[0]; final StringJoiner joiner = new StringJoiner(":"); - Arrays.stream(packages).forEach(p -> joiner.add(p)); + Arrays.stream(packages).forEach(joiner::add); initialize(joiner.toString()); } diff --git a/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java b/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java index cb9f929..5cd7753 100644 --- a/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java +++ b/src/main/java/de/kosit/validationtool/impl/input/SourceInput.java @@ -52,7 +52,7 @@ public class SourceInput extends AbstractInput { } private void validate() { - if (!isHashcodeComputed() && !isSupported()) { + if (!isHashcodeComputed() && isNotSupported()) { throw new IllegalStateException("Unsupported source. Only StreamSource supported yet"); } if (!isHashcodeComputed() && ((StreamSource) this.source).getInputStream() == null) { @@ -62,7 +62,7 @@ public class SourceInput extends AbstractInput { @Override public Source getSource() throws IOException { - if (!isHashcodeComputed() && !isSupported()) { + if (!isHashcodeComputed() && isNotSupported()) { throw new IllegalStateException("Unsupported source. Only InputStream-based StreamSource supported yet"); } if (isConsumed()) { @@ -71,8 +71,8 @@ public class SourceInput extends AbstractInput { return isHashcodeComputed() ? this.source : wrappedSource(); } - private boolean isSupported() { - return isStreamSource(); + private boolean isNotSupported() { + return !isStreamSource(); } private boolean isConsumed() throws IOException { @@ -107,9 +107,7 @@ public class SourceInput extends AbstractInput { return result; } - private boolean isWrappingRequired() { - return !isHashcodeComputed(); - } + @Override public boolean supportsMultipleReads() { diff --git a/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java b/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java index bd8de8a..ad94155 100644 --- a/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java +++ b/src/main/java/de/kosit/validationtool/impl/input/StreamHelper.java @@ -24,6 +24,7 @@ public class StreamHelper { * Helper class, which generates the hashcode while reading the stream e.g. for parsing the document. This allows * generating the hashcode without an aditional reading step. */ + @SuppressWarnings("squid:S4929") // efficient read is done by internally used stream private static class DigestingInputStream extends FilterInputStream { private final MessageDigest digest; @@ -44,6 +45,7 @@ public class StreamHelper { } + @SuppressWarnings("squid:S4929") // efficient read is done by internally used stream private static class CountInputStream extends FilterInputStream { private final LazyReadInput reference; @@ -123,10 +125,12 @@ public class StreamHelper { * @param input the input * @throws IOException on I/O errors */ + @SuppressWarnings("squid:S1854") public static void drain(final InputStream input) throws IOException { final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int n; + while (EOF != (n = input.read(buffer))) { // nothing } diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java b/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java index b6a670b..36c4179 100644 --- a/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java +++ b/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java @@ -43,7 +43,7 @@ public abstract class BaseOutput { * @return true wenn mindestens ein {@link FailedAssert} vorhanden ist */ public boolean hasFailedAsserts() { - return getFailedAsserts().size() > 0; + return !getFailedAsserts().isEmpty(); } /** @@ -69,4 +69,8 @@ public abstract class BaseOutput { return getFailedAsserts().stream().filter(e -> e.getId().equals(name)).findAny(); } + public List getMessages() { + return getFailedAsserts().stream().map(FailedAssert::getText).flatMap(e -> e.getContent().stream()).map(Object::toString) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java b/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java index ed4e188..957952c 100644 --- a/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java +++ b/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java @@ -53,30 +53,6 @@ public abstract class BaseXMLSyntaxError implements XmlError { return String.format("%s At row %s at pos %s", getMessage(), getRowNumber(), getColumnNumber()); } - /** - * Getter aus dem schema - * - * @return Spalte des Fehlers - */ - @Override - public abstract Integer getColumnNumber(); - - /** - * Getter aus dem schema - * - * @return Zeile des Fehlers - */ - @Override - public abstract Integer getRowNumber(); - - /** - * Getter aus dem schema - * - * @return Fehlermeldung - */ - @Override - public abstract String getMessage(); - /** * Getter aus dem schema * diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java index a2396c8..22cca81 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java @@ -191,9 +191,11 @@ public class SchemaValidationAction implements CheckAction { } + @SuppressWarnings("squid:S2095") // intentionally return open stream/autoclosable here private SerializedDocument serialize(final Input input, final XdmNode object) throws IOException, SaxonApiException { final SerializedDocument doc; if (input instanceof AbstractInput && ((AbstractInput) input).getLength() < getInMemoryLimit()) { + doc = new ByteArraySerializedDocument(this.processor); } else { doc = new FileSerializedDocument(this.processor); diff --git a/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java b/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java index f88229a..3f5f375 100644 --- a/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java +++ b/src/main/java/de/kosit/validationtool/impl/xml/StrictRelativeResolvingStrategy.java @@ -70,6 +70,7 @@ public class StrictRelativeResolvingStrategy extends BaseResolvingStrategy { @Override public SchemaFactory createSchemaFactory() { + forceOpenJdkXmlImplementation(); final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); disableExternalEntities(sf); allowExternalSchema(sf, "file"); @@ -82,7 +83,7 @@ public class StrictRelativeResolvingStrategy extends BaseResolvingStrategy { // verhindere global im Prinzip alle resolving strategien final SecureUriResolver resolver = new SecureUriResolver(); processor.getUnderlyingConfiguration().setCollectionFinder(resolver); - processor.getUnderlyingConfiguration().setOutputURIResolver(resolver); + processor.getUnderlyingConfiguration().setOutputURIResolver(resolver);// NOSONAR processor.getUnderlyingConfiguration().setUnparsedTextURIResolver(resolver); // grundsätzlich Feature-konfiguration: @@ -92,10 +93,10 @@ public class StrictRelativeResolvingStrategy extends BaseResolvingStrategy { processor.setConfigurationProperty(Feature.ALLOW_EXTERNAL_FUNCTIONS, false); // Konfiguration des zu verwendenden Parsers, wenn Saxon selbst einen erzeugen muss, bspw. beim XSL parsen - processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(FEATURE_SECURE_PROCESSING), true); - processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(DISSALLOW_DOCTYPE_DECL_FEATURE), true); - processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(LOAD_EXTERNAL_DTD_FEATURE), false); - processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(XMLConstants.ACCESS_EXTERNAL_DTD), false); + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(FEATURE_SECURE_PROCESSING), true); // NOSONAR + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(DISSALLOW_DOCTYPE_DECL_FEATURE), true);// NOSONAR + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(LOAD_EXTERNAL_DTD_FEATURE), false);// NOSONAR + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(XMLConstants.ACCESS_EXTERNAL_DTD), false);// NOSONAR return processor; } diff --git a/src/test/java/de/kosit/validationtool/daemon/CheckHandlerIT.java b/src/test/java/de/kosit/validationtool/daemon/CheckHandlerIT.java index 0642137..4664422 100644 --- a/src/test/java/de/kosit/validationtool/daemon/CheckHandlerIT.java +++ b/src/test/java/de/kosit/validationtool/daemon/CheckHandlerIT.java @@ -1,17 +1,20 @@ package de.kosit.validationtool.daemon; import static io.restassured.RestAssured.given; +import static org.apache.http.HttpStatus.SC_OK; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; -import org.junit.Ignore; +import org.apache.http.HttpStatus; import org.junit.Test; import de.kosit.validationtool.impl.Helper.Simple; +import io.restassured.builder.MultiPartSpecBuilder; import io.restassured.http.ContentType; +import io.restassured.specification.MultiPartSpecification; /** * Testet the Daemon-Mode input , Methoden , Output Content-Type and the success case @@ -24,22 +27,21 @@ public class CheckHandlerIT extends BaseIT { private static final String APPLICATION_XML = "application/xml"; @Test - public void makeSureThatSuccessTest() throws IOException { + public void simpleTest() throws IOException { try ( final InputStream io = Simple.SIMPLE_VALID.toURL().openStream() ) { - given().contentType(ContentType.XML).body(toContent(io)).when().post("/").then().statusCode(200); + given().contentType(ContentType.XML).body(toContent(io)).when().post("/").then().statusCode(SC_OK); } } @Test - public void NoInputTest() { - given().body("").contentType(APPLICATION_XML).when().post("/").then().statusCode(400); + public void noInputTest() { + given().body("").contentType(APPLICATION_XML).when().post("/").then().statusCode(HttpStatus.SC_BAD_REQUEST); } @Test - @Ignore // no default error report yet - public void internalServerErrorTest() throws IOException { - try ( final InputStream io = Simple.SCHEMA_INVALID.toURL().openStream() ) { - given().contentType(APPLICATION_XML).body(toContent(io)).when().post("/").then().statusCode(200); + public void testUnknown() throws IOException { + try ( final InputStream io = Simple.UNKNOWN.toURL().openStream() ) { + given().contentType(APPLICATION_XML).body(toContent(io)).when().post("/").then().statusCode(SC_OK); } } @@ -47,13 +49,19 @@ public class CheckHandlerIT extends BaseIT { return IOUtils.toByteArray(io); } - - @Test public void xmlResultTest() throws IOException { - try ( final InputStream io = Simple.SIMPLE_VALID.toURL().openStream() ) { - given().body(toContent(io)).when().post("/").then().contentType(APPLICATION_XML).and().statusCode(200); + given().body(toContent(io)).when().post("/").then().contentType(APPLICATION_XML).and().statusCode(SC_OK); } } + + @Test + public void testMultipart() throws IOException { + try ( final InputStream io = Simple.SIMPLE_VALID.toURL().openStream() ) { + final MultiPartSpecification spec = new MultiPartSpecBuilder(io).fileName("file").controlName("file").build(); + given().multiPart(spec).when().post("/").then().statusCode(HttpStatus.SC_BAD_REQUEST); + } + } + } diff --git a/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java b/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java index d952e90..c3e5e1b 100644 --- a/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java +++ b/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java @@ -29,7 +29,6 @@ import static de.kosit.validationtool.impl.Helper.Simple.SIMPLE_VALID; import static de.kosit.validationtool.impl.Helper.Simple.UNKNOWN; import static org.assertj.core.api.Assertions.assertThat; -import java.io.File; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -39,7 +38,7 @@ import org.junit.Test; import org.w3c.dom.Document; import de.kosit.validationtool.api.AcceptRecommendation; -import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.Result; import de.kosit.validationtool.impl.Helper.Simple; @@ -60,12 +59,10 @@ public class DefaultCheckTest { @Before public void setup() { - final CheckConfiguration validConfig = new CheckConfiguration(Simple.SCENARIOS); - validConfig.setScenarioRepository(new File(Simple.REPOSITORY_URI).toURI()); + final Configuration validConfig = Configuration.load(Simple.SCENARIOS, Simple.REPOSITORY_URI).build(); this.validCheck = new DefaultCheck(validConfig); - final CheckConfiguration errorConfig = new CheckConfiguration(Simple.ERROR_SCENARIOS); - errorConfig.setScenarioRepository(new File(Simple.REPOSITORY_URI).toURI()); + final Configuration errorConfig = Configuration.load(Simple.ERROR_SCENARIOS, Simple.REPOSITORY_URI).build(); this.errorCheck = new DefaultCheck(errorConfig); } diff --git a/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheckTest.java b/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheckTest.java index b9b5de7..0ac2c9f 100644 --- a/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheckTest.java +++ b/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheckTest.java @@ -8,7 +8,7 @@ import org.junit.Before; import org.junit.Test; import de.kosit.validationtool.api.AcceptRecommendation; -import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.api.Result; import de.kosit.validationtool.impl.Helper.Simple; @@ -24,8 +24,7 @@ public class SimpleScenarioCheckTest { @Before public void setup() { - final CheckConfiguration d = new CheckConfiguration(Simple.SCENARIOS); - d.setScenarioRepository(Simple.REPOSITORY_URI); + final Configuration d = Configuration.load(Simple.SCENARIOS, Simple.REPOSITORY_URI).build(); this.implementation = new DefaultCheck(d); }