Implementation for Restconf api call node
[ccsdk/sli/plugins.git] / restconf-client / provider / src / main / java / org / onap / ccsdk / sli / plugins / yangserializers / dfserializer / MdsalSerializerHelper.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - CCSDK
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
22
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.model.api.DataSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
35 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
36
37 import java.util.Deque;
38
39 import static java.lang.String.format;
40 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.DF_ERR;
41 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
42 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.PROP_NODE_ERR;
43 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getResolvedNamespace;
44 import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.resolveBaseTypeFrom;
45 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
46 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
47 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
48 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
49 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
50 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
51 import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
52 import static org.opendaylight.yangtools.yang.data.util.ParserStreamUtils.findSchemaNodeByNameAndNamespace;
53
54 /**
55  * Representation of MDSAL based serializer helper, which adds properties
56  * node to the properties tree based on its types.
57  */
58 public class MdsalSerializerHelper extends SerializerHelper<SchemaNode, SchemaContext> {
59
60     /**
61      * Current properties node.
62      */
63     private PropertiesNode propNode;
64
65     /**
66      * Current schema node.
67      */
68     private SchemaNode curSchemaNode;
69
70
71     /**
72      * Creates MDSAL serializer helper with root schema node, schema context
73      * and URI.
74      *
75      * @param n schema node of the URI's last node
76      * @param c schema context
77      * @param u URI of the request
78      */
79     public MdsalSerializerHelper(SchemaNode n, SchemaContext c,
80                                  String u) {
81         super(n, c, u);
82         Namespace ns = new Namespace(n.getQName().getLocalName(),
83                                      n.getQName().getNamespace(),
84                                      getRevision(n.getQName().getRevision()));
85         propNode = new RootNode<>(n.getQName().getLocalName(), ns,
86                                   getSchemaNode(), u);
87         curSchemaNode = getSchemaNode();
88     }
89
90     @Override
91     protected SchemaNode getSchemaNode() {
92         return schemaNode;
93     }
94
95     @Override
96     protected SchemaContext getSchemaCtx() {
97         return schemaCtx;
98     }
99
100     @Override
101     protected SchemaNode getCurSchema() {
102         return curSchemaNode;
103     }
104
105     @Override
106     protected void addNode(String name, String nameSpace, String value,
107                            String valNameSpace, NodeType type)
108             throws SvcLogicException {
109         Namespace ns;
110         if (type == null) {
111             ns = getResolvedNamespace(null, curSchemaNode, getSchemaCtx(),
112                                       nameSpace, propNode);
113         } else {
114             ns = getResolvedNamespace(nameSpace, curSchemaNode, getSchemaCtx(),
115                                       nameSpace, propNode);
116         }
117         if (isChildPresent(name, ns)) {
118             addNodeToProperty(name, ns, value, valNameSpace, type);
119         }
120     }
121
122     @Override
123     protected void exitNode() throws SvcLogicException {
124         propNode = propNode.parent();
125         if (propNode != null) {
126             NodeType type = propNode.nodeType();
127             if (type == MULTI_INSTANCE_HOLDER_NODE ||
128                     type == MULTI_INSTANCE_LEAF_HOLDER_NODE) {
129                 propNode = propNode.parent();
130             }
131         }
132         if (propNode == null || propNode.appInfo() == null
133                 || !(propNode.appInfo() instanceof SchemaNode)) {
134             throw new SvcLogicException(PROP_NODE_ERR);
135         }
136         curSchemaNode = (SchemaNode) propNode.appInfo();
137     }
138
139     @Override
140     protected PropertiesNode getPropertiesNode() {
141         return propNode;
142     }
143
144     /**
145      * Adds the node to property node based on the type of the schema node,
146      * which is decided based on the name and namespace of the input
147      * information.
148      *
149      * @param name         name of the node
150      * @param ns           namespace of the node
151      * @param value        value of the node if its a leaf/leaf-list
152      * @param valNamespace namespace of the value
153      * @param type         type of the node
154      * @throws SvcLogicException when adding child fails
155      */
156     private void addNodeToProperty(String name, Namespace ns, String value,
157                                    String valNamespace, NodeType type)
158             throws SvcLogicException {
159         Namespace valueNs;
160         if (type != null) {
161             validateNodeType(type);
162         }
163         if (curSchemaNode instanceof LeafSchemaNode) {
164             valueNs = getValueNs(curSchemaNode, valNamespace, type);
165             propNode = propNode.addChild(name, ns,
166                                          SINGLE_INSTANCE_LEAF_NODE,
167                                          value, valueNs, curSchemaNode);
168         } else if (curSchemaNode instanceof LeafListSchemaNode) {
169             valueNs = getValueNs(curSchemaNode, valNamespace, type);
170             propNode = propNode.addChild(null, name, ns,
171                                          MULTI_INSTANCE_LEAF_NODE, value,
172                                          valueNs, curSchemaNode);
173         } else if (curSchemaNode instanceof ListSchemaNode) {
174             propNode = propNode.addChild(null, name, ns, MULTI_INSTANCE_NODE,
175                                          curSchemaNode);
176         } else {
177             propNode = propNode.addChild(name, ns, SINGLE_INSTANCE_NODE,
178                                          curSchemaNode);
179         }
180     }
181
182     /**
183      * Returns the namespace of the value namespace in case of identity ref.
184      *
185      * @param schemaNode schema node
186      * @param valNs      value name space
187      * @param nodeType   node type
188      * @return namespace of value namespace
189      * @throws SvcLogicException when namespace resolution fails for identityref
190      */
191     private Namespace getValueNs(SchemaNode schemaNode, String valNs,
192                                  NodeType nodeType) throws SvcLogicException {
193         Namespace ns = null;
194         if (valNs != null) {
195             TypeDefinition type = ((LeafSchemaNode) schemaNode).getType();
196             TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
197             if (baseType instanceof IdentityrefTypeDefinition) {
198                 if (nodeType == null) {
199                     ns = getResolvedNamespace(null,schemaNode, getSchemaCtx(),
200                                               valNs, propNode);
201                 } else {
202                     ns = getResolvedNamespace(valNs, schemaNode, getSchemaCtx(),
203                                               null, propNode);
204                 }
205             }
206         }
207         return ns;
208     }
209
210     /**
211      * Validates that the node type from the data format matches with that of
212      * the corresponding schema node.
213      *
214      * @param type node type from the abstract data format
215      * @throws SvcLogicException when the node type is wrong
216      */
217     private void validateNodeType(NodeType type) throws SvcLogicException {
218         boolean verify;
219         switch (type) {
220             case SINGLE_INSTANCE_LEAF_NODE:
221                 verify = curSchemaNode instanceof LeafSchemaNode;
222                 break;
223
224             case MULTI_INSTANCE_LEAF_NODE:
225                 verify = curSchemaNode instanceof LeafListSchemaNode;
226                 break;
227
228             case MULTI_INSTANCE_NODE:
229                 verify = curSchemaNode instanceof ListSchemaNode;
230                 break;
231
232             case SINGLE_INSTANCE_NODE:
233                 verify = (!(curSchemaNode instanceof LeafSchemaNode) &&
234                         !(curSchemaNode instanceof LeafListSchemaNode) &&
235                         !(curSchemaNode instanceof ListSchemaNode));
236                 break;
237
238             default:
239                 throw new SvcLogicException(format(NODE_TYPE_ERR,
240                                                    type.toString()));
241         }
242         if (!verify) {
243             throw new SvcLogicException(format(DF_ERR, curSchemaNode
244                     .getQName().getLocalName(), type.toString()));
245         }
246     }
247
248     /**
249      * Returns true if the child schema is present with the name and
250      * namespace inside the current schema node, if present updates the
251      * current schema node; false otherwise.
252      *
253      * @param name      name of the child schema node
254      * @param namespace namespace of the child schema node
255      * @return returns true if the child schema is available; false otherwise
256      */
257     private boolean isChildPresent(String name, Namespace namespace) {
258         Deque<DataSchemaNode> dataSchema = findSchemaNodeByNameAndNamespace(
259                 (DataSchemaNode) curSchemaNode, name, namespace.moduleNs());
260         if (dataSchema != null) {
261             DataSchemaNode node = dataSchema.pop();
262             if (node != null) {
263                 curSchemaNode = node;
264                 return true;
265             }
266         }
267         return false;
268     }
269 }