From 3716c70e7b6da0d24d4d534c80029ce049c683b6 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 26 Oct 2021 13:37:48 +0200 Subject: [PATCH] Add support for odl-pretty-print Somehow we did not have plumbing for this simple usability extension, make sure we have feature parity with bierman02. JIRA: NETCONF-825 Change-Id: I011e7369826ca7e07fcb5df1abdada726fa532d6 Signed-off-by: Robert Varga --- .../restconf/nb/rfc8040/PrettyPrintParam.java | 70 +++++++++++++++++++ .../restconf/nb/rfc8040/ReadDataParams.java | 16 +++-- .../rfc8040/databind/jaxrs/QueryParams.java | 8 ++- .../handlers/SchemaContextHandler.java | 2 + .../JsonNormalizedNodeBodyWriter.java | 3 +- .../XmlNormalizedNodeBodyWriter.java | 4 +- .../nb/rfc8040/legacy/QueryParameters.java | 8 +-- .../handlers/SchemaContextHandlerTest.java | 1 + 8 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/PrettyPrintParam.java diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/PrettyPrintParam.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/PrettyPrintParam.java new file mode 100644 index 0000000000..80457a01ad --- /dev/null +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/PrettyPrintParam.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.restconf.nb.rfc8040; + +import java.net.URI; +import org.eclipse.jdt.annotation.NonNull; + +/** + * OpenDaylight extension parameter. When used as {@code odl-pretty-print=true}, it will instruct outbound XML/JSON + * formatters to make the output easier for humans to understand. + */ +public final class PrettyPrintParam implements RestconfQueryParam { + // API consistency: must not be confused with enum constants + @SuppressWarnings("checkstyle:ConstantName") + public static final String uriName = "odl-pretty-print"; + + private static final @NonNull URI CAPABILITY = + URI.create("urn:opendaylight:params:restconf:capability:pretty-print:1.0"); + private static final @NonNull PrettyPrintParam FALSE = new PrettyPrintParam(false); + private static final @NonNull PrettyPrintParam TRUE = new PrettyPrintParam(true); + + private final boolean value; + + private PrettyPrintParam(final boolean value) { + this.value = value; + } + + public static @NonNull PrettyPrintParam of(final boolean value) { + return value ? TRUE : FALSE; + } + + public static @NonNull PrettyPrintParam forUriValue(final String uriValue) { + switch (uriValue) { + case "false": + return FALSE; + case "true": + return TRUE; + default: + throw new IllegalArgumentException("Value can be 'false' or 'true', not '" + uriValue + "'"); + } + } + + @Override + public Class<@NonNull PrettyPrintParam> javaClass() { + return PrettyPrintParam.class; + } + + @Override + public String paramName() { + return uriName; + } + + @Override + public String paramValue() { + return String.valueOf(value); + } + + public boolean value() { + return value; + } + + public static @NonNull URI capabilityUri() { + return CAPABILITY; + } +} diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java index e1faefad39..8a4a5417be 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java @@ -22,17 +22,17 @@ import org.opendaylight.yangtools.concepts.Immutable; // FIXME: this should be a record once we have JDK17+ public final class ReadDataParams implements Immutable { private static final @NonNull ReadDataParams EMPTY = - new ReadDataParams(ContentParam.ALL, null, null, null, false, false); + new ReadDataParams(ContentParam.ALL, null, null, null, false, null); private final @NonNull ContentParam content; private final WithDefaultsParam withDefaults; + private final PrettyPrintParam prettyPrint; private final FieldsParam fields; private final DepthParam depth; - private final boolean prettyPrint; private final boolean tagged; private ReadDataParams(final ContentParam content, final DepthParam depth, final FieldsParam fields, - final WithDefaultsParam withDefaults, final boolean tagged, final boolean prettyPrint) { + final WithDefaultsParam withDefaults, final boolean tagged, final PrettyPrintParam prettyPrint) { this.content = requireNonNull(content); this.depth = depth; this.fields = fields; @@ -47,7 +47,7 @@ public final class ReadDataParams implements Immutable { public static @NonNull ReadDataParams of(final ContentParam content, final DepthParam depth, final FieldsParam fields, final WithDefaultsParam withDefaults, final boolean tagged, - final boolean prettyPrint) { + final PrettyPrintParam prettyPrint) { return new ReadDataParams(content, depth, fields, withDefaults, tagged, prettyPrint); } @@ -67,7 +67,7 @@ public final class ReadDataParams implements Immutable { return withDefaults; } - public boolean prettyPrint() { + public @Nullable PrettyPrintParam prettyPrint() { return prettyPrint; } @@ -88,6 +88,10 @@ public final class ReadDataParams implements Immutable { if (withDefaults != null) { helper.add("withDefaults", withDefaults.paramValue()); } - return helper.add("tagged", tagged).add("prettyPrint", prettyPrint).toString(); + helper.add("tagged", tagged); + if (prettyPrint != null) { + helper.add("prettyPrint", prettyPrint.value()); + } + return helper.toString(); } } diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/jaxrs/QueryParams.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/jaxrs/QueryParams.java index 4848b11e97..9d7b7b459b 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/jaxrs/QueryParams.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/jaxrs/QueryParams.java @@ -32,6 +32,7 @@ import org.opendaylight.restconf.nb.rfc8040.InsertParam; import org.opendaylight.restconf.nb.rfc8040.LeafNodesOnlyParam; import org.opendaylight.restconf.nb.rfc8040.NotificationQueryParams; import org.opendaylight.restconf.nb.rfc8040.PointParam; +import org.opendaylight.restconf.nb.rfc8040.PrettyPrintParam; import org.opendaylight.restconf.nb.rfc8040.ReadDataParams; import org.opendaylight.restconf.nb.rfc8040.SkipNotificationDataParam; import org.opendaylight.restconf.nb.rfc8040.StartTimeParam; @@ -133,6 +134,7 @@ public final class QueryParams { DepthParam depth = null; FieldsParam fields = null; WithDefaultsParam withDefaults = null; + PrettyPrintParam prettyPrint = null; boolean tagged = false; for (Entry> entry : uriInfo.getQueryParameters().entrySet()) { @@ -194,13 +196,15 @@ public final class QueryParams { } } break; + case PrettyPrintParam.uriName: + prettyPrint = optionalParam(PrettyPrintParam::forUriValue, paramName, paramValues); + break; default: - // FIXME: recognize pretty-print here throw unhandledParam("read", paramName); } } - return ReadDataParams.of(content, depth, fields, withDefaults, tagged, false); + return ReadDataParams.of(content, depth, fields, withDefaults, tagged, prettyPrint); } public static @NonNull WriteDataParams newWriteDataParams(final UriInfo uriInfo) { diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandler.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandler.java index 495eb9e340..8b0cbf1cf6 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandler.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandler.java @@ -33,6 +33,7 @@ import org.opendaylight.restconf.nb.rfc8040.DepthParam; import org.opendaylight.restconf.nb.rfc8040.FieldsParam; import org.opendaylight.restconf.nb.rfc8040.FilterParam; import org.opendaylight.restconf.nb.rfc8040.LeafNodesOnlyParam; +import org.opendaylight.restconf.nb.rfc8040.PrettyPrintParam; import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary; import org.opendaylight.restconf.nb.rfc8040.SkipNotificationDataParam; import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParam; @@ -185,6 +186,7 @@ public class SchemaContextHandler implements EffectiveModelContextListener, Auto .withChildValue(FilterParam.capabilityUri().toString()) .withChildValue(AbstractReplayParam.capabilityUri().toString()) .withChildValue(WithDefaultsParam.capabilityUri().toString()) + .withChildValue(PrettyPrintParam.capabilityUri().toString()) .withChildValue(LeafNodesOnlyParam.capabilityUri().toString()) .withChildValue(SkipNotificationDataParam.capabilityUri().toString()) .build()) diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/JsonNormalizedNodeBodyWriter.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/JsonNormalizedNodeBodyWriter.java index 604f7a3c6a..15c4a829a1 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/JsonNormalizedNodeBodyWriter.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/JsonNormalizedNodeBodyWriter.java @@ -67,8 +67,9 @@ public class JsonNormalizedNodeBodyWriter extends AbstractNormalizedNodeBodyWrit final InstanceIdentifierContext identifierCtx = (InstanceIdentifierContext) context.getInstanceIdentifierContext(); final SchemaPath path = identifierCtx.getSchemaNode().getPath(); + final var pretty = context.getWriterParameters().prettyPrint(); - try (JsonWriter jsonWriter = createJsonWriter(entityStream, context.getWriterParameters().prettyPrint())) { + try (JsonWriter jsonWriter = createJsonWriter(entityStream, pretty == null ? false : pretty.value())) { jsonWriter.beginObject(); writeNormalizedNode(jsonWriter, path, identifierCtx, data, context.getWriterParameters().depth(), context.getWriterParameters().fields()); diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/XmlNormalizedNodeBodyWriter.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/XmlNormalizedNodeBodyWriter.java index 74ef222971..b5c085ca67 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/XmlNormalizedNodeBodyWriter.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/XmlNormalizedNodeBodyWriter.java @@ -74,7 +74,9 @@ public class XmlNormalizedNodeBodyWriter extends AbstractNormalizedNodeBodyWrite XMLStreamWriter xmlWriter; try { xmlWriter = XML_FACTORY.createXMLStreamWriter(entityStream, StandardCharsets.UTF_8.name()); - if (context.getWriterParameters().prettyPrint()) { + + final var prettyPrint = context.getWriterParameters().prettyPrint(); + if (prettyPrint != null && prettyPrint.value()) { xmlWriter = new IndentingXMLStreamWriter(xmlWriter); } } catch (final XMLStreamException | FactoryConfigurationError e) { diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/QueryParameters.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/QueryParameters.java index 52a72c8cbb..e30b18b44e 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/QueryParameters.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/QueryParameters.java @@ -15,6 +15,7 @@ import java.util.Set; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.restconf.nb.rfc8040.DepthParam; +import org.opendaylight.restconf.nb.rfc8040.PrettyPrintParam; import org.opendaylight.restconf.nb.rfc8040.ReadDataParams; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -65,6 +66,9 @@ public final class QueryParameters { return params.depth(); } + public @Nullable PrettyPrintParam prettyPrint() { + return params.prettyPrint(); + } public @Nullable List> fields() { return fields; @@ -73,8 +77,4 @@ public final class QueryParameters { public @Nullable List fieldPaths() { return fieldPaths; } - - public boolean prettyPrint() { - return params.prettyPrint(); - } } diff --git a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandlerTest.java b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandlerTest.java index 68b40980e6..87c12f7c8d 100644 --- a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandlerTest.java +++ b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandlerTest.java @@ -154,6 +154,7 @@ public class SchemaContextHandlerTest { equalTo("urn:ietf:params:restconf:capability:filter:1.0"), equalTo("urn:ietf:params:restconf:capability:replay:1.0"), equalTo("urn:ietf:params:restconf:capability:with-defaults:1.0"), + equalTo("urn:opendaylight:params:restconf:capability:pretty-print:1.0"), equalTo("urn:opendaylight:params:restconf:capability:leaf-nodes-only:1.0"), equalTo("urn:opendaylight:params:restconf:capability:skip-notification-data:1.0"))); } -- 2.36.6