Merge "Prevent ConfigPusher from killing its thread"
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / rest / impl / XmlMapper.java
index 39525f85994966c71dae3ba2f186a7ebcdf9707f..e76e1962a058bea7c0bdb8a22b6a2c7285e785cd 100644 (file)
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
 package org.opendaylight.controller.sal.rest.impl;
 
-import java.util.Set;
-
 import javax.activation.UnsupportedDataTypeException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
 
-import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-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.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.YangNode;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.Leafref;
 import org.w3c.dom.Document;
-import org.w3c.dom.Element;
 
-import com.google.common.base.Preconditions;
+import com.google.common.base.Optional;
 
 public class XmlMapper {
+    private static final LeafrefCodecImpl LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl(
+            Optional.<LeafrefTypeDefinition> absent());
 
-    public Document write(CompositeNode data, DataNodeContainer schema) throws UnsupportedDataTypeException {
-        Preconditions.checkNotNull(data);
-        Preconditions.checkNotNull(schema);
+    private static class LeafrefCodecImpl extends TypeDefinitionAwareCodec<Object, LeafrefTypeDefinition> implements
+            LeafrefCodec<String> {
 
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        Document doc = null;
-        try {
-            DocumentBuilder bob = dbf.newDocumentBuilder();
-            doc = bob.newDocument();
-        } catch (ParserConfigurationException e) {
-            return null;
+        protected LeafrefCodecImpl(Optional<LeafrefTypeDefinition> typeDef) {
+            super(typeDef, Object.class);
         }
 
-        if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
-            doc.appendChild(translateToXmlAndReturnRootElement(doc, data, schema));
-            return doc;
-        } else {
-            throw new UnsupportedDataTypeException(
-                    "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+        @Override
+        public String serialize(Object data) {
+            return String.valueOf(data);
         }
-    }
-
-    private Element translateToXmlAndReturnRootElement(Document doc, Node<?> data, YangNode schema)
-            throws UnsupportedDataTypeException {
-        QName dataType = data.getNodeType();
-        Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
 
-        if (data instanceof SimpleNode<?>) {
-            if (schema instanceof LeafListSchemaNode) {
-                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType());
-            } else if (schema instanceof LeafSchemaNode) {
-                writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType());
-            } else {
-                Object value = data.getValue();
-                if (value != null) {
-                    itemEl.setTextContent(String.valueOf(value));
-                }
-            }
-        } else { // CompositeNode
-            for (Node<?> child : ((CompositeNode) data).getChildren()) {
-                DataSchemaNode childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
-                if (childSchema == null) {
-                    throw new UnsupportedDataTypeException("Probably the data node \""
-                            + child.getNodeType().getLocalName() + "\" is not conform to schema");
-                }
-                itemEl.appendChild(translateToXmlAndReturnRootElement(doc, child, childSchema));
-            }
+        @Override
+        public Object deserialize(String data) {
+            return data;
         }
-        return itemEl;
     }
 
-    private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type) {
+    private static class XmlCodecProviderImpl implements XmlCodecProvider {
+        @Override
+        public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(TypeDefinition<?> baseType) {
+            TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = TypeDefinitionAwareCodec
+                    .from(baseType);
 
-        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
-
-        if (baseType instanceof IdentityrefTypeDefinition && node.getValue() instanceof QName) {
-            QName value = (QName) node.getValue();
-            element.setAttribute("xmlns:x", value.getNamespace().toString());
-            element.setTextContent("x:" + value.getLocalName());
-        } else {
-            Object value = node.getValue();
-            if (value != null) {
-                element.setTextContent(String.valueOf(value));
-            }
-        }
-    }
-
-    private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
-        for (DataSchemaNode dsn : dataSchemaNode) {
-            if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
-                return dsn;
-            } else if (dsn instanceof ChoiceNode) {
-                for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
-                    DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
-                    if (foundDsn != null) {
-                        return foundDsn;
-                    }
+            if (codec == null) {
+                if (baseType instanceof Leafref) {
+                    return LEAFREF_DEFAULT_CODEC;
                 }
             }
+            return codec;
         }
-        return null;
     }
 
-    private TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
-        return type.getBaseType() != null ? resolveBaseTypeFrom(type.getBaseType()) : type;
-    }
+    private static final XmlCodecProvider XML_CODEC_PROVIDER_IMPL = new XmlCodecProviderImpl();
 
+    public Document write(CompositeNode data, DataNodeContainer schema) throws UnsupportedDataTypeException {
+        return XmlDocumentUtils.toDocument(data, schema, XML_CODEC_PROVIDER_IMPL);
+    }
 }