Implementation of Data Format serializer 25/62025/1
authorjanani b <janani.b@huawei.com>
Thu, 23 Aug 2018 09:11:22 +0000 (14:41 +0530)
committerjanani b <janani.b@huawei.com>
Thu, 23 Aug 2018 09:11:22 +0000 (14:41 +0530)
Data format serializer code

Issue-ID: CCSDK-376

Change-Id: Ie1954e6237374411ce3f07039030027042581d33
Signed-off-by: janani b <janani.b@huawei.com>
25 files changed:
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java [new file with mode: 0644]
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java
restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java

index 57280e2..cab6439 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
 import java.util.List;
 import java.util.Map;
 
@@ -57,17 +59,20 @@ public abstract class DataFormatSerializer {
      * @param param context memory parameter
      * @param annotations annotations
      * @return data format body
+     * @throws SvcLogicException when serialization fails
      */
     public abstract String encode(Map<String, String> param,
-        Map<String, List<Annotation>> annotations);
+        Map<String, List<Annotation>> annotations) throws SvcLogicException;
 
     /**
      * Decodes data format body to context memory parameters.
      *
      * @param dataFormatBody abstract node
      * @return context memory parameters
+     * @throws SvcLogicException when serialization fails
      */
-    public abstract Map<String, String> decode(String dataFormatBody);
+    public abstract Map<String, String> decode(String dataFormatBody)
+            throws SvcLogicException;
 
     /**
      * Returns data format serializer context.
index 5e71eea..107585a 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
 
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
+
 
 /**
  * Representation of default implementation of JSON listener.
@@ -54,13 +62,40 @@ public class DefaultJsonListener implements JsonListener {
     }
 
     @Override
-    public void enterJsonNode(String nodeName, JsonNode node, NodeType nodeType) {
-        //TODO: Implementation code.
+    public void enterJsonNode(String nodeName, JsonNode node,
+                              NodeType nodeType) throws SvcLogicException {
+        getNodeName(nodeName);
+
+        switch (nodeType) {
+            case SINGLE_INSTANCE_LEAF_NODE:
+                serializerHelper.addNode(name, modName, node.asText(), null,
+                                         SINGLE_INSTANCE_LEAF_NODE);
+                break;
+
+            case MULTI_INSTANCE_LEAF_NODE:
+                serializerHelper.addNode(name, modName, node.asText(), null,
+                                         MULTI_INSTANCE_LEAF_NODE);
+                break;
+
+            case SINGLE_INSTANCE_NODE:
+                serializerHelper.addNode(name, modName, null, null,
+                                         SINGLE_INSTANCE_NODE);
+                break;
+
+            case MULTI_INSTANCE_NODE:
+                serializerHelper.addNode(name, modName, null, null,
+                                         MULTI_INSTANCE_NODE);
+                break;
+
+            default:
+                throw new SvcLogicException(format(NODE_TYPE_ERR,
+                                                   nodeType.toString()));
+        }
     }
 
     @Override
-    public void exitJsonNode(JsonNode node) {
-        //TODO: Implementation code.
+    public void exitJsonNode(JsonNode node) throws SvcLogicException {
+        serializerHelper.exitNode();
     }
 
     @Override
@@ -68,4 +103,20 @@ public class DefaultJsonListener implements JsonListener {
         return serializerHelper;
     }
 
+    /**
+     * Parses the abstract JSON name and fills the node name and node
+     * namespace of the current JSON node.
+     *
+     * @param abstractName abstract JSON name
+     */
+    private void getNodeName(String abstractName) {
+        String[] val = abstractName.split(":");
+        if (val.length == 2) {
+            modName = val[0];
+            name = val[1];
+        } else {
+            name = val[0];
+        }
+    }
+
 }
index 20d4fa7..47cb8b2 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import static com.fasterxml.jackson.databind.node.JsonNodeType.NUMBER;
+import static com.fasterxml.jackson.databind.node.JsonNodeType.STRING;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
 
 /**
  * Implementation of JSON walker to walk through the nodes and process it.
@@ -28,8 +42,19 @@ import com.fasterxml.jackson.databind.JsonNode;
 public class DefaultJsonWalker implements JsonWalker {
 
     @Override
-    public void walk(JsonListener listener, JsonNode jsonNode) {
-        //TODO: Implementation code.
+    public void walk(JsonListener listener, JsonNode jsonNode) throws
+            SvcLogicException {
+        Iterator<Map.Entry<String, JsonNode>> children = jsonNode.fields();
+        while (children.hasNext()) {
+            Map.Entry<String, JsonNode> child = children.next();
+            JsonNode value = child.getValue();
+            String key = child.getKey();
+            if (value.isArray()) {
+                processMultiNodes(key, value, listener);
+            } else {
+                processSingleNode(key, value, listener);
+            }
+        }
     }
 
     /**
@@ -39,10 +64,18 @@ public class DefaultJsonWalker implements JsonWalker {
      * @param key      JSON name
      * @param value    JSON node
      * @param listener JSON listener
+     * @throws SvcLogicException when processing the node fails
      */
     private void processSingleNode(String key, JsonNode value,
-                                   JsonListener listener) {
-        //TODO: Implementation code.
+                                   JsonListener listener)
+            throws SvcLogicException {
+        NodeType nodeType;
+        if (!value.isContainerNode()) {
+            nodeType = SINGLE_INSTANCE_LEAF_NODE;
+        } else {
+            nodeType = SINGLE_INSTANCE_NODE;
+        }
+        processNode(key, value, nodeType, listener);
     }
 
     /**
@@ -52,9 +85,57 @@ public class DefaultJsonWalker implements JsonWalker {
      * @param key      JSON name
      * @param value    JSON node
      * @param listener JSON listener
+     * @throws SvcLogicException when processing a single instance fails
      */
     private void processMultiNodes(String key, JsonNode value,
-                                   JsonListener listener) {
-        //TODO: Implementation code.
+                                   JsonListener listener)
+            throws SvcLogicException {
+        NodeType nodeType;
+        Iterator<JsonNode> multiNodes = value.elements();
+        while (multiNodes.hasNext()) {
+            if (isLeafListNode((ArrayNode) value)) {
+                nodeType = MULTI_INSTANCE_LEAF_NODE;
+            } else {
+                nodeType = MULTI_INSTANCE_NODE;
+            }
+            JsonNode multiNode = multiNodes.next();
+            processNode(key, multiNode, nodeType, listener);
+        }
+    }
+
+    /**
+     * Processes each node by first entering the JSON node through JSON
+     * listener, second a call back to walking the rest of the tree of the
+     * node and finally exiting the node.
+     *
+     * @param key      JSON name
+     * @param node     JSON node
+     * @param nodeType JSON node type
+     * @param listener JSON listener
+     * @throws SvcLogicException when entering a JSON node fails
+     */
+    private void processNode(String key, JsonNode node, NodeType nodeType,
+                             JsonListener listener) throws SvcLogicException {
+        listener.enterJsonNode(key, node, nodeType);
+        walk(listener, node);
+        listener.exitJsonNode(node);
+    }
+
+    /**
+     * Returns true if the node corresponds to a leaf-list node; false
+     * otherwise.
+     *
+     * @param node JSON node
+     * @return true if node corresponds to leaf-list node; false otherwise
+     */
+    private boolean isLeafListNode(ArrayNode node) {
+        Iterator<JsonNode> children = node.elements();
+        while (children.hasNext()) {
+            JsonNodeType type = children.next().getNodeType();
+            if (type != STRING && type != NUMBER) {
+                return false;
+            }
+        }
+        return true;
     }
 }
index 7946d8d..5796914 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
 
 /**
  * Representation of default implementation of XML listener.
@@ -42,17 +46,34 @@ public class DefaultXmlListener implements XmlListener {
     }
 
     @Override
-    public void enterXmlElement(Element element, XmlNodeType nodeType) {
-        //TODO: Implementation code.
+    public void enterXmlElement(Element element, XmlNodeType nodeType)
+            throws SvcLogicException {
+        switch (nodeType) {
+            case TEXT_NODE:
+                serializerHelper.addNode(element.getName(),
+                                         element.getNamespace().getURI(),
+                                         element.getText(), null, null);
+                break;
+
+            case OBJECT_NODE:
+                serializerHelper.addNode(element.getName(),
+                                         element.getNamespace().getURI(),
+                                         null, null, null);
+                break;
+
+            default:
+                throw new SvcLogicException(format(NODE_TYPE_ERR,
+                                                   nodeType.toString()));
+        }
     }
 
     @Override
-    public void exitXmlElement(Element element) {
-        //TODO: Implementation code.
+    public void exitXmlElement(Element element) throws SvcLogicException {
+        serializerHelper.exitNode();
     }
 
     @Override
     public SerializerHelper serializerHelper() {
         return serializerHelper;
     }
-    }
+}
index cd2a3d4..cdc713f 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.Iterator;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlNodeType;
 
 /**
  * Implementation of XML walker to walk through the nodes and process it.
@@ -28,7 +33,16 @@ import org.dom4j.Element;
 public class DefaultXmlWalker implements XmlWalker {
 
     @Override
-    public void walk(XmlListener listener, Element xmlElement) {
-        //TODO: Implementation code.
+    public void walk(XmlListener listener, Element xmlElement) throws
+            SvcLogicException {
+        listener.enterXmlElement(xmlElement, getXmlNodeType(xmlElement));
+        if (xmlElement.hasContent() && !xmlElement.isTextOnly()) {
+            Iterator i = xmlElement.elementIterator();
+            while (i.hasNext()) {
+                Element childElement = (Element) i.next();
+                walk(listener, childElement);
+            }
+        }
+        listener.exitXmlElement(xmlElement);
     }
 }
index 851f1b4..e10a085 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR;
+
 /**
  * Represents the data format listener factory which will return JSON or XML
  * listener according to the serializer helper.
@@ -52,9 +57,11 @@ public final class DfListenerFactory {
      * @param serHelper serializer helper
      * @param params    parameters
      * @return data format listener
+     * @throws SvcLogicException when the data format type is wrong
      */
     public Listener getListener(SerializerHelper serHelper,
-                                YangParameters params) {
+                                YangParameters params)
+            throws SvcLogicException {
         Listener listener;
         switch (params.format) {
             case JSON:
@@ -65,9 +72,9 @@ public final class DfListenerFactory {
                 listener = new DefaultXmlListener(serHelper);
                 break;
 
-            //TODO: DataFormat Exception code to be added.
             default:
-                throw new IllegalArgumentException("In correct format");
+                throw new SvcLogicException(format(FORMAT_ERR,
+                                                   params.format));
         }
         return listener;
     }
index 25b23fe..bd0285e 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR;
+
 /**
  * Represents the data format serializer factory which will return JSON or XML
  * serializer according to the serializer context.
@@ -52,10 +57,11 @@ public final class DfSerializerFactory {
      * @param serCtx serializer context
      * @param params parameters
      * @return data format serializer
+     * @throws SvcLogicException when the data format type is wrong
      */
-    public DataFormatSerializer getSerializer(DataFormatSerializerContext
-                                                      serCtx,
-                                YangParameters params) {
+    public DataFormatSerializer getSerializer(DataFormatSerializerContext serCtx,
+                                              YangParameters params)
+            throws SvcLogicException {
         DataFormatSerializer serializer;
         switch (params.format) {
             case JSON:
@@ -66,9 +72,9 @@ public final class DfSerializerFactory {
                 serializer = new XmlSerializer(serCtx);
                 break;
 
-            //TODO: DataFormat Exception code to be added.
             default:
-                throw new IllegalArgumentException("In correct format");
+                throw new SvcLogicException(format(FORMAT_ERR,
+                                                   params.format));
         }
         return serializer;
     }
diff --git a/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java b/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java
new file mode 100644 (file)
index 0000000..6acb04a
--- /dev/null
@@ -0,0 +1,216 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import static javax.xml.transform.OutputKeys.INDENT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.XmlNodeType.OBJECT_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.XmlNodeType.TEXT_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+
+/**
+ * Utilities for data format serializer.
+ */
+public final class DfSerializerUtil {
+
+    static final String JSON_WRITE_ERR = "Unable to write to JSON from " +
+            "properties.";
+
+    static final String NODE_TYPE_ERR = "The node type %s is not supported.";
+
+    static final String JSON_LIS_ERR = "The JSON serializer doesn't have " +
+            "JSON listener";
+
+    static final String XML_LIS_ERR = "The XML serializer doesn't have XML " +
+            "listener";
+
+    static final String JSON_TREE_ERR = "Unable to form JSON tree object from" +
+            " the JSON body provided.";
+
+    static final String XML_TREE_ERR = "Unable to form XML tree object from " +
+            "the XML body provided.";
+
+    static final String FORMAT_ERR = "Only JSON and XML formats are supported" +
+            ". %s is not supported";
+
+    static final String PROP_NODE_ERR = "The property node doesn't have " +
+            "schema node bound to it.";
+
+    static final String DF_ERR = "Type mismatch for the node %s. The schema " +
+            "node does not match with the data format node type %s.";
+
+    static final String UTF_HEADER = "<?xml version=\"1.0\" " +
+            "encoding=\"UTF-8\"?>";
+
+    static final String XML_PREFIX = "yangid";
+
+    private static final String YES = "yes";
+
+    private static final String INDENT_XMLNS = "{http://xml.apache" +
+            ".org/xslt}indent-amount";
+
+    private static final String XML_PARSE_ERR = "Unable to parse the xml to " +
+            "document : \n";
+
+    private static final String URI_ERR = "Unable to parse the URI";
+
+    //No instantiation.
+    private DfSerializerUtil() {
+    }
+
+    /**
+     * Returns the writer which contains the pretty formatted XML string.
+     *
+     * @param input  input XML
+     * @param indent indentation level
+     * @return writer with XML
+     * @throws SvcLogicException when transformation of source fails
+     */
+    static Writer getXmlWriter(String input, String indent) 
+            throws SvcLogicException {
+        try {
+            Transformer transformer = TransformerFactory.newInstance()
+                    .newTransformer();
+            transformer.setOutputProperty(INDENT, YES);
+            transformer.setOutputProperty(INDENT_XMLNS, indent);
+            StreamResult result = new StreamResult(new StringWriter());
+            DOMSource source = new DOMSource(parseXml(input));
+            transformer.transform(source, result);
+            return result.getWriter();
+        } catch (TransformerException e) {
+            throw new SvcLogicException(XML_PARSE_ERR + input, e);
+        }
+    }
+
+    /**
+     * Parses the XML and converts it into dom document which can be used for
+     * formatting the XML.
+     *
+     * @param in input XML
+     * @return dom document of XML
+     * @throws SvcLogicException when document building fails
+     */
+    private static Document parseXml(String in) throws SvcLogicException {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        DocumentBuilder db;
+        try {
+            db = dbf.newDocumentBuilder();
+            InputSource is = new InputSource(new StringReader(in));
+            return db.parse(is);
+        } catch (SAXException | IOException | ParserConfigurationException e) {
+            throw new SvcLogicException(XML_PARSE_ERR + in, e);
+        }
+    }
+
+    /**
+     * Returns the resolved namespace object from the input received from the
+     * abstract data format.
+     *
+     * @param mName     module name
+     * @param curSchema current schema
+     * @param ctx       schema context
+     * @param mUri      module URI
+     * @param pNode     properties node
+     * @return namespace
+     * @throws SvcLogicException when resolving namespace fails
+     */
+    static Namespace getResolvedNamespace(String mName, SchemaNode curSchema,
+                                          SchemaContext ctx, String mUri,
+                                          PropertiesNode pNode)
+            throws SvcLogicException {
+        Module m = null;
+        URI namespace = curSchema.getQName().getNamespace();
+
+        if (mName != null) {
+            m = ctx.findModule(mName).get();
+            namespace = m == null ? null : m.getNamespace();
+        }
+        if (mUri != null) {
+            try {
+                m = ctx.findModule(new URI(mUri)).get();
+            } catch (URISyntaxException e) {
+                throw new SvcLogicException(URI_ERR, e);
+            }
+            namespace = m == null ? null : m.getNamespace();
+            mName = m.getName();
+        }
+
+        if (mName == null && mUri == null) {
+            return pNode.namespace();
+        }
+
+        return new Namespace(mName, namespace, getRevision(m.getRevision()));
+    }
+
+    /**
+     * Returns the node type of a XML element.
+     *
+     * @param element XML element
+     * @return node type of the XML element
+     */
+    static XmlNodeType getXmlNodeType(Element element) {
+        Element newElement = element.createCopy();
+        newElement.remove(element.getNamespace());
+        return newElement.hasContent() && newElement.isTextOnly() ?
+                TEXT_NODE : OBJECT_NODE;
+    }
+
+    /**
+     * Resolves the super type to the base type from type definition.
+     *
+     * @param type super type
+     * @return base type definition
+     */
+    static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+        TypeDefinition superType;
+        for(superType = type; superType.getBaseType() != null;
+            superType = superType.getBaseType()) {
+        }
+        return superType;
+    }
+
+}
index 2a9220a..89fd4c8 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
 
 /**
@@ -38,14 +39,17 @@ public interface JsonListener extends Listener {
      * @param nodeName JSON node name
      * @param node     JSON node
      * @param nodeType JSON node type
+     * @throws SvcLogicException when node type is of wrong format
      */
-    void enterJsonNode(String nodeName, JsonNode node, NodeType nodeType);
+    void enterJsonNode(String nodeName, JsonNode node, NodeType nodeType)
+            throws SvcLogicException;
 
     /**
      * Call back invoked during JSON node exit. All the related information
      * can be obtained from the JSON node.
      *
      * @param node JSON node
+     * @throws SvcLogicException when JSON node exit doesn't happen
      */
-    void exitJsonNode(JsonNode node);
+    void exitJsonNode(JsonNode node) throws SvcLogicException;
 }
index b562e71..1be1309 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeWalker;
+
+import java.io.IOException;
+import java.io.Writer;
 import java.util.List;
 import java.util.Map;
 
 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormat.JSON;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.*;
 
 /**
  * Representation of JSON serializer which encodes properties to JSON and
@@ -42,14 +52,38 @@ public class JsonSerializer extends DataFormatSerializer {
 
     @Override
     public String encode(Map<String, String> param,
-                         Map<String, List<Annotation>> annotations) {
-        //TODO: Implementation code.
-        return null;
+                         Map<String, List<Annotation>> annotations)
+            throws SvcLogicException {
+        PropertiesNode propNode = serializerContext().getPropNodeSerializer()
+                .encode(param);
+        PropertiesNodeWalker nodeWalker = new DefaultPropertiesNodeWalker<>();
+        PropertiesNodeJsonListener jsonLis = new PropertiesNodeJsonListener();
+        nodeWalker.walk(jsonLis, propNode);
+        Writer writer = jsonLis.getWriter();
+        return writer.toString();
     }
 
     @Override
-    public Map<String, String> decode(String dataFormatBody) {
-        //TODO: Implementation code.
-        return null;
+    public Map<String, String> decode(String dataFormatBody)
+            throws SvcLogicException {
+        if (!(serializerContext().listener() instanceof JsonListener)) {
+            throw new SvcLogicException(JSON_LIS_ERR);
+        }
+
+        JsonListener listener = (JsonListener) serializerContext().listener();
+        JsonWalker walker = new DefaultJsonWalker();
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode jsonNode;
+
+        try {
+            jsonNode = mapper.readTree(dataFormatBody);
+        } catch (IOException e) {
+            throw new SvcLogicException(JSON_TREE_ERR, e);
+        }
+
+        walker.walk(listener, jsonNode);
+
+        return serializerContext().getPropNodeSerializer().decode(
+                listener.serializerHelper().getPropertiesNode());
     }
 }
index e3fb4d5..588070a 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 
 /**
  * Abstraction of an entity which provides interface for JSON walk. This
@@ -36,6 +37,8 @@ public interface JsonWalker {
      *
      * @param listener JSON listener implemented by the protocol
      * @param jsonNode root node of the JSON data tree
+     * @throws SvcLogicException when walking the JSON node fails
      */
-    void walk(JsonListener listener, JsonNode jsonNode);
+    void walk(JsonListener listener, JsonNode jsonNode)
+            throws SvcLogicException;
 }
index 1f8195e..a3e30c4 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+
+import java.util.Deque;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.DF_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.PROP_NODE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getResolvedNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.resolveBaseTypeFrom;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
+import static org.opendaylight.yangtools.yang.data.util.ParserStreamUtils.findSchemaNodeByNameAndNamespace;
 
 /**
  * Representation of MDSAL based serializer helper, which adds properties
@@ -53,6 +79,12 @@ public class MdsalSerializerHelper extends SerializerHelper<SchemaNode, SchemaCo
     protected MdsalSerializerHelper(SchemaNode n, SchemaContext c,
                                     String u) {
         super(n, c, u);
+        Namespace ns = new Namespace(n.getQName().getLocalName(),
+                                     n.getQName().getNamespace(),
+                                     getRevision(n.getQName().getRevision()));
+        propNode = new RootNode<>(n.getQName().getLocalName(), ns,
+                                  getSchemaNode(), u);
+        curSchemaNode = getSchemaNode();
     }
 
     @Override
@@ -72,18 +104,166 @@ public class MdsalSerializerHelper extends SerializerHelper<SchemaNode, SchemaCo
 
     @Override
     protected void addNode(String name, String nameSpace, String value,
-                           String valNameSpace, NodeType type) {
-        //TODO: Implementation code.
+                           String valNameSpace, NodeType type)
+            throws SvcLogicException {
+        Namespace ns;
+        if (type == null) {
+            ns = getResolvedNamespace(null, curSchemaNode, getSchemaCtx(),
+                                      nameSpace, propNode);
+        } else {
+            ns = getResolvedNamespace(nameSpace, curSchemaNode, getSchemaCtx(),
+                                      nameSpace, propNode);
+        }
+        if (isChildPresent(name, ns)) {
+            addNodeToProperty(name, ns, value, valNameSpace, type);
+        }
     }
 
     @Override
-    protected void exitNode() {
-        //TODO: Implementation code.
+    protected void exitNode() throws SvcLogicException {
+        propNode = propNode.parent();
+        if (propNode != null) {
+            NodeType type = propNode.nodeType();
+            if (type == MULTI_INSTANCE_HOLDER_NODE ||
+                    type == MULTI_INSTANCE_LEAF_HOLDER_NODE) {
+                propNode = propNode.parent();
+            }
+        }
+        if (propNode == null || propNode.appInfo() == null
+                || !(propNode.appInfo() instanceof SchemaNode)) {
+            throw new SvcLogicException(PROP_NODE_ERR);
+        }
+        curSchemaNode = (SchemaNode) propNode.appInfo();
     }
 
     @Override
     protected PropertiesNode getPropertiesNode() {
-        //TODO: Implementation code.
-        return null;
+        return propNode;
+    }
+
+    /**
+     * Adds the node to property node based on the type of the schema node,
+     * which is decided based on the name and namespace of the input
+     * information.
+     *
+     * @param name         name of the node
+     * @param ns           namespace of the node
+     * @param value        value of the node if its a leaf/leaf-list
+     * @param valNamespace namespace of the value
+     * @param type         type of the node
+     * @throws SvcLogicException when adding child fails
+     */
+    private void addNodeToProperty(String name, Namespace ns, String value,
+                                   String valNamespace, NodeType type)
+            throws SvcLogicException {
+        Namespace valueNs;
+        if (type != null) {
+            validateNodeType(type);
+        }
+        if (curSchemaNode instanceof LeafSchemaNode) {
+            valueNs = getValueNs(curSchemaNode, valNamespace, type);
+            propNode = propNode.addChild(name, ns,
+                                         SINGLE_INSTANCE_LEAF_NODE,
+                                         value, valueNs, curSchemaNode);
+        } else if (curSchemaNode instanceof LeafListSchemaNode) {
+            valueNs = getValueNs(curSchemaNode, valNamespace, type);
+            propNode = propNode.addChild(null, name, ns,
+                                         MULTI_INSTANCE_LEAF_NODE, value,
+                                         valueNs, curSchemaNode);
+        } else if (curSchemaNode instanceof ListSchemaNode) {
+            propNode = propNode.addChild(null, name, ns, MULTI_INSTANCE_NODE,
+                                         curSchemaNode);
+        } else {
+            propNode = propNode.addChild(name, ns, SINGLE_INSTANCE_NODE,
+                                         curSchemaNode);
+        }
+    }
+
+    /**
+     * Returns the namespace of the value namespace in case of identity ref.
+     *
+     * @param schemaNode schema node
+     * @param valNs      value name space
+     * @param nodeType   node type
+     * @return namespace of value namespace
+     * @throws SvcLogicException when namespace resolution fails for identityref
+     */
+    private Namespace getValueNs(SchemaNode schemaNode, String valNs,
+                                 NodeType nodeType) throws SvcLogicException {
+        Namespace ns = null;
+        if (valNs != null) {
+            TypeDefinition type = ((LeafSchemaNode) schemaNode).getType();
+            TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+            if (baseType instanceof IdentityrefTypeDefinition) {
+                if (nodeType == null) {
+                    ns = getResolvedNamespace(null,schemaNode, getSchemaCtx(),
+                                              valNs, propNode);
+                } else {
+                    ns = getResolvedNamespace(valNs, schemaNode, getSchemaCtx(),
+                                              null, propNode);
+                }
+            }
+        }
+        return ns;
+    }
+
+    /**
+     * Validates that the node type from the data format matches with that of
+     * the corresponding schema node.
+     *
+     * @param type node type from the abstract data format
+     * @throws SvcLogicException when the node type is wrong
+     */
+    private void validateNodeType(NodeType type) throws SvcLogicException {
+        boolean verify;
+        switch (type) {
+            case SINGLE_INSTANCE_LEAF_NODE:
+                verify = curSchemaNode instanceof LeafSchemaNode;
+                break;
+
+            case MULTI_INSTANCE_LEAF_NODE:
+                verify = curSchemaNode instanceof LeafListSchemaNode;
+                break;
+
+            case MULTI_INSTANCE_NODE:
+                verify = curSchemaNode instanceof ListSchemaNode;
+                break;
+
+            case SINGLE_INSTANCE_NODE:
+                verify = (!(curSchemaNode instanceof LeafSchemaNode) &&
+                        !(curSchemaNode instanceof LeafListSchemaNode) &&
+                        !(curSchemaNode instanceof ListSchemaNode));
+                break;
+
+            default:
+                throw new SvcLogicException(format(NODE_TYPE_ERR,
+                                                   type.toString()));
+        }
+        if (!verify) {
+            throw new SvcLogicException(format(DF_ERR, curSchemaNode
+                    .getQName().getLocalName(), type.toString()));
+        }
+    }
+
+    /**
+     * Returns true if the child schema is present with the name and
+     * namespace inside the current schema node, if present updates the
+     * current schema node; false otherwise.
+     *
+     * @param name      name of the child schema node
+     * @param namespace namespace of the child schema node
+     * @return returns true if the child schema is available; false otherwise
+     */
+    private boolean isChildPresent(String name, Namespace namespace) {
+        Deque<DataSchemaNode> dataSchema = findSchemaNodeByNameAndNamespace(
+                (DataSchemaNode) curSchemaNode, name, namespace.moduleNs());
+        if (dataSchema != null) {
+            DataSchemaNode node = dataSchema.pop();
+            if (node != null) {
+                curSchemaNode = node;
+                return true;
+            }
+        }
+        return false;
     }
 }
index ec13067..e51ccf7 100644 (file)
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import com.google.gson.stream.JsonWriter;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.LeafNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeListener;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
 
+import java.io.IOException;
+import java.io.StringWriter;
 import java.io.Writer;
+import java.util.Collection;
+import java.util.Map;
+
+import static com.google.common.base.Strings.repeat;
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.JSON_WRITE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
 
 /**
  * Representation of JSON implementation of properties node listener.
@@ -46,25 +60,160 @@ public class PropertiesNodeJsonListener implements PropertiesNodeListener{
      * indenting the writer.
      */
     public PropertiesNodeJsonListener() {
+        writer = new StringWriter();
+        jsonWriter = new JsonWriter(writer);
+        jsonWriter.setIndent(repeat(" ", 4));
     }
 
     @Override
-    public void start(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void start(PropertiesNode node) throws SvcLogicException {
+        try {
+            jsonWriter.beginObject();
+        } catch (IOException e) {
+            throw new SvcLogicException(JSON_WRITE_ERR, e);
+        }
     }
 
     @Override
-    public void end(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void end(PropertiesNode node) throws SvcLogicException {
+        try {
+            jsonWriter.endObject();
+            jsonWriter.flush();
+        } catch (IOException e) {
+            throw new SvcLogicException(JSON_WRITE_ERR, e);
+        }
     }
 
     @Override
-    public void enterPropertiesNode(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void enterPropertiesNode(PropertiesNode node)
+            throws SvcLogicException {
+        String val;
+        String nodeName = getNodeName(node);
+        try {
+            switch (node.nodeType()) {
+                case SINGLE_INSTANCE_NODE:
+                    jsonWriter.name(nodeName);
+                    jsonWriter.beginObject();
+                    break;
+
+                case MULTI_INSTANCE_NODE:
+                    jsonWriter.beginObject();
+                    break;
+
+                case SINGLE_INSTANCE_LEAF_NODE:
+                    val = getValueWithNs((LeafNode) node);
+                    jsonWriter.name(nodeName).value(val);
+                    break;
+
+                case MULTI_INSTANCE_HOLDER_NODE:
+                case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+                    jsonWriter.name(nodeName);
+                    jsonWriter.beginArray();
+                    break;
+
+                case MULTI_INSTANCE_LEAF_NODE:
+                    val = getValueWithNs((LeafNode) node);
+                    jsonWriter.value(val);
+                    break;
+
+                default:
+                    throw new SvcLogicException(format(
+                            NODE_TYPE_ERR, node.nodeType().toString()));
+
+            }
+        } catch (IOException e) {
+            throw new SvcLogicException(JSON_WRITE_ERR, e);
+        }
     }
 
     @Override
-    public void exitPropertiesNode(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void exitPropertiesNode(PropertiesNode node) throws SvcLogicException {
+        walkAugmentationNode(node);
+        try {
+            switch (node.nodeType()) {
+                case SINGLE_INSTANCE_NODE:
+                case MULTI_INSTANCE_NODE:
+                    jsonWriter.endObject();
+                    break;
+
+                case MULTI_INSTANCE_HOLDER_NODE:
+                case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+                    jsonWriter.endArray();
+                    break;
+
+                case  SINGLE_INSTANCE_LEAF_NODE:
+                case MULTI_INSTANCE_LEAF_NODE:
+                    break;
+
+                default:
+                    throw new SvcLogicException(format(
+                            NODE_TYPE_ERR, node.nodeType().toString()));
+            }
+        } catch (IOException e) {
+            throw new SvcLogicException(JSON_WRITE_ERR, e);
+        }
+    }
+
+    /**
+     * Returns the writer.
+     *
+     * @return writer
+     */
+    public Writer getWriter() {
+        return writer;
+    }
+
+    /**
+     * Returns the abstract JSON node name to be used in JSON data format
+     * from the properties node.
+     *
+     * @param node properties node
+     * @return abstract JSON node
+     */
+    private String getNodeName(PropertiesNode node) {
+        PropertiesNode parent = node.parent();
+        if (parent instanceof RootNode || !parent.namespace().moduleName()
+                .equals(node.namespace().moduleName())) {
+            return node.namespace().moduleName() + ":" + node.name();
+        }
+        return node.name();
+    }
+
+    /**
+     * Returns the value of JSON leaf node with module name if required.
+     *
+     * @param node properties node
+     * @return value with namespace
+     */
+    private String getValueWithNs(LeafNode node) {
+        Namespace valNs = node.valueNs();
+        String modName = (valNs == null) ? null : valNs.moduleName();
+        if (modName != null) {
+            return modName + ":" + node.value();
+        }
+        return node.value();
+    }
+
+    /**
+     * Gets all the augmentation of the given node and walks through it.
+     *
+     * @param node properties node
+     * @throws SvcLogicException when walking the properties node fails
+     */
+    private void walkAugmentationNode(PropertiesNode node)
+            throws SvcLogicException {
+        for (Map.Entry<Object, Collection<PropertiesNode>>
+                augToChild : node.augmentations().asMap().entrySet()) {
+            Collection<PropertiesNode> augChild = augToChild.getValue();
+            if (!augChild.isEmpty()) {
+                DefaultPropertiesNodeWalker walker = new
+                        DefaultPropertiesNodeWalker();
+                for (PropertiesNode p : augChild) {
+                    enterPropertiesNode(p);
+                    walker.walkChildNode(this, p);
+                    exitPropertiesNode(p);
+                }
+            }
+        }
     }
 }
index cfc59ca..cf59b77 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
 import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.LeafNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeListener;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
 
 import java.io.Writer;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
 import java.util.Stack;
 
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.UTF_HEADER;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_PREFIX;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlWriter;
+
 /**
  * Representation of XML implementation of properties node listener.
  */
@@ -60,21 +76,169 @@ public class PropertiesNodeXmlListener implements PropertiesNodeListener {
 
     @Override
     public void start(PropertiesNode node) {
-        //TODO: Implementation code.
+        //Do Nothing.
     }
 
     @Override
-    public void end(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void end(PropertiesNode node) throws SvcLogicException {
+        xmlData = UTF_HEADER + xmlData;
+        writer = getXmlWriter(xmlData, "4");
     }
 
     @Override
-    public void enterPropertiesNode(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void enterPropertiesNode(PropertiesNode node)
+            throws SvcLogicException {
+        Element element = null;
+        String ns = getNodeNamespace(node);
+        switch (node.nodeType()) {
+            case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+            case MULTI_INSTANCE_HOLDER_NODE:
+                break;
+
+            case SINGLE_INSTANCE_NODE:
+            case MULTI_INSTANCE_NODE:
+                element = addElement(ns, node);
+                break;
+
+            case MULTI_INSTANCE_LEAF_NODE:
+            case SINGLE_INSTANCE_LEAF_NODE:
+                element = addElement(ns, node);
+                setValueWithNs(element, (LeafNode) node);
+                break;
+
+            default:
+                throw new SvcLogicException(format(
+                        NODE_TYPE_ERR, node.nodeType().toString()));
+        }
+        if (element != null) {
+            if (elementStack.isEmpty()) {
+                rootElement = element;
+            }
+            elementStack.push(element);
+        }
     }
 
     @Override
-    public void exitPropertiesNode(PropertiesNode node) {
-        //TODO: Implementation code.
+    public void exitPropertiesNode(PropertiesNode node)
+            throws SvcLogicException {
+        walkAugmentationNode(node);
+        switch (node.nodeType()) {
+            case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+            case MULTI_INSTANCE_HOLDER_NODE:
+                break;
+
+            case SINGLE_INSTANCE_NODE:
+            case MULTI_INSTANCE_NODE:
+            case MULTI_INSTANCE_LEAF_NODE:
+            case SINGLE_INSTANCE_LEAF_NODE:
+                if (!elementStack.isEmpty() &&
+                        elementStack.peek().equals(rootElement)) {
+                    xmlData = rootElement.asXML();
+                } else {
+                    elementStack.pop();
+                }
+                break;
+
+            default:
+                throw new SvcLogicException(format(
+                        NODE_TYPE_ERR, node.nodeType().toString()));
+        }
+    }
+
+    /**
+     * Returns the writer.
+     *
+     * @return writer
+     */
+    public Writer getWriter() {
+        return writer;
+    }
+
+    /**
+     * Adds an XML element to the stack with namespace if present. If the
+     * stack is empty it creates new document and adds element else adds to
+     * the parent element.
+     *
+     * @param ns   namespace of the element
+     * @param node properties node
+     * @return new added element
+     */
+    private Element addElement(String ns, PropertiesNode node) {
+        Element element;
+        if (elementStack.isEmpty()) {
+            Document doc = DocumentHelper.createDocument();
+            if (ns != null) {
+                element = doc.addElement(node.name(), ns);
+            } else {
+                element = doc.addElement(node.name());
+            }
+        } else {
+            element = elementStack.peek();
+            if (ns != null) {
+                element = element.addElement(node.name(), ns);
+            } else {
+                element = element.addElement(node.name());
+            }
+        }
+
+        return element;
+    }
+
+    /**
+     * Returns the abstract XML namespace to be used in XML data format from
+     * the properties node.
+     *
+     * @param node properties node
+     * @return abstract XML namespace
+     */
+    private String getNodeNamespace(PropertiesNode node) {
+        PropertiesNode parent = node.parent();
+        if (parent instanceof RootNode || !parent.namespace().moduleName()
+                .equals(node.namespace().moduleName())) {
+            return node.namespace().moduleNs().toString();
+        }
+        return null;
+    }
+
+    /**
+     * Sets the value to the element for a leaf node and adds the value
+     * namespace if required.
+     *
+     * @param element XML element
+     * @param node leaf properties node
+     */
+    private void setValueWithNs(Element element, LeafNode node) {
+        Namespace valNs = node.valueNs();
+        URI modNs = (valNs == null) ? null : valNs.moduleNs();
+        String val = node.value();
+        if (modNs != null) {
+            element.addNamespace(XML_PREFIX, modNs.toString());
+            element.setText(XML_PREFIX + ":" + val);
+        } else {
+            element.setText(val);
+        }
+    }
+
+    /**
+     * Gets all the augmentation of the given node and walks through it.
+     *
+     * @param node properties node
+     * @throws SvcLogicException when walking the properties node fails
+     */
+    private void walkAugmentationNode(PropertiesNode node)
+            throws SvcLogicException {
+        for (Map.Entry<Object, Collection<PropertiesNode>>
+                augToChild : node.augmentations().asMap().entrySet()) {
+            Collection<PropertiesNode> augChild = augToChild.getValue();
+            if (!augChild.isEmpty()) {
+                DefaultPropertiesNodeWalker walker = new
+                        DefaultPropertiesNodeWalker();
+                for (PropertiesNode p : augChild) {
+                    enterPropertiesNode(p);
+                    walker.walkChildNode(this, p);
+                    exitPropertiesNode(p);
+                }
+            }
+        }
     }
 }
index 2466023..db9befb 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
 
@@ -92,15 +93,19 @@ public abstract class SerializerHelper<T, P> {
      * @param valNameSpace value namespace for identityref, could be module
      *                     name or namespace
      * @param type         type of node if known like in case of JSON
+     * @throws SvcLogicException when adding node fails
      */
     protected abstract void addNode(String name, String nameSpace, String value,
-                                    String valNameSpace, NodeType type);
+                                    String valNameSpace, NodeType type)
+            throws SvcLogicException;
 
     /**
      * Exits the node, in case if it's leaf node then it adds to the properties
      * map.
+     *
+     * @throws SvcLogicException when properties node tree is improper
      */
-    protected abstract void exitNode();
+    protected abstract void exitNode() throws SvcLogicException;
 
     /**
      * Returns the built properties corresponding to the data.
index 0fbf4c3..784e7af 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 
 /**
  * Abstraction of an entity which provides call back methods, which in turn
@@ -36,14 +37,17 @@ public interface XmlListener extends Listener {
      *
      * @param element  current XML element
      * @param nodeType node type of the element
+     * @throws SvcLogicException when node type is of wrong format
      */
-    void enterXmlElement(Element element, XmlNodeType nodeType);
+    void enterXmlElement(Element element, XmlNodeType nodeType)
+            throws SvcLogicException;
 
     /**
      * Callback invoked during a node exit. All the related information about
      * the node can be obtained from the element.
      *
      * @param element current xml element.
+     * @throws SvcLogicException when XML node exit doesn't happen
      */
-    void exitXmlElement(Element element);
+    void exitXmlElement(Element element) throws SvcLogicException;
 }
index 5164700..6eeb4b8 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeWalker;
+
+import java.io.Writer;
 import java.util.List;
 import java.util.Map;
 
 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormat.XML;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_LIS_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_TREE_ERR;
 
 /**
  * Representation of XML serializer which encodes properties to XML and
@@ -42,14 +53,36 @@ public class XmlSerializer extends DataFormatSerializer {
 
     @Override
     public String encode(Map<String, String> param,
-                         Map<String, List<Annotation>> annotations) {
-        //TODO: Implementation code.
-        return null;
+                         Map<String, List<Annotation>> annotations)
+            throws SvcLogicException {
+        PropertiesNode propNode = serializerContext().getPropNodeSerializer()
+                .encode(param);
+        PropertiesNodeWalker nodeWalker = new DefaultPropertiesNodeWalker<>();
+        PropertiesNodeXmlListener xmlListener = new PropertiesNodeXmlListener();
+        nodeWalker.walk(xmlListener, propNode);
+        Writer writer = xmlListener.getWriter();
+        return writer.toString();
     }
 
     @Override
-    public Map<String, String> decode(String dataFormatBody) {
-        //TODO: Implementation code.
-        return null;
+    public Map<String, String> decode(String dataFormatBody)
+            throws SvcLogicException {
+        if (!(serializerContext().listener() instanceof XmlListener)) {
+            throw new SvcLogicException(XML_LIS_ERR);
+        }
+
+        XmlListener listener = (XmlListener) serializerContext().listener();
+        XmlWalker walker = new DefaultXmlWalker();
+        Document document;
+
+        try {
+            document = DocumentHelper.parseText(dataFormatBody);
+        } catch (DocumentException e) {
+            throw new SvcLogicException(XML_TREE_ERR, e);
+        }
+        walker.walk(listener, document.getRootElement());
+
+        return serializerContext().getPropNodeSerializer().decode(
+                listener.serializerHelper().getPropertiesNode());
     }
 }
\ No newline at end of file
index 6fed510..3835faa 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
 import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 
 /**
  * Abstraction of an entity which provides interface for XML walk. This
@@ -36,6 +37,8 @@ public interface XmlWalker {
      *
      * @param listener   XML listener implemented by the protocol
      * @param xmlElement root element of the XML data tree
+     * @throws SvcLogicException when walking the XML node fails
      */
-    void walk(XmlListener listener, Element xmlElement);
+    void walk(XmlListener listener, Element xmlElement) throws
+            SvcLogicException;
 }
index a8a9b49..d912091 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -40,7 +42,7 @@ public class DefaultPropertiesNodeListener implements PropertiesNodeListener {
     }
 
     @Override
-    public void end(PropertiesNode node) {
+    public void end(PropertiesNode node) throws SvcLogicException {
         exitPropertiesNode(node);
     }
 
@@ -57,7 +59,8 @@ public class DefaultPropertiesNodeListener implements PropertiesNodeListener {
     }
 
     @Override
-    public void exitPropertiesNode(PropertiesNode node) {
+    public void exitPropertiesNode(PropertiesNode node) throws
+            SvcLogicException {
         if (!node.augmentations().isEmpty()) {
             for (Map.Entry<Object, Collection<PropertiesNode>> augmentationTochild
                     : node.augmentations().asMap().entrySet()) {
index 041210f..8497805 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
 import java.util.Map;
 
 /**
@@ -31,7 +33,7 @@ public class DefaultPropertiesNodeWalker<T extends NodeChild> implements Propert
 
     @Override
     public void walk(PropertiesNodeListener listener,
-                     PropertiesNode propertiesNode) {
+                     PropertiesNode propertiesNode) throws SvcLogicException {
         listener.start(propertiesNode);
         walkChildNode(listener, propertiesNode);
         listener.end(propertiesNode);
@@ -42,9 +44,11 @@ public class DefaultPropertiesNodeWalker<T extends NodeChild> implements Propert
      *
      * @param listener properties node listener
      * @param propertiesNode properties node
+     * @throws SvcLogicException when properties node walking fails
      */
     public void walkChildNode(PropertiesNodeListener listener,
-                              PropertiesNode propertiesNode) {
+                              PropertiesNode propertiesNode)
+            throws SvcLogicException {
         Map<String, T> children = getChildren(propertiesNode);
         if (children != null) {
             for (Map.Entry<String, T> entry : children.entrySet()) {
index 20b06d0..c241462 100644 (file)
@@ -86,7 +86,8 @@ public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<Sche
     }
 
     @Override
-    public Map<String, String> decode(PropertiesNode propertiesNode) {
+    public Map<String, String> decode(PropertiesNode propertiesNode)
+            throws SvcLogicException {
         PropertiesNodeWalker walker = new DefaultPropertiesNodeWalker<>();
         DefaultPropertiesNodeListener listener = new DefaultPropertiesNodeListener();
         walker.walk(listener, propertiesNode);
index 5bf7fe9..7b97ffa 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
 /**
  * Abstraction of properties node listener.
  */
@@ -29,27 +31,31 @@ public interface PropertiesNodeListener {
      * Pre-configurations required before starting the walking.
      *
      * @param node properties node
+     * @throws SvcLogicException when the pre-configuration fails
      */
-    void start(PropertiesNode node);
+    void start(PropertiesNode node) throws SvcLogicException;
 
     /**
      * Post-configurations required after starting the walking.
      *
      * @param node properties node
+     * @throws SvcLogicException when the post-configuration fails
      */
-    void end(PropertiesNode node);
+    void end(PropertiesNode node) throws SvcLogicException;
 
     /**
      * Enters the properties node.
      *
      * @param node properties node
+     * @throws SvcLogicException when entering the properties node fails
      */
-    void enterPropertiesNode(PropertiesNode node);
+    void enterPropertiesNode(PropertiesNode node) throws SvcLogicException;
 
     /**
      * Enters the properties node.
      *
      * @param node properties node
+     * @throws SvcLogicException when exiting the properties node fails
      */
-    void exitPropertiesNode(PropertiesNode node);
+    void exitPropertiesNode(PropertiesNode node) throws SvcLogicException;
 }
index 3e34837..fe6fed4 100644 (file)
@@ -77,10 +77,11 @@ public abstract class PropertiesNodeSerializer<T, P> {
      * Decodes from properties-node to properties map.
      *
      * @param propertiesNode properties-node
-     * @throws SvcLogicException fails to decode properties node to properties
      * @return parameter map
+     * @throws SvcLogicException fails to decode properties node to properties
      */
-    public abstract Map<String, String> decode(PropertiesNode propertiesNode) throws SvcLogicException;
+    public abstract Map<String, String> decode(PropertiesNode propertiesNode)
+            throws SvcLogicException;
 
     /**
      * Returns the schema node of the property
index 48433e2..36ee4dd 100644 (file)
 
 package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
 
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
 /**
  * Abstraction of properties node walker
  */
 public interface PropertiesNodeWalker {
-
     /**
      * Walks the properties node with the listener.
      *
      * @param listener properties node listener.
      * @param propertiesNode properties node
+     * @throws SvcLogicException when walking the properties node fails
      */
-    void walk(PropertiesNodeListener listener, PropertiesNode propertiesNode);
+    void walk(PropertiesNodeListener listener, PropertiesNode propertiesNode)
+            throws SvcLogicException;
 }
index 7d9035e..c7f7340 100644 (file)
@@ -44,7 +44,15 @@ public class RootNode<T extends NodeChild> extends PropertiesNode {
 
     private Map<String, T> children = new HashMap<String, T>();
 
-    protected RootNode(String name, Namespace namespace,
+    /**
+     * Creates an instance of the root node to build the properties.
+     *
+     * @param name      name of the node
+     * @param namespace namespace of the node
+     * @param appInfo   application info
+     * @param uri       URI of the node
+     */
+    public RootNode(String name, Namespace namespace,
                        Object appInfo, String uri) {
         super(name, namespace, uri, null, appInfo, null);
     }