public static String alternateSpelling(final String current, final Collection<String> alternates) { return alternateSpelling(current, alternates, dynamicThreshold(current)); }
@Override public String asString(Object value) { final List<?> list = (List<?>)value; final List<String> values = list.stream() .map(Stringify::asString) .distinct() .limit(limit > 0 ? limit : list.size()) .collect(Collectors.toList()); final StringBuilder sb = new StringBuilder(); if (this.listThreshold == -1 || values.size() <= this.listThreshold) { sb.append(Util.asCommaString(values)).append(' '); } else { sb.append('\n'); if (this.asBulletList) { values.forEach(v -> sb.append("- ").append(v).append('\n')); } else { sb.append(Util.asColumns(values)); } } if (this.limit < list.size()) { sb.append(I18N.format(I18N.Key.AND_N_MORE, list.size() - limit)); } return sb.toString(); }
private void init(final ValidationContext ctx) { if (prefix.isEmpty()) { this.rootElement = Util.extractFirstElement(ctx.documentLines()); prefix.add(this.rootElement); if (this.rootElement.getLocalPart().equals("domain")) { prefix.add(new QName(this.rootElement.getNamespaceURI(), "profiles")); } prefix.add(new QName(this.rootElement.getNamespaceURI(), "profile")); final String uri = this.rootElement.getNamespaceURI(); if (this.rootElement.getLocalPart().equals("server")) { excludedRoots.add(new QName(uri, "domain")); excludedRoots.add(new QName(uri, "host")); } else if (this.rootElement.getLocalPart().equals("domain")) { excludedRoots.add(new QName(uri, "server")); excludedRoots.add(new QName(uri, "host")); } else { excludedRoots.add(new QName(uri, "domain")); excludedRoots.add(new QName(uri, "server")); } } }
public static String wrapAndIndentEachLine(final int width, final int indent, final String str) { return preserveFinalNewline(str, String.join("\n", Arrays.stream(str.split("\\n")) .map(l -> wrapLine(width, l)) .map(l -> indentLinesAfterFirst(indent, l)) .collect(Collectors.toList()))); }
public ValidationContext(final URL document, final List<URL> schemas) throws IOException { this.document = document; this.docWalker = new DocWalker(document); try (final BufferedReader reader = new BufferedReader(new InputStreamReader(document.openStream(), detectCharset(document)))) { this.lines = reader.lines().collect(Collectors.toList()); } final Set<String> xmlnses = Util.extractXMLNS(this.lines); for (URL url : schemas) { if (Util.providesXMLNS(xmlnses, url)) { this.schemas.add(url); } } }
public void print(ValidationError error) { final ErrorHandler.HandledResult res = this.context.handle(error); if (res != null) { final StringBuilder out = new StringBuilder() .append('\n') .append(divider(I18N.validationErrorIn(Util.documentName(this.docURL)))); formatResult(out, res); out.append(divider(1)) .append('\n'); this.printer.printlnErr(Util.withPrefixAfterNth(2, "|", out.toString())); } }
private void formatResult(final StringBuilder out, final ErrorHandler.HandledResult result) { final int linum = result.line(); final int maxLinumWidth = ("" + linum + CONTEXT_LINES).length(); final List<PrefixedLine> preambleLines = preambleLines(linum, maxLinumWidth); final List<PrefixedLine> postambleLines = postambleLines(linum, maxLinumWidth); final List<PrefixedLine> allLines = new ArrayList<>(); allLines.addAll(preambleLines); allLines.addAll(postambleLines); final int removeSpaces = smallestPrefixWhitespace(allLines); out.append('\n') .append(Util.withPrefix(" ", ambleString(preambleLines, removeSpaces))) .append(alignPointerMessage(maxLinumWidth + result.column() + 2 - removeSpaces, result.primaryMessages())) .append("\n") .append(Util.withPrefix(" ", ambleString(postambleLines, removeSpaces))); if (!result.secondaryMessages().isEmpty()) { result.secondaryMessages().forEach(m -> out.append("\n").append(Util.withPrefix(" ", m.toString())).append("\n")); } if (!result.secondaryResults().isEmpty()) { result.secondaryResults().forEach(r -> formatResult(out, r)); } else { out.append("\n"); } if (result.originalMessage() != null) { out.append(Util.withPrefix(" ", I18N.lookup(I18N.Key.ORIGINAL_ERROR))).append("\n") .append(Util.withPrefix(" > ", Util.indentLinesAfterNth(2, WRAPPED_LINE_INDENT, Util.wrapString(WRAPPED_LINE_WIDTH, result.originalMessage())))) .append("\n\n"); } }
public ErrorHandler.HandledResult handle(ValidationError error) { final ErrorHandler.HandledResult result = error.type().handler().handle(this, error); if (result.isPossiblyMalformed() && !this.docWalker.valid()) { @SuppressWarnings("ThrowableResultOfMethodCallIgnored") final SAXParseException ex = this.docWalker.validationFailure(); final ErrorHandler.HandledResult validationResult = new ErrorHandler.HandledResult(ex.getLineNumber(), ex.getColumnNumber(), null); validationResult.addPrimaryMessage(I18N.Key.PASSTHRU, Util.stripPeriod(ex.getLocalizedMessage())); result.addSecondaryMessage(I18N.Key.MALFORMED_XML, Util.documentName(this.document)); result.addSecondaryResult(validationResult); } return result; }
@Override public HandledResult handle(ValidationContext ctx, ValidationError error) { final String el = error.element().getLocalPart(); final Set<String> alts = error.alternatives(); final HandledResult result = HandledResult.from(error) .addPrimaryMessage(I18N.Key.ATTRIBUTE_REQUIRED_MISSING, el); if (!alts.isEmpty()) { final List<SchemaElement> path = ctx.mapDocLocationToSchemaPath(error.element(), error.position()); if (path.isEmpty()) { result.possiblyMalformed(true); } final Set<String> attributesForElement = ctx.attributesForElement(path); result.addPrimaryMessage(I18N.Key.ATTRIBUTE_REQUIRED_MISSING_LIST, Util.asSortedList(alts).stream() .map(String::toLowerCase) .map(Util.possiblyUnderscoredName(attributesForElement)) .collect(Collectors.toList())); } return result; } }
if (!schemaPath.isEmpty()) { otherElements = Util.asSortedList(ctx.elementsForElement(schemaPath).stream() .map(SchemaElement::name) .collect(Collectors.toList())); otherElements = Util.asSortedList(error.alternatives()); final String altSpelling = Util.alternateSpelling(elName, otherElements);
private String alignPointerMessage(final int length, final List<Message> msg) { if (msg.isEmpty()) { return String.format("%" + (length + POINTER.length()) + "s\n", POINTER); } // join all the messages together into one string, then split back out. This will handle individual messages that // contain \n final String[] lines = String.join("\n", msg.stream() .map(Object::toString) .map(s -> s + "\n") .map(line -> Util.wrapString(WRAPPED_LINE_WIDTH, line)) .map(line -> Util.indentLinesAfterFirst(WRAPPED_LINE_INDENT, line)) .collect(Collectors.toList())) .split("\n"); final StringBuilder sb = new StringBuilder(); sb.append(String.format("%" + (length + lines[0].length() + POINTER.length() + 1) + "s", POINTER + " " + lines[0])) .append('\n'); for (int i = 1; i < lines.length; i++) { sb.append(String.format("%" + (length + lines[i].length() + POINTER.length() + 1) + "s", lines[i])) .append('\n'); } return sb.toString(); }
printed = true; } else { printer().println(I18N.documentHasNoContent(Util.documentName(document)));
public static String indentLinesAfterFirst(final int indent, final String str) { return indentLinesAfterNth(1, indent, str); }
@Override public HandledResult handle(ValidationContext ctx, ValidationError error) { final String el = error.element().getLocalPart(); final Set<String> alts = error.alternatives(); final Location loc = error.location(); final Position pos = ctx.searchBackward(loc.getLineNumber() - 1, loc.getColumnNumber(), Pattern.compile(String.format("<%s[ >/]", el))); final HandledResult result = HandledResult.from(error) .addPrimaryMessage(this.primaryMessageKey, el); if (pos != null) { result.line(pos.line).column(pos.col); } if (!alts.isEmpty()) { final List<SchemaElement> path = ctx.mapDocLocationToSchemaPath(error.element(), error.position()); if (path.isEmpty()) { result.possiblyMalformed(true); } Set<String> otherElements = ctx.elementsForElement(path).stream() .map(SchemaElement::name) .collect(Collectors.toSet()); result.addPrimaryMessage(this.optionsMessageKey, Util.asSortedList(alts).stream() .map(String::toLowerCase) .map(Util.possiblyUnderscoredName(otherElements)) .collect(Collectors.toList())); } return result; }
otherAttributes = Util.asSortedList(ctx.attributesForElement(schemaPath)); } else { otherAttributes = Util.asSortedList(error.alternatives()); result.addPrimaryMessage(I18N.Key.ELEMENT_HAS_NO_ATTRIBUTES, el); } else { final String altSpelling = Util.alternateSpelling(attr, otherAttributes); if (altSpelling != null) { result.addPrimaryMessage(I18N.Key.DID_YOU_MEAN, altSpelling);