Implementation of Data Format serializer
[ccsdk/sli/plugins.git] / restconf-client / provider / src / main / java / org / onap / ccsdk / sli / plugins / yangserializers / dfserializer / PropertiesNodeXmlListener.java
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);
+                }
+            }
+        }
     }
 }