Bug 2153 - pretty printer 77/20877/8
authorJan Hajnar <jhajnar@cisco.com>
Thu, 21 May 2015 07:46:57 +0000 (09:46 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 10 Jun 2015 11:29:42 +0000 (11:29 +0000)
NormalizedNodeJsonBodyWriter - added ability to create JsonWritter with
prettyPrint enabled
NormalizedNodeXmlBodyWriter - added IndentingXMLStreamWriter when
prettyPrint is enabled

NormalizedNodeContext - info about requirements on indentation (true |
false) was added

RestconfImpl - added pretty print parsing method and added pretty print
detection to GET methods and RPC call methods

Change-Id: I44cfa778279d67f7dc1bf1532cd7fc1087b492dc
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
Signed-off-by: Jan Hajnar <jhajnar@cisco.com>
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeJsonBodyWriter.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/NormalizedNodeXmlBodyWriter.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/NormalizedNodeContext.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/QueryParametersParser.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/WriterParameters.java [new file with mode: 0644]

index 3fcecfd9296c91d4731506570ddb643738332ab0..ee13e1c898ee56269184cdefef7242962794744c 100644 (file)
       <version>0.7.0-SNAPSHOT</version>
     </dependency>
 
+    <dependency>
+      <groupId>net.java.dev.stax-utils</groupId>
+      <artifactId>stax-utils</artifactId>
+      <version>20070216</version>
+    </dependency>
+
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
             </Private-Package>
             <Import-Package>*,
             com.sun.jersey.spi.container.servlet, org.eclipse.jetty.servlets</Import-Package>
+            <Embed-Dependency>stax-utils</Embed-Dependency>
             <Web-ContextPath>/restconf</Web-ContextPath>
           </instructions>
         </configuration>
index 5c17f2a14ab2558c4acd089e224828a9248530eb..2fa37c7745a9fc144ff7147c93a2e88932293522 100644 (file)
@@ -47,6 +47,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
     Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
 public class NormalizedNodeJsonBodyWriter implements MessageBodyWriter<NormalizedNodeContext> {
 
+    private static final int DEFAULT_INDENT_SPACES_NUM = 2;
+
     @Override
     public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
         return type.equals(NormalizedNodeContext.class);
@@ -70,7 +72,7 @@ public class NormalizedNodeJsonBodyWriter implements MessageBodyWriter<Normalize
         final InstanceIdentifierContext<SchemaNode> context = (InstanceIdentifierContext<SchemaNode>) t.getInstanceIdentifierContext();
 
         SchemaPath path = context.getSchemaNode().getPath();
-        final JsonWriter jsonWriter = createJsonWriter(entityStream);
+        final JsonWriter jsonWriter = createJsonWriter(entityStream, t.getWriterParameters().isPrettyPrint());
         jsonWriter.beginObject();
         writeNormalizedNode(jsonWriter,path,context,data);
         jsonWriter.endObject();
@@ -136,10 +138,13 @@ public class NormalizedNodeJsonBodyWriter implements MessageBodyWriter<Normalize
         return NormalizedNodeWriter.forStreamWriter(streamWriter);
     }
 
-    private JsonWriter createJsonWriter(final OutputStream entityStream) {
-        // FIXME BUG-2153: Add pretty print support
-        return JsonWriterFactory.createJsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
-
+    private JsonWriter createJsonWriter(final OutputStream entityStream, boolean prettyPrint) {
+        if (prettyPrint) {
+            return JsonWriterFactory.createJsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8),
+                    DEFAULT_INDENT_SPACES_NUM);
+        } else {
+            return JsonWriterFactory.createJsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
+        }
     }
 
     private JSONCodecFactory getCodecFactory(final InstanceIdentifierContext<?> context) {
index f6b7027b34a9994d43c2d731a40a11bcf7551bb6..9a540e72e95cc2bb729780bf9c96f5b2625acbac 100644 (file)
@@ -12,6 +12,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
+import javanet.staxutils.IndentingXMLStreamWriter;
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
@@ -76,6 +77,9 @@ public class NormalizedNodeXmlBodyWriter implements MessageBodyWriter<Normalized
         XMLStreamWriter xmlWriter;
         try {
             xmlWriter = XML_FACTORY.createXMLStreamWriter(entityStream);
+            if (t.getWriterParameters().isPrettyPrint()) {
+                xmlWriter = new IndentingXMLStreamWriter(xmlWriter);
+            }
         } catch (final XMLStreamException e) {
             throw new IllegalStateException(e);
         } catch (final FactoryConfigurationError e) {
index 3a8eecc349b5b9f3cee8d632f3725d8cec2c1b22..d72be873ec91c5e6444af53c2d6fdb85d11666cf 100644 (file)
@@ -7,10 +7,21 @@ public class NormalizedNodeContext {
 
     private final InstanceIdentifierContext<? extends SchemaNode> context;
     private final NormalizedNode<?,?> data;
+    private final WriterParameters writerParameters;
 
-    public NormalizedNodeContext(final InstanceIdentifierContext<? extends SchemaNode> context, final NormalizedNode<?, ?> data) {
+    public NormalizedNodeContext(final InstanceIdentifierContext<? extends SchemaNode> context,
+                                 final NormalizedNode<?, ?> data, WriterParameters writerParameters) {
         this.context = context;
         this.data = data;
+        this.writerParameters = writerParameters;
+    }
+
+    public NormalizedNodeContext(final InstanceIdentifierContext<? extends SchemaNode> context,
+                                 final NormalizedNode<?, ?> data) {
+        this.context = context;
+        this.data = data;
+        // default writer parameters
+        this.writerParameters = new WriterParameters(false, Integer.MAX_VALUE);
     }
 
     public InstanceIdentifierContext<? extends SchemaNode> getInstanceIdentifierContext() {
@@ -20,4 +31,8 @@ public class NormalizedNodeContext {
     public NormalizedNode<?, ?> getData() {
         return data;
     }
+
+    public WriterParameters getWriterParameters() {
+        return writerParameters;
+    }
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/QueryParametersParser.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/QueryParametersParser.java
new file mode 100644 (file)
index 0000000..b567d2a
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015 Cisco Systems, Inc. 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.controller.sal.restconf.impl;
+
+import com.google.common.base.Strings;
+import javax.ws.rs.core.UriInfo;
+
+public class QueryParametersParser {
+
+    private enum UriParameters {
+        PRETTY_PRINT("prettyPrint"),
+        DEPTH("depth");
+
+        private String uriParameterName;
+
+        UriParameters(final String uriParameterName) {
+            this.uriParameterName = uriParameterName;
+        }
+
+        @Override
+        public String toString() {
+            return uriParameterName;
+        }
+    }
+
+    public static WriterParameters parseKnownWriterParameters(final UriInfo info) {
+        boolean prettyPrint;
+        int depth;
+        String param = info.getQueryParameters(false).getFirst(UriParameters.DEPTH.toString());
+        if (Strings.isNullOrEmpty(param) || "unbounded".equals(param)) {
+            depth = Integer.MAX_VALUE;
+        } else {
+            try {
+                depth = Integer.valueOf(param);
+                if (depth < 1) {
+                    throw new RestconfDocumentedException(new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE,
+                            "Invalid depth parameter: " + depth, null,
+                            "The depth parameter must be an integer > 1 or \"unbounded\""));
+                }
+            } catch (final NumberFormatException e) {
+                throw new RestconfDocumentedException(new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE,
+                        "Invalid depth parameter: " + e.getMessage(), null,
+                        "The depth parameter must be an integer > 1 or \"unbounded\""));
+            }
+        }
+        param = info.getQueryParameters(false).getFirst(UriParameters.PRETTY_PRINT.toString());
+        prettyPrint = "true".equals(param);
+        return new WriterParameters(prettyPrint, depth);
+    }
+
+}
index d37f8dda5c1c759d90c7dc8fe731a5ddc5b417d3..38d41ddb2e664e5e018b73bc2f8c46aeaf05ad45 100644 (file)
@@ -103,22 +103,6 @@ import org.slf4j.LoggerFactory;
 
 public class RestconfImpl implements RestconfService {
 
-    private enum UriParameters {
-        PRETTY_PRINT("prettyPrint"),
-        DEPTH("depth");
-
-        private String uriParameterName;
-
-        UriParameters(final String uriParameterName) {
-            this.uriParameterName = uriParameterName;
-        }
-
-        @Override
-        public String toString() {
-            return uriParameterName;
-        }
-    }
-
     private static final RestconfImpl INSTANCE = new RestconfImpl();
 
     private static final int NOTIFICATION_PORT = 8181;
@@ -209,7 +193,8 @@ public class RestconfImpl implements RestconfService {
         moduleContainerBuilder.withChild(allModuleMap);
 
         return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, modulesSchemaNode,
-                null, schemaContext), moduleContainerBuilder.build());
+                null, schemaContext), moduleContainerBuilder.build(),
+                QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     /**
@@ -240,7 +225,8 @@ public class RestconfImpl implements RestconfService {
         moduleContainerBuilder.withChild(mountPointModulesMap);
 
         return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, modulesSchemaNode,
-                mountPoint, controllerContext.getGlobalSchema()), moduleContainerBuilder.build());
+                mountPoint, controllerContext.getGlobalSchema()), moduleContainerBuilder.build(),
+                QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     @Override
@@ -276,7 +262,7 @@ public class RestconfImpl implements RestconfService {
         Preconditions.checkState(moduleSchemaNode instanceof ListSchemaNode);
 
         return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, moduleSchemaNode, mountPoint,
-                schemaContext), moduleMap);
+                schemaContext), moduleMap, QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     @Override
@@ -305,7 +291,7 @@ public class RestconfImpl implements RestconfService {
 
 
         return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, streamsContainerSchemaNode, null,
-                schemaContext), streamsContainerBuilder.build());
+                schemaContext), streamsContainerBuilder.build(), QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     @Override
@@ -475,7 +461,8 @@ public class RestconfImpl implements RestconfService {
         }
 
         return new NormalizedNodeContext(new InstanceIdentifierContext<RpcDefinition>(null,
-                resultNodeSchema, mountPoint, schemaContext), resultData);
+                resultNodeSchema, mountPoint, schemaContext), resultData,
+                QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     private DOMRpcResult checkRpcResponse(final CheckedFuture<DOMRpcResult, DOMRpcException> response) {
@@ -653,7 +640,7 @@ public class RestconfImpl implements RestconfService {
         }
 
         return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, resultNodeSchema, mountPoint,
-                schemaContext), resultData);
+                schemaContext), resultData, QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     private RpcDefinition findRpc(final SchemaContext schemaContext, final String identifierDecoded) {
@@ -691,35 +678,11 @@ public class RestconfImpl implements RestconfService {
             LOG.debug(errMsg + identifier);
             throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.DATA_MISSING);
         }
-        return new NormalizedNodeContext(iiWithData, data);
-    }
-
-    // FIXME: Move this to proper place
-    @SuppressWarnings("unused")
-    private Integer parseDepthParameter(final UriInfo info) {
-        final String param = info.getQueryParameters(false).getFirst(UriParameters.DEPTH.toString());
-        if (Strings.isNullOrEmpty(param) || "unbounded".equals(param)) {
-            return null;
-        }
-
-        try {
-            final Integer depth = Integer.valueOf(param);
-            if (depth < 1) {
-                throw new RestconfDocumentedException(new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
-                        "Invalid depth parameter: " + depth, null,
-                        "The depth parameter must be an integer > 1 or \"unbounded\""));
-            }
-
-            return depth;
-        } catch (final NumberFormatException e) {
-            throw new RestconfDocumentedException(new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
-                    "Invalid depth parameter: " + e.getMessage(), null,
-                    "The depth parameter must be an integer > 1 or \"unbounded\""));
-        }
+        return new NormalizedNodeContext(iiWithData, data, QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     @Override
-    public NormalizedNodeContext readOperationalData(final String identifier, final UriInfo info) {
+    public NormalizedNodeContext readOperationalData(final String identifier, final UriInfo uriInfo) {
         final InstanceIdentifierContext<?> iiWithData = controllerContext.toInstanceIdentifier(identifier);
         final DOMMountPoint mountPoint = iiWithData.getMountPoint();
         NormalizedNode<?, ?> data = null;
@@ -734,7 +697,7 @@ public class RestconfImpl implements RestconfService {
             LOG.debug(errMsg + identifier);
             throw new RestconfDocumentedException(errMsg , ErrorType.APPLICATION, ErrorTag.DATA_MISSING);
         }
-        return new NormalizedNodeContext(iiWithData, data);
+        return new NormalizedNodeContext(iiWithData, data, QueryParametersParser.parseKnownWriterParameters(uriInfo));
     }
 
     @Override
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/WriterParameters.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/WriterParameters.java
new file mode 100644 (file)
index 0000000..9b26f60
--- /dev/null
@@ -0,0 +1,20 @@
+package org.opendaylight.controller.sal.restconf.impl;
+
+public class WriterParameters {
+    private final int depth;
+    private final boolean prettyPrint;
+
+    public WriterParameters(final boolean prettyPrint, final int depth) {
+        this.prettyPrint = prettyPrint;
+        this.depth = depth;
+    }
+
+    public int getDepth() {
+        return depth;
+    }
+
+    public boolean isPrettyPrint() {
+        return prettyPrint;
+    }
+}
+