Bug 8622: convert sal-rest-docgen to Jackson 39/58839/3
authorStephen Kitt <skitt@redhat.com>
Tue, 13 Jun 2017 16:25:59 +0000 (18:25 +0200)
committerStephen Kitt <skitt@redhat.com>
Wed, 14 Jun 2017 14:19:37 +0000 (16:19 +0200)
This removes the requirement for org.json in sal-rest-docgen, which
causes bundle wiring issues in Karaf 4 (sal-rest-docgen ends up
exporting org.json, which Jackson’s compatibility layer consumes,
creating a dependency loop which causes refreshes anytime anything
touches the sal-rest-docgen).

Change-Id: I877f3e567fdeba3258a19a40f1f9e31bb19df24d
Signed-off-by: Stephen Kitt <skitt@redhat.com>
restconf/sal-rest-docgen/pom.xml
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ApiDocServiceImpl.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/BaseYangSwaggerGenerator.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/impl/ModelGenerator.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/jaxrs/JaxbContextResolver.java
restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/swagger/ApiDeclaration.java
restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java
restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGenTestHelper.java
restconf/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGeneratorTest.java

index 8a21e7e244b6f58a7135ed3b99a1859999b43544..262448a461b9d6757c2b78096830f063e71563eb 100644 (file)
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
     </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.datatype</groupId>
-      <artifactId>jackson-datatype-json-org</artifactId>
-    </dependency>
 
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>jaxrs-api</artifactId>
     </dependency>
 
-    <dependency>
-      <groupId>org.json</groupId>
-      <artifactId>json</artifactId>
-    </dependency>
-
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-core-api</artifactId>
               org.apache.shiro.web.env
             </Import-Package>
             <Export-Package>
-              com.fasterxml.jackson.datatype.*,
-              org.json
+              com.fasterxml.jackson.datatype.*
             </Export-Package>
             <Bundle-Activator>org.opendaylight.netconf.sal.rest.doc.DocProvider</Bundle-Activator>
             <Web-ContextPath>/apidoc</Web-ContextPath>
index 2f22fa9a426bc5db11d82f021d0523f99f4a9c68..f5002e03714f36dce76c32778202972b3a2965b8 100644 (file)
@@ -7,13 +7,14 @@
  */
 package org.opendaylight.netconf.sal.rest.doc.impl;
 
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStreamWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.Map.Entry;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-import org.json.JSONWriter;
 import org.opendaylight.netconf.sal.rest.doc.api.ApiDocService;
 import org.opendaylight.netconf.sal.rest.doc.mountpoints.MountPointSwagger;
 import org.opendaylight.netconf.sal.rest.doc.swagger.ApiDeclaration;
@@ -86,16 +87,16 @@ public class ApiDocServiceImpl implements ApiDocService {
     public synchronized Response getListOfMounts(final UriInfo uriInfo) {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try (OutputStreamWriter streamWriter = new OutputStreamWriter(baos, StandardCharsets.UTF_8)) {
-            final JSONWriter writer = new JSONWriter(streamWriter);
-            writer.array();
+            JsonGenerator writer = new JsonFactory().createGenerator(streamWriter);
+            writer.writeStartArray();
             for (final Entry<String, Long> entry : MountPointSwagger.getInstance().getInstanceIdentifiers()
                     .entrySet()) {
-                writer.object();
-                writer.key("instance").value(entry.getKey());
-                writer.key("id").value(entry.getValue());
-                writer.endObject();
+                writer.writeStartObject();
+                writer.writeObjectField("instance", entry.getKey());
+                writer.writeObjectField("id", entry.getValue());
+                writer.writeEndObject();
             }
-            writer.endArray();
+            writer.writeEndArray();
         } catch (final Exception e) {
             return Response.status(500).entity(e.getMessage()).build();
         }
index 7ffc4c58169500bbbffe35eab9678adc4013e1dd..91612c1eac0354fa9bc42d1de953e1eeb243e82b 100644 (file)
@@ -11,7 +11,7 @@ import static org.opendaylight.netconf.sal.rest.doc.util.RestDocgenUtil.resolveP
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.base.Preconditions;
 import java.io.IOException;
 import java.net.URI;
@@ -28,8 +28,6 @@ import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import javax.ws.rs.core.UriInfo;
-import org.json.JSONException;
-import org.json.JSONObject;
 import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder;
 import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.Delete;
 import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.Get;
@@ -72,7 +70,6 @@ public class BaseYangSwaggerGenerator {
     private static boolean newDraft;
 
     protected BaseYangSwaggerGenerator() {
-        this.mapper.registerModule(new JsonOrgModule());
         this.mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
     }
 
@@ -231,7 +228,7 @@ public class BaseYangSwaggerGenerator {
 
         if (!apis.isEmpty()) {
             doc.setApis(apis);
-            JSONObject models = null;
+            ObjectNode models = null;
 
             try {
                 models = this.jsonConverter.convertToJsonSchema(module, schemaContext);
@@ -239,7 +236,7 @@ public class BaseYangSwaggerGenerator {
                 if (LOG.isDebugEnabled()) {
                     LOG.debug(this.mapper.writeValueAsString(doc));
                 }
-            } catch (IOException | JSONException e) {
+            } catch (IOException e) {
                 LOG.error("Exception occured in ModelGenerator", e);
             }
 
index f4ba8d41899199b2b82055e311a9d72017374006..5149200a091064f75b2f169527c3ee053c1edbd6 100644 (file)
@@ -9,17 +9,18 @@ package org.opendaylight.netconf.sal.rest.doc.impl;
 
 import static org.opendaylight.netconf.sal.rest.doc.util.RestDocgenUtil.resolveNodesName;
 
-import com.google.common.base.Optional;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.NullNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
 import com.mifmif.common.regex.Generex;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.regex.Pattern;
 import javax.annotation.concurrent.NotThreadSafe;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
 import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder;
 import org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.Post;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -103,14 +104,13 @@ public class ModelGenerator {
      *
      * @param module        - Yang module to be converted
      * @param schemaContext - SchemaContext of all Yang files used by Api Doc
-     * @return JSONObject containing data used for creating examples and models in Api Doc
+     * @return ObjectNode containing data used for creating examples and models in Api Doc
      * @throws IOException if I/O operation fails
-     * @throws JSONException when things are amiss
      */
-    public JSONObject convertToJsonSchema(final Module module,
-                                          final SchemaContext schemaContext) throws IOException, JSONException {
-        final JSONObject models = new JSONObject();
-        models.put(UNIQUE_EMPTY_IDENTIFIER, new JSONObject());
+    public ObjectNode convertToJsonSchema(final Module module,
+                                          final SchemaContext schemaContext) throws IOException {
+        final ObjectNode models = JsonNodeFactory.instance.objectNode();
+        models.put(UNIQUE_EMPTY_IDENTIFIER, NullNode.getInstance());
         topLevelModule = module;
         processModules(module, models, schemaContext);
         processContainersAndLists(module, models, schemaContext);
@@ -119,14 +119,14 @@ public class ModelGenerator {
         return models;
     }
 
-    private void processModules(final Module module, final JSONObject models,
-                                final SchemaContext schemaContext) throws JSONException {
+    private void processModules(final Module module, final ObjectNode models,
+                                final SchemaContext schemaContext) {
         createConcreteModelForPost(models, module.getName() + BaseYangSwaggerGenerator.MODULE_NAME_SUFFIX,
                 createPropertiesForPost(module, schemaContext, module.getName()));
     }
 
-    private void processContainersAndLists(final Module module, final JSONObject models,
-                                           final SchemaContext schemaContext) throws IOException, JSONException {
+    private void processContainersAndLists(final Module module, final ObjectNode models,
+                                           final SchemaContext schemaContext) throws IOException {
         final String moduleName = module.getName();
 
         for (final DataSchemaNode childNode : module.getChildNodes()) {
@@ -144,22 +144,20 @@ public class ModelGenerator {
      * for each RPC that contains input & output elements.
      *
      * @param module module
-     * @throws JSONException when things are amiss
      * @throws IOException if I/O operation fails
      */
-    private void processRPCs(final Module module, final JSONObject models,
-                             final SchemaContext schemaContext) throws JSONException,
-            IOException {
+    private void processRPCs(final Module module, final ObjectNode models,
+                             final SchemaContext schemaContext) throws IOException {
         final Set<RpcDefinition> rpcs = module.getRpcs();
         final String moduleName = module.getName();
         for (final RpcDefinition rpc : rpcs) {
             final ContainerSchemaNode input = rpc.getInput();
             if (!input.getChildNodes().isEmpty()) {
-                final JSONObject properties =
+                final ObjectNode properties =
                         processChildren(input.getChildNodes(), moduleName, models, true, schemaContext);
 
                 final String filename = "(" + rpc.getQName().getLocalName() + ")input";
-                final JSONObject childSchema = getSchemaTemplate();
+                final ObjectNode childSchema = getSchemaTemplate();
                 childSchema.put(TYPE_KEY, OBJECT_TYPE);
                 childSchema.put(PROPERTIES_KEY, properties);
                 childSchema.put(ID_KEY, filename);
@@ -170,10 +168,10 @@ public class ModelGenerator {
 
             final ContainerSchemaNode output = rpc.getOutput();
             if (!output.getChildNodes().isEmpty()) {
-                final JSONObject properties =
+                final ObjectNode properties =
                         processChildren(output.getChildNodes(), moduleName, models, true, schemaContext);
                 final String filename = "(" + rpc.getQName().getLocalName() + ")output";
-                final JSONObject childSchema = getSchemaTemplate();
+                final ObjectNode childSchema = getSchemaTemplate();
                 childSchema.put(TYPE_KEY, OBJECT_TYPE);
                 childSchema.put(PROPERTIES_KEY, properties);
                 childSchema.put(ID_KEY, filename);
@@ -184,18 +182,18 @@ public class ModelGenerator {
         }
     }
 
-    private JSONObject processTopData(final String filename, final JSONObject models, final SchemaNode schemaNode) {
-        final JSONObject items = new JSONObject();
+    private ObjectNode processTopData(final String filename, final ObjectNode models, final SchemaNode schemaNode) {
+        final ObjectNode items = JsonNodeFactory.instance.objectNode();
 
         items.put(REF_KEY, filename);
-        final JSONObject dataNodeProperties = new JSONObject();
+        final ObjectNode dataNodeProperties = JsonNodeFactory.instance.objectNode();
         dataNodeProperties.put(TYPE_KEY, schemaNode instanceof ListSchemaNode ? ARRAY_TYPE : OBJECT_TYPE);
         dataNodeProperties.put(ITEMS_KEY, items);
 
-        dataNodeProperties.putOpt(DESCRIPTION_KEY, schemaNode.getDescription());
-        final JSONObject properties = new JSONObject();
+        putIfNonNull(dataNodeProperties, DESCRIPTION_KEY, schemaNode.getDescription());
+        final ObjectNode properties = JsonNodeFactory.instance.objectNode();
         properties.put(topLevelModule.getName() + ":" + schemaNode.getQName().getLocalName(), dataNodeProperties);
-        final JSONObject finalChildSchema = getSchemaTemplate();
+        final ObjectNode finalChildSchema = getSchemaTemplate();
         finalChildSchema.put(TYPE_KEY, OBJECT_TYPE);
         finalChildSchema.put(PROPERTIES_KEY, properties);
         finalChildSchema.put(ID_KEY, filename + OperationBuilder.TOP);
@@ -208,42 +206,42 @@ public class ModelGenerator {
      * Processes the 'identity' statement in a yang model and maps it to a 'model' in the Swagger JSON spec.
      *
      * @param module The module from which the identity stmt will be processed
-     * @param models The JSONObject in which the parsed identity will be put as a 'model' obj
+     * @param models The ObjectNode in which the parsed identity will be put as a 'model' obj
      */
-    private static void processIdentities(final Module module, final JSONObject models) throws JSONException {
+    private static void processIdentities(final Module module, final ObjectNode models) {
 
         final String moduleName = module.getName();
         final Set<IdentitySchemaNode> idNodes = module.getIdentities();
         LOG.debug("Processing Identities for module {} . Found {} identity statements", moduleName, idNodes.size());
 
         for (final IdentitySchemaNode idNode : idNodes) {
-            final JSONObject identityObj = new JSONObject();
+            final ObjectNode identityObj = JsonNodeFactory.instance.objectNode();
             final String identityName = idNode.getQName().getLocalName();
             LOG.debug("Processing Identity: {}", identityName);
 
             identityObj.put(ID_KEY, identityName);
-            identityObj.put(DESCRIPTION_KEY, idNode.getDescription());
+            putIfNonNull(identityObj, DESCRIPTION_KEY, idNode.getDescription());
 
-            final JSONObject props = new JSONObject();
+            final ObjectNode props = JsonNodeFactory.instance.objectNode();
             final IdentitySchemaNode baseId = idNode.getBaseIdentity();
 
             if (baseId == null) {
-                /**
+                /*
                  * This is a base identity. So lets see if it has sub types. If it does, then add them to the model
                  * definition.
                  */
                 final Set<IdentitySchemaNode> derivedIds = idNode.getDerivedIdentities();
 
                 if (derivedIds != null) {
-                    final JSONArray subTypes = new JSONArray();
+                    final ArrayNode subTypes = new ArrayNode(JsonNodeFactory.instance);
                     for (final IdentitySchemaNode derivedId : derivedIds) {
-                        subTypes.put(derivedId.getQName().getLocalName());
+                        subTypes.add(derivedId.getQName().getLocalName());
                     }
                     identityObj.put(SUB_TYPES_KEY, subTypes);
 
                 }
             } else {
-                /**
+                /*
                  * This is a derived entity. Add it's base type & move on.
                  */
                 props.put(TYPE_KEY, baseId.getQName().getLocalName());
@@ -255,18 +253,18 @@ public class ModelGenerator {
         }
     }
 
-    private JSONObject processDataNodeContainer(
-            final DataNodeContainer dataNode, final String parentName, final JSONObject models, final boolean isConfig,
-            final SchemaContext schemaContext) throws JSONException, IOException {
+    private ObjectNode processDataNodeContainer(
+            final DataNodeContainer dataNode, final String parentName, final ObjectNode models, final boolean isConfig,
+            final SchemaContext schemaContext) throws IOException {
         if (dataNode instanceof ListSchemaNode || dataNode instanceof ContainerSchemaNode) {
             final Iterable<DataSchemaNode> containerChildren = dataNode.getChildNodes();
             final String localName = ((SchemaNode) dataNode).getQName().getLocalName();
-            final JSONObject properties =
+            final ObjectNode properties =
                     processChildren(containerChildren, parentName + "/" + localName, models, isConfig, schemaContext);
             final String nodeName = parentName + (isConfig ? OperationBuilder.CONFIG : OperationBuilder.OPERATIONAL)
                     + localName;
 
-            final JSONObject childSchema = getSchemaTemplate();
+            final ObjectNode childSchema = getSchemaTemplate();
             childSchema.put(TYPE_KEY, OBJECT_TYPE);
             childSchema.put(PROPERTIES_KEY, properties);
 
@@ -283,30 +281,29 @@ public class ModelGenerator {
         return null;
     }
 
-    private static void createConcreteModelForPost(final JSONObject models, final String localName,
-                                                   final JSONObject properties) throws JSONException {
+    private static void createConcreteModelForPost(final ObjectNode models, final String localName,
+                                                   final JsonNode properties) {
         final String nodePostName = OperationBuilder.CONFIG + localName + Post.METHOD_NAME;
-        final JSONObject postSchema = getSchemaTemplate();
+        final ObjectNode postSchema = getSchemaTemplate();
         postSchema.put(TYPE_KEY, OBJECT_TYPE);
         postSchema.put(ID_KEY, nodePostName);
         postSchema.put(PROPERTIES_KEY, properties);
         models.put(nodePostName, postSchema);
     }
 
-    private JSONObject createPropertiesForPost(final DataNodeContainer dataNodeContainer,
-                                               final SchemaContext schemaContext, final String parentName)
-            throws JSONException {
-        final JSONObject properties = new JSONObject();
+    private JsonNode createPropertiesForPost(final DataNodeContainer dataNodeContainer,
+                                               final SchemaContext schemaContext, final String parentName) {
+        final ObjectNode properties = JsonNodeFactory.instance.objectNode();
         for (final DataSchemaNode childNode : dataNodeContainer.getChildNodes()) {
             if (childNode instanceof ListSchemaNode || childNode instanceof ContainerSchemaNode) {
-                final JSONObject items = new JSONObject();
+                final ObjectNode items = JsonNodeFactory.instance.objectNode();
                 items.put(REF_KEY, parentName + "(config)" + childNode.getQName().getLocalName());
-                final JSONObject property = new JSONObject();
+                final ObjectNode property = JsonNodeFactory.instance.objectNode();
                 property.put(TYPE_KEY, childNode instanceof ListSchemaNode ? ARRAY_TYPE : OBJECT_TYPE);
                 property.put(ITEMS_KEY, items);
                 properties.put(childNode.getQName().getLocalName(), property);
             } else if (childNode instanceof LeafSchemaNode) {
-                final JSONObject property = processLeafNode((LeafSchemaNode) childNode, schemaContext);
+                final ObjectNode property = processLeafNode((LeafSchemaNode) childNode, schemaContext);
                 properties.put(childNode.getQName().getLocalName(), property);
             }
         }
@@ -316,15 +313,14 @@ public class ModelGenerator {
     /**
      * Processes the nodes.
      */
-    private JSONObject processChildren(
-            final Iterable<DataSchemaNode> nodes, final String parentName, final JSONObject models,
-            final boolean isConfig, final SchemaContext schemaContext)
-            throws JSONException, IOException {
-        final JSONObject properties = new JSONObject();
+    private ObjectNode processChildren(
+            final Iterable<DataSchemaNode> nodes, final String parentName, final ObjectNode models,
+            final boolean isConfig, final SchemaContext schemaContext) throws IOException {
+        final ObjectNode properties = JsonNodeFactory.instance.objectNode();
         for (final DataSchemaNode node : nodes) {
             if (node.isConfiguration() == isConfig) {
                 final String name = resolveNodesName(node, topLevelModule, schemaContext);
-                final JSONObject property;
+                final ObjectNode property;
                 if (node instanceof LeafSchemaNode) {
                     property = processLeafNode((LeafSchemaNode) node, schemaContext);
 
@@ -352,22 +348,22 @@ public class ModelGenerator {
                 } else {
                     throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass());
                 }
-                property.putOpt(DESCRIPTION_KEY, node.getDescription());
+                putIfNonNull(property, DESCRIPTION_KEY, node.getDescription());
                 properties.put(topLevelModule.getName() + ":" + name, property);
             }
         }
         return properties;
     }
 
-    private JSONObject processLeafListNode(final LeafListSchemaNode listNode,
-                                           final SchemaContext schemaContext) throws JSONException {
-        final JSONObject props = new JSONObject();
+    private ObjectNode processLeafListNode(final LeafListSchemaNode listNode,
+                                           final SchemaContext schemaContext) {
+        final ObjectNode props = JsonNodeFactory.instance.objectNode();
         props.put(TYPE_KEY, ARRAY_TYPE);
 
-        final JSONObject itemsVal = new JSONObject();
+        final ObjectNode itemsVal = JsonNodeFactory.instance.objectNode();
         final ConstraintDefinition constraints = listNode.getConstraints();
-        final Optional<Integer> maxOptional = Optional.fromNullable(constraints.getMaxElements());
-        if (maxOptional.or(2) >= 2) {
+        int max = constraints.getMaxElements() == null ? 2 : constraints.getMaxElements();
+        if (max >= 2) {
             processTypeDef(listNode.getType(), listNode, itemsVal, schemaContext);
             processTypeDef(listNode.getType(), listNode, itemsVal, schemaContext);
         } else {
@@ -382,12 +378,12 @@ public class ModelGenerator {
     }
 
     private void processChoiceNode(
-            final Iterable<DataSchemaNode> nodes, final String moduleName, final JSONObject models,
-            final SchemaContext schemaContext, final boolean isConfig, final JSONObject properties)
-            throws JSONException, IOException {
+            final Iterable<DataSchemaNode> nodes, final String moduleName, final ObjectNode models,
+            final SchemaContext schemaContext, final boolean isConfig, final ObjectNode properties)
+           throws IOException {
         for (final DataSchemaNode node : nodes) {
             final String name = resolveNodesName(node, topLevelModule, schemaContext);
-            final JSONObject property;
+            final ObjectNode property;
 
             if (node instanceof LeafSchemaNode) {
                 property = processLeafNode((LeafSchemaNode) node, schemaContext);
@@ -417,13 +413,13 @@ public class ModelGenerator {
                 throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass());
             }
 
-            property.putOpt(DESCRIPTION_KEY, node.getDescription());
+            putIfNonNull(property, DESCRIPTION_KEY, node.getDescription());
             properties.put(name, property);
         }
     }
 
     private static void processConstraints(final ConstraintDefinition constraints,
-                                           final JSONObject props) throws JSONException {
+                                           final ObjectNode props) {
         final boolean isMandatory = constraints.isMandatory();
         props.put(REQUIRED_KEY, isMandatory);
 
@@ -437,23 +433,23 @@ public class ModelGenerator {
         }
     }
 
-    private JSONObject processLeafNode(final LeafSchemaNode leafNode,
-                                       final SchemaContext schemaContext) throws JSONException {
-        final JSONObject property = new JSONObject();
+    private ObjectNode processLeafNode(final LeafSchemaNode leafNode,
+                                       final SchemaContext schemaContext) {
+        final ObjectNode property = JsonNodeFactory.instance.objectNode();
 
         final String leafDescription = leafNode.getDescription();
-        property.put(DESCRIPTION_KEY, leafDescription);
+        putIfNonNull(property, DESCRIPTION_KEY, leafDescription);
         processConstraints(leafNode.getConstraints(), property);
         processTypeDef(leafNode.getType(), leafNode, property, schemaContext);
 
         return property;
     }
 
-    private static JSONObject processAnyXMLNode(final AnyXmlSchemaNode leafNode) throws JSONException {
-        final JSONObject property = new JSONObject();
+    private static ObjectNode processAnyXMLNode(final AnyXmlSchemaNode leafNode) {
+        final ObjectNode property = JsonNodeFactory.instance.objectNode();
 
         final String leafDescription = leafNode.getDescription();
-        property.put(DESCRIPTION_KEY, leafDescription);
+        putIfNonNull(property, DESCRIPTION_KEY, leafDescription);
 
         processConstraints(leafNode.getConstraints(), property);
         final String localName = leafNode.getQName().getLocalName();
@@ -463,7 +459,7 @@ public class ModelGenerator {
     }
 
     private String processTypeDef(final TypeDefinition<?> leafTypeDef, final DataSchemaNode node,
-                                  final JSONObject property, final SchemaContext schemaContext) throws JSONException {
+                                  final ObjectNode property, final SchemaContext schemaContext) {
         final String jsonType;
         if (leafTypeDef.getDefaultValue() == null) {
             if (leafTypeDef instanceof BinaryTypeDefinition) {
@@ -514,11 +510,11 @@ public class ModelGenerator {
         } else {
             jsonType = String.valueOf(leafTypeDef.getDefaultValue());
         }
-        property.putOpt(TYPE_KEY, jsonType);
+        putIfNonNull(property, TYPE_KEY, jsonType);
         return jsonType;
     }
 
-    private String processLeafRef(final DataSchemaNode node, final JSONObject property,
+    private String processLeafRef(final DataSchemaNode node, final ObjectNode property,
                                   final SchemaContext schemaContext, final TypeDefinition<?> leafTypeDef) {
         RevisionAwareXPath xpath = ((LeafrefTypeDefinition) leafTypeDef).getPathStatement();
         final SchemaNode schemaNode;
@@ -544,42 +540,41 @@ public class ModelGenerator {
                 .findModuleByNamespaceAndRevision(qualifiedName.getNamespace(), qualifiedName.getRevision());
     }
 
-    private static String processBinaryType(final JSONObject property) throws JSONException {
-        final JSONObject media = new JSONObject();
+    private static String processBinaryType(final ObjectNode property) {
+        final ObjectNode media = JsonNodeFactory.instance.objectNode();
         media.put(BINARY_ENCODING_KEY, BASE_64);
         property.put(MEDIA_KEY, media);
         return "bin1 bin2";
     }
 
     private static String processEnumType(final EnumTypeDefinition enumLeafType,
-                                          final JSONObject property) throws JSONException {
+                                          final ObjectNode property) {
         final List<EnumPair> enumPairs = enumLeafType.getValues();
-        final List<String> enumNames = new ArrayList<>();
+        ArrayNode enumNames = new ArrayNode(JsonNodeFactory.instance);
         for (final EnumPair enumPair : enumPairs) {
-            enumNames.add(enumPair.getName());
+            enumNames.add(new TextNode(enumPair.getName()));
         }
 
-        property.putOpt(ENUM, new JSONArray(enumNames));
+        property.put(ENUM, enumNames);
         return enumLeafType.getValues().iterator().next().getName();
     }
 
     private static String processBitsType(final BitsTypeDefinition bitsType,
-                                          final JSONObject property) throws JSONException {
+                                          final ObjectNode property) {
         property.put(MIN_ITEMS, 0);
         property.put(UNIQUE_ITEMS_KEY, true);
-        final List<String> enumNames = new ArrayList<>();
+        ArrayNode enumNames = new ArrayNode(JsonNodeFactory.instance);
         final List<Bit> bits = bitsType.getBits();
         for (final Bit bit : bits) {
-            enumNames.add(bit.getName());
+            enumNames.add(new TextNode(bit.getName()));
         }
-        property.put(ENUM, new JSONArray(enumNames));
+        property.put(ENUM, enumNames);
 
         return enumNames.iterator().next() + " " + enumNames.get(enumNames.size() - 1);
     }
 
     private static String processStringType(final TypeDefinition<?> stringType,
-                                            final JSONObject property, final String nodeName)
-            throws JSONException {
+                                            final ObjectNode property, final String nodeName) {
         StringTypeDefinition type = (StringTypeDefinition) stringType;
         List<LengthConstraint> lengthConstraints = ((StringTypeDefinition) stringType).getLengthConstraints();
         while (lengthConstraints.isEmpty() && type.getBaseType() != null) {
@@ -592,8 +587,8 @@ public class ModelGenerator {
         for (final LengthConstraint lengthConstraint : lengthConstraints) {
             final Number min = lengthConstraint.getMin();
             final Number max = lengthConstraint.getMax();
-            property.putOpt(MIN_LENGTH_KEY, min);
-            property.putOpt(MAX_LENGTH_KEY, max);
+            putIfNonNull(property, MIN_LENGTH_KEY, min);
+            putIfNonNull(property, MAX_LENGTH_KEY, max);
         }
         if (type.getPatternConstraints().iterator().hasNext()) {
             final PatternConstraint pattern = type.getPatternConstraints().iterator().next();
@@ -606,25 +601,46 @@ public class ModelGenerator {
         }
     }
 
-    private String processUnionType(final UnionTypeDefinition unionType, final JSONObject property,
-                                    final SchemaContext schemaContext, final DataSchemaNode node)
-            throws JSONException {
-        final List<String> unionNames = new ArrayList<>();
+    private String processUnionType(final UnionTypeDefinition unionType, final ObjectNode property,
+                                    final SchemaContext schemaContext, final DataSchemaNode node) {
+        final ArrayNode unionNames = new ArrayNode(JsonNodeFactory.instance);
         for (final TypeDefinition<?> typeDef : unionType.getTypes()) {
             unionNames.add(processTypeDef(typeDef, node, property, schemaContext));
         }
-        property.put(ENUM, new JSONArray(unionNames));
-        return unionNames.iterator().next();
+        property.put(ENUM, unionNames);
+        return unionNames.iterator().next().asText();
     }
 
     /**
      * Helper method to generate a pre-filled JSON schema object.
      */
-    private static JSONObject getSchemaTemplate() throws JSONException {
-        final JSONObject schemaJSON = new JSONObject();
+    private static ObjectNode getSchemaTemplate() {
+        final ObjectNode schemaJSON = JsonNodeFactory.instance.objectNode();
         schemaJSON.put(SCHEMA_KEY, SCHEMA_URL);
 
         return schemaJSON;
     }
 
+    private static void putIfNonNull(ObjectNode property, String key, Number number) {
+        if (key != null && number != null) {
+            if (number instanceof Double) {
+                property.put(key, (Double) number);
+            } else if (number instanceof Float) {
+                property.put(key, (Float) number);
+            } else if (number instanceof Integer) {
+                property.put(key, (Integer) number);
+            } else if (number instanceof Short) {
+                property.put(key, (Short) number);
+            } else if (number instanceof Long) {
+                property.put(key, (Long) number);
+            }
+        }
+    }
+
+    private static void putIfNonNull(ObjectNode property, String key, String value) {
+        if (key != null && value != null) {
+            property.put(key, value);
+        }
+    }
+
 }
\ No newline at end of file
index de8c5bc50163f590e8aa37dc088cb6ab59fcf23b..a8baa7774c544d7167c63a758b8a0b99c91741db 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.netconf.sal.rest.doc.jaxrs;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
@@ -26,7 +25,6 @@ public class JaxbContextResolver implements ContextResolver<ObjectMapper> {
 
     public JaxbContextResolver() {
         ctx = new ObjectMapper();
-        ctx.registerModule(new JsonOrgModule());
         ctx.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.ALWAYS);
     }
 
index 3d735ac2f6898e49729cf6b7729a7052b9389593..00c6de8fe3d7818d3e5adb88fe18077843f8ab7d 100644 (file)
@@ -7,8 +7,8 @@
  */
 package org.opendaylight.netconf.sal.rest.doc.swagger;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.util.List;
-import org.json.JSONObject;
 
 /**
  * Implementation of swagger spec (see <a href=
@@ -23,13 +23,13 @@ public class ApiDeclaration {
     private String resourcePath;
     private List<String> produces;
     private List<Api> apis;
-    private JSONObject models;
+    private ObjectNode models;
 
-    public JSONObject getModels() {
+    public ObjectNode getModels() {
         return models;
     }
 
-    public void setModels(JSONObject models) {
+    public void setModels(ObjectNode models) {
         this.models = models;
     }
 
@@ -86,6 +86,6 @@ public class ApiDeclaration {
     }
 
     public boolean hasModel() {
-        return (models != null && models.length() > 0);
+        return (models != null && models.size() > 0);
     }
 }
index 91cbcec2c7d3888077d4af2d28b8f18c83588946..50fe6b62254d757172a0404103c652b888e88e8c 100644 (file)
@@ -13,6 +13,8 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.base.Preconditions;
 import java.sql.Date;
 import java.util.Arrays;
@@ -21,8 +23,6 @@ import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 import javax.ws.rs.core.UriInfo;
-import org.json.JSONException;
-import org.json.JSONObject;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -164,72 +164,67 @@ public class ApiDocGeneratorTest {
      * Validates whether doc {@code doc} contains concrete specified models.
      */
     private void validateSwaggerModules(final ApiDeclaration doc) {
-        final JSONObject models = doc.getModels();
+        final ObjectNode models = doc.getModels();
         assertNotNull(models);
-        try {
-            final JSONObject configLstTop = models.getJSONObject("toaster2(config)lst-TOP");
-            assertNotNull(configLstTop);
 
-            containsReferences(configLstTop, "toaster2:lst", "toaster2(config)");
+        final JsonNode configLstTop = models.get("toaster2(config)lst-TOP");
+        assertNotNull(configLstTop);
 
-            final JSONObject configLst = models.getJSONObject("toaster2(config)lst");
-            assertNotNull(configLst);
+        containsReferences(configLstTop, "toaster2:lst", "toaster2(config)");
 
-            containsReferences(configLst, "toaster2:lst1", "toaster2/lst(config)");
-            containsReferences(configLst, "toaster2:cont1", "toaster2/lst(config)");
+        final JsonNode configLst = models.get("toaster2(config)lst");
+        assertNotNull(configLst);
 
-            final JSONObject configLst1Top = models.getJSONObject("toaster2/lst(config)lst1-TOP");
-            assertNotNull(configLst1Top);
+        containsReferences(configLst, "toaster2:lst1", "toaster2/lst(config)");
+        containsReferences(configLst, "toaster2:cont1", "toaster2/lst(config)");
 
-            containsReferences(configLst1Top, "toaster2:lst1", "toaster2/lst(config)");
+        final JsonNode configLst1Top = models.get("toaster2/lst(config)lst1-TOP");
+        assertNotNull(configLst1Top);
 
-            final JSONObject configLst1 = models.getJSONObject("toaster2/lst(config)lst1");
-            assertNotNull(configLst1);
+        containsReferences(configLst1Top, "toaster2:lst1", "toaster2/lst(config)");
 
-            final JSONObject configCont1Top = models.getJSONObject("toaster2/lst(config)cont1-TOP");
-            assertNotNull(configCont1Top);
+        final JsonNode configLst1 = models.get("toaster2/lst(config)lst1");
+        assertNotNull(configLst1);
 
-            containsReferences(configCont1Top, "toaster2:cont1", "toaster2/lst(config)");
-            final JSONObject configCont1 = models.getJSONObject("toaster2/lst(config)cont1");
-            assertNotNull(configCont1);
+        final JsonNode configCont1Top = models.get("toaster2/lst(config)cont1-TOP");
+        assertNotNull(configCont1Top);
 
-            containsReferences(configCont1, "toaster2:cont11", "toaster2/lst/cont1(config)");
-            containsReferences(configCont1, "toaster2:lst11", "toaster2/lst/cont1(config)");
+        containsReferences(configCont1Top, "toaster2:cont1", "toaster2/lst(config)");
+        final JsonNode configCont1 = models.get("toaster2/lst(config)cont1");
+        assertNotNull(configCont1);
 
-            final JSONObject configCont11Top = models.getJSONObject("toaster2/lst/cont1(config)cont11-TOP");
-            assertNotNull(configCont11Top);
+        containsReferences(configCont1, "toaster2:cont11", "toaster2/lst/cont1(config)");
+        containsReferences(configCont1, "toaster2:lst11", "toaster2/lst/cont1(config)");
 
-            containsReferences(configCont11Top, "toaster2:cont11", "toaster2/lst/cont1(config)");
-            final JSONObject configCont11 = models.getJSONObject("toaster2/lst/cont1(config)cont11");
-            assertNotNull(configCont11);
+        final JsonNode configCont11Top = models.get("toaster2/lst/cont1(config)cont11-TOP");
+        assertNotNull(configCont11Top);
 
-            final JSONObject configlst11Top = models.getJSONObject("toaster2/lst/cont1(config)lst11-TOP");
-            assertNotNull(configlst11Top);
+        containsReferences(configCont11Top, "toaster2:cont11", "toaster2/lst/cont1(config)");
+        final JsonNode configCont11 = models.get("toaster2/lst/cont1(config)cont11");
+        assertNotNull(configCont11);
 
-            containsReferences(configlst11Top, "toaster2:lst11", "toaster2/lst/cont1(config)");
-            final JSONObject configLst11 = models.getJSONObject("toaster2/lst/cont1(config)lst11");
-            assertNotNull(configLst11);
-        } catch (final JSONException e) {
-            fail("JSONException wasn't expected");
-        }
+        final JsonNode configlst11Top = models.get("toaster2/lst/cont1(config)lst11-TOP");
+        assertNotNull(configlst11Top);
 
+        containsReferences(configlst11Top, "toaster2:lst11", "toaster2/lst/cont1(config)");
+        final JsonNode configLst11 = models.get("toaster2/lst/cont1(config)lst11");
+        assertNotNull(configLst11);
     }
 
     /**
      * Checks whether object {@code mainObject} contains in properties/items key $ref with concrete value.
      */
-    private void containsReferences(final JSONObject mainObject, final String childObject, final String prefix)
-            throws JSONException {
-        final JSONObject properties = mainObject.getJSONObject("properties");
+    private void containsReferences(final JsonNode mainObject, final String childObject, final String prefix) {
+        final JsonNode properties = mainObject.get("properties");
         assertNotNull(properties);
 
-        final JSONObject nodeInProperties = properties.getJSONObject(childObject);
+        final JsonNode nodeInProperties = properties.get(childObject);
         assertNotNull(nodeInProperties);
 
-        final JSONObject itemsInNodeInProperties = nodeInProperties.getJSONObject("items");
+        final JsonNode itemsInNodeInProperties = nodeInProperties.get("items");
         assertNotNull(itemsInNodeInProperties);
 
-        final String itemRef = itemsInNodeInProperties.getString("$ref");
+        final String itemRef = itemsInNodeInProperties.get("$ref").asText();
         assertEquals(prefix + childObject.split(":")[1], itemRef);
     }
 
@@ -246,7 +241,7 @@ public class ApiDocGeneratorTest {
 
                 // testing bugs.opendaylight.org bug 1290. UnionType model type.
                 final String jsonString = doc.getModels().toString();
-                assertTrue(jsonString.contains("testUnion\":{\"type\":\"-2147483648\",\"required\":false,"
+                assertTrue(jsonString.contains("testUnion\":{\"required\":false,\"type\":\"-2147483648\","
                         + "\"enum\":[\"-2147483648\",\"Some testUnion\"]}"));
             }
         }
@@ -263,13 +258,13 @@ public class ApiDocGeneratorTest {
                         this.schemaContext);
                 assertNotNull(doc);
 
-                final JSONObject models = doc.getModels();
-                final JSONObject inputTop = models.getJSONObject("(make-toast)input-TOP");
+                final ObjectNode models = doc.getModels();
+                final JsonNode inputTop = models.get("(make-toast)input-TOP");
                 final String testString =
                         "{\"toaster:input\":{\"type\":\"object\",\"items\":{\"$ref\":\"(make-toast)input\"}}}";
-                assertEquals(testString, inputTop.getJSONObject("properties").toString());
-                final JSONObject input = models.getJSONObject("(make-toast)input");
-                final JSONObject properties = input.getJSONObject("properties");
+                assertEquals(testString, inputTop.get("properties").toString());
+                final JsonNode input = models.get("(make-toast)input");
+                final JsonNode properties = input.get("properties");
                 assertTrue(properties.has("toaster:toasterDoneness"));
                 assertTrue(properties.has("toaster:toasterToastType"));
             }
@@ -322,7 +317,7 @@ public class ApiDocGeneratorTest {
 
         // TODO: we should really do some more validation of the
         // documentation...
-        /**
+        /*
          * Missing validation: Explicit validation of URLs, and their methods Input / output models.
          */
     }
@@ -355,28 +350,24 @@ public class ApiDocGeneratorTest {
     }
 
     private void validateTosterDocContainsModulePrefixes(final ApiDeclaration doc) {
-        final JSONObject topLevelJson = doc.getModels();
-        try {
-            final JSONObject configToaster = topLevelJson.getJSONObject("toaster2(config)toaster");
-            assertNotNull("(config)toaster JSON object missing", configToaster);
-            // without module prefix
-            containsProperties(configToaster, "toaster2:toasterSlot");
-
-            final JSONObject toasterSlot = topLevelJson.getJSONObject("toaster2/toaster(config)toasterSlot");
-            assertNotNull("(config)toasterSlot JSON object missing", toasterSlot);
-            // with module prefix
-            containsProperties(toasterSlot, "toaster2:toaster-augmented:slotInfo");
-
-        } catch (final JSONException e) {
-            fail("Json exception while reading JSON object. Original message " + e.getMessage());
-        }
+        final ObjectNode topLevelJson = doc.getModels();
+
+        final JsonNode configToaster = topLevelJson.get("toaster2(config)toaster");
+        assertNotNull("(config)toaster JSON object missing", configToaster);
+        // without module prefix
+        containsProperties(configToaster, "toaster2:toasterSlot");
+
+        final JsonNode toasterSlot = topLevelJson.get("toaster2/toaster(config)toasterSlot");
+        assertNotNull("(config)toasterSlot JSON object missing", toasterSlot);
+        // with module prefix
+        containsProperties(toasterSlot, "toaster2:toaster-augmented:slotInfo");
     }
 
-    private void containsProperties(final JSONObject jsonObject, final String... properties) throws JSONException {
+    private void containsProperties(final JsonNode jsonObject, final String... properties) {
         for (final String property : properties) {
-            final JSONObject propertiesObject = jsonObject.getJSONObject("properties");
+            final JsonNode propertiesObject = jsonObject.get("properties");
             assertNotNull("Properties object missing in ", propertiesObject);
-            final JSONObject concretePropertyObject = propertiesObject.getJSONObject(property);
+            final JsonNode concretePropertyObject = propertiesObject.get(property);
             assertNotNull(property + " is missing", concretePropertyObject);
         }
     }
index 3adc8569837f3638c5a97cb422899d44d6000daa..a8196dac47d562035afaa33cfa15d626e9e8c122 100644 (file)
@@ -12,7 +12,6 @@ import static org.mockito.Mockito.when;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.net.URI;
@@ -65,7 +64,6 @@ public class DocGenTestHelper {
     public void setUp() throws Exception {
         this.modules = loadModules("/yang");
         this.mapper = new ObjectMapper();
-        this.mapper.registerModule(new JsonOrgModule());
         this.mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
     }
 
index b4ab8f4f5620477c4181f610e07c82b83959a863..58478425b9d4866edea4462a897ddca078e4abf4 100644 (file)
@@ -8,9 +8,9 @@
 
 package org.opendaylight.controller.sal.rest.doc.impl;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.base.Preconditions;
 import java.sql.Date;
-import org.json.JSONObject;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -45,7 +45,7 @@ public class ModelGeneratorTest {
             if (m.getQNameModule().getNamespace().toString().equals(NAMESPACE)
                     && m.getQNameModule().getRevision().equals(REVISION)) {
 
-                final JSONObject jsonObject = generator.convertToJsonSchema(m, this.schemaContext);
+                final ObjectNode jsonObject = generator.convertToJsonSchema(m, this.schemaContext);
                 Assert.assertNotNull(jsonObject);
             }
         }