2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
 
   6  * ================================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License");
 
   8  * you may not use this file except in compliance with the License.
 
   9  * You may obtain a copy of the License at
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  13  * Unless required by applicable law or agreed to in writing, software
 
  14  * distributed under the License is distributed on an "AS IS" BASIS,
 
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  16  * See the License for the specific language governing permissions and
 
  17  * limitations under the License.
 
  18  * ============LICENSE_END=========================================================
 
  21 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
 
  23 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
 
  24 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
 
  25 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
 
  26 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
 
  27 import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
 
  28 import org.opendaylight.yangtools.yang.common.QName;
 
  29 import org.opendaylight.yangtools.yang.common.Revision;
 
  30 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 
  31 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
  32 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 
  33 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 
  34 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
  35 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
  36 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 
  37 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
  38 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 
  40 import java.util.Deque;
 
  42 import static java.lang.String.format;
 
  43 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.DF_ERR;
 
  44 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
 
  45 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.PROP_NODE_ERR;
 
  46 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getResolvedNamespace;
 
  47 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.resolveBaseTypeFrom;
 
  48 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
 
  49 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
 
  50 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
 
  51 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
 
  52 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
 
  53 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
 
  54 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
 
  55 import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findDataChildSchemaByQName;
 
  56 import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findSchemaForChild;
 
  57 import static org.opendaylight.yangtools.yang.data.util.ParserStreamUtils.findSchemaNodeByNameAndNamespace;
 
  60  * Representation of MDSAL based serializer helper, which adds properties
 
  61  * node to the properties tree based on its types.
 
  63 public class MdsalSerializerHelper extends SerializerHelper<SchemaNode, SchemaContext> {
 
  66      * Current properties node.
 
  68     private PropertiesNode propNode;
 
  71      * Current schema node.
 
  73     private SchemaNode curSchemaNode;
 
  77      * Creates MDSAL serializer helper with root schema node, schema context
 
  80      * @param n schema node of the URI's last node
 
  81      * @param c schema context
 
  82      * @param u URI of the request
 
  84     public MdsalSerializerHelper(SchemaNode n, SchemaContext c,
 
  87         Namespace ns = new Namespace(n.getQName().getLocalName(),
 
  88                                      n.getQName().getNamespace(),
 
  89                                      getRevision(n.getQName().getRevision()));
 
  90         propNode = new RootNode<>(n.getQName().getLocalName(), ns,
 
  92         curSchemaNode = getSchemaNode();
 
  96     protected SchemaNode getSchemaNode() {
 
 101     protected SchemaContext getSchemaCtx() {
 
 106     protected SchemaNode getCurSchema() {
 
 107         return curSchemaNode;
 
 111     protected void addNode(String name, String nameSpace, String value,
 
 112                            String valNameSpace, NodeType type)
 
 113             throws SvcLogicException {
 
 116             ns = getResolvedNamespace(null, nameSpace,
 
 117                                       getSchemaCtx(), propNode);
 
 119             ns = getResolvedNamespace(nameSpace, null,
 
 120                                       getSchemaCtx(), propNode);
 
 122         if (isChildPresent(name, ns)) {
 
 123             addNodeToProperty(name, ns, value, valNameSpace, type);
 
 125             throw new SvcLogicException(format(
 
 126                     "Unable to add the node %s", name));
 
 131     protected void exitNode() throws SvcLogicException {
 
 132         propNode = propNode.parent();
 
 133         if (propNode != null) {
 
 134             NodeType type = propNode.nodeType();
 
 135             if (type == MULTI_INSTANCE_HOLDER_NODE ||
 
 136                     type == MULTI_INSTANCE_LEAF_HOLDER_NODE) {
 
 137                 propNode = propNode.parent();
 
 140         if (propNode == null || propNode.appInfo() == null
 
 141                 || !(propNode.appInfo() instanceof SchemaNode)) {
 
 142             throw new SvcLogicException(PROP_NODE_ERR);
 
 144         curSchemaNode = (SchemaNode) propNode.appInfo();
 
 148     protected PropertiesNode getPropertiesNode() {
 
 153      * Adds the node to property node based on the type of the schema node,
 
 154      * which is decided based on the name and namespace of the input
 
 157      * @param name         name of the node
 
 158      * @param ns           namespace of the node
 
 159      * @param value        value of the node if its a leaf/leaf-list
 
 160      * @param valNamespace namespace of the value
 
 161      * @param type         type of the node
 
 162      * @throws SvcLogicException when adding child fails
 
 164     private void addNodeToProperty(String name, Namespace ns, String value,
 
 165                                    String valNamespace, NodeType type)
 
 166             throws SvcLogicException {
 
 169             validateNodeType(type);
 
 171         if (curSchemaNode instanceof LeafSchemaNode) {
 
 172             valueNs = getValueNs(curSchemaNode, valNamespace, type);
 
 173             propNode = propNode.addChild(name, ns,
 
 174                                          SINGLE_INSTANCE_LEAF_NODE,
 
 175                                          value, valueNs, curSchemaNode);
 
 176         } else if (curSchemaNode instanceof LeafListSchemaNode) {
 
 177             valueNs = getValueNs(curSchemaNode, valNamespace, type);
 
 178             propNode = propNode.addChild(null, name, ns,
 
 179                                          MULTI_INSTANCE_LEAF_NODE, value,
 
 180                                          valueNs, curSchemaNode);
 
 181         } else if (curSchemaNode instanceof ListSchemaNode) {
 
 182             propNode = propNode.addChild(null, name, ns, MULTI_INSTANCE_NODE,
 
 185             propNode = propNode.addChild(name, ns, SINGLE_INSTANCE_NODE,
 
 191      * Returns the namespace of the value namespace in case of identity ref.
 
 193      * @param schemaNode schema node
 
 194      * @param valNs      value name space
 
 195      * @param nodeType   node type
 
 196      * @return namespace of value namespace
 
 197      * @throws SvcLogicException when namespace resolution fails for identityref
 
 199     private Namespace getValueNs(SchemaNode schemaNode, String valNs,
 
 200                                  NodeType nodeType) throws SvcLogicException {
 
 204             if (schemaNode instanceof LeafSchemaNode) {
 
 205                 type = ((LeafSchemaNode) schemaNode).getType();
 
 207                 type = ((LeafListSchemaNode) schemaNode).getType();
 
 209             TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
 
 210             if (baseType instanceof IdentityrefTypeDefinition) {
 
 211                 if (nodeType == null) {
 
 212                     ns = getResolvedNamespace(null, valNs, getSchemaCtx(),
 
 215                     ns = getResolvedNamespace(valNs, null, getSchemaCtx(),
 
 224      * Validates that the node type from the data format matches with that of
 
 225      * the corresponding schema node.
 
 227      * @param type node type from the abstract data format
 
 228      * @throws SvcLogicException when the node type is wrong
 
 230     private void validateNodeType(NodeType type) throws SvcLogicException {
 
 233             case SINGLE_INSTANCE_LEAF_NODE:
 
 234                 verify = curSchemaNode instanceof LeafSchemaNode;
 
 237             case MULTI_INSTANCE_LEAF_NODE:
 
 238                 verify = curSchemaNode instanceof LeafListSchemaNode;
 
 241             case MULTI_INSTANCE_NODE:
 
 242                 verify = curSchemaNode instanceof ListSchemaNode;
 
 245             case SINGLE_INSTANCE_NODE:
 
 246                 verify = (!(curSchemaNode instanceof LeafSchemaNode) &&
 
 247                         !(curSchemaNode instanceof LeafListSchemaNode) &&
 
 248                         !(curSchemaNode instanceof ListSchemaNode));
 
 252                 throw new SvcLogicException(format(NODE_TYPE_ERR,
 
 256             throw new SvcLogicException(format(DF_ERR, curSchemaNode
 
 257                     .getQName().getLocalName(), type.toString()));
 
 262      * Returns true if the child schema is present with the name and
 
 263      * namespace inside the current schema node, if present updates the
 
 264      * current schema node; false otherwise.
 
 266      * @param name      name of the child schema node
 
 267      * @param namespace namespace of the child schema node
 
 268      * @return returns true if the child schema is available; false otherwise
 
 270     private boolean isChildPresent(String name, Namespace namespace) {
 
 271         QName qname =  QName.create(namespace.moduleNs(),
 
 272                                     Revision.of(namespace.revision()), name);
 
 273         SchemaNode childNode = null;
 
 274         if (curSchemaNode instanceof DataSchemaNode) {
 
 275             Deque<DataSchemaNode> dataSchema = findSchemaNodeByNameAndNamespace(
 
 276                     (DataSchemaNode) curSchemaNode, name, namespace.moduleNs());
 
 277             if (dataSchema != null && !dataSchema.isEmpty()) {
 
 278                 childNode = dataSchema.pop();
 
 281             if (!dataSchema.isEmpty()) {
 
 282                 childNode = findSchemaForChild(((ChoiceSchemaNode) childNode),
 
 287             childNode = findDataChildSchemaByQName(curSchemaNode, qname);
 
 290         if (childNode != null) {
 
 291             curSchemaNode = childNode;