summaryrefslogtreecommitdiffstats
path: root/plugins/restconf-client
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/restconf-client')
-rwxr-xr-xplugins/restconf-client/.gitignore34
-rwxr-xr-xplugins/restconf-client/installer/pom.xml127
-rw-r--r--plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml58
-rw-r--r--plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml48
-rw-r--r--plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh38
-rwxr-xr-xplugins/restconf-client/pom.xml23
-rwxr-xr-xplugins/restconf-client/provider/pom.xml132
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java484
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java265
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java166
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java46
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java76
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java310
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java122
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java110
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java178
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java66
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java37
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java94
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java104
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java145
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java141
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java120
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java48
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java87
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java87
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java231
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java55
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java91
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java44
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java34
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java297
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java233
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java246
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java116
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java53
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java37
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java104
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java44
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java42
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java27
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java105
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java119
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java59
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java215
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java28
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java93
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java122
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java28
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java73
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java227
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java578
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java32
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java100
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java28
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java34
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java280
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java61
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java112
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java38
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java212
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java77
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java33
-rwxr-xr-xplugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml51
-rwxr-xr-xplugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml51
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java68
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java175
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java996
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java631
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java762
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java469
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java1144
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang43
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang77
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang25
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang17
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang106
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang231
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang108
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang231
80 files changed, 12639 insertions, 0 deletions
diff --git a/plugins/restconf-client/.gitignore b/plugins/restconf-client/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/plugins/restconf-client/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/plugins/restconf-client/installer/pom.xml b/plugins/restconf-client/installer/pom.xml
new file mode 100755
index 000000000..9114c7a22
--- /dev/null
+++ b/plugins/restconf-client/installer/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-restconf-client</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features
+ </features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml b/plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..8ffcb88a1
--- /dev/null
+++ b/plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,58 @@
+<!--
+ * ============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=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..252c39d3c
--- /dev/null
+++ b/plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,48 @@
+<!--
+ * ============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=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh b/plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..8e9195d57
--- /dev/null
+++ b/plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+###
+# ============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=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/restconf-client/pom.xml b/plugins/restconf-client/pom.xml
new file mode 100755
index 000000000..ee2d0423c
--- /dev/null
+++ b/plugins/restconf-client/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client</name>
+ <description>This is an implementation of DG Execute Node that makes a call to an external RESTCONF API</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/restconf-client/provider/pom.xml b/plugins/restconf-client/provider/pom.xml
new file mode 100755
index 000000000..ab57af017
--- /dev/null
+++ b/plugins/restconf-client/provider/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>restconf-nb-rfc8040</artifactId>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.xml</groupId>
+ <artifactId>jsr173</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- For test -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-test-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java
new file mode 100644
index 000000000..620df282f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java
@@ -0,0 +1,484 @@
+/*-
+ * ============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.restconfapicall;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonWriter;
+
+import javax.ws.rs.core.UriBuilder;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.plugins.restapicall.Format;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restapicall.XmlParser;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatSerializer;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatSerializerContext;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerFactory;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.Listener;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.MdsalSerializerHelper;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.SerializerHelper;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeSerializer;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeSerializer;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Strings.repeat;
+import static java.lang.String.format;
+import static java.lang.String.valueOf;
+import static org.apache.commons.lang3.StringUtils.join;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.DELETE;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.GET;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PATCH;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PUT;
+import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.ATTEMPTS_MSG;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COLON;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COMMA;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COMM_FAIL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HEADER;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HTTP_REQ;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HTTP_RES;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.MAX_RETRY_ERR;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.NO_MORE_RETRY;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.REQ_ERR;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.REST_API_URL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RES_CODE;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RES_MSG;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RES_PRE;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RETRY_COUNT;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RETRY_FAIL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.UPDATED_URL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getSchemaCtxFromDir;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getUpdatedXmlReq;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getYangParameters;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.parseUrl;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfListenerFactory.instance;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.UTF_HEADER;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_TREE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlWriter;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getModuleNamespace;
+import static org.osgi.framework.FrameworkUtil.getBundle;
+
+/**
+ * Representation of a plugin to enable RESTCONF based CRUD operations from DG.
+ */
+public class RestconfApiCallNode implements SvcLogicJavaPlugin {
+
+ /**
+ * Logger for the restconf api call node class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(
+ RestconfApiCallNode.class);
+
+ /**
+ * Rest api call node service instance
+ */
+ private RestapiCallNode restapiCallNode;
+
+ /**
+ * Creates an instance of restconf api call node with restapi call node.
+ *
+ * @param r restapi call node
+ */
+ public RestconfApiCallNode(RestapiCallNode r) {
+ this.restapiCallNode = r;
+ }
+
+ /**
+ * Returns the restapi call node instance.
+ * @return
+ */
+ public RestapiCallNode getRestapiCallNode() {
+ return restapiCallNode;
+ }
+
+ /**
+ * Sends the restconf request using the parameters map and the memory
+ * context. And this method allows the directed graphs to interact with
+ * the restconf api call node
+ *
+ * @param paramMap parameters map
+ * @param ctx service logic context
+ * @throws SvcLogicException when svc logic exception occurs
+ */
+ public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx)
+ throws SvcLogicException {
+ sendRequest(paramMap, ctx, 0);
+ }
+
+ /**
+ * Sends the restconf request using the parameters map and the memory
+ * context along with the retry count.
+ *
+ * @param paramMap parameters map
+ * @param ctx service logic context
+ * @param retryCount number of retry counts
+ * @throws SvcLogicException when svc logic exception occurs
+ */
+ public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx,
+ Integer retryCount) throws SvcLogicException {
+ RestapiCallNode rest = getRestapiCallNode();
+ HttpResponse r = new HttpResponse();
+ try {
+ YangParameters p = getYangParameters(paramMap);
+
+ String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
+ Map<String, String> props = new HashMap<>((Map)ctx.toProperties());
+ String uri = parseUrl(p.restapiUrl, p.httpMethod);
+ InstanceIdentifierContext<?> insIdCtx = getInsIdCtx(p, uri);
+
+ String req = null;
+ if (p.httpMethod != GET && p.httpMethod != DELETE) {
+ req = serializeRequest(props, p, uri, insIdCtx);
+ if (p.httpMethod == PUT || p.httpMethod == PATCH) {
+ updateReq(req, p, insIdCtx);
+ }
+ }
+ if (req == null && p.requestBody != null) {
+ req = p.requestBody;
+ }
+
+ r = rest.sendHttpRequest(req, p);
+ if (p.returnRequestPayload && req != null) {
+ ctx.setAttribute(pp + HTTP_REQ, req);
+ }
+
+ String response = getResponse(ctx, p, pp, r);
+ if (response != null) {
+ try {
+ Map<String, String> resProp = serializeResponse(
+ p, uri, response, insIdCtx);
+ for (Map.Entry<String, String> pro : resProp.entrySet()) {
+ ctx.setAttribute(pro.getKey(), pro.getValue());
+ }
+ } catch (SvcLogicException e) {
+ convertToNormalRes(ctx, p, pp, response);
+ }
+ }
+ } catch (SvcLogicException e) {
+ boolean shouldRetry = false;
+ if (e.getCause().getCause() instanceof SocketException) {
+ shouldRetry = true;
+ }
+
+ log.error(REQ_ERR + e.getMessage(), e);
+ String prefix = parseParam(paramMap, RES_PRE, false, null);
+ setFailureResponseStatus(ctx, prefix, e.getMessage());
+ }
+
+ if (r != null && r.code >= 300) {
+ throw new SvcLogicException(valueOf(r.code) +
+ COLON + " " + r.message);
+ }
+ }
+
+ private void convertToNormalRes(SvcLogicContext ctx ,
+ YangParameters p, String pp, String body)
+ throws SvcLogicException {
+ if (p.convertResponse) {
+ Map<String, String> mm = null;
+ if (p.format == Format.XML) {
+ mm = XmlParser.convertToProperties(body, p.listNameList);
+ } else if (p.format == Format.JSON) {
+ mm = org.onap.ccsdk.sli.plugins.restapicall.JsonParser
+ .convertToProperties(body);
+ }
+
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ ctx.setAttribute(pp + entry.getKey(),
+ entry.getValue());
+ }
+ }
+ }
+ }
+
+ /**
+ * Serializes the request message to JSON or XML from the properties.
+ *
+ * @param properties properties
+ * @param params YANG parameters
+ * @param uri URI
+ * @param insIdCtx instance identifier context
+ * @return JSON or XML message to be sent
+ * @throws SvcLogicException when serializing the request fails
+ */
+ public String serializeRequest(Map<String, String> properties,
+ YangParameters params, String uri,
+ InstanceIdentifierContext insIdCtx)
+ throws SvcLogicException {
+ PropertiesNodeSerializer propSer = new MdsalPropertiesNodeSerializer(
+ insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri);
+ DataFormatSerializerContext serCtx = new DataFormatSerializerContext(
+ null, uri, null, propSer);
+ DataFormatSerializer ser = DfSerializerFactory.instance()
+ .getSerializer(serCtx, params);
+ //TODO: Handling of XML annotations
+ return ser.encode(properties, null);
+ }
+
+ /**
+ * Serializes the response message from JSON or XML to the properties.
+ *
+ * @param params YANG parameters
+ * @param uri URI
+ * @param response response message
+ * @param insIdCtx instance identifier context
+ * @return response message as properties
+ * @throws SvcLogicException when serializing the response fails
+ */
+ public Map<String, String> serializeResponse(YangParameters params,
+ String uri, String response,
+ InstanceIdentifierContext insIdCtx)
+ throws SvcLogicException {
+ PropertiesNodeSerializer propSer = new MdsalPropertiesNodeSerializer(
+ insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri);
+ SerializerHelper helper = new MdsalSerializerHelper(
+ insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri);
+ Listener listener = instance().getListener(helper, params);
+ DataFormatSerializerContext serCtx = new DataFormatSerializerContext(
+ listener, uri, null, propSer);
+ DataFormatSerializer ser = DfSerializerFactory.instance()
+ .getSerializer(serCtx, params);
+ return ser.decode(response);
+ }
+
+ /**
+ * Returns instance identifier context for a uri using the schema context.
+ *
+ * @param params YANG parameters
+ * @param uri URI
+ * @return instance identifier context
+ * @throws SvcLogicException when getting schema context fails
+ */
+ private InstanceIdentifierContext<?> getInsIdCtx(YangParameters params,
+ String uri)
+ throws SvcLogicException {
+ SchemaContext context = getSchemaContext(params);
+ return ParserIdentifier.toInstanceIdentifier(uri, context, null);
+ }
+
+ /**
+ * Returns the global schema context or schema context of particular YANG
+ * files present in a directory path.
+ *
+ * @param params YANG parameters
+ * @return schema context
+ * @throws SvcLogicException when schema context fetching fails
+ */
+ private SchemaContext getSchemaContext(YangParameters params)
+ throws SvcLogicException {
+ if (params.dirPath != null) {
+ return getSchemaCtxFromDir(params.dirPath);
+ }
+ BundleContext bc = getBundle(SchemaContext.class).getBundleContext();
+ SchemaContext schemaContext = null;
+ if (bc != null) {
+ ServiceReference reference = bc.getServiceReference(
+ SchemaContext.class);
+ if (reference != null) {
+ schemaContext = (SchemaContext) bc.getService(reference);
+ }
+ }
+ return schemaContext;
+ }
+
+ /**
+ * Returns the response message body of a http response message.
+ *
+ * @param ctx svc logic context
+ * @param params parameters
+ * @param pre prefix to be appended
+ * @param res http response
+ * @return response message body
+ */
+ public String getResponse(SvcLogicContext ctx, YangParameters params,
+ String pre, HttpResponse res) {
+ ctx.setAttribute(pre + RES_CODE, valueOf(res.code));
+ ctx.setAttribute(pre + RES_MSG, res.message);
+
+ if (params.dumpHeaders && res.headers != null) {
+ for (Map.Entry<String, List<String>> a : res.headers.entrySet()) {
+ ctx.setAttribute(pre + HEADER + a.getKey(),
+ join(a.getValue(), COMMA));
+ }
+ }
+
+ if (res.body != null && res.body.trim().length() > 0) {
+ ctx.setAttribute(pre + HTTP_RES, res.body);
+ return res.body;
+ }
+ return null;
+ }
+
+ /**
+ * Sets the failure response status in the context memory.
+ *
+ * @param ctx service logic context
+ * @param prefix prefix to be added
+ * @param errMsg error message
+ */
+ private void setFailureResponseStatus(SvcLogicContext ctx, String prefix,
+ String errMsg) {
+ HttpResponse res = new HttpResponse();
+ res.code = 500;
+ res.message = errMsg;
+ ctx.setAttribute(prefix + RES_CODE, valueOf(res.code));
+ ctx.setAttribute(prefix + RES_MSG, res.message);
+ }
+
+ /**
+ * Updates request message for JSON and XML data format, when the HTTP
+ * method points it as PUT or PATCH.
+ *
+ * @param req current request message
+ * @param p YANG parameters
+ * @param insIdCtx instance identifier context
+ * @return update request message
+ * @throws SvcLogicException when the data format type is wrong
+ */
+ public String updateReq(String req, YangParameters p,
+ InstanceIdentifierContext<?> insIdCtx)
+ throws SvcLogicException {
+
+ SchemaNode schemaNode = insIdCtx.getSchemaNode();
+ Namespace modNs = getModuleNamespace(schemaNode.getQName(),
+ insIdCtx.getSchemaContext());
+ String nodeName = schemaNode.getQName().getLocalName();
+
+ switch (p.format) {
+ case JSON:
+ return getUpdatedJsonReq(req, nodeName, modNs.moduleName());
+
+ case XML:
+ return getXmlReqForPutOp(req, nodeName, modNs.moduleNs());
+
+ default:
+ throw new SvcLogicException(format(FORMAT_ERR, p.format));
+ }
+ }
+
+ /**
+ * Returns the updated JSON request message, when the HTTP method
+ * points to PUT or PATCH.
+ *
+ * @param req current JSON request message
+ * @param nodeName root node name
+ * @param modName module name of the root node
+ * @return update JSON request message
+ */
+ private String getUpdatedJsonReq(String req, String nodeName,
+ String modName) {
+ Writer writer = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(writer);
+ jsonWriter.setIndent(repeat(" ", 4));
+
+ JsonParser jsonParser = new JsonParser();
+ JsonObject oldJson = (JsonObject)jsonParser.parse(req);
+ oldJson = remChildModName(oldJson, modName);
+ JsonObject newJson = new JsonObject();
+ newJson.add(modName + COLON + nodeName, oldJson.deepCopy());
+
+ Gson gson= new Gson();
+ gson.toJson(newJson, jsonWriter);
+ return writer.toString();
+ }
+
+ /**
+ * Removes module name from all the updated first level child node, if it
+ * is same as the root node added.
+ *
+ * @param oldJson JSON object for old request
+ * @param modName module name of root node
+ * @return JSON object for old request with updated child module name
+ */
+ private JsonObject remChildModName(JsonObject oldJson, String modName) {
+ Iterator<Map.Entry<String, JsonElement>> it = oldJson.entrySet().iterator();
+ Map<String, JsonElement> m = new HashMap<>();
+ while (it.hasNext()) {
+ Map.Entry<String, JsonElement> jNode = it.next();
+ if (jNode.getKey().contains(COLON)) {
+ String[] modArr = jNode.getKey().split(COLON);
+ if (modArr[0].equals(modName)) {
+ it.remove();
+ m.put(modArr[1], jNode.getValue());
+ }
+ }
+ }
+ if (!m.isEmpty()) {
+ for (Map.Entry<String, JsonElement> element : m.entrySet()) {
+ oldJson.add(element.getKey(), element.getValue());
+ }
+ }
+ return oldJson;
+ }
+
+ /**
+ * Returns the updated XML request message, when the HTTP method points
+ * to PUT or PATCH.
+ *
+ * @param req current JSON request message
+ * @param nodeName root node name
+ * @param modNs module namespace of the root node
+ * @return update JSON request message
+ * @throws SvcLogicException when XML parsing fails
+ */
+ private String getXmlReqForPutOp(String req, String nodeName,
+ URI modNs) throws SvcLogicException {
+ req = getUpdatedXmlReq(req, nodeName, modNs.toString());
+ Document oldDoc;
+ try {
+ oldDoc = DocumentHelper.parseText(req);
+ } catch (DocumentException e) {
+ throw new SvcLogicException(XML_TREE_ERR, e);
+ }
+ Writer writer = getXmlWriter(
+ UTF_HEADER + oldDoc.getRootElement().asXML(), "4");
+ return writer.toString();
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java
new file mode 100644
index 000000000..1309102b3
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java
@@ -0,0 +1,265 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.restconfapicall;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpMethod;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+
+import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.getParameters;
+import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam;
+import static org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode.DEFAULT_MODE;
+import static org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource.forFile;
+import static org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors.defaultReactor;
+import static org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource.create;
+
+/**
+ * Utilities for restconf api call node.
+ */
+public final class RestconfApiUtils {
+
+ static final String RES_CODE = "response-code";
+
+ static final String HTTP_REQ ="httpRequest";
+
+ static final String RES_PRE = "responsePrefix";
+
+ static final String RES_MSG = "response-message";
+
+ static final String HEADER = "header.";
+
+ static final String COMMA = ",";
+
+ static final String COLON = ":";
+
+ static final String HTTP_RES = "httpResponse";
+
+ static final String REST_API_URL = "restapiUrl";
+
+ static final String UPDATED_URL = "URL was set to";
+
+ static final String COMM_FAIL = "Failed to communicate with host %s." +
+ "Request will be re-attempted using the host %s.";
+
+ static final String RETRY_COUNT = "This is retry attempt %d out of %d";
+
+ static final String RETRY_FAIL = "Retry attempt has failed. No further " +
+ "retry shall be attempted, calling setFailureResponseStatus";
+
+ static final String NO_MORE_RETRY = "Could not attempt retry";
+
+ static final String MAX_RETRY_ERR = "Maximum retries reached, calling " +
+ "setFailureResponseStatus";
+
+ static final String ATTEMPTS_MSG = "%d attempts were made out of %d " +
+ "maximum retries";
+
+ static final String REQ_ERR = "Error sending the request: ";
+
+ private static final String SLASH = "/";
+
+ private static final String DIR_PATH = "dirPath";
+
+ private static final String URL_SYNTAX = "The following URL cannot be " +
+ "parsed into URI : ";
+
+ private static final String YANG = ".yang";
+
+ private static final String YANG_FILE_ERR = "Unable to parse the YANG " +
+ "file provided";
+
+ //No instantiation.
+ private RestconfApiUtils() {
+ }
+
+ /**
+ * Returns the YANG parameters after parsing it from the map.
+ *
+ * @param paramMap parameters map
+ * @return YANG parameters
+ * @throws SvcLogicException when parsing of parameters map fail
+ */
+ static YangParameters getYangParameters(Map<String, String> paramMap)
+ throws SvcLogicException {
+ YangParameters param = (YangParameters) getParameters(
+ paramMap, new YangParameters());
+ param.dirPath = parseParam(paramMap, DIR_PATH, false, null);
+ return param;
+ }
+
+ /**
+ * Parses the restconf URL and gives the YANG path from it, which can be
+ * used to get schema node. If it is a PUT operation, then a node must be
+ * reduced from the url to make it always point to the parent.
+ *
+ * @param url restconf URL
+ * @param method HTTP operation
+ * @return YANG path pointing to parent
+ * @throws SvcLogicException when parsing the URL fails
+ */
+ public static String parseUrl(String url, HttpMethod method)
+ throws SvcLogicException {
+ URI uri;
+ try {
+ uri = new URI(url);
+ } catch (URISyntaxException e) {
+ throw new SvcLogicException(URL_SYNTAX + url, e);
+ }
+
+ String path = uri.getPath();
+ path = getParsedPath(path);
+ return path;
+ }
+
+ /**
+ * Returns the path which contains only the schema nodes.
+ *
+ * @param path path
+ * @return path representing schema
+ */
+ private static String getParsedPath(String path) {
+ String firstHalf;
+ String secondHalf;
+ if (path.contains(COLON)) {
+ String[] p = path.split(COLON);
+ if (p[0].contains(SLASH)) {
+ int slash = p[0].lastIndexOf(SLASH);
+ firstHalf = p[0].substring(slash + 1);
+ } else {
+ firstHalf = p[0];
+ }
+ secondHalf = path.substring(p[0].length() + 1);
+ return firstHalf + COLON + secondHalf;
+ } else if (path.contains(SLASH)) {
+ String[] p = path.split(SLASH);
+ if (p.length > 4) {
+ String actual = p[3] + COLON + p[4];
+ if (p.length > 5) {
+ secondHalf = path.substring(
+ p[1].length() + p[2].length() + actual.length() + 3);
+ path = actual + secondHalf;
+ } else {
+ path = actual;
+ }
+ }
+ }
+ return path;
+ }
+
+ /**
+ * Returns the schema context of the YANG files present in a directory.
+ *
+ * @param di directory path
+ * @return YANG schema context
+ * @throws SvcLogicException when YANG file reading fails
+ */
+ static SchemaContext getSchemaCtxFromDir(String di)
+ throws SvcLogicException {
+ Path d = Paths.get(di);
+ File dir = d.toFile();
+ List<File> yangFiles = new LinkedList<>();
+ getYangFiles(dir, yangFiles);
+ final Collection<YangStatementStreamSource> sources =
+ new ArrayList<>(yangFiles.size());
+ for (File file : yangFiles) {
+ try {
+ sources.add(create(forFile(file)));
+ } catch (IOException | YangSyntaxErrorException e) {
+ throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
+ }
+ }
+
+ final CrossSourceStatementReactor.BuildAction reactor = defaultReactor()
+ .newBuild(DEFAULT_MODE).addSources(sources);
+ try {
+ return reactor.buildEffective();
+ } catch (ReactorException e) {
+ throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Returns all the YANG files present in a directory recursively.
+ *
+ * @param dir path of the directory
+ * @param yangFiles list of YANG files
+ */
+ private static void getYangFiles(File dir, List<File> yangFiles) {
+ if (dir.exists()) {
+ File[] files = dir.listFiles();
+ if (files != null) {
+ processFiles(files, yangFiles);
+ }
+ }
+ }
+
+ /**
+ * Processes all the obtained files by isolating all the YANG files from
+ * all the directory of the given path recursively.
+ *
+ * @param files files in the given path
+ * @param yangFiles YANG files list
+ */
+ private static void processFiles(File[] files, List<File> yangFiles) {
+ for (File file : files) {
+ if (file.isFile() && file.getName().endsWith(YANG)) {
+ yangFiles.add(file);
+ } else if (file.isDirectory()) {
+ getYangFiles(file, yangFiles);
+ }
+ }
+ }
+
+ /**
+ * Returns the updated XML request message by adding root node to it.
+ *
+ * @param req XML request
+ * @param nodeName root node name
+ * @param modNs module namespace of the root node
+ * @return updated XML request message
+ */
+ static String getUpdatedXmlReq(String req, String nodeName, String modNs) {
+ String rootNode = "\n<" + nodeName + " xmlns=\"" + modNs +
+ "\">\n";
+ req = req.replaceFirst("\n", rootNode);
+ req = req + "</" + nodeName + ">";
+ return req.replaceAll(">\\s+<", "><");
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java
new file mode 100644
index 000000000..3213cae15
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.restconfdiscovery;
+
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+import java.util.Map;
+
+/**
+ * Adds additional headers for SSE request.
+ */
+class AdditionalHeaderWebTarget implements WebTarget {
+ private WebTarget base;
+ private String token;
+
+ private String accessToken = "X-ACCESS-TOKEN";
+
+ public AdditionalHeaderWebTarget(WebTarget target, String token) {
+ base = target;
+ this.token = token;
+ }
+
+ @Override
+ public Invocation.Builder request() {
+ return base.request().header(accessToken, token);
+ }
+
+ @Override
+ public Invocation.Builder request(String... acceptedResponseTypes) {
+ return base.request().header(accessToken, token);
+ }
+
+ @Override
+ public Invocation.Builder request(MediaType... acceptedResponseTypes) {
+ return base.request().header(accessToken, token);
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return base.getConfiguration();
+ }
+
+ @Override
+ public URI getUri() {
+ return base.getUri();
+ }
+
+ @Override
+ public UriBuilder getUriBuilder() {
+ return base.getUriBuilder();
+ }
+
+ @Override
+ public WebTarget path(String path) {
+ return base.path(path);
+ }
+
+ @Override
+ public WebTarget resolveTemplate(String name, Object value) {
+ return base.resolveTemplate(name, value);
+ }
+
+ @Override
+ public WebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath) {
+ return base.resolveTemplate(name, value, encodeSlashInPath);
+ }
+
+ @Override
+ public WebTarget resolveTemplateFromEncoded(String name, Object value) {
+ return base.resolveTemplateFromEncoded(name, value);
+ }
+
+ @Override
+ public WebTarget resolveTemplates(Map<String, Object> templateValues) {
+ return base.resolveTemplates(templateValues);
+ }
+
+ @Override
+ public WebTarget resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath) {
+ return base.resolveTemplates(templateValues, encodeSlashInPath);
+ }
+
+ @Override
+ public WebTarget resolveTemplatesFromEncoded(Map<String, Object> templateValues) {
+ return base.resolveTemplatesFromEncoded(templateValues);
+ }
+
+ @Override
+ public WebTarget matrixParam(String name, Object... values) {
+ return base.matrixParam(name, values);
+ }
+
+ @Override
+ public WebTarget queryParam(String name, Object... values) {
+ return base.queryParam(name, values);
+ }
+
+ @Override
+ public WebTarget property(String name, Object value) {
+ return base.property(name, value);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass) {
+ return base.register(componentClass);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass, int priority) {
+ return base.register(componentClass, priority);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass, Class<?>... contracts) {
+ return base.register(componentClass, contracts);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {
+ return base.register(componentClass, contracts);
+ }
+
+ @Override
+ public WebTarget register(Object component) {
+ return base.register(component);
+ }
+
+ @Override
+ public WebTarget register(Object component, int priority) {
+ return base.register(component, priority);
+ }
+
+ @Override
+ public WebTarget register(Object component, Class<?>... contracts) {
+ return base.register(component, contracts);
+ }
+
+ @Override
+ public WebTarget register(Object component, Map<Class<?>, Integer> contracts) {
+ return base.register(component, contracts);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java
new file mode 100644
index 000000000..a76554d5a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java
@@ -0,0 +1,46 @@
+/*-
+ * ============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.restconfdiscovery;
+
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.glassfish.jersey.media.sse.EventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listener that can be registered to listen for notifications.
+ */
+class EventHandler implements EventListener {
+ private static final Logger log = LoggerFactory.getLogger(EventListener.class);
+ private RestconfDiscoveryNode node;
+
+ public EventHandler(RestconfDiscoveryNode node) {
+ this.node = node;
+ }
+
+ @Override
+ public void onEvent(InboundEvent event) {
+ String payload = event.readData();
+ if (!node.eventQueue().offer(payload)) {
+ log.error("Unable to process event {} as processing queue is full", payload);
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java
new file mode 100644
index 000000000..4f28072d3
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.restconfdiscovery;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+
+import java.util.Map;
+
+import static org.onap.ccsdk.sli.plugins.restapicall.JsonParser.convertToProperties;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Processes the events from event queue and executes callback DG.
+ */
+class EventProcessor implements Runnable {
+
+ private static final Logger log = getLogger(EventProcessor.class);
+ private RestconfDiscoveryNode node;
+
+ private static final String EVENT_SUBSCRIPTION_ID = "notification." +
+ "push-change-update.subscription-id";
+
+ public EventProcessor(RestconfDiscoveryNode node) {
+ this.node = node;
+ }
+
+ @Override
+ public void run() {
+ while(true) {
+ try {
+ String payload = node.eventQueue().take();
+ Map<String, String> param = convertToProperties(payload);
+ String id = param.get(EVENT_SUBSCRIPTION_ID);
+ SubscriptionInfo info = node.subscriptionInfoMap().get(id);
+ if (info != null) {
+ SvcLogicContext ctx = setContext(param);
+ SvcLogicGraphInfo callbackDG = info.callBackDG();
+ callbackDG.executeGraph(ctx);
+ }
+ } catch (InterruptedException | SvcLogicException e) {
+ log.error("Interrupted!", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ private SvcLogicContext setContext(Map<String, String> param) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ for (Map.Entry<String, String> entry : param.entrySet()) {
+ ctx.setAttribute(entry.getKey(), entry.getValue());
+ }
+ return ctx;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java
new file mode 100644
index 000000000..cf69d7a3c
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java
@@ -0,0 +1,310 @@
+/*-
+ * ============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.restconfdiscovery;
+
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.Parameters;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+import org.slf4j.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Representation of a plugin to subscribe for notification and then
+ * to handle the received notifications.
+ */
+public class RestconfDiscoveryNode implements SvcLogicDiscoveryPlugin {
+
+ private static final Logger log = getLogger(RestconfDiscoveryNode.class);
+
+ private ExecutorService executor = Executors.newCachedThreadPool();
+ private Map<String, PersistentConnection> runnableInfo = new ConcurrentHashMap<>();
+ private RestconfApiCallNode restconfApiCallNode;
+
+ private volatile Map<String, SubscriptionInfo> subscriptionInfoMap = new ConcurrentHashMap<>();
+ private volatile LinkedBlockingQueue<String> eventQueue = new LinkedBlockingQueue<>();
+
+ private static final String SUBSCRIBER_ID = "subscriberId";
+ private static final String RESPONSE_CODE = "response-code";
+ private static final String RESPONSE_PREFIX = "responsePrefix";
+ private static final String OUTPUT_IDENTIFIER = "ietf-subscribed-notif" +
+ "ications:establish-subscription.output.identifier";
+ private static final String RESPONSE_CODE_200 = "200";
+ private static final String SSE_URL = "sseConnectURL";
+
+ /**
+ * Creates an instance of RestconfDiscoveryNode and starts processing of
+ * event.
+ *
+ * @param r restconf api call node
+ */
+ public RestconfDiscoveryNode(RestconfApiCallNode r) {
+ this.restconfApiCallNode = r;
+ ExecutorService e = Executors.newFixedThreadPool(20);
+ EventProcessor p = new EventProcessor(this);
+ for (int i = 0; i < 20; ++i) {
+ e.execute(p);
+ }
+ }
+
+ @Override
+ public void establishSubscription(Map<String, String> paramMap,
+ SvcLogicContext ctx) throws SvcLogicException {
+ String subscriberId = paramMap.get(SUBSCRIBER_ID);
+ if (subscriberId == null) {
+ throw new SvcLogicException("Subscriber Id is null");
+ }
+
+ restconfApiCallNode.sendRequest(paramMap, ctx);
+
+ if (getResponseCode(paramMap.get(RESPONSE_PREFIX), ctx).equals(RESPONSE_CODE_200)) {
+ // TODO: save subscription id and subscriber in MYSQL
+
+ establishPersistentConnection(paramMap, ctx, subscriberId);
+ } else {
+ log.info("Failed to subscribe {}", subscriberId);
+ throw new SvcLogicException(ctx.getAttribute(RESPONSE_CODE));
+ }
+ }
+
+ @Override
+ public void modifySubscription(Map<String, String> paramMap, SvcLogicContext ctx) {
+ // TODO: to be implemented
+ }
+
+ @Override
+ public void deleteSubscription(Map<String, String> paramMap, SvcLogicContext ctx) {
+ String id = getSubscriptionId(paramMap.get(SUBSCRIBER_ID));
+ if (id != null) {
+ PersistentConnection conn = runnableInfo.get(id);
+ conn.terminate();
+ runnableInfo.remove(id);
+ subscriptionInfoMap.remove(id);
+ }
+ }
+
+ class PersistentConnection implements Runnable {
+ private String url;
+ private volatile boolean running = true;
+ private Map<String, String> paramMap;
+
+ PersistentConnection(String url, Map<String, String> paramMap) {
+ this.url = url;
+ this.paramMap = paramMap;
+ }
+
+ private void terminate() {
+ running = false;
+ }
+
+ @Override
+ public void run() {
+ Parameters p;
+ WebTarget target = null;
+ try {
+ RestapiCallNode restapi = restconfApiCallNode.getRestapiCallNode();
+ p = RestapiCallNode.getParameters(paramMap, new Parameters());
+ Client client = ignoreSslClient().register(SseFeature.class);
+ target = restapi.addAuthType(client, p).target(url);
+ } catch (SvcLogicException e) {
+ log.error("Exception occured!", e);
+ Thread.currentThread().interrupt();
+ }
+
+ target = addToken(target, paramMap.get("customHttpHeaders"));
+ EventSource eventSource = EventSource.target(target).build();
+ eventSource.register(new EventHandler(RestconfDiscoveryNode.this));
+ eventSource.open();
+ log.info("Connected to SSE source");
+ while (running) {
+ try {
+ log.info("SSE state " + eventSource.isOpen());
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ log.error("Interrupted!", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ eventSource.close();
+ log.info("Closed connection to SSE source");
+ }
+
+ private Client ignoreSslClient() {
+ SSLContext sslcontext = null;
+
+ try {
+ sslcontext = SSLContext.getInstance("TLS");
+ sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ } }, new java.security.SecureRandom());
+ } catch (NoSuchAlgorithmException | KeyManagementException e) {
+ throw new IllegalStateException(e);
+ }
+
+ return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true).build();
+ }
+ }
+
+ protected String getTokenId(String customHttpHeaders) {
+ if (customHttpHeaders.contains("=")) {
+ String[] s = customHttpHeaders.split("=");
+ return s[1];
+ }
+ return customHttpHeaders;
+ }
+
+ protected WebTarget addToken(WebTarget target, String customHttpHeaders) {
+ if (customHttpHeaders == null) {
+ return target;
+ }
+
+ return new AdditionalHeaderWebTarget(
+ target, getTokenId(customHttpHeaders));
+ }
+
+ /**
+ * Establishes a persistent between the client and server.
+ *
+ * @param paramMap input paramter map
+ * @param ctx service logic context
+ * @param subscriberId subscriber identifier
+ */
+ void establishPersistentConnection(Map<String, String> paramMap, SvcLogicContext ctx,
+ String subscriberId) {
+ String id = getOutputIdentifier(paramMap.get(RESPONSE_PREFIX), ctx);
+ SvcLogicGraphInfo callbackDG = new SvcLogicGraphInfo(paramMap.get("module"),
+ paramMap.get("rpc"),
+ paramMap.get("version"),
+ paramMap.get("mode"));
+ SubscriptionInfo info = new SubscriptionInfo();
+ info.callBackDG(callbackDG);
+ info.subscriptionId(id);
+ info.subscriberId(subscriberId);
+ subscriptionInfoMap.put(id, info);
+
+ String url = paramMap.get(SSE_URL);
+ PersistentConnection connection = new PersistentConnection(url, paramMap);
+ runnableInfo.put(id, connection);
+ executor.execute(connection);
+ }
+
+ /**
+ * Returns response code.
+ *
+ * @param prefix prefix given in input parameter
+ * @param ctx service logic context
+ * @return response code
+ */
+ String getResponseCode(String prefix, SvcLogicContext ctx) {
+ return ctx.getAttribute(getPrefix(prefix) + RESPONSE_CODE);
+ }
+
+ /**
+ * Returns subscription id from event.
+ *
+ * @param prefix prefix given in input parameter
+ * @param ctx service logic context
+ * @return subscription id from event
+ */
+ String getOutputIdentifier(String prefix, SvcLogicContext ctx) {
+ return ctx.getAttribute(getPrefix(prefix) + OUTPUT_IDENTIFIER);
+ }
+
+ private String getPrefix(String prefix) {
+ return prefix != null ? prefix + "." : "";
+ }
+
+ private String getSubscriptionId(String subscriberId) {
+ for (Map.Entry<String,SubscriptionInfo> entry
+ : subscriptionInfoMap.entrySet()) {
+ if (entry.getValue().subscriberId()
+ .equals(subscriberId)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns restconfApiCallNode.
+ *
+ * @return restconfApiCallNode
+ */
+ protected RestconfApiCallNode restconfapiCallNode() {
+ return restconfApiCallNode;
+ }
+
+ /**
+ * Sets restconfApiCallNode.
+ *
+ * @param node restconfApiCallNode
+ */
+ void restconfapiCallNode(RestconfApiCallNode node) {
+ restconfApiCallNode = node;
+ }
+
+ Map<String, SubscriptionInfo> subscriptionInfoMap() {
+ return subscriptionInfoMap;
+ }
+
+ void subscriptionInfoMap(Map<String, SubscriptionInfo> subscriptionInfoMap) {
+ this.subscriptionInfoMap = subscriptionInfoMap;
+ }
+
+ LinkedBlockingQueue<String> eventQueue() {
+ return eventQueue;
+ }
+
+ void eventQueue(LinkedBlockingQueue<String> eventQueue) {
+ this.eventQueue = eventQueue;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java
new file mode 100644
index 000000000..4ed3660ca
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java
@@ -0,0 +1,122 @@
+/*-
+ * ============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.restconfdiscovery;
+
+/**
+ * Holder to store information of subscription.
+ */
+public class SubscriptionInfo {
+ private String subscriptionId;
+ private String subscriberId;
+ private SvcLogicGraphInfo callbackDG;
+ private String yangFilePath;
+ private String filterUrl;
+
+ /**
+ * Returns callback DG.
+ *
+ * @return callback DG
+ */
+ public SvcLogicGraphInfo callBackDG() {
+ return callbackDG;
+ }
+
+ /**
+ * Sets callback DG.
+ *
+ * @param callbackDg callback DG
+ */
+ public void callBackDG(SvcLogicGraphInfo callbackDg) {
+ this.callbackDG = callbackDg;
+ }
+
+ /**
+ * Returns YANG file path.
+ *
+ * @return YANG file path
+ */
+ public String yangFilePath() {
+ return yangFilePath;
+ }
+
+ /**
+ * Sets YANG file path.
+ *
+ * @param yangFilePath yang file path
+ */
+ public void yangFilePath(String yangFilePath) {
+ this.yangFilePath = yangFilePath;
+ }
+
+ /**
+ * Returns filter URL.
+ *
+ * @return filter URL
+ */
+ public String filterUrl() {
+ return filterUrl;
+ }
+
+ /**
+ * Sets filter URL.
+ *
+ * @param filterUrl filter URL
+ */
+ public void filterUrl(String filterUrl) {
+ this.filterUrl = filterUrl;
+ }
+
+ /**
+ * Returns subscription Id.
+ *
+ * @return subscription Id
+ */
+ public String subscriptionId() {
+ return subscriptionId;
+ }
+
+ /**
+ * Sets subscription id.
+ *
+ * @param subscriptionId subscription id
+ */
+ public void subscriptionId(String subscriptionId) {
+ this.subscriptionId = subscriptionId;
+ }
+
+ /**
+ * Returns subscription Id.
+ *
+ * @return subscription Id
+ */
+ public String subscriberId() {
+ return subscriberId;
+ }
+
+ /**
+ * Sets subscriber id.
+ *
+ * @param subscriberId subscriber id
+ */
+ public void subscriberId(String subscriberId) {
+ this.subscriberId = subscriberId;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java
new file mode 100644
index 000000000..dfe8cd5b7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java
@@ -0,0 +1,110 @@
+/*-
+ * ============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.restconfdiscovery;
+
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+/**
+ * Abstraction of a plugin to enable discovery from DG.
+ */
+public interface SvcLogicDiscoveryPlugin extends SvcLogicJavaPlugin {
+
+ /**
+ * Allows directed graphs to establish a discovery subscription for a given subscriber.
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>templateDirName</td><td>Optional</td><td>full path to YANG directory that can be used to build a request</td><td>/sdncopt/bvc/resconfapi/test</td></tr>
+ * <tr><td>establishSubscriptionURL</td><td>Mandatory</td><td>url to establish connection with server</td><td>https://127.0.0.1:8181/restconf/operations/ietf-subscribed-notifications:establish-subscription</td></tr>
+ * <tr><td>sseConnectURL</td><td>Mandatory</td><td>url to setup SSE connection with server</td><td>https://127.0.0.1:8181/restconf/streams/yang-push-json</td></tr>
+ * <tr><td>callbackDG</td><td>Mandatory</td><td>callback DG to process the received notification</td><td>Resource-Discovery:handleSOTNTopology</td></tr>
+ * <tr><td>filterURL</td><td>Optional</td><td>url which needs to be subscribed, if null subscribe to all</td><td>http://example.com/sample-data/1.0</td></tr>
+ * <tr><td>subscriptionType</td><td>Optional</td><td>type of subscription, periodic or onDataChange</td><td>onDataChange</td></tr>
+ * <tr><td>updateFrequency</td><td>Optional</td><td>update frequency in milli seconds when subscription type is periodic</td><td>1000</td></tr>
+ * <tr><td>restapiUser</td><td>Optional</td><td>user name to use for http basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>restapiPassword</td><td>Optional</td><td>unencrypted password to use for http basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>contentType</td><td>Optional</td><td>http content type to set in the http header</td><td>usually application/json or application/xml</td></tr>
+ * <tr><td>format</td><td>Optional</td><td>should match request body format</td><td>json or xml</td></tr>
+ * <tr><td>responsePrefix</td><td>Optional</td><td>location the notification response will be written to in context memory</td><td>tmp.restconfdiscovery.result</td></tr>
+ * <tr><td>skipSending</td><td>Optional</td><td></td><td>true or false</td></tr>
+ * <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>customHttpHeaders</td><td>Optional</td><td>a list additional http headers to be passed in, follow the format in the example</td><td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td></tr>
+ * <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes http header content to context memory</td><td>true or false</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ * @see String#split(String, int)
+ */
+ void establishSubscription(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException;
+
+ /**
+ * Allows directed graphs to modify a discovery subscription for a given subscriber.
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>subscriberId</td><td>Mandatory</td><td>subscription subscriber's identifier</td><td>topologyId/1111</td></tr>
+ * <tr><td>templateDirName</td><td>Optional</td><td>full path to YANG directory that can be used to build a request</td><td>/sdncopt/bvc/resconfapi/test</td></tr>
+ * <tr><td>establishSubscriptionURL</td><td>Mandatory</td><td>url to establish connection with server</td><td>https://127.0.0.1:8181/restconf/operations/ietf-subscribed-notifications:establish-subscription</td></tr>
+ * <tr><td>sseConnectURL</td><td>Mandatory</td><td>url to setup SSE connection with server</td><td>https://127.0.0.1:8181/restconf/streams/yang-push-json</td></tr>
+ * <tr><td>callbackDG</td><td>Mandatory</td><td>callback DG to process the received notification</td><td>Resource-Discovery:handleSOTNTopology</td></tr>
+ * <tr><td>filterURL</td><td>Optional</td><td>url filter list which needs to be subscribed, if null subscribe to all</td><td>http://example.com/sample-data/1.0</td></tr>
+ * <tr><td>subscriptionType</td><td>Optional</td><td>type of subscription, periodic or onDataChange</td><td>onDataChange</td></tr>
+ * <tr><td>updateFrequency</td><td>Optional</td><td>update frequency in milli seconds when subscription type is periodic</td><td>1000</td></tr>
+ * <tr><td>restapiUser</td><td>Optional</td><td>user name to use for http basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>restapiPassword</td><td>Optional</td><td>unencrypted password to use for http basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>contentType</td><td>Optional</td><td>http content type to set in the http header</td><td>usually application/json or application/xml</td></tr>
+ * <tr><td>format</td><td>Optional</td><td>should match request body format</td><td>json or xml</td></tr>
+ * <tr><td>responsePrefix</td><td>Optional</td><td>location the notification response will be written to in context memory</td><td>tmp.restconfdiscovery.result</td></tr>
+ * <tr><td>skipSending</td><td>Optional</td><td></td><td>true or false</td></tr>
+ * <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>customHttpHeaders</td><td>Optional</td><td>a list additional http headers to be passed in, follow the format in the example</td><td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td></tr>
+ * <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes http header content to context memory</td><td>true or false</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ * @see String#split(String, int)
+ */
+ void modifySubscription(Map<String, String> paramMap, SvcLogicContext ctx);
+
+ /**
+ * Allows directed graphs to delete the discovery subscription for a given subscriber.
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>subscriberId</td><td>Mandatory</td><td>subscription subscriber's identifier</td><td>topologyId/1111</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ */
+ void deleteSubscription(Map<String, String> paramMap, SvcLogicContext ctx);
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java
new file mode 100644
index 000000000..1cc6261ab
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java
@@ -0,0 +1,178 @@
+/*-
+ * ============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.restconfdiscovery;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Holder to store callback directed graph info.
+ */
+class SvcLogicGraphInfo {
+ private String module;
+ private String rpc;
+ private String mode;
+ private String version;
+
+ /**
+ * Creates an instance of SvcLogicGraphInfo.
+ *
+ * @param module module name of callback DG
+ * @param rpc rpc name of callback DG
+ * @param mode mode of callback DG
+ * @param version version of callback DG
+ */
+ public SvcLogicGraphInfo(String module, String rpc, String mode, String version) {
+ this.module = module;
+ this.rpc = rpc;
+ this.mode = mode;
+ this.version = version;
+ }
+
+ public SvcLogicGraphInfo() {}
+
+ /**
+ * Returns module name of callback DG.
+ *
+ * @return module name of callback DG
+ */
+ public String module() {
+ return module;
+ }
+
+ /**
+ * Sets module of callback DG.
+ *
+ * @param module module name of the DG
+ */
+ public void module(String module) {
+ this.module = module;
+ }
+
+ /**
+ * Returns rpc of callback DG.
+ *
+ * @return rpc of callback DG
+ */
+ public String rpc() {
+ return rpc;
+ }
+
+ /**
+ * Sets rpc of callback DG.
+ *
+ * @param rpc rpc attribute of the DG
+ */
+ public void rpc(String rpc) {
+ this.rpc = rpc;
+ }
+
+ /**
+ * Returns mode of callback DG.
+ *
+ * @return mode of callback DG
+ */
+ public String mode() {
+ return mode;
+ }
+
+ /**
+ * Sets mode of DG.
+ *
+ * @param mode mode of the DG
+ */
+ public void mode(String mode) {
+ this.mode = mode;
+ }
+
+ /**
+ * Returns version of callback DG.
+ *
+ * @return version of callback DG
+ */
+ public String version() {
+ return version;
+ }
+
+ /**
+ * Sets version of DG.
+ *
+ * @param version version of the DG
+ */
+ public void version(String version) {
+ this.version = version;
+ }
+
+ /**
+ * Executes call back DG.
+ *
+ * @param ctx service logic context
+ * @throws SvcLogicException service logic error
+ */
+ public void executeGraph(SvcLogicContext ctx) throws SvcLogicException {
+ SvcLogicService service = findSvcLogicService();
+ if (service == null) {
+ throw new SvcLogicException("\"Could not get SvcLogicService reference\"");
+ }
+
+ SvcLogicStore store = service.getStore();
+ if (store != null) {
+ SvcLogicGraph subGraph = store.fetch(module, rpc, mode, version);
+ if (subGraph != null) {
+ ctx.setAttribute("subGraph", subGraph.toString());
+ service.execute(subGraph, ctx);
+ } else {
+ throw new SvcLogicException("Failed to call child [" + module +
+ "," + rpc + "," + version +
+ "," + mode + "] because" +
+ " the" + " graph could" +
+ " not be found");
+ }
+ } else {
+ throw new SvcLogicException("\"Could not get SvcLogicStore reference\"");
+ }
+ }
+
+ private static SvcLogicService findSvcLogicService() throws SvcLogicException {
+ Bundle bundle = FrameworkUtil.getBundle(SvcLogicService.class);
+ if (bundle == null) {
+ throw new SvcLogicException("Cannot find bundle reference for "
+ + SvcLogicService.NAME);
+ }
+
+ BundleContext bctx = bundle.getBundleContext();
+ ServiceReference<SvcLogicService> sref = bctx.getServiceReference(
+ SvcLogicService.class);
+ if (sref != null) {
+ return bctx.getService(sref);
+ } else {
+ throw new SvcLogicException("Cannot find service reference for "
+ + SvcLogicService.NAME);
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java
new file mode 100644
index 000000000..185f70ba0
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java
@@ -0,0 +1,66 @@
+/*-
+ * ============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;
+
+/**
+ * Representation of an entity that represents annotated attribute.
+ */
+public class Annotation {
+
+ /**
+ * Name of the annotation.
+ */
+ private String name;
+
+ /**
+ * Value of the annotation.
+ */
+ private String value;
+
+ /**
+ * Creates an instance of annotation.
+ *
+ * @param n annotation name
+ * @param v annotation value
+ */
+ public Annotation(String n, String v) {
+ name = n;
+ value = v;
+ }
+
+ /**
+ * Returns name of annotation.
+ *
+ * @return name of annotation
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns value of annotation.
+ *
+ * @return value of annotation
+ */
+ public String value() {
+ return value;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java
new file mode 100644
index 000000000..c692f1dd2
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java
@@ -0,0 +1,37 @@
+/*-
+ * ============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;
+
+/**
+ * Representation of data format.
+ */
+public enum DataFormat {
+
+ /**
+ * XML data format.
+ */
+ XML,
+
+ /**
+ * JSON data format.
+ */
+ JSON
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java
new file mode 100644
index 000000000..cab64391a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java
@@ -0,0 +1,94 @@
+/*-
+ * ============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.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstraction of serializer to encode/decode context memory parameters
+ * to/from specified data format.
+ */
+public abstract class DataFormatSerializer {
+
+ /**
+ * Data format type of the serializer.
+ */
+ private DataFormat dataFormat;
+
+ /**
+ * Data format serializer context.
+ */
+ private DataFormatSerializerContext serializerContext;
+
+ /**
+ * Creates an instance of data format serializer.
+ *
+ * @param d type of data format
+ * @param s data format serializer context
+ */
+ protected DataFormatSerializer(DataFormat d,
+ DataFormatSerializerContext s) {
+ this.dataFormat = d;
+ this.serializerContext = s;
+ }
+
+ /**
+ * Encodes context memory parameters to data format.
+ *
+ * @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) 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)
+ throws SvcLogicException;
+
+ /**
+ * Returns data format serializer context.
+ *
+ * @return data format serializer context
+ */
+ public DataFormatSerializerContext serializerContext() {
+ return serializerContext;
+ }
+
+ /**
+ * Returns supported data format.
+ *
+ * @return supported data format
+ */
+ public DataFormat dataFormat() {
+ return dataFormat;
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java
new file mode 100644
index 000000000..919e82af3
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java
@@ -0,0 +1,104 @@
+/*-
+ * ============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.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeSerializer;
+
+import java.util.Map;
+
+/**
+ * Abstraction of data format serializer context.
+ */
+public class DataFormatSerializerContext {
+
+ /**
+ * Data format listener.
+ */
+ private Listener listener;
+
+ /**
+ * URI corresponding to the instance identifier.
+ */
+ private String uri;
+
+ /**
+ * Protocol annotation.
+ */
+ private Map<String, String> protocolAnnotation;
+
+ /**
+ * Properties node serializer.
+ */
+ private PropertiesNodeSerializer propNodeSerializer;
+
+ /**
+ * Creates an instance of data format serializer context.
+ *
+ * @param l data format listener
+ * @param u URI corresponding to instance identifier
+ * @param p protocol annotations
+ * @param s properties node serializer
+ */
+ public DataFormatSerializerContext(Listener l, String u,
+ Map<String, String> p,
+ PropertiesNodeSerializer s) {
+ listener = l;
+ uri = u;
+ protocolAnnotation = p;
+ propNodeSerializer = s;
+ }
+
+ /**
+ * Returns the data format listener.
+ *
+ * @return data format listener
+ */
+ public Listener listener() {
+ return listener;
+ }
+
+ /**
+ * Returns the URI.
+ *
+ * @return URI
+ */
+ public String uri() {
+ return uri;
+ }
+
+ /**
+ * Returns the protocol annotations.
+ *
+ * @return protocol annotations
+ */
+ public Map<String, String> getProtocolAnnotation() {
+ return protocolAnnotation;
+ }
+
+ /**
+ * Returns the properties node serializer.
+ *
+ * @return properties node serializer
+ */
+ public PropertiesNodeSerializer getPropNodeSerializer() {
+ return propNodeSerializer;
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java
new file mode 100644
index 000000000..45317522a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java
@@ -0,0 +1,145 @@
+/*-
+ * ============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 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.
+ */
+public class DefaultJsonListener implements JsonListener {
+
+ /**
+ * Serializer helper to convert to properties node.
+ */
+ private SerializerHelper serializerHelper;
+
+ /**
+ * Name of the current JSON node.
+ */
+ private String name;
+
+ /**
+ * Module name of the current JSON node.
+ */
+ private String modName;
+
+ /**
+ * Value of the current JSON node.
+ */
+ private String value;
+
+ /**
+ * Value namespace of the current JSON node.
+ */
+ private String valueNs;
+
+ /**
+ * Creates an instance of default json listener with its serializer helper.
+ *
+ * @param serializerHelper serializer helper
+ */
+ public DefaultJsonListener(SerializerHelper serializerHelper) {
+ this.serializerHelper = serializerHelper;
+ }
+
+ @Override
+ public void enterJsonNode(String nodeName, JsonNode node,
+ NodeType nodeType) throws SvcLogicException {
+ getNodeName(nodeName, false);
+
+ switch (nodeType) {
+ case SINGLE_INSTANCE_LEAF_NODE:
+ getNodeName(node.asText(), true);
+ serializerHelper.addNode(name, modName, value, valueNs,
+ SINGLE_INSTANCE_LEAF_NODE);
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ getNodeName(node.asText(), true);
+ serializerHelper.addNode(name, modName, value, valueNs,
+ 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) throws SvcLogicException {
+ serializerHelper.exitNode();
+ }
+
+ @Override
+ public SerializerHelper serializerHelper() {
+ return serializerHelper;
+ }
+
+ /**
+ * Parses the abstract JSON name and fills the node name and node
+ * namespace or value and value namespace of the current JSON node .
+ *
+ * @param abstractName full name value
+ * @param isVal if it is for value parsing
+ */
+ private void getNodeName(String abstractName, boolean isVal) {
+ String[] val = abstractName.split(":");
+ if (val.length == 2) {
+ if (isVal) {
+ valueNs = val[0];
+ value = val[1];
+ } else {
+ modName = val[0];
+ name = val[1];
+ }
+ } else {
+ if (isVal) {
+ value = val[0];
+ valueNs = null;
+ } else {
+ name = val[0];
+ modName = null;
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java
new file mode 100644
index 000000000..47cb8b292
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java
@@ -0,0 +1,141 @@
+/*-
+ * ============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 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.
+ */
+public class DefaultJsonWalker implements JsonWalker {
+
+ @Override
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Processes single instance node or leaf, by adding the node to from
+ * JSON and walking through all its children recursively.
+ *
+ * @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)
+ throws SvcLogicException {
+ NodeType nodeType;
+ if (!value.isContainerNode()) {
+ nodeType = SINGLE_INSTANCE_LEAF_NODE;
+ } else {
+ nodeType = SINGLE_INSTANCE_NODE;
+ }
+ processNode(key, value, nodeType, listener);
+ }
+
+ /**
+ * Processes multi instance node or leaf, by adding the node to from JSON
+ * and walking through all its instance recursively.
+ *
+ * @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)
+ 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;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java
new file mode 100644
index 000000000..03abf44fd
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java
@@ -0,0 +1,120 @@
+/*-
+ * ============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.dom4j.Namespace;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.List;
+
+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.
+ */
+public class DefaultXmlListener implements XmlListener {
+
+ /**
+ * Serializer helper to convert to properties node.
+ */
+ private SerializerHelper serializerHelper;
+
+ /**
+ * Creates an instance of default XML listener with its serializer helper.
+ *
+ * @param serializerHelper serializer helper
+ */
+ public DefaultXmlListener(SerializerHelper serializerHelper) {
+ this.serializerHelper = serializerHelper;
+ }
+
+ @Override
+ 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:
+ List cont = element.content();
+ if (cont != null && cont.size() == 2 &&
+ isValueNsForLeaf(cont, element)) {
+ return;
+ }
+ serializerHelper.addNode(element.getName(),
+ element.getNamespace().getURI(),
+ null, null, null);
+ break;
+
+ default:
+ throw new SvcLogicException(format(NODE_TYPE_ERR,
+ nodeType.toString()));
+ }
+ }
+
+ /**
+ * Returns true if element has value namespace and adds the node to
+ * property tree; false otherwise.
+ *
+ * @param cont content of the element
+ * @param element element
+ * @return true if element has value namespace; false otherwise
+ * @throws SvcLogicException
+ */
+ private boolean isValueNsForLeaf(List cont, Element element)
+ throws SvcLogicException {
+ for (Object c : cont) {
+ if (c instanceof Namespace) {
+ String value = element.getText();
+ if (value != null) {
+ String[] val = value.split(":");
+ String valPrefix = val[0];
+ String actVal = val[1];
+ if (valPrefix != null && actVal != null &&
+ valPrefix.equals(((Namespace) c).getPrefix())) {
+ serializerHelper.addNode(
+ element.getName(),
+ element.getNamespace().getURI(),
+ actVal,
+ ((Namespace) c).getURI(), null);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void exitXmlElement(Element element) throws SvcLogicException {
+ serializerHelper.exitNode();
+ }
+
+ @Override
+ public SerializerHelper serializerHelper() {
+ return serializerHelper;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java
new file mode 100644
index 000000000..cdc713f31
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java
@@ -0,0 +1,48 @@
+/*-
+ * ============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 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.
+ */
+public class DefaultXmlWalker implements XmlWalker {
+
+ @Override
+ 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);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java
new file mode 100644
index 000000000..06a811e15
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java
@@ -0,0 +1,87 @@
+/*-
+ * ============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.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.
+ */
+public final class DfListenerFactory {
+
+ /**
+ * Creates a new DfListenerFactory.
+ */
+ private DfListenerFactory() {
+ }
+
+ /**
+ * Returns the instance of the data format listener factory.
+ *
+ * @return instance of the data format listener factory
+ */
+ public static DfListenerFactory instance() {
+ return DfListenerFactory.LazyHolder.INSTANCE;
+ }
+
+ /**
+ * Bill pugh singleton pattern. Instance will not be instantiated until
+ * the lazy holder class is loaded via a call to the instance of method
+ * below.
+ */
+ private static class LazyHolder {
+ private static final DfListenerFactory INSTANCE =
+ new DfListenerFactory();
+ }
+
+ /**
+ * Returns the data format listener by deciding it based on the format of
+ * the parameter.
+ *
+ * @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)
+ throws SvcLogicException {
+ Listener listener;
+ switch (params.format) {
+ case JSON:
+ listener = new DefaultJsonListener(serHelper);
+ break;
+
+ case XML:
+ listener = new DefaultXmlListener(serHelper);
+ break;
+
+ default:
+ throw new SvcLogicException(format(FORMAT_ERR,
+ params.format));
+ }
+ return listener;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java
new file mode 100644
index 000000000..4d95235e5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java
@@ -0,0 +1,87 @@
+/*-
+ * ============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.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.
+ */
+public final class DfSerializerFactory {
+
+ /**
+ * Creates a new DfSerializerFactory.
+ */
+ private DfSerializerFactory() {
+ }
+
+ /**
+ * Returns the instance of the data format serializer factory.
+ *
+ * @return instance of the data format serializer factory
+ */
+ public static DfSerializerFactory instance() {
+ return DfSerializerFactory.LazyHolder.INSTANCE;
+ }
+
+ /**
+ * Bill pugh singleton pattern. Instance will not be instantiated until
+ * the lazy holder class is loaded via a call to the instance of method
+ * below.
+ */
+ private static class LazyHolder {
+ private static final DfSerializerFactory INSTANCE =
+ new DfSerializerFactory();
+ }
+
+ /**
+ * Returns the data format serializer by deciding it based on the format of
+ * the parameter.
+ *
+ * @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)
+ throws SvcLogicException {
+ DataFormatSerializer serializer;
+ switch (params.format) {
+ case JSON:
+ serializer = new JsonSerializer(serCtx);
+ break;
+
+ case XML:
+ serializer = new XmlSerializer(serCtx);
+ break;
+
+ default:
+ throw new SvcLogicException(format(FORMAT_ERR,
+ params.format));
+ }
+ return serializer;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java
new file mode 100644
index 000000000..707c29444
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java
@@ -0,0 +1,231 @@
+/*-
+ * ============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.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 java.util.Iterator;
+
+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 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 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";
+
+ /**
+ * Data format error message for unsupported types.
+ */
+ public static final String FORMAT_ERR = "Only JSON and XML formats are " +
+ "supported. %s is not supported";
+
+ /**
+ * UTF header message for XML data format message.
+ */
+ public static final String UTF_HEADER = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\"?>";
+
+ /**
+ * Error message when a JSON tree creation fails.
+ */
+ public static final String JSON_TREE_ERR = "Unable to form JSON tree " +
+ "object from the JSON body provided.";
+
+ /**
+ * Error message when a XML tree creation fails.
+ */
+ public static final String XML_TREE_ERR = "Unable to form XML tree object" +
+ " from the XML body provided.";
+
+ //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
+ */
+ public 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 mUri module URI
+ * @param ctx schema context
+ * @param parent parent properties node
+ * @return namespace
+ * @throws SvcLogicException when resolving namespace fails
+ */
+ static Namespace getResolvedNamespace(String mName, String mUri,
+ SchemaContext ctx,
+ PropertiesNode parent)
+ throws SvcLogicException {
+ if (mName == null && mUri == null) {
+ Namespace parentNs = parent.namespace();
+ return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
+ parentNs.revision());
+ }
+
+ Iterator<Module> it;
+ Module mod;
+ if (mName != null) {
+ it = ctx.findModules(mName).iterator();
+ } else {
+ URI modUri = null;
+ try {
+ modUri = new URI(mUri);
+ } catch (URISyntaxException e) {
+ throw new SvcLogicException(URI_ERR, e);
+ }
+ it = ctx.findModules(modUri).iterator();
+ }
+
+ if (!it.hasNext()) {
+ return null;
+ }
+ mod = it.next();
+
+ return new Namespace(mod.getName(), mod.getQNameModule().getNamespace(),
+ getRevision(mod.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 = type;
+ while (superType.getBaseType() != null) {
+ superType = superType.getBaseType();
+ }
+ return superType;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java
new file mode 100644
index 000000000..89fd4c8c8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java
@@ -0,0 +1,55 @@
+/*-
+ * ============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 com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+
+/**
+ * Abstraction of an entity which provides call back methods, which in turn
+ * are called by JSON walker while walking the JSON tree. This interface
+ * needs to be implemented by protocol, implementing listener based call
+ * while doing JSON walk.
+ */
+public interface JsonListener extends Listener {
+
+ /**
+ * Call back invoked during JSON node entry. All other related
+ * information can be obtained from the JSON node.
+ *
+ * @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)
+ 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) throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java
new file mode 100644
index 000000000..91adb8126
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java
@@ -0,0 +1,91 @@
+/*-
+ * ============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 com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+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 static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormat.JSON;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.JSON_LIS_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.JSON_TREE_ERR;
+
+/**
+ * Representation of JSON serializer which encodes properties to JSON and
+ * decodes properties from JSON with the data format serializer.
+ */
+public class JsonSerializer extends DataFormatSerializer {
+
+ /**
+ * Creates an instance of data format serializer.
+ *
+ * @param serializerContext data format serializer context
+ */
+ protected JsonSerializer(DataFormatSerializerContext serializerContext) {
+ super(JSON, serializerContext);
+ }
+
+ @Override
+ public String encode(Map<String, String> param,
+ 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)
+ 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());
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java
new file mode 100644
index 000000000..588070a12
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java
@@ -0,0 +1,44 @@
+/*-
+ * ============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 com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of an entity which provides interface for JSON walk. This
+ * interface serves as a common tool for anyone who needs to parse the JSON
+ * node with depth-first algorithm.
+ */
+public interface JsonWalker {
+
+ /**
+ * Walks the JSON data tree. Protocols implement JSON listener service
+ * and walks the JSON tree with input as implemented object. JSON walker
+ * provides call back to the implemented methods.
+ *
+ * @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)
+ throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java
new file mode 100644
index 000000000..e5812dbb7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java
@@ -0,0 +1,34 @@
+/*-
+ * ============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;
+
+/**
+ * Abstraction of listener.
+ */
+public interface Listener {
+
+ /**
+ * Returns serializer helper for this listener.
+ *
+ * @return serializer helper
+ */
+ SerializerHelper serializerHelper();
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java
new file mode 100644
index 000000000..1fd0d2dee
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java
@@ -0,0 +1,297 @@
+/*-
+ * ============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.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.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+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.impl.schema.SchemaUtils.findDataChildSchemaByQName;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findSchemaForChild;
+import static org.opendaylight.yangtools.yang.data.util.ParserStreamUtils.findSchemaNodeByNameAndNamespace;
+
+/**
+ * Representation of MDSAL based serializer helper, which adds properties
+ * node to the properties tree based on its types.
+ */
+public class MdsalSerializerHelper extends SerializerHelper<SchemaNode, SchemaContext> {
+
+ /**
+ * Current properties node.
+ */
+ private PropertiesNode propNode;
+
+ /**
+ * Current schema node.
+ */
+ private SchemaNode curSchemaNode;
+
+
+ /**
+ * Creates MDSAL serializer helper with root schema node, schema context
+ * and URI.
+ *
+ * @param n schema node of the URI's last node
+ * @param c schema context
+ * @param u URI of the request
+ */
+ public 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
+ protected SchemaNode getSchemaNode() {
+ return schemaNode;
+ }
+
+ @Override
+ protected SchemaContext getSchemaCtx() {
+ return schemaCtx;
+ }
+
+ @Override
+ protected SchemaNode getCurSchema() {
+ return curSchemaNode;
+ }
+
+ @Override
+ protected void addNode(String name, String nameSpace, String value,
+ String valNameSpace, NodeType type)
+ throws SvcLogicException {
+ Namespace ns;
+ if (type == null) {
+ ns = getResolvedNamespace(null, nameSpace,
+ getSchemaCtx(), propNode);
+ } else {
+ ns = getResolvedNamespace(nameSpace, null,
+ getSchemaCtx(), propNode);
+ }
+ if (isChildPresent(name, ns)) {
+ addNodeToProperty(name, ns, value, valNameSpace, type);
+ } else {
+ throw new SvcLogicException(format(
+ "Unable to add the node %s", name));
+ }
+ }
+
+ @Override
+ 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() {
+ 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;
+ if (schemaNode instanceof LeafSchemaNode) {
+ type = ((LeafSchemaNode) schemaNode).getType();
+ } else {
+ type = ((LeafListSchemaNode) schemaNode).getType();
+ }
+ TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+ if (baseType instanceof IdentityrefTypeDefinition) {
+ if (nodeType == null) {
+ ns = getResolvedNamespace(null, valNs, getSchemaCtx(),
+ propNode);
+ } else {
+ ns = getResolvedNamespace(valNs, null, getSchemaCtx(),
+ 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) {
+ QName qname = QName.create(namespace.moduleNs(),
+ Revision.of(namespace.revision()), name);
+ SchemaNode childNode = null;
+ if (curSchemaNode instanceof DataSchemaNode) {
+ Deque<DataSchemaNode> dataSchema = findSchemaNodeByNameAndNamespace(
+ (DataSchemaNode) curSchemaNode, name, namespace.moduleNs());
+
+ if (dataSchema != null && !dataSchema.isEmpty()) {
+ childNode = dataSchema.pop();
+ }
+
+ if (dataSchema != null && !dataSchema.isEmpty()) {
+ childNode = findSchemaForChild(((ChoiceSchemaNode) childNode),
+ qname);
+ }
+
+ } else {
+ childNode = findDataChildSchemaByQName(curSchemaNode, qname);
+ }
+
+ if (childNode != null) {
+ curSchemaNode = childNode;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java
new file mode 100644
index 000000000..0f03039e5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java
@@ -0,0 +1,233 @@
+/*-
+ * ============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 com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Map;
+
+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 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.
+ */
+public class PropertiesNodeJsonListener implements PropertiesNodeListener{
+
+ /**
+ * JSON writer to write the JSON data format.
+ */
+ private JsonWriter jsonWriter;
+
+ /**
+ * Writer to write the JSON.
+ */
+ private Writer writer;
+
+ /**
+ * Creates the properties node JSON listener by instantiating and
+ * indenting the writer.
+ */
+ public PropertiesNodeJsonListener() {
+ writer = new StringWriter();
+ jsonWriter = new JsonWriter(writer);
+ jsonWriter.setIndent(repeat(" ", 4));
+ }
+
+ @Override
+ 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) throws SvcLogicException {
+ try {
+ jsonWriter.endObject();
+ jsonWriter.flush();
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ }
+
+ @Override
+ 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;
+
+ case ANY_XML_NODE:
+ jsonWriter.name(nodeName);
+ val = ((LeafNode) node).value();
+ try {
+ jsonWriter.jsonValue(val);
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ 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) 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:
+ case ANY_XML_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())) {
+ if (!parent.nonAppend()) {
+ 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);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java
new file mode 100644
index 000000000..f098195e4
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java
@@ -0,0 +1,246 @@
+/*-
+ * ============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.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;
+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;
+
+/**
+ * Representation of XML implementation of properties node listener.
+ */
+public class PropertiesNodeXmlListener implements PropertiesNodeListener {
+
+ /**
+ * XML data from the element.
+ */
+ private String xmlData;
+
+ /**
+ * Root element of the XML document.
+ */
+ private Element rootElement;
+
+ /**
+ * Writer to write the XML.
+ */
+ private Writer writer;
+
+ /**
+ * XML element stack to store the elements.
+ */
+ private final Stack<Element> elementStack = new Stack<>();
+
+ /**
+ * Creates the properties node XML listener.
+ */
+ public PropertiesNodeXmlListener() {
+ }
+
+ @Override
+ public void start(PropertiesNode node) {
+ rootElement = addElement(null, node);
+ elementStack.push(rootElement);
+ }
+
+ @Override
+ public void end(PropertiesNode node) throws SvcLogicException {
+ xmlData = rootElement.asXML();
+ xmlData = UTF_HEADER + xmlData;
+ writer = getXmlWriter(xmlData, "4");
+ }
+
+ @Override
+ 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) {
+ elementStack.push(element);
+ }
+ }
+
+ @Override
+ 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.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.nodeType() == MULTI_INSTANCE_HOLDER_NODE ||
+ parent.nodeType() == MULTI_INSTANCE_LEAF_HOLDER_NODE) {
+ parent = parent.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);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java
new file mode 100644
index 000000000..db9befb21
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java
@@ -0,0 +1,116 @@
+/*-
+ * ============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.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+
+/**
+ * Abstraction of an entity which helps the data format serializers to obtain
+ * schema context details and to build properties from data.
+ *
+ * @param <T> type of schema node
+ * @param <P> type of schema context
+ */
+public abstract class SerializerHelper<T, P> {
+
+ /**
+ * Schema node of the last element in the URI.
+ */
+ protected T schemaNode;
+
+ /**
+ * Root schema context.
+ */
+ protected P schemaCtx;
+
+ /**
+ * Root URI.
+ */
+ protected String rootUri;
+
+ /**
+ * Creates an instance of the serializer helper with the schema node,
+ * schema context and the URI.
+ *
+ * @param t schema node
+ * @param p schema context
+ * @param u root URI
+ */
+ protected SerializerHelper(T t, P p, String u) {
+ schemaNode = t;
+ schemaCtx = p;
+ rootUri = u;
+ }
+
+ /**
+ * Returns schema node of the last element in the URI.
+ *
+ * @return schema node
+ */
+ protected abstract T getSchemaNode();
+
+ /**
+ * Returns the root schema context.
+ *
+ * @return schema context
+ */
+ protected abstract P getSchemaCtx();
+
+ /**
+ * Returns the current schema context node.
+ *
+ * @return current schema context node
+ */
+ protected abstract T getCurSchema();
+
+ /**
+ * Adds a node to the properties node tree.
+ *
+ * @param name name of the node
+ * @param nameSpace name space of the node, it can be either module
+ * name or namespace; null indicates parent namespace
+ * @param value value of the node; applicable for leaf/leaf-list node
+ * @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)
+ 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() throws SvcLogicException;
+
+ /**
+ * Returns the built properties corresponding to the data.
+ *
+ * @return properties node.
+ */
+ protected abstract PropertiesNode getPropertiesNode();
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java
new file mode 100644
index 000000000..784e7af1f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java
@@ -0,0 +1,53 @@
+/*-
+ * ============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;
+
+/**
+ * Abstraction of an entity which provides call back methods, which in turn
+ * are called by XML walker while walking the XML tree. This interface needs
+ * to be implemented by protocol implementing listener based call while doing
+ * XML walk.
+ */
+public interface XmlListener extends Listener {
+
+ /**
+ * Callback invoked during a node entry. All the related information
+ * about the node can be obtained from the element.
+ *
+ * @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)
+ 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) throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java
new file mode 100644
index 000000000..7a6db3c86
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java
@@ -0,0 +1,37 @@
+/*-
+ * ============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;
+
+/**
+ * Represents the XML node type.
+ */
+public enum XmlNodeType {
+
+ /**
+ * Object XML node type.
+ */
+ OBJECT_NODE,
+
+ /**
+ * Text XML node type.
+ */
+ TEXT_NODE
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java
new file mode 100644
index 000000000..f3c6723e1
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java
@@ -0,0 +1,104 @@
+/*-
+ * ============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.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
+ * decodes properties from XML with the data format serializer.
+ */
+public class XmlSerializer extends DataFormatSerializer {
+
+ /**
+ * Creates an instance of XML serializer.
+ *
+ * @param serializerContext data format serializer context
+ */
+ protected XmlSerializer(DataFormatSerializerContext serializerContext) {
+ super(XML, serializerContext);
+ }
+
+ @Override
+ public String encode(Map<String, String> param,
+ 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 removeRootNode(writer.toString(), propNode.name());
+ }
+
+ @Override
+ 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());
+ }
+
+ /**
+ * Removes root node from the XML data format message and makes the
+ * string to be pretty print.
+ *
+ * @param xml XML data format message
+ * @param rootName root node name
+ * @return pretty print format XML message
+ */
+ private static String removeRootNode(String xml, String rootName) {
+ xml = xml.replace("\n<" + rootName + ">", "\n");
+ xml = xml.replace("</" + rootName + ">" + "\n", "");
+ xml = xml.replaceAll("\n" + " ", "\n");
+ xml = xml.replaceFirst("\n", "");
+ return xml;
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java
new file mode 100644
index 000000000..3835faa7e
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java
@@ -0,0 +1,44 @@
+/*-
+ * ============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;
+
+/**
+ * Abstraction of an entity which provides interface for XML walk. This
+ * interface serves as a common tool for anyone who needs to parse the XML
+ * node with depth-first algorithm.
+ */
+public interface XmlWalker {
+
+ /**
+ * Walks the XML data tree. Protocols implement XML listener service and
+ * walks the XML tree with input as implemented object. XML walker
+ * provides call back to the implemented methods.
+ *
+ * @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) throws
+ SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java
new file mode 100644
index 000000000..8eb3fb6e8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.onap.ccsdk.sli.plugins.restapicall.Parameters;
+
+/**
+ * Representation of the YANG parameters for the restconf api call node.
+ */
+public class YangParameters extends Parameters {
+ /**
+ * Directory path of the YANG file.
+ */
+ public String dirPath;
+
+ /**
+ * Creates an instance of the YANG parameters.
+ */
+ public YangParameters() {
+ super();
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java
new file mode 100644
index 000000000..7be54690a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java
@@ -0,0 +1,27 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Abstraction of entity representing child's to data node.
+ */
+public interface DataNodeChild extends NodeChild {
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java
new file mode 100644
index 000000000..2fa00bfb7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java
@@ -0,0 +1,105 @@
+/*-
+ * ============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.pnserializer;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.COLON;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.UNDERSCORE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+
+/**
+ * Represents implementation of PropertiesNodeListener.
+ */
+public class DefaultPropertiesNodeListener implements PropertiesNodeListener {
+
+ private Map<String, String> params = new HashMap<>();
+
+ @Override
+ public void start(PropertiesNode node) {
+ // do nothing
+ }
+
+ @Override
+ public void end(PropertiesNode node) throws SvcLogicException {
+ exitPropertiesNode(node);
+ }
+
+ @Override
+ public void enterPropertiesNode(PropertiesNode node) {
+ /*
+ * Only if it is leaf node or leaf-list node,
+ * then create a property entry and add to map
+ */
+ if (node.nodeType() == SINGLE_INSTANCE_LEAF_NODE
+ || node.nodeType() == MULTI_INSTANCE_LEAF_NODE) {
+ String val = ((LeafNode) node).value();
+ if (((LeafNode) node).valueNs() != null) {
+ val = ((LeafNode) node).valueNs().moduleName() + COLON + val;
+ }
+ String uri = node.uri().replaceAll(COLON, UNDERSCORE);
+ params.put(uri, val);
+ }
+ }
+
+ @Override
+ public void exitPropertiesNode(PropertiesNode node) throws
+ SvcLogicException {
+ if (!node.augmentations().isEmpty()) {
+ for (Map.Entry<Object, Collection<PropertiesNode>> augmentationTochild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> childsFromAugmentations = augmentationTochild
+ .getValue();
+ if (!childsFromAugmentations.isEmpty()) {
+ PropertiesNodeWalker walker = new DefaultPropertiesNodeWalker<>();
+ for (PropertiesNode pNode : childsFromAugmentations) {
+ enterPropertiesNode(pNode);
+ walker.walk(this, pNode);
+ exitPropertiesNode(pNode);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns properties.
+ *
+ * @return properties
+ */
+ public Map<String, String> params() {
+ return params;
+ }
+
+ /**
+ * Sets properties.
+ *
+ * @param params properties
+ */
+ public void params(Map<String, String> params) {
+ this.params = params;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java
new file mode 100644
index 000000000..5034530d5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java
@@ -0,0 +1,119 @@
+/*-
+ * ============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.pnserializer;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Implementation of properties node walker which helps in forming a new tree from properties node.
+ *
+ * @param <T> node child of properties node.
+ */
+public class DefaultPropertiesNodeWalker<T extends NodeChild> implements PropertiesNodeWalker {
+
+ @Override
+ public void walk(PropertiesNodeListener listener,
+ PropertiesNode propertiesNode) throws SvcLogicException {
+ listener.start(propertiesNode);
+ walkChildNode(listener, propertiesNode);
+ listener.end(propertiesNode);
+ }
+
+ /**
+ * Walks the children node from the parent node.
+ *
+ * @param listener properties node listener
+ * @param propertiesNode properties node
+ * @throws SvcLogicException when properties node walking fails
+ */
+ public void walkChildNode(PropertiesNodeListener listener,
+ PropertiesNode propertiesNode)
+ throws SvcLogicException {
+ Map<String, T> children = getChildren(propertiesNode);
+ if (children != null) {
+ for (Map.Entry<String, T> entry : children.entrySet()) {
+ PropertiesNode node = ((PropertiesNode) entry.getValue());
+ listener.enterPropertiesNode(node);
+ walkChildNode(listener, node);
+ listener.exitPropertiesNode(node);
+ }
+ }
+ if (propertiesNode instanceof RootNode) {
+ processAugments(propertiesNode, listener);
+ }
+ }
+
+ /**
+ * Processes the augments present in the root node.
+ *
+ * @param node root node
+ * @param listener properties node listener
+ * @throws SvcLogicException when augment node walking fails
+ */
+ private void processAugments(PropertiesNode node,
+ PropertiesNodeListener listener)
+ throws SvcLogicException {
+ for (Map.Entry<Object, Collection<PropertiesNode>>
+ augToChild : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ for (PropertiesNode p : child) {
+ listener.enterPropertiesNode(p);
+ walkChildNode(listener, p);
+ listener.exitPropertiesNode(p);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the children node according to the property node type.
+ *
+ * @param value property node
+ * @return property node children
+ */
+ private Map<String,T> getChildren(PropertiesNode value) {
+ if (value instanceof RootNode) {
+ return ((RootNode) value).children();
+ }
+ switch (value.nodeType()) {
+ case SINGLE_INSTANCE_NODE:
+ return ((InnerNode) value).children();
+ case MULTI_INSTANCE_HOLDER_NODE:
+ return ((Map<String, T>) ((ListHolderNode) value).children());
+ case MULTI_INSTANCE_NODE:
+ return ((Map<String, T>) ((MultiInstanceNode) value)
+ .children());
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ return ((Map<String, T>) ((LeafListHolderNode) value)
+ .children());
+ case SINGLE_INSTANCE_LEAF_NODE:
+ case MULTI_INSTANCE_LEAF_NODE:
+ case ANY_XML_NODE:
+ return null;
+ default:
+ throw new IllegalArgumentException("No more types allowed");
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java
new file mode 100644
index 000000000..52bec3412
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java
@@ -0,0 +1,59 @@
+/*-
+ * ============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.pnserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Abstraction of an entity that represents holder node to multi instance node
+ * in properties data tree.
+ *
+ * @param <T> type of child
+ */
+public abstract class HolderNode<T extends NodeChild> extends PropertiesNode {
+
+ private Map<String, T> children = new HashMap<>();
+
+ protected HolderNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo,
+ NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ /**
+ * Returns children.
+ *
+ * @return children
+ */
+ public Map<String, T> children() {
+ return children;
+ }
+
+ /**
+ * Returns child based on index.
+ *
+ * @return child based on index
+ */
+ public T child(String index) {
+ return children.get(index);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java
new file mode 100644
index 000000000..1cf99b2d4
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java
@@ -0,0 +1,215 @@
+/*-
+ * ============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.pnserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.addToAugmentations;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.createNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getAugmentationNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getUri;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.isNamespaceAsParent;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+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.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findCorrespondingAugment;
+
+/**
+ * Abstraction of an entity that represents an inner node to properties data
+ * tree.
+ *
+ * @param <T> type of child
+ */
+public abstract class InnerNode<T extends NodeChild> extends PropertiesNode {
+
+ private Map<String, T> children = new HashMap<String, T>();
+
+ protected InnerNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ /**
+ * Returns children.
+ *
+ * @return children
+ */
+ public Map<String, T> children() {
+ return children;
+ }
+
+ /**
+ * Sets children.
+ *
+ * @param children child nodes
+ */
+ public void children(Map<String, T> children) {
+ this.children = children;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ PropertiesNode node = ((PropertiesNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ // get augment schema, if it is augmented node
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()), ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, name);
+ }
+
+ // create node based on type
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = createNode(name, namespace, uri, this, appInfo, type);
+ }
+
+ // If namespace is not same as parent then it is augmented node
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ LeafNode node = ((LeafNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ AugmentationSchemaNode augSchema = null;
+ String uri = getUri(this, name, namespace);
+ node = new LeafNode(name, namespace, uri, this,
+ appInfo, type, value);
+
+ if (type != NodeType.ANY_XML_NODE) {
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(
+ ((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ }
+ node.valueNs(valueNs);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ Object appInfo) throws SvcLogicException {
+ String localname = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localname));
+
+ if (node == null) {
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localname);
+ }
+
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = new ListHolderNode(localname, namespace, uri,
+ this, appInfo, MULTI_INSTANCE_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localname, ((T) node));
+ }
+
+ node = node.addChild(index, localname, namespace, type, appInfo);
+ } else if (node instanceof ListHolderNode) {
+ ListHolderChild child = ((ListHolderNode) node).child(index);
+ node = (child != null ? ((MultiInstanceNode) child) :
+ node.addChild(index, localname, namespace, type, appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ String localName = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localName));
+
+ if (node == null) {
+
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localName);
+ }
+
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = new LeafListHolderNode(localName, namespace, uri, this,
+ appInfo, MULTI_INSTANCE_LEAF_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localName, ((T) node));
+ }
+
+ node = node.addChild(index, localName, namespace, type, value, valueNs, appInfo);
+ } else if (node instanceof LeafListHolderNode) {
+ LeafNode child = ((LeafNode) ((HolderNode) node).child(index));
+ node = (child != null ? child : node.addChild(index, localName,
+ namespace, type,
+ value, valueNs,
+ appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java
new file mode 100644
index 000000000..e43249a3d
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java
@@ -0,0 +1,28 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Abstraction of entity representing child's to leaf list holder.
+ */
+public interface LeafListHolderChild extends NodeChild {
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java
new file mode 100644
index 000000000..46ab5bb63
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Representation of leaf list holder node which will hold multi instance leaf
+ * node in properties data tree.
+ */
+public class LeafListHolderNode extends HolderNode<LeafListHolderChild> implements DataNodeChild {
+
+ private static final String node = " holder node";
+
+ /**
+ * Creates an instance of LeafListHolderNode.
+ *
+ * @param name name of the leaf-list node
+ * @param namespace namespace of the leaf-list node
+ * @param uri uri of the leaf-list node
+ * @param parent parent node of the leaf-list
+ * @param appInfo application info
+ * @param nodeType node type
+ */
+ public LeafListHolderNode(String name, Namespace namespace,
+ String uri, PropertiesNode parent,
+ Object appInfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf cannot be child of leaf-list" +
+ node);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Container cannot be child of leaf-list" +
+ node);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("List cannot be child of leaf-list" +
+ node);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ LeafNode node = ((LeafNode) children().get(index));
+ if (index == null) {
+ index = String.valueOf(children().size());
+ }
+ String uri = this.uri() + "[" + index + "]";
+ node = (node != null) ? node : new LeafNode(name, namespace, uri,
+ this, appInfo, type, value);
+ node.valueNs(valueNs);
+ children().put(index, node);
+ return node;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java
new file mode 100644
index 000000000..041175ca7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Representation of leaf node in properties data tree.
+ */
+public class LeafNode extends PropertiesNode implements LeafListHolderChild, DataNodeChild {
+
+ private String value;
+ private Namespace valueNs;
+ private static final String svcLogicException = "Leaf cannot hold child nodes";
+
+ /**
+ * Creates an instance of leaf node.
+ *
+ * @param name name of the leaf node
+ * @param namespace namespace of the leaf node
+ * @param uri uri of the leaf node
+ * @param parent parent of the leaf node
+ * @param appInfo application info
+ * @param nodeType node type
+ * @param value value of the leaf
+ */
+ public LeafNode(String name, Namespace namespace,
+ String uri, PropertiesNode parent,
+ Object appInfo, NodeType nodeType,
+ String value) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ this.value = value;
+ }
+
+ /**
+ * Returns value of the leaf.
+ *
+ * @return value of the leaf
+ */
+ public String value() {
+ return value;
+ }
+
+ /**
+ * Sets value of the leaf.
+ *
+ * @param value value of the leaf
+ */
+ public void value(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns value namespace.
+ *
+ * @return value namespace
+ */
+ public Namespace valueNs() {
+ return valueNs;
+ }
+
+ /**
+ * Sets value namespace.
+ *
+ * @param valueNs value namespace
+ */
+ public void valueNs(Namespace valueNs) {
+ this.valueNs = valueNs;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException(svcLogicException);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException(svcLogicException);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException(svcLogicException);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf cannot hold child nodes");
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java
new file mode 100644
index 000000000..ec9cc2a0f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java
@@ -0,0 +1,28 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Abstraction of entity representing child's to list holder.
+ */
+public interface ListHolderChild extends NodeChild {
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java
new file mode 100644
index 000000000..ba9da54cf
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java
@@ -0,0 +1,73 @@
+/*-
+ * ============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.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Representation of list holder node which will hold multi instance node in
+ * properties data tree.
+ */
+public class ListHolderNode extends HolderNode<ListHolderChild> implements DataNodeChild {
+
+ protected ListHolderNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf cannot be child of list holder node");
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Container cannot be child of list holder node");
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ Object appInfo) throws SvcLogicException {
+ MultiInstanceNode node = ((MultiInstanceNode) children().get(index));
+ if (index == null) {
+ index = String.valueOf(children().size());
+ }
+ String uri = this.uri() + "[" + index + "]";
+ node = (node != null) ? node : new MultiInstanceNode(name, namespace, uri,
+ this, appInfo, type);
+ children().put(index, node);
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf-list cannot be child of list holder node");
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
new file mode 100644
index 000000000..8a6e75668
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
@@ -0,0 +1,227 @@
+/*-
+ * ============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.pnserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+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.util.SchemaContextUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.DOT_REGEX;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.SLASH;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getChildSchemaNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getIndex;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getListName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNodeType;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getParsedValue;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getProcessedPath;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getValueNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.ANY_XML_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;
+
+/**
+ * Representation of mdsal based properties node serializer implementation.
+ */
+public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<SchemaNode, SchemaContext> {
+
+ private static final Logger log = LoggerFactory.getLogger(
+ MdsalPropertiesNodeSerializer.class);
+ private SchemaNode curSchema;
+ private PropertiesNode node;
+
+ /**
+ * Creates the properties node serializer.
+ *
+ * @param schemaNode schema node.
+ * @param schemaCtx schema context
+ * @param uri URL of the request
+ */
+ public MdsalPropertiesNodeSerializer(SchemaNode schemaNode,
+ SchemaContext schemaCtx, String uri) {
+ super(schemaNode, schemaCtx, uri);
+ }
+
+ @Override
+ public PropertiesNode encode(Map<String, String> paramMap) throws SvcLogicException {
+ curSchema = schemaNode();
+ String nodeInUri[] = uri().split("\\/");
+ String lastNodeName = nodeInUri[nodeInUri.length - 1];
+ String rootUri = uri().replaceAll("\\/", "\\.");
+ node = createRootNode(lastNodeName, rootUri);
+
+ paramMap = convertToValidParam(paramMap);
+
+ updateModNameReq(paramMap, rootUri);
+
+ for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+ String[] names = entry.getKey().split("\\.");
+ for (int i = 0; i < names.length; i++) {
+ if (i < nodeInUri.length) {
+ if (!(nodeInUri[i].equals(names[i]))) {
+ break;
+ }
+ } else {
+ createPropertyNode(i, names.length, names[i],
+ entry.getValue());
+ }
+ }
+ }
+ return node;
+ }
+
+ private void updateModNameReq(Map<String, String> paramMap,
+ String rootUri) {
+ String isReqStr = rootUri + "." + "isNonAppend";
+ String val = paramMap.get(isReqStr);
+ if (val != null && val.equals("true")) {
+ node.nonAppend(true);
+ }
+ }
+
+ /**
+ * Converts all the params in the svc logic context into a valid param by
+ * replacing the underscore in module name to colon at necessary places.
+ *
+ * @param paramMap list of invalid parameters
+ * @return list of partially valid parameters
+ */
+ private Map<String, String> convertToValidParam(Map<String, String> paramMap) {
+ Map<String, String> fixedParams = new HashMap<>();
+ for(Map.Entry<String, String> entry : paramMap.entrySet()) {
+ String key = entry.getKey().replaceAll(DOT_REGEX, SLASH);
+ try {
+ SchemaPathHolder fixedUrl = getProcessedPath(key, schemaCtx());
+ String fixedUri = fixedUrl.getUri().replaceAll(
+ SLASH, DOT_REGEX);
+ fixedParams.put(fixedUri, entry.getValue());
+ } catch (IllegalArgumentException | RestconfDocumentedException
+ | NullPointerException e) {
+ log.info("Exception while processing properties by replacing " +
+ "underscore with colon. Process the properties as it is." + e);
+ fixedParams.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return fixedParams;
+ }
+
+ @Override
+ public Map<String, String> decode(PropertiesNode propertiesNode)
+ throws SvcLogicException {
+ PropertiesNodeWalker walker = new DefaultPropertiesNodeWalker<>();
+ DefaultPropertiesNodeListener listener = new DefaultPropertiesNodeListener();
+ walker.walk(listener, propertiesNode);
+ return listener.params();
+ }
+
+ private RootNode createRootNode(String lastNodeName, String rootUri) {
+ Module m = SchemaContextUtil.findParentModule(schemaCtx(), curSchema);
+ Namespace ns = new Namespace(m.getName(), m.getNamespace(),
+ getRevision(m.getRevision()));
+ return new RootNode(lastNodeName, ns, schemaNode(), rootUri);
+ }
+
+ private void createPropertyNode(int index, int length, String name,
+ String value) throws SvcLogicException {
+
+ Namespace ns = getNamespace(getListName(name), schemaCtx(),
+ node, curSchema);
+ String localName = resolveName(ns, name);
+ SchemaNode schema = getChildSchemaNode(curSchema, localName, ns);
+ if (schema == null) {
+ return;
+ }
+
+ switch (getNodeType(index, length, name, schema)) {
+ case SINGLE_INSTANCE_NODE:
+ node = node.addChild(localName, ns,
+ SINGLE_INSTANCE_NODE, schema);
+ curSchema = schema;
+ break;
+
+ case MULTI_INSTANCE_NODE:
+ node = node.addChild(getIndex(name), localName, ns,
+ MULTI_INSTANCE_NODE, schema);
+ curSchema = schema;
+ break;
+
+ case SINGLE_INSTANCE_LEAF_NODE:
+ addLeafNode(value, SINGLE_INSTANCE_LEAF_NODE, localName,
+ ns, schema, name);
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ addLeafNode(value, MULTI_INSTANCE_LEAF_NODE, localName,
+ ns, schema, name);
+ break;
+
+ case ANY_XML_NODE:
+ node = node.addChild(localName, ns, ANY_XML_NODE,
+ value, null, schema);
+ node = node.endNode();
+ curSchema = ((SchemaNode) node.appInfo());
+ break;
+
+ default:
+ throw new SvcLogicException("Invalid node type");
+ }
+ }
+
+ /**
+ * Adds leaf property node to the current node.
+ *
+ * @param value value of the leaf node
+ * @param type single instance or multi instance leaf node
+ * @param localName name of the leaf node
+ * @param ns namespace of the leaf node
+ * @param schema schema of the leaf node
+ * @param name name of the leaf in properties
+ * @throws SvcLogicException exception while adding leaf node
+ */
+ private void addLeafNode(String value, NodeType type,
+ String localName, Namespace ns,
+ SchemaNode schema, String name) throws SvcLogicException {
+ Namespace valNs = getValueNamespace(value, schemaCtx());
+ value = getParsedValue(valNs, value);
+ if (SINGLE_INSTANCE_LEAF_NODE == type) {
+ node = node.addChild(localName, ns, SINGLE_INSTANCE_LEAF_NODE,
+ value, valNs, schema);
+ } else {
+ node = node.addChild(getIndex(name), localName, ns,
+ MULTI_INSTANCE_LEAF_NODE, value,
+ valNs, schema);
+ }
+ node = node.endNode();
+ curSchema = ((SchemaNode) node.appInfo());
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java
new file mode 100644
index 000000000..e6fa064f5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java
@@ -0,0 +1,578 @@
+/*-
+ * ============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.pnserializer;
+
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.Optional;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.data.util.ParserStreamUtils;
+import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static java.util.regex.Pattern.quote;
+import static org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier.toInstanceIdentifier;
+
+/**
+ * Represents utilities for properties node tree.
+ */
+public final class MdsalPropertiesNodeUtils {
+
+ static final String COLON = ":";
+
+ static final String UNDERSCORE = "_";
+
+ static final String SLASH = "/";
+
+ static final String DOT_REGEX = "\\.";
+
+ private static final String INFO_MSG = "The %s formed is currently not" +
+ " valid";
+
+ private static final String EXC_MSG = "Unable to form a formatted path";
+
+ /**
+ * Logger for the Mdsal properties util class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(
+ MdsalPropertiesNodeUtils.class);
+
+ private MdsalPropertiesNodeUtils() {
+ }
+
+ /**
+ * Returns the index from multi instance property name.
+ *
+ * @param name name of the property
+ * @return index from multi instance property name
+ */
+ public static String getIndex(String name) {
+ return name.substring(name.indexOf("[") + 1,
+ name.indexOf("]"));
+ }
+
+ /**
+ * Returns the multi instance property name.
+ *
+ * @param name name of the property
+ * @return the multi instance property name
+ */
+ public static String getListName(String name) {
+ String[] s = name.split("\\[");
+ return s[0];
+ }
+
+ /**
+ * Returns true if property is multi instance.
+ *
+ * @param name name of the property
+ * @return true if property is multi instance
+ */
+ public static boolean isListEntry(String name) {
+ String s[] = name.split("\\[");
+ return s.length > 1;
+ }
+
+ /**
+ * Returns name of the property after pruning namespace and
+ * index if the property is multi instance.
+ *
+ * @param name name of the property
+ * @return name of the property
+ */
+ static String resolveName(String name) {
+ String localName = getListName(name);
+ final int lastIndexOfColon = localName.lastIndexOf(":");
+ if (lastIndexOfColon != -1) {
+ localName = localName.substring(lastIndexOfColon + 1);
+ }
+ return localName;
+ }
+
+ /**
+ * Returns name of the property after pruning namespace and index if the
+ * property is multi instance by knowing the module name from namespace.
+ *
+ * @param ns namespace
+ * @param name name of the node
+ * @return resolved name
+ */
+ static String resolveName(Namespace ns, String name) {
+ String localName = getListName(name);
+ String modName = ns.moduleName();
+ if ((localName.contains(COLON) || localName.contains(UNDERSCORE))
+ && localName.startsWith(modName)) {
+ localName = localName.substring(modName.length()+1);
+ }
+ return localName;
+ }
+
+ /**
+ * Adds current node to parent's augmentation map.
+ *
+ * @param augSchema augment schema
+ * @param parent parent property node
+ * @param curNode current property node
+ */
+ public static void addToAugmentations(AugmentationSchemaNode augSchema,
+ PropertiesNode parent,
+ PropertiesNode curNode) {
+ Collection<PropertiesNode> childsFromAugmentation = parent
+ .augmentations().get(augSchema);
+ if (!childsFromAugmentation.isEmpty()) {
+ for (PropertiesNode pNode : childsFromAugmentation) {
+ if (pNode.name().equals(curNode.name())) {
+ return;
+ }
+ }
+ }
+ parent.augmentations().put(augSchema, curNode);
+ }
+
+
+ /**
+ * Returns augmented properties node if it is already
+ * added in properties tree.
+ *
+ * @param augSchema augmented schema node
+ * @param parent parent properties node
+ * @param name name of the properties
+ * @return augmented properties node if it is already added
+ */
+ public static PropertiesNode getAugmentationNode(
+ AugmentationSchemaNode augSchema,
+ PropertiesNode parent, String name) {
+ if (augSchema == null) {
+ return null;
+ }
+
+ Collection<PropertiesNode> childsFromAugmentation = parent
+ .augmentations().get(augSchema);
+ if (!childsFromAugmentation.isEmpty()) {
+ for (PropertiesNode pNode : childsFromAugmentation) {
+ if (pNode.name().equals(name)) {
+ return pNode;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates uri with specified name and namespace.
+ *
+ * @param parent parent properties node
+ * @param name name of the node
+ * @param ns namespace of the node
+ * @return uri with specified name and namespace
+ */
+ public static String getUri(PropertiesNode parent, String name,
+ Namespace ns) {
+ String uri = name;
+ if (!(parent.namespace().moduleNs().equals(ns.moduleNs()))) {
+ uri = ns.moduleName() + ":" + name;
+ }
+ return parent.uri() + "." + uri;
+ }
+
+ /**
+ * Creates new properties with specified parameters.
+ *
+ * @param name name of the properties node
+ * @param namespace namespace of the properties node
+ * @param uri uri of the properties node
+ * @param parent parent node
+ * @param appInfo application info
+ * @param type node type
+ * @return new properties node
+ * @throws SvcLogicException exception while creating properties node
+ */
+ public static PropertiesNode createNode(String name, Namespace namespace,
+ String uri, PropertiesNode parent,
+ Object appInfo, NodeType type)
+ throws SvcLogicException {
+ switch (type) {
+ case SINGLE_INSTANCE_NODE:
+ return new SingleInstanceNode(name, namespace, uri, parent, appInfo, type);
+ case MULTI_INSTANCE_HOLDER_NODE:
+ return new ListHolderNode(name, namespace, uri, parent, appInfo, type);
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ return new LeafListHolderNode(name, namespace, uri, parent, appInfo, type);
+ default:
+ throw new SvcLogicException("Invalid node type " + type);
+ }
+ }
+
+ /**
+ * Returns true if namespace is same as parent's namespace.
+ *
+ * @param parent parent property node
+ * @param curNode current property node
+ * @return true if namespace is same as parent namespace
+ */
+ public static boolean isNamespaceAsParent(PropertiesNode parent,
+ PropertiesNode curNode) {
+ return parent.namespace().moduleNs().equals(curNode.namespace().moduleNs());
+ }
+
+ /**
+ * Returns the schema path holder with a formatted url and the instance
+ * identifier context from a given uri or the parameters from svc logic
+ * context.
+ *
+ * @param uri unformatted uri or parameter
+ * @param context schema context
+ * @return schema path holder
+ */
+ public static SchemaPathHolder getProcessedPath(String uri,
+ SchemaContext context) {
+
+ String uri1 = uri.replaceAll(UNDERSCORE, COLON);
+ try {
+ InstanceIdentifierContext<?> id = toInstanceIdentifier(
+ uri1, context, null);
+ return new SchemaPathHolder(id, uri1);
+ } catch (IllegalArgumentException | RestconfDocumentedException
+ | NullPointerException e) {
+ log.info("Exception while converting uri to instance identifier" +
+ " context. Process each node in uri to get instance identifier" +
+ " context " + e);
+ return processNodesAndAppendPath(uri, context);
+ }
+ }
+
+ /**
+ * Processes the nodes in the given uri and finds instance identifier
+ * context till it reaches the last node in uri. If its not able to find
+ * schema for the path, it appends the suffix part and puts it back in
+ * the param list.
+ *
+ * @param uri uri with underscore
+ * @param context schema context
+ * @return schema and path holder
+ */
+ private static SchemaPathHolder processNodesAndAppendPath(String uri,
+ SchemaContext context) {
+
+ String actPath = "";
+ SchemaPathHolder id = new SchemaPathHolder(null, "");
+ String[] uriParts = uri.split(SLASH);
+ String sec = "";
+ if (uri.contains(UNDERSCORE)) {
+ sec = uri.substring(uriParts[0].length()+1);
+ }
+ for (int i = 0; i<uriParts.length; i++) {
+
+ try {
+ id = processIdentifier(uriParts[i], context, actPath);
+ } catch (IllegalArgumentException e) {
+ log.info(format(EXC_MSG, e));
+ id.setUri(actPath+ uriParts[i] + sec);
+ return id;
+ }
+
+ actPath = actPath + id.getUri() + SLASH;
+ if (sec.startsWith(SLASH)) {
+ sec = sec.replaceFirst(SLASH, "");
+ }
+ if (i+1 < uriParts.length) {
+ sec = sec.replaceFirst(quote(uriParts[i + 1]), "");
+ }
+ }
+ id.setUri(actPath.substring(0,actPath.length() - 1));
+ return id;
+ }
+
+ /**
+ * Processes the schema and path holder for a given node in the path. It
+ * figures if the path is valid by replacing underscore in the node
+ * consecutively, till it finds the proper schema for the node.
+ *
+ * @param node node in the path
+ * @param context schema context
+ * @param prefix prefix for the node in the path
+ * @return schema and path holder
+ */
+ private static SchemaPathHolder processIdentifier(String node,
+ SchemaContext context,
+ String prefix) {
+
+ String[] values = node.split(UNDERSCORE);
+ String val = values[0];
+ StringBuilder firstHalf = new StringBuilder();
+ String secondHalf = "";
+ if (node.contains(UNDERSCORE)) {
+ secondHalf = node.substring(values[0].length()+1);
+ }
+ InstanceIdentifierContext<?> id;
+ for (int i = 0; i< values.length-1; i++) {
+ val = values[i];
+ val = firstHalf + val + COLON + secondHalf;
+ try {
+ id = toInstanceIdentifier(prefix + val, context, null);
+ return new SchemaPathHolder(id, val);
+ } catch (IllegalArgumentException | RestconfDocumentedException |
+ NullPointerException e) {
+ log.info(format(INFO_MSG, val, e));
+ }
+ firstHalf.append(values[i]).append(UNDERSCORE);
+ secondHalf = secondHalf.replaceFirst(
+ values[i + 1] + UNDERSCORE,"");
+ }
+ val = val.replace(COLON,UNDERSCORE);
+ try {
+ id = toInstanceIdentifier(prefix + val, context, null);
+ return new SchemaPathHolder(id, val);
+ } catch (IllegalArgumentException | RestconfDocumentedException |
+ NullPointerException e1) {
+ throw new IllegalArgumentException(EXC_MSG, e1);
+ }
+ }
+
+ /**
+ * Returns the namespace of the given node name. If the node name is
+ * separated by colon, the it splits with colon and forms the namespace.
+ * If the node name is formed with underscore, then it splits the node
+ * name consecutively to figure out the proper module name.
+ *
+ * @param childName node name
+ * @param ctx schema context
+ * @param parent parent properties node
+ * @param curSchema current schema
+ * @return namespace of the given node
+ */
+ static Namespace getNamespace(String childName, SchemaContext ctx,
+ PropertiesNode parent, SchemaNode curSchema) {
+
+ Namespace parentNs = parent.namespace();
+ Namespace ns = new Namespace(parentNs.moduleName(),
+ parentNs.moduleNs(), parentNs.revision());
+ int lastIndexOfColon = childName.lastIndexOf(COLON);
+ if (lastIndexOfColon != -1) {
+ String moduleName = childName.substring(0, lastIndexOfColon);
+ childName = childName.substring(lastIndexOfColon+1);
+ Namespace ns1 = getNs(moduleName, ctx);
+ if (ns1 != null) {
+ ns = ns1;
+ }
+ }
+
+ SchemaNode child = getChildSchemaNode(curSchema, childName, ns);
+
+ if (child == null && childName.contains(UNDERSCORE)) {
+ String[] children = childName.split(UNDERSCORE);
+ String second = childName.substring(children[0].length() + 1);
+ StringBuilder first = new StringBuilder();
+
+ for (int i =0; i< children.length; i++) {
+ String moduleName = first + children[i];
+ Namespace newNs = getNs(moduleName, ctx);
+ if (newNs != null) {
+ return newNs;
+ }
+ first.append(children[i]).append(UNDERSCORE);
+ if (i + 1 < children.length) {
+ second = second.replaceFirst(
+ children[i + 1] + UNDERSCORE, "");
+ }
+ }
+ return ns;
+ }
+ return ns;
+ }
+
+ /**
+ * Returns the namespace by finding the given module in the schema context.
+ *
+ * @param modName module name
+ * @param ctx schema context
+ * @return namespace of the given node name
+ */
+ private static Namespace getNs(String modName, SchemaContext ctx) {
+ Iterator<Module> it = ctx.findModules(modName).iterator();
+ if (it.hasNext()) {
+ Module m = it.next();
+ return new Namespace(modName, m.getQNameModule().getNamespace(),
+ getRevision(m.getRevision()));
+ }
+ return null;
+ }
+
+ /**
+ * Returns child schema node.
+ *
+ * @param curSchema current schema node
+ * @param name name of the property
+ * @param namespace namespace of the property
+ * @return child schema node
+ */
+ public static SchemaNode getChildSchemaNode(SchemaNode curSchema,
+ String name,
+ Namespace namespace) {
+ if (namespace == null) {
+ return null;
+ }
+
+ QName qname = QName.create(namespace.moduleNs(),
+ Revision.of(namespace.revision()), name);
+
+ // YANG RPC will not be instance of DataSchemaNode
+ if (curSchema instanceof DataSchemaNode) {
+ Deque<DataSchemaNode> schemaNodeDeque = ParserStreamUtils.
+ findSchemaNodeByNameAndNamespace(((DataSchemaNode)
+ curSchema), name, namespace.moduleNs());
+ if (schemaNodeDeque.isEmpty()) {
+ // could not find schema node
+ return null;
+ }
+
+ DataSchemaNode schemaNode = schemaNodeDeque.pop();
+ if (schemaNodeDeque.isEmpty()){
+ // Simple node
+ return schemaNode;
+ }
+
+ // node is child of Choice/case
+ return SchemaUtils.findSchemaForChild(((ChoiceSchemaNode) schemaNode),
+ qname);
+ } else {
+ return SchemaUtils.findDataChildSchemaByQName(curSchema, qname);
+ }
+ }
+
+ /**
+ * Returns the property node type.
+ *
+ * @param index current index
+ * @param length length of the properties
+ * @param name name of the property
+ * @return the property node type
+ */
+ public static NodeType getNodeType(int index, int length, String name,
+ SchemaNode schema) {
+ if (index == length-1) {
+ if (schema instanceof AnyXmlSchemaNode){
+ return NodeType.ANY_XML_NODE;
+ }
+ return (isListEntry(name) ? NodeType.MULTI_INSTANCE_LEAF_NODE :
+ NodeType.SINGLE_INSTANCE_LEAF_NODE);
+ } else {
+ return (isListEntry(name) ? NodeType.MULTI_INSTANCE_NODE :
+ NodeType.SINGLE_INSTANCE_NODE);
+ }
+ }
+
+ /**
+ * Returns revision in string.
+ *
+ * @param r YANG revision
+ * @return revision in string
+ */
+ public static String getRevision(Optional<Revision> r) {
+ return (r.isPresent()) ? r.get().toString() : null;
+ }
+
+ /**
+ * Returns value namespace for leaf value.
+ *
+ * @param value value of the leaf
+ * @param ctx schema context
+ * @return value namespace
+ * @throws SvcLogicException if identity/module could not be found
+ */
+ static Namespace getValueNamespace(String value,
+ SchemaContext ctx)
+ throws SvcLogicException {
+ String prefix = getPrefixFromValue(value);
+ if (prefix == null) {
+ return null;
+ }
+
+ IdentitySchemaNode id = IdentityCodecUtil.parseIdentity(value,
+ ctx,
+ prefixToModule -> {
+ final Iterator<Module> modules = ctx.findModules(prefix).iterator();
+ checkArgument(modules.hasNext(), "Could not find " +
+ "module %s", prefix);
+ return modules.next().getQNameModule();
+ });
+
+ if (id == null) {
+ throw new SvcLogicException("Could not find identity");
+ }
+
+ return getModuleNamespace(id.getQName(), ctx);
+ }
+
+ private static String getPrefixFromValue(String value) {
+ int lastIndexOfColon = value.lastIndexOf(":");
+ if (lastIndexOfColon != -1) {
+ return value.substring(0, lastIndexOfColon);
+ }
+ return null;
+ }
+
+ /**
+ * Returns module namespace from a given qName.
+ *
+ * @param qName qName of a node
+ * @param ctx schema context
+ * @return module namespace of the node
+ * @throws SvcLogicException when the module is not available
+ */
+ public static Namespace getModuleNamespace(QName qName, SchemaContext ctx)
+ throws SvcLogicException {
+ Optional<Module> module = ctx.findModule(qName.getModule());
+ if (!module.isPresent()) {
+ throw new SvcLogicException("Could not find module node");
+ }
+ Module m = module.get();
+ return new Namespace(m.getName(), m.getQNameModule().getNamespace(),
+ getRevision(m.getRevision()));
+ }
+
+ static String getParsedValue(Namespace valNs, String value) {
+ if (valNs != null && value.contains(":")) {
+ String[] valArr = value.split(":");
+ return valArr[1];
+ }
+ return value;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java
new file mode 100644
index 000000000..c251cdaea
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java
@@ -0,0 +1,32 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Representation of multi instance node in properties data tree.
+ */
+public class MultiInstanceNode extends InnerNode<DataNodeChild> implements ListHolderChild {
+
+ public MultiInstanceNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appinfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appinfo, nodeType);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java
new file mode 100644
index 000000000..4f27ee1e7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java
@@ -0,0 +1,100 @@
+/*-
+ * ============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.pnserializer;
+
+import java.net.URI;
+
+/**
+ * Representation of YANG namespace.
+ */
+public class Namespace {
+ private String moduleName;
+ private URI moduleNs;
+ private String revision;
+
+ /**
+ * Creates an instance of namespace with specified module name,
+ * namespace and revision.
+ *
+ * @param modulename module name
+ * @param moduleNs module namespace
+ * @param revision revision
+ */
+ public Namespace(String modulename, URI moduleNs, String revision) {
+ this.moduleName = modulename;
+ this.moduleNs = moduleNs;
+ this.revision = revision;
+ }
+
+ /**
+ * Returns module name.
+ *
+ * @return module name
+ */
+ public String moduleName() {
+ return moduleName;
+ }
+
+ /**
+ * Sets module name.
+ *
+ * @param moduleName module name
+ */
+ public void moduleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ /**
+ * Sets module namespace.
+ *
+ * @return module namespace
+ */
+ public URI moduleNs() {
+ return moduleNs;
+ }
+
+ /**
+ * Sets module namespace.
+ *
+ * @param moduleNs module namespace
+ */
+ public void moduleNs(URI moduleNs) {
+ this.moduleNs = moduleNs;
+ }
+
+ /**
+ * Returns revision.
+ *
+ * @return revision
+ */
+ public String revision() {
+ return revision;
+ }
+
+ /**
+ * Sets revision.
+ *
+ * @param revision revision
+ */
+ public void revision(String revision) {
+ this.revision = revision;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java
new file mode 100644
index 000000000..d482c6763
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java
@@ -0,0 +1,28 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Abstraction of an entity that represents child's of a node.
+ */
+public interface NodeChild {
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java
new file mode 100644
index 000000000..0b6974e3e
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java
@@ -0,0 +1,34 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Representation of types of node in properties node tree.
+ */
+public enum NodeType {
+ SINGLE_INSTANCE_NODE,
+ MULTI_INSTANCE_NODE,
+ SINGLE_INSTANCE_LEAF_NODE,
+ MULTI_INSTANCE_LEAF_NODE,
+ MULTI_INSTANCE_HOLDER_NODE,
+ MULTI_INSTANCE_LEAF_HOLDER_NODE,
+ ANY_XML_NODE
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java
new file mode 100644
index 000000000..7e0ad631e
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java
@@ -0,0 +1,280 @@
+/*-
+ * ============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.pnserializer;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of properties node data tree. This intermediate representation
+ * will enable data format serializers to be agnostic of DG context memory
+ * nuances and thereby will enable faster development of new data format
+ * serializers.
+ */
+public abstract class PropertiesNode {
+
+ private String name;
+ private Namespace namespace;
+ private String uri;
+ private PropertiesNode parent;
+ private Object appInfo;
+ private NodeType nodeType;
+ private boolean nonAppend;
+ private Multimap<Object, PropertiesNode> augmentations = ArrayListMultimap.create();
+
+ /**
+ * Creates an instance of properties node.
+ *
+ * @param name name of node
+ * @param namespace namespace of node, null indicates parent namespace
+ * @param uri URI of this node, if null its calculated based on parent and
+ * current value of name and namespace
+ * @param parent parent's node
+ * @param appInfo application related information
+ * @param nodeType node type
+ */
+ protected PropertiesNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo, NodeType nodeType) {
+ this.name = name;
+ this.namespace = namespace;
+ this.uri = uri;
+ this.parent = parent;
+ this.appInfo = appInfo;
+ this.nodeType = nodeType;
+ }
+
+ /**
+ * Sets name.
+ *
+ * @param name name of the node
+ */
+ public void name(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets namespace.
+ *
+ * @param namespace namespace of the node
+ */
+ public void namespace(Namespace namespace) {
+ this.namespace = namespace;
+ }
+
+ /**
+ * Sets uri.
+ *
+ * @param uri uri of the node
+ */
+ public void uri(String uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Sets parent node.
+ *
+ * @param parent parent node
+ */
+ public void parent(PropertiesNode parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Sets application info.
+ *
+ * @param appInfo application info
+ */
+ public void appInfo(Object appInfo) {
+ this.appInfo = appInfo;
+ }
+
+ /**
+ * Sets to true if module name is required in forming a request; false
+ * otherwise.
+ *
+ * @param isNotReq true if required; false otherwise
+ */
+ public void nonAppend(boolean isNotReq) {
+ this.nonAppend = isNotReq;
+ }
+
+ /**
+ * Returns parent.
+ *
+ * @return parent node
+ */
+ public PropertiesNode parent() {
+ return parent;
+ }
+
+ /**
+ * Returns name.
+ *
+ * @return name of the node
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns namespace.
+ *
+ * @return namespace of the node
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ /**
+ * Returns uri.
+ *
+ * @return uri of the node
+ */
+ public String uri() {
+ return uri;
+ }
+
+ /**
+ * Returns application info.
+ *
+ * @return application info
+ */
+ public Object appInfo() {
+ return appInfo;
+ }
+
+ /**
+ * Returns node type.
+ *
+ * @return node type
+ */
+ public NodeType nodeType() {
+ return nodeType;
+ }
+
+ /**
+ * Returns if module name is required.
+ *
+ * @return status of module name if required
+ */
+ public boolean nonAppend() {
+ return nonAppend;
+ }
+
+ /**
+ * Returns augmentations.
+ *
+ * @return augmentations
+ */
+ public Multimap<Object, PropertiesNode> augmentations() {
+ return augmentations;
+ }
+
+ /**
+ * Sets augmentations.
+ *
+ * @param augmentations augmentations of the node
+ */
+ public void augmentations(Multimap<Object, PropertiesNode> augmentations) {
+ this.augmentations = augmentations;
+ }
+
+ /**
+ * Adds a child to a current node.
+ *
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param appInfo application info
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Adds a child with value to a current node.
+ *
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param value value of node
+ * @param valueNs value namespace
+ * @param appInfo application info
+ * @throws SvcLogicException if failed to add child
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Adds a child at a given index to a current node. To be used in case of
+ * leaf holder child's which is multi instance node.
+ *
+ * @param index index at which node is to be added
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param appInfo application info
+ * @throws SvcLogicException if failed to add child
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Adds a child at a given index to a current node. To be used in case of
+ * leaf holder child's which is multi instance node.
+ *
+ * @param index index at which node is to be added
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param value value of node
+ * @param valueNs value namespace
+ * @param appInfo application info
+ * @throws SvcLogicException if failed to add child
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Returns root node.
+ *
+ * @return root node
+ */
+ public PropertiesNode endNode() {
+ PropertiesNode node = this;
+ while (node.parent() != null){
+ node = node.parent();
+ }
+ return node;
+ }
+}
+
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java
new file mode 100644
index 000000000..7b97ffaf8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java
@@ -0,0 +1,61 @@
+/*-
+ * ============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.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of properties node listener.
+ */
+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) throws SvcLogicException;
+
+ /**
+ * Post-configurations required after starting the walking.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when the post-configuration fails
+ */
+ 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) throws SvcLogicException;
+
+ /**
+ * Enters the properties node.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when exiting the properties node fails
+ */
+ void exitPropertiesNode(PropertiesNode node) throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java
new file mode 100644
index 000000000..fe6fed484
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java
@@ -0,0 +1,112 @@
+/*-
+ * ============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.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.Map;
+
+/**
+ * Abstraction of an entity to enable encoding and decoding of properties
+ * to an abstract properties node tree using YANG based schema.
+ * This serializer will be used by other data format serializers and will keep
+ * them abstract from properties nuances thereby enabling quick addition of any
+ * new data format serializer.
+ *
+ * @param <T> type of schema node
+ * @param <P> schema context of the model
+ */
+public abstract class PropertiesNodeSerializer<T, P> {
+
+ /**
+ * Schema node from which the property is made.
+ */
+ private T schemaNode;
+
+ /**
+ * Schema context of the model.
+ */
+ private P schemaCtx;
+
+ /**
+ * URL pointing to the schema node.
+ */
+ private String uri;
+
+ /**
+ * Creates the properties node serializer.
+ *
+ * @param schemaNode schema node.
+ * @param schemaCtx schema context
+ * @param uri URL of the request
+ */
+ public PropertiesNodeSerializer(T schemaNode, P schemaCtx, String uri) {
+ this.schemaNode = schemaNode;
+ this.schemaCtx = schemaCtx;
+ this.uri = uri;
+ }
+
+ /**
+ * Encodes from properties to properties-node tree.
+ *
+ * @param paramMap parameter map
+ * @throws SvcLogicException fails to encode properties to properties node
+ * @return properties node
+ */
+ public abstract PropertiesNode encode(Map<String, String> paramMap) throws SvcLogicException;
+
+ /**
+ * Decodes from properties-node to properties map.
+ *
+ * @param propertiesNode properties-node
+ * @return parameter map
+ * @throws SvcLogicException fails to decode properties node to properties
+ */
+ public abstract Map<String, String> decode(PropertiesNode propertiesNode)
+ throws SvcLogicException;
+
+ /**
+ * Returns the schema node of the property
+ *
+ * @return schema node
+ */
+ public T schemaNode(){
+ return schemaNode;
+ }
+
+ /**
+ * Returns the schema context
+ *
+ * @return schema node
+ */
+ public P schemaCtx() {
+ return schemaCtx;
+ }
+
+ /**
+ * Returns the URI.
+ *
+ * @return uri
+ */
+ public String uri() {
+ return uri;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java
new file mode 100644
index 000000000..36ee4dd9d
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java
@@ -0,0 +1,38 @@
+/*-
+ * ============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.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)
+ throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java
new file mode 100644
index 000000000..c7f7340fd
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java
@@ -0,0 +1,212 @@
+/*-
+ * ============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.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.addToAugmentations;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.createNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getAugmentationNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getUri;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.isNamespaceAsParent;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+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.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findCorrespondingAugment;
+
+/**
+ * Abstraction of node representing properties data tree.
+ */
+public class RootNode<T extends NodeChild> extends PropertiesNode {
+
+ private Map<String, T> children = new HashMap<String, T>();
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Returns children.
+ *
+ * @return children
+ */
+ public Map<String, T> children() {
+ return children;
+ }
+
+ /**
+ * Sets children.
+ *
+ * @param children child nodes
+ */
+ public void children(Map<String, T> children) {
+ this.children = children;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ PropertiesNode node = ((PropertiesNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ // get augment schema, if it is augmented node
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, name);
+ }
+
+ // create node based on type, this api will be invoked only for these three types
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = createNode(name, namespace, uri, this, appInfo, type);
+ }
+
+ // If namespace is not same as parent then it is augmented node
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valuens,
+ Object appInfo) throws SvcLogicException {
+ LeafNode node = ((LeafNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ }
+
+ String uri = getUri(this, name, namespace);
+ node = new LeafNode(name, namespace, uri, this,
+ appInfo, type, value);
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ Object appInfo) throws SvcLogicException {
+ String localname = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localname));
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localname);
+ }
+
+ if (node == null) {
+ node = new ListHolderNode(localname, namespace, uri,
+ this, appInfo, MULTI_INSTANCE_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localname, ((T) node));
+ }
+ node = node.addChild(index, localname, namespace, type, appInfo);
+ } else if (node instanceof ListHolderNode) {
+ ListHolderChild child = ((ListHolderNode) node).child(index);
+ node = (child != null ? ((MultiInstanceNode) child) :
+ node.addChild(index, localname, namespace, type, appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ String localName = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localName));
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localName);
+ }
+
+ if (node == null) {
+ node = new LeafListHolderNode(localName, namespace, uri, this,
+ appInfo, MULTI_INSTANCE_LEAF_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localName, ((T) node));
+ }
+ node = node.addChild(index, localName, namespace, type, value, valueNs, appInfo);
+ } else if (node instanceof LeafListHolderNode) {
+ LeafNode child = ((LeafNode) ((HolderNode) node).child(index));
+ node = (child != null ? child : node.addChild(index, localName,
+ namespace, type,
+ value, valueNs,
+ appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java
new file mode 100644
index 000000000..4ef1bc664
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 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.pnserializer;
+
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+
+/**
+ * Representation of a holder for a proper path and its corresponding schema.
+ */
+public class SchemaPathHolder {
+
+ /**
+ * Schema context for the path.
+ */
+ private InstanceIdentifierContext insId;
+
+ /**
+ * Formatted path.
+ */
+ private String uri;
+
+ /**
+ * Constructs schema path holder with path and its schema.
+ *
+ * @param insId instance identifier context
+ * @param uri path
+ */
+ public SchemaPathHolder(InstanceIdentifierContext insId, String uri) {
+ this.insId = insId;
+ this.uri = uri;
+ }
+
+ /**
+ * Returns the instance identifier context of the path.
+ *
+ * @return schema of the path
+ */
+ public InstanceIdentifierContext getInsId() {
+ return insId;
+ }
+
+ /**
+ * Returns the formatted path.
+ *
+ * @return formatted path
+ */
+ public String getUri() {
+ return uri;
+ }
+
+ /**
+ * Sets the formatted path.
+ *
+ * @param uri formatted path
+ */
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java
new file mode 100644
index 000000000..6eb24c1a4
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java
@@ -0,0 +1,33 @@
+/*-
+ * ============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.pnserializer;
+
+/**
+ * Representation of single instance node in properties data tree.
+ */
+public class SingleInstanceNode extends InnerNode<DataNodeChild> implements DataNodeChild {
+
+ public SingleInstanceNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo,
+ NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml b/plugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml
new file mode 100755
index 000000000..45c335b13
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * ============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=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+ id="restapiCallNodeProvider"
+ interface="org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode"
+ ext:proxy-method="classes"/>
+
+ <bean id="restconfapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode" >
+ <argument ref="restapiCallNodeProvider"/>
+ </bean>
+
+ <bean id="restconfDiscoveryNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode" >
+ <argument ref="restconfapiCallNodeProvider"/>
+ </bean>
+
+ <service ref="restconfapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode</value>
+ </interfaces>
+ </service>
+
+ <service ref="restconfDiscoveryNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml b/plugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml
new file mode 100755
index 000000000..45c335b13
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * ============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=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+ id="restapiCallNodeProvider"
+ interface="org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode"
+ ext:proxy-method="classes"/>
+
+ <bean id="restconfapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode" >
+ <argument ref="restapiCallNodeProvider"/>
+ </bean>
+
+ <bean id="restconfDiscoveryNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode" >
+ <argument ref="restconfapiCallNodeProvider"/>
+ </bean>
+
+ <service ref="restconfapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode</value>
+ </interfaces>
+ </service>
+
+ <service ref="restconfDiscoveryNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java
new file mode 100644
index 000000000..35ac221fb
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java
@@ -0,0 +1,68 @@
+/*-
+ * ============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.restconfdiscovery;
+
+import org.glassfish.jersey.media.sse.EventOutput;
+import org.glassfish.jersey.media.sse.OutboundEvent;
+import org.glassfish.jersey.media.sse.SseFeature;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import java.io.IOException;
+
+@Path("events")
+public class SseServerMock {
+
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput getServerSentEvents() throws IOException {
+ String data = "{" +
+ "\"ietf-restconf:notification\" : {" +
+ " \"eventTime\" : \"2017-10-25T08:22:33.44Z\"," +
+ " \"ietf-yang-push:push-change-update\": {" +
+ "\"subscription-id\":\"89\"," +
+ "\"datastore-changes\": {" +
+ "\"ietf-yang-patch:yang-patch\":{" +
+ "\"patch-id\":\"1\"," +
+ "\"edit\":[{" +
+ "\"edit-id\":\"edit1\"," +
+ "\"operation\":\"merge\"," +
+ "\"target\":\"/ietf-interfaces:interfaces-state\"," +
+ "\"value\": {" +
+ "\"ietf-interfaces:interfaces-state\":{"+
+ "\"interface\": {" +
+ "\"name\":\"eth0\"," +
+ "\"oper-status\":\"down\"," +
+ "}" +
+ "}" +
+ "}" +
+ "}]"+
+ "}" +
+ "}" +
+ "}" +
+ "}" +
+ "}";
+ final EventOutput result = new EventOutput();
+ result.write(new OutboundEvent.Builder().data(String.class, data).build());
+ result.close();
+ return result;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java
new file mode 100644
index 000000000..aa89d67d7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java
@@ -0,0 +1,175 @@
+/*-
+ * ============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.restconfdiscovery;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class TestRestconfDiscoveryNode {
+
+ private static final URI CONTEXT = URI.create("http://localhost:8080/");
+
+ @Test
+ public void sendRequest() throws SvcLogicException, InterruptedException, IOException {
+ final ResourceConfig resourceConfig = new ResourceConfig(
+ SseServerMock.class, SseFeature.class);
+ HttpServer server = GrizzlyHttpServerFactory.createHttpServer(CONTEXT,
+ resourceConfig);
+ server.start();
+ RestconfApiCallNode restconf = mock(RestconfApiCallNode.class);
+ doNothing().when(restconf)
+ .sendRequest(any(Map.class), any(SvcLogicContext.class));
+ RestapiCallNode restApi = new RestapiCallNode();
+ doReturn(restApi).when(restconf).getRestapiCallNode();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.encoding-json", "encoding-json");
+ ctx.setAttribute("restapi-result.response-code", "200");
+ ctx.setAttribute("restapi-result.ietf-subscribed-notifications" +
+ ":establish-subscription.output.identifier",
+ "89");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("sseConnectURL", "http://localhost:8080/events");
+ p.put("subscriberId", "networkId");
+ p.put("responsePrefix", "restapi-result");
+ p.put("restapiUser", "access");
+ p.put("restapiPassword", "abc@123");
+ p.put("customHttpHeaders", "X-ACCESS-TOKEN=x-ik2ps4ikvzupbx0486ft" +
+ "1ebzs7rt85futh9ho6eofy3wjsap7wqktemlqm4bbsmnar3vrtbyrzuk" +
+ "bv5itd6m1cftldpjarnyle3sdcqq9hftc4lebz464b5ffxmlbvg9");
+ p.put("restapiUrl", "https://localhost:8080/restconf/operations/" +
+ "ietf-subscribed-notifications:establish-subscription");
+ p.put("module", "testmodule");
+ p.put("rpc", "testrpc");
+ p.put("version", "1.0");
+ p.put("mode", "sync");
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(restconf);
+ rdn.establishSubscription(p, ctx);
+ Thread.sleep(1000);
+ rdn.deleteSubscription(p, ctx);
+ server.shutdown();
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testSubGraphExecution() throws SvcLogicException{
+ SvcLogicGraphInfo subDg = new SvcLogicGraphInfo();
+ subDg.mode("sync");
+ subDg.module("l3VpnService");
+ subDg.rpc("createVpn");
+ subDg.version("1.0");
+ SvcLogicContext ctx = new SvcLogicContext();
+ subDg.executeGraph(ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testEstablishSubscriptionWithoutSubscriberId()
+ throws SvcLogicException{
+ SvcLogicContext ctx = new SvcLogicContext();
+ Map<String, String> p = new HashMap<>();
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+ rdn.establishSubscription(p, ctx);
+ }
+
+ @Test
+ public void testResponseCode() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("restapi-result.response-code", "200");
+ ctx.setAttribute("response-code", "404");
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+ assertThat(rdn.getResponseCode("restapi-result", ctx),
+ is("200"));
+ assertThat(rdn.getResponseCode(null, ctx),
+ is("404"));
+ }
+
+ @Test
+ public void testOutputIdentifier() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("restapi-result.ietf-subscribed-notifications:" +
+ "establish-subscription.output.identifier",
+ "89");
+ ctx.setAttribute("ietf-subscribed-notifications:establish-subscripti" +
+ "on.output.identifier", "89");
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+ assertThat(rdn.getOutputIdentifier("restapi-result", ctx),
+ is("89"));
+ }
+
+ @Test
+ public void testGetTokenId() {
+ String customHttpHeaders = "X-ACCESS-TOKEN=x-ik2ps4ikvzupbx0486ft1ebzs7rt85" +
+ "futh9ho6eofy3wjsap7wqktemlqm4bbsmnar3vrtbyrzukbv5itd6m1cftldpjarny" +
+ "le3sdcqq9hftc4lebz464b5ffxmlbvg9";
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+
+ assertThat(rdn.getTokenId(customHttpHeaders),
+ is("x-ik2ps4ikvzupbx0486ft1ebzs7rt85futh9ho6eofy3wjsap7wqkt" +
+ "emlqm4bbsmnar3vrtbyrzukbv5itd6m1cftldpjarnyle3sdcqq9h" +
+ "ftc4lebz464b5ffxmlbvg9"));
+ }
+
+ @Test
+ public void testSubscriptionInfo() throws SvcLogicException {
+ SubscriptionInfo info = new SubscriptionInfo();
+ info.subscriberId("network-id");
+ info.subscriptionId("8");
+ info.filterUrl("/ietf-interfaces:interfaces");
+ info.yangFilePath("/opt/yang");
+ SvcLogicGraphInfo svcLogicGraphInfo = new SvcLogicGraphInfo();
+ svcLogicGraphInfo.mode("sync");
+ svcLogicGraphInfo.module("testModule");
+ svcLogicGraphInfo.rpc("testRpc");
+ svcLogicGraphInfo.version("1.0");
+ info.callBackDG(svcLogicGraphInfo);
+ assertThat(info.subscriberId(), is("network-id"));
+ assertThat(info.subscriptionId(), is("8"));
+ assertThat(info.filterUrl(), is("/ietf-interfaces:interfaces"));
+ assertThat(info.yangFilePath(), is("/opt/yang"));
+ assertThat(info.callBackDG().module(), is("testModule"));
+ assertThat(info.callBackDG().mode(), is("sync"));
+ assertThat(info.callBackDG().rpc(), is("testRpc"));
+ assertThat(info.callBackDG().version(), is("1.0"));
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java
new file mode 100644
index 000000000..aa1e50d6a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java
@@ -0,0 +1,996 @@
+/*-
+ * ============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 java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.GET;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PATCH;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.POST;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PUT;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.parseUrl;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.DECODE_ANYXML_RESPONSE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.DECODE_FROM_JSON_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.DECODE_FROM_XML_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_ANYXML;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_ID_PUT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_YANG;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_YANG_AUG_POST;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_YANG_PUT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_ID_PUT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_YANG;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_YANG_AUG_POST;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_YANG_PUT;
+
+
+/**
+ * Unit test cases for data format serialization and restconf api call node.
+ */
+public class DataFormatSerializerTest {
+
+ private Map<String, String> p;
+
+ private RestconfApiCallNode restconf;
+
+ private RestapiCallNode restApi;
+
+ private DfCaptor dfCaptor;
+
+ /**
+ * Sets up the pre-requisite for each test case.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Before
+ public void setUp() throws SvcLogicException {
+ p = new HashMap<>();
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+ restApi = new RestapiCallNode();
+ restconf = mock(RestconfApiCallNode.class);
+ dfCaptor = new DfCaptor();
+ createMethodMocks();
+ }
+
+ /**
+ * Creates method mocks using mockito for RestconfApiCallNode class.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMethodMocks() throws SvcLogicException {
+ doReturn(restApi).when(restconf).getRestapiCallNode();
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class));
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class), any(Integer.class));
+ doAnswer(dfCaptor).when(restconf).serializeRequest(
+ any(Map.class), any(YangParameters.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ doAnswer(dfCaptor).when(restconf).updateReq(
+ any(String.class), any(YangParameters.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Creates mock using mockito with input data for decoding.
+ *
+ * @param decodeData input data
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMockForDecode(String decodeData)
+ throws SvcLogicException {
+ doReturn(decodeData).when(restconf).getResponse(
+ any(SvcLogicContext.class), any(YangParameters.class),
+ any(String.class), any(HttpResponse.class));
+ doCallRealMethod().when(restconf).serializeResponse(
+ any(YangParameters.class), any(String.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonId() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ ctx.setAttribute(pre + "l", "abc");
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format any xml in it.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeForAnyXml() throws SvcLogicException {
+ String pre = "execution-service_process.";
+ SvcLogicContext ctx = createAnyXmlAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/api/v1/execution-service/process");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_ANYXML));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with identity-ref
+ * and inter-file linking for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonIdWithPut() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ ctx.setAttribute(pre + "l", "abc");
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_ID_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with identity-ref
+ * and inter-file linking for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonIdWithPatch() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ ctx.setAttribute(pre + "l", "abc");
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_ID_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlId() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with identity-ref
+ * and inter-file linking for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlIdWithPut() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_ID_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with identity-ref
+ * and inter-file linking for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlIdWithPatch() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_ID_PUT));
+ }
+
+ /**
+ * Verifies decoding of parameters from JSON data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToJsonId() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_JSON_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "identity-test_test.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(ctx.getAttribute(pre + "l"), is("abc"));
+ verifyAttList(ctx, pre);
+ }
+
+ /**
+ * Verifies decoding of parameters from XML data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToXmlId() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_XML_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "identity-test_test.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ verifyAttList(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYang() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPut() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPatch() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_AUG_POST));
+ }
+
+ /**
+ * Verifies decoding of parameters from JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToJsonYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_JSON_YANG);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test-yang_cont1.cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYang() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for put operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPut() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for patch operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPatch() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_AUG_POST));
+ }
+
+ /**
+ * Verifies decoding of parameters from XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToXmlYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_XML_YANG);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test-yang_cont1.cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, JSON respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToJsonRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_JSON_RPC);
+ String inPre = "test-yang_create-sfc.input.";
+ String outPre = "test-yang_create-sfc.output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_RPC));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, JSON for ANYXML.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecForNormalAnyXml() throws SvcLogicException {
+ createMockForDecode(DECODE_ANYXML_RESPONSE);
+ String inPre = "execution-service_process.";
+ SvcLogicContext ctx = createAnyXmlAttList(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "pp");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/api/v1/execution-service/process");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_ANYXML));
+ verifyOutputOfAnyXml(ctx);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, XML respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToXmlRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_XML_RPC);
+ String inPre = "test-yang_create-sfc.input.";
+ String outPre = "test-yang_create-sfc.output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_RPC));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Verifies URL parser returning path with only schema information for all
+ * kind of URL.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void validateUrlParser() throws SvcLogicException {
+ String actVal = "identity-test:test";
+ String putId = "/for-put";
+ String url1 = "http://echo.getpostman.com/restconf/operations/" +
+ actVal;
+ String url2 = "http://echo.getpostman.com/restconf/data/" + actVal;
+ String url3 = "https://echo.getpostman.com/restconf/operations/" +
+ actVal;
+ String url4 = "https://echo.getpostman.com/restconf/data/" + actVal +
+ putId;
+ String url5 = "http://localhost:8282/restconf/operations/" + actVal;
+ String url6 = "https://localhost:8282/restconf/operations/" + actVal;
+ String url7 = "http://localhost:8282/restconf/data/" + actVal +
+ putId;
+ String url8 = "https://localhost:8282/restconf/data/" + actVal;
+ String url9 = "http://182.2.61.24:2250/restconf/data/" + actVal;
+ String url10 = "https://182.2.61.24:2250/restconf/operations/" + actVal;
+ String url11 = "https://182.2.61.24:2250/api/v1/execution-service" +
+ "/process";
+ String url12 = "https://182.2.61.24:2250/api/v1/execution-service" +
+ "/process/payload";
+ String url13 = "https://182.2.61.24:2250/api/v1/execution-service" +
+ "/process/payload/";
+ String val1 = parseUrl(url1, POST);
+ String val2 = parseUrl(url2, GET);
+ String val3 = parseUrl(url3, PATCH);
+ String val4 = parseUrl(url4, PUT);
+ String val5 = parseUrl(url5, GET);
+ String val6 = parseUrl(url6, POST);
+ String val7 = parseUrl(url7, PUT);
+ String val8 = parseUrl(url8, POST);
+ String val9 = parseUrl(url9, GET);
+ String val10 = parseUrl(url10, POST);
+ String val11 = parseUrl(url11, POST);
+ String val12 = parseUrl(url12, POST);
+ String val13 = parseUrl(url13, POST);
+ assertThat(val1, is(actVal));
+ assertThat(val2, is(actVal));
+ assertThat(val3, is(actVal));
+ assertThat(val4, is(actVal + putId));
+ assertThat(val5, is(actVal));
+ assertThat(val6, is(actVal));
+ assertThat(val7, is(actVal + putId));
+ assertThat(val8, is(actVal));
+ assertThat(val9, is(actVal));
+ assertThat(val10, is(actVal));
+ assertThat(val11, is("execution-service:process"));
+ assertThat(val12, is("execution-service:process/payload"));
+ assertThat(val13, is("execution-service:process/payload/"));
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with ANYXML YANG
+ * file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAnyXmlAttList(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre1 = pre + "commonHeader.";
+ String pre2 = pre + "actionIdentifiers.";
+ ctx.setAttribute(pre + "isNonAppend", "true");
+ ctx.setAttribute(pre1 + "originatorId", "SDNC_DG");
+ ctx.setAttribute(pre1 + "requestId", "123456-1000");
+ ctx.setAttribute(pre1 + "subRequestId", "sub-123456-1000");
+ ctx.setAttribute(pre2 + "blueprintName",
+ "baseconfiguration");
+ ctx.setAttribute(pre2 + "blueprintVersion", "1.0.0");
+ ctx.setAttribute(pre2 + "actionName", "assign-activate");
+ ctx.setAttribute(pre2 + "mode", "sync");
+ ctx.setAttribute(pre + "payload." +
+ "template-prefix", "vDNS-test");
+ ctx.setAttribute(pre + "payload.resource-assignment-request" +
+ ".resource-assignment-properties",
+ "{\n" +
+ " \"service-instance-id\": " +
+ "\"1234\",\n" +
+ " \"vnf-id\": \"3526\",\n" +
+ " \"customer-name\": \"htipl\",\n" +
+ " \"subscriber-name\": \"huawei\"\n" +
+ " }");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with identity-ref YANG
+ * file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttList(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre1 = pre + "con1.interfaces.";
+ ctx.setAttribute(pre + "con1.interface", "identity-types:physical");
+ ctx.setAttribute(pre1 + "int-list[0].iden", "optical");
+ ctx.setAttribute(pre1 + "int-list[0].available.ll[0]", "Giga");
+ ctx.setAttribute(pre1 + "int-list[0].available.ll[1]",
+ "identity-types:Loopback");
+ ctx.setAttribute(pre1 + "int-list[0].available.ll[2]",
+ "identity-types-second:Ethernet");
+ ctx.setAttribute(pre1 + "int-list[0].available.leaf1", "58");
+ ctx.setAttribute(pre1 + "int-list[0].available.leaf2",
+ "identity-types-second:iden2");
+
+ ctx.setAttribute(pre1 + "int-list[1].iden", "214748364");
+ ctx.setAttribute(pre1 + "int-list[1].available.ll[0]", "Giga");
+ ctx.setAttribute(pre1 + "int-list[1].available.ll[1]",
+ "identity-types:Loopback");
+ ctx.setAttribute(pre1 + "int-list[1].available.ll[2]",
+ "identity-types-second:Ethernet");
+ ctx.setAttribute(pre1 + "int-list[1].available.leaf1",
+ "8888");
+ ctx.setAttribute(pre1 + "int-list[1].available.leaf2",
+ "identity-types-second:iden2");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with container,
+ * grouping and augmented YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListYang(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "cont3.leaf10", "abc");
+ ctx.setAttribute(pre + "list1[0].leaf1", "true");
+ ctx.setAttribute(pre + "list1[0].leaf2", "abc");
+ ctx.setAttribute(pre + "list1[0].leaf3", "abc");
+ ctx.setAttribute(pre + "list1[0].ll1[0]", "abc");
+ ctx.setAttribute(pre + "list1[0].ll1[1]", "abc");
+ ctx.setAttribute(pre + "list1[0].ll2[0]", "abc");
+ ctx.setAttribute(pre + "list1[0].ll2[1]", "abc");
+ ctx.setAttribute(pre + "list1[0].cont4.leaf11", "abc");
+ ctx.setAttribute(pre + "list1[0].list4[0].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[0].list4[1].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[0].list5[0].leaf9", "abc");
+ ctx.setAttribute(pre + "list1[0].list5[1].leaf9", "abc");
+ ctx.setAttribute(pre + "list1[1].leaf1", "true");
+ ctx.setAttribute(pre + "list1[1].leaf2", "abc");
+ ctx.setAttribute(pre + "list1[1].leaf3", "abc");
+ ctx.setAttribute(pre + "list1[1].ll1[0]", "abc");
+ ctx.setAttribute(pre + "list1[1].ll1[1]", "abc");
+ ctx.setAttribute(pre + "list1[1].ll2[0]", "abc");
+ ctx.setAttribute(pre + "list1[1].ll2[1]", "abc");
+ ctx.setAttribute(pre + "list1[1].cont4.leaf11", "abc");
+ ctx.setAttribute(pre + "list1[1].list4[0].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[1].list4[1].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[1].list5[0].leaf9", "abc");
+ ctx.setAttribute(pre + "list1[1].list5[1].leaf9", "abc");
+ ctx.setAttribute(pre + "list2[0].leaf4", "abc");
+ ctx.setAttribute(pre + "list2[1].leaf4", "abc");
+ ctx.setAttribute(pre + "leaf5", "abc");
+ ctx.setAttribute(pre + "leaf6", "abc");
+ ctx.setAttribute(pre + "ll3[0]", "abc");
+ ctx.setAttribute(pre + "ll3[1]", "abc");
+ ctx.setAttribute(pre + "ll4[0]", "abc");
+ ctx.setAttribute(pre + "ll4[1]", "abc");
+ ctx.setAttribute(pre + "cont4.leaf10", "abc");
+ ctx.setAttribute(pre + "list6[0].leaf11", "abc");
+ ctx.setAttribute(pre + "list6[1].leaf11", "abc");
+ ctx.setAttribute(pre + "leaf12", "abc");
+ ctx.setAttribute(pre + "ll5[0]", "abc");
+ ctx.setAttribute(pre + "ll5[1]", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont5.leaf13", "true");
+ ctx.setAttribute(pre + "cont4.test-augment_list7[0].leaf14", "test");
+ ctx.setAttribute(pre + "cont4.test-augment_list7[1].leaf14", "create");
+ ctx.setAttribute(pre + "cont4.test-augment_leaf15", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_ll6[0]", "unbounded");
+ ctx.setAttribute(pre + "cont4.test-augment_ll6[1]", "8");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.cont12.leaf26",
+ "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.list9[0].leaf27",
+ "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.list9[1].leaf27",
+ "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.leaf28", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.ll9[0]", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.ll9[1]", "abc");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with RPC YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListRpc(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "cont14.leaf28", "abc");
+ ctx.setAttribute(pre + "list10[0].leaf29", "abc");
+ ctx.setAttribute(pre + "list10[1].leaf29", "abc");
+ ctx.setAttribute(pre + "leaf30", "abc");
+ ctx.setAttribute(pre + "ll10[0]", "abc");
+ ctx.setAttribute(pre + "ll10[1]", "abc");
+ ctx.setAttribute(pre + "cont15.leaf31", "abc");
+ ctx.setAttribute(pre + "cont13.list9[0].leaf27", "abc");
+ ctx.setAttribute(pre + "cont13.list9[1].leaf27", "abc");
+ ctx.setAttribute(pre + "cont13.leaf28", "abc");
+ ctx.setAttribute(pre + "cont13.ll9[0]", "abc");
+ ctx.setAttribute(pre + "cont13.ll9[1]", "abc");
+ return ctx;
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * identity-ref YANG file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttList(SvcLogicContext ctx, String pre) {
+ String pre1 = pre + "con1.interfaces.";
+ assertThat(ctx.getAttribute(pre + "con1.interface"), is(
+ "identity-types:physical"));
+ assertThat(ctx.getAttribute(pre + "con1.interface"), is(
+ "identity-types:physical"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].iden"), is("optical"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.ll[0]"), is(
+ "Giga"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.ll[1]"), is(
+ "identity-types:Loopback"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.ll[2]"), is(
+ "identity-types-second:Ethernet"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.leaf1"), is(
+ "58"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.leaf2"), is(
+ "identity-types-second:iden2"));
+
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].iden"), is(
+ "214748364"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.ll[0]"), is(
+ "Giga"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.ll[1]"), is(
+ "identity-types:Loopback"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.ll[2]"), is(
+ "identity-types-second:Ethernet"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.leaf1"), is(
+ "8888"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.leaf2"), is(
+ "identity-types-second:iden2"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * container, grouping and augmented file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListYang(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "cont3.leaf10"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "list1[0].leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].cont4.leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list4[0].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list4[1].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list5[0].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list5[1].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "list1[1].leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].cont4.leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list4[0].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list4[1].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list5[0].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list5[1].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list2[0].leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list2[1].leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf5"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf6"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll3[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll3[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll4[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll4[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.leaf10"), is( "abc"));
+ assertThat(ctx.getAttribute(pre + "list6[0].leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list6[1].leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf12"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll5[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll5[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont5.leaf13"),
+ is("true"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_list7[0].leaf14"),
+ is("test"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_list7[1].leaf14"),
+ is("create"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_leaf15"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_ll6[0]"),
+ is("unbounded"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_ll6[1]"),
+ is("8"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13" +
+ ".cont12.leaf26"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.list9[0]" +
+ ".leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.list9[1]" +
+ ".leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.leaf28"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.ll9[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.ll9[1]"),
+ is("abc"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * RPC YANG file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListRpc(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "cont16.leaf32"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list11[0].leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list11[1].leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf34"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll11[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll11[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont17.leaf35"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.cont12.leaf26"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.list9[0].leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.list9[1].leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.ll9[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.ll9[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.leaf28"), is("abc"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * ANYXML YANG file.
+ *
+ * @param ctx service logic context
+ */
+ private void verifyOutputOfAnyXml(SvcLogicContext ctx) {
+ System.out.println(ctx.getAttribute("pp.status.eventType"));
+ assertThat(ctx.getAttribute("pp.status.eventType"), is(
+ "EVENT_COMPONENT_EXECUTED"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.blueprintName"),
+ is("golden"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.mode"),
+ is("sync"));
+ assertThat(ctx.getAttribute("pp.stepData.name"),
+ is("resource-assignment"));
+ assertThat(ctx.getAttribute("pp.status.message"),
+ is("success"));
+ assertThat(ctx.getAttribute("pp.commonHeader.originatorId"),
+ is("System"));
+ assertThat(ctx.getAttribute("pp.status.code"),
+ is("200"));
+ assertThat(ctx.getAttribute("pp.commonHeader.requestId"),
+ is("1234"));
+ assertThat(ctx.getAttribute("pp.commonHeader.subRequestId"),
+ is("1234-12234"));
+ assertThat(ctx.getAttribute("pp.commonHeader.timestamp"),
+ is("2019-05-18T23:42:41.658Z"));
+ assertThat(ctx.getAttribute("pp.status.timestamp"),
+ is("2019-05-18T23:42:41.950Z"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.blueprintV" +
+ "ersion"), is("1.0.0"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.actionName"),
+ is("resource-assignment"));
+ assertThat(ctx.getAttribute("pp.payload.resource-assignment-resp" +
+ "onse.meshed-template.vf-module-1"),
+ is("<interface>\n <description>This i" +
+ "s the Virtual Firewall entity</description>\n" +
+ " <vfw>10.0.101.20/24</vfw>\n" +
+ "</interface>"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.actionName"),
+ is("resource-assignment"));
+ }
+
+
+ /**
+ * Captures the data format messages by mocking it, which can be used in
+ * testing the value.
+ *
+ * @param <String> capturing data format
+ */
+ public class DfCaptor<String> implements Answer {
+
+ private String result;
+
+ /**
+ * Returns the captured data format message.
+ *
+ * @return data format message.
+ */
+ public String getResult() {
+ return result;
+ }
+
+ @Override
+ public String answer(InvocationOnMock invocationOnMock)
+ throws Throwable {
+ result = (String) invocationOnMock.callRealMethod();
+ return result;
+ }
+ }
+
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java
new file mode 100644
index 000000000..c1bb71985
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java
@@ -0,0 +1,631 @@
+/*-
+ * ============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;
+
+/**
+ * Unit test case utilities for data format serializer and restconf api call
+ * node.
+ */
+public final class DataFormatUtilsTest {
+
+ static final String ENCODE_TO_JSON_ID_COMMON = "\n \"interfaces\"" +
+ ": " +
+ "{\n" +
+ " \"int-list\": [\n" +
+ " {\n" +
+ " \"iden\": \"optical\",\n" +
+ " \"available\": {\n" +
+ " \"ll\": [\n" +
+ " \"Giga\",\n" +
+ " \"identity-types:Loopback\",\n" +
+ " \"identity-types-second:Ethernet" +
+ "\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"58\",\n" +
+ " \"leaf2\": \"identity-types-second:iden" +
+ "2\"\n" +
+ " }\n" +
+ " },\n" +
+ " {\n" +
+ " \"iden\": \"214748364\",\n" +
+ " \"available\": {\n" +
+ " \"ll\": [\n" +
+ " \"Giga\",\n" +
+ " \"identity-types:Loopback\",\n" +
+ " \"identity-types-second:Ethernet" +
+ "\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"8888\",\n" +
+ " \"leaf2\": \"identity-types-second:ide" +
+ "n2\"\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"interface\": \"identity-types:physical\"\n" +
+ " }";
+
+ static final String ENCODE_TO_JSON_ID = "{\n" +
+ " \"identity-test:con1\": {" + ENCODE_TO_JSON_ID_COMMON +
+ ",\n" +
+ " \"identity-test:l\": \"abc\"\n" +
+ "}";
+
+ static final String ENCODE_TO_ANYXML = "{\n" +
+ " \"actionIdentifiers\": {\n" +
+ " \"mode\": \"sync\",\n" +
+ " \"blueprintName\": \"baseconfiguration\",\n" +
+ " \"blueprintVersion\": \"1.0.0\",\n" +
+ " \"actionName\": \"assign-activate\"\n" +
+ " },\n" +
+ " \"payload\": {\n" +
+ " \"template-prefix\": \"vDNS-test\",\n" +
+ " \"resource-assignment-request\": {\n" +
+ " \"resource-assignment-properties\": {\n" +
+ " \"service-instance-id\": \"1234\",\n" +
+ " \"vnf-id\": \"3526\",\n" +
+ " \"customer-name\": \"htipl\",\n" +
+ " \"subscriber-name\": \"huawei\"\n" +
+ " }\n" +
+ " }\n" +
+ " },\n" +
+ " \"commonHeader\": {\n" +
+ " \"subRequestId\": \"sub-123456-1000\",\n" +
+ " \"requestId\": \"123456-1000\",\n" +
+ " \"originatorId\": \"SDNC_DG\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_ID_PUT = "{\n" +
+ " \"identity-test:test\": {\n" +
+ " \"con1\": {" + addSpace(ENCODE_TO_JSON_ID_COMMON, 4) +
+ ",\n" +
+ " \"l\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_ID_COMMON = "\n <interfaces>\n" +
+ " <int-list>\n" +
+ " <iden>optical</iden>\n" +
+ " <available>\n" +
+ " <ll>Giga</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:ns:test:json:se" +
+ "r\">yangid:Loopback</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:second:ns:test" +
+ ":json:ser\">yangid:Ethernet</ll>\n" +
+ " <leaf1>58</leaf1>\n" +
+ " <leaf2 xmlns:yangid=\"identity:list:second:ns:t" +
+ "est:json:ser\">yangid:iden2</leaf2>\n" +
+ " </available>\n" +
+ " </int-list>\n" +
+ " <int-list>\n" +
+ " <iden>214748364</iden>\n" +
+ " <available>\n" +
+ " <ll>Giga</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:ns:test:json:s" +
+ "er\">yangid:Loopback</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:second:ns:test" +
+ ":json:ser\">yangid:Ethernet</ll>\n" +
+ " <leaf1>8888</leaf1>\n" +
+ " <leaf2 xmlns:yangid=\"identity:list:second:ns:t" +
+ "est:json:ser\">yangid:iden2</leaf2>\n" +
+ " </available>\n" +
+ " </int-list>\n" +
+ " </interfaces>\n" +
+ " <interface xmlns:yangid=\"identity:list:ns:test:json:ser\">" +
+ "yangid:physical</interface>";
+
+ static final String ENCODE_TO_XML_ID = "<?xml version=\"1.0\" encoding=" +
+ "\"UTF-8\" standalone=\"no\"?>\n" +
+ "<con1 xmlns=\"identity:ns:test:json:ser\">" +
+ ENCODE_TO_XML_ID_COMMON + "\n</con1>\n";
+
+ static final String ENCODE_TO_XML_ID_PUT = "<?xml version=\"1.0\" enco" +
+ "ding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<test xmlns=\"identity:ns:test:json:ser\">\n" +
+ " <con1>" + addSpace(ENCODE_TO_XML_ID_COMMON, 4)
+ + "\n </con1>\n" +
+ "</test>\n";
+
+ static final String ENCODE_TO_JSON_YANG_COMMON = "\n " +
+ "\"test-augment:ll6\": [\n" +
+ " \"unbounded\",\n" +
+ " \"8\"\n" +
+ " ],\n" +
+ " \"test-augment:cont13\": {\n" +
+ " \"ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"list9\": [\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf28\": \"abc\",\n" +
+ " \"cont12\": {\n" +
+ " \"leaf26\": \"abc\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"test-augment:list7\": [\n" +
+ " {\n" +
+ " \"leaf14\": \"test\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf14\": \"create\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"test-augment:leaf15\": \"abc\",\n" +
+ " \"test-augment:cont5\": {\n" +
+ " \"leaf13\": \"true\"\n" +
+ " }";
+
+ static final String ENCODE_TO_JSON_YANG_AUG_POST = "{\n" +
+ " \"test-yang:leaf10\": \"abc\"," +
+ ENCODE_TO_JSON_YANG_COMMON + "\n}";
+
+ static final String ENCODE_TO_JSON_YANG = "{\n" +
+ " \"test-yang:cont2\": {\n" +
+ " \"list1\": [\n" +
+ " {\n" +
+ " \"ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"true\",\n" +
+ " \"ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"list5\": [\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf3\": \"abc\",\n" +
+ " \"leaf2\": \"abc\",\n" +
+ " \"list4\": [\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"cont4\": {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " }\n" +
+ " },\n" +
+ " {\n" +
+ " \"ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"true\",\n" +
+ " \"ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf3\": \"abc\",\n" +
+ " \"list5\": [\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"list4\": [\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf2\": \"abc\",\n" +
+ " \"cont4\": {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ " ],\n" +
+ " \"ll3\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"ll5\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"cont4\": {\n" +
+ " \"leaf10\": \"abc\"," +
+ addSpace(ENCODE_TO_JSON_YANG_COMMON, 8) + "\n" +
+ " },\n" +
+ " \"ll4\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"cont3\": {\n" +
+ " \"leaf10\": \"abc\"\n" +
+ " },\n" +
+ " \"leaf5\": \"abc\",\n" +
+ " \"list2\": [\n" +
+ " {\n" +
+ " \"leaf4\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf4\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf12\": \"abc\",\n" +
+ " \"leaf6\": \"abc\",\n" +
+ " \"list6\": [\n" +
+ " {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_YANG_PUT = "{\n" +
+ " \"test-yang:cont4\": {" + addSpace(
+ ENCODE_TO_JSON_YANG_COMMON, 4) + ",\n" +
+ " \"leaf10\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_YANG_COMMON = "\n" +
+ "<ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:aug" +
+ "ment\">unbounded</ll6>\n" +
+ "<ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:aug" +
+ "ment\">8</ll6>\n" +
+ "<cont13 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "augment\">\n" +
+ " <ll9>abc</ll9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " <cont12>\n" +
+ " <leaf26>abc</leaf26>\n" +
+ " </cont12>\n" +
+ "</cont13>\n" +
+ "<list7 xmlns=\"urn:opendaylight:params:xml:ns:yang:a" +
+ "ugment\">\n" +
+ " <leaf14>test</leaf14>\n" +
+ "</list7>\n" +
+ "<list7 xmlns=\"urn:opendaylight:params:xml:ns:yang:a" +
+ "ugment\">\n" +
+ " <leaf14>create</leaf14>\n" +
+ "</list7>\n" +
+ "<leaf15 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "augment\">abc</leaf15>\n" +
+ "<cont5 xmlns=\"urn:opendaylight:params:xml:ns:yang:a" +
+ "ugment\">\n" +
+ " <leaf13>true</leaf13>\n" +
+ "</cont5>";
+
+ static final String ENCODE_TO_XML_YANG_AUG_POST = "<?xml version=\"1.0\"" +
+ " encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<leaf10 xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">abc" +
+ "</leaf10>" +
+ ENCODE_TO_XML_YANG_COMMON + "\n";
+
+ static final String ENCODE_TO_XML_YANG_PUT = "<?xml version=\"1.0\" enc" +
+ "oding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<cont4 xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <leaf10>abc</leaf10>" +
+ addSpace(ENCODE_TO_XML_YANG_COMMON, 4) + "\n</cont4>\n";
+
+ static final String ENCODE_TO_XML_YANG = "<?xml version=\"1.0\" encoding" +
+ "=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<cont2 xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <list1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <leaf1>true</leaf1>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <leaf3>abc</leaf3>\n" +
+ " <leaf2>abc</leaf2>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <cont4>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </cont4>\n" +
+ " </list1>\n" +
+ " <list1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <leaf1>true</leaf1>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <leaf3>abc</leaf3>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <leaf2>abc</leaf2>\n" +
+ " <cont4>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </cont4>\n" +
+ " </list1>\n" +
+ " <ll3>abc</ll3>\n" +
+ " <ll3>abc</ll3>\n" +
+ " <ll5>abc</ll5>\n" +
+ " <ll5>abc</ll5>\n" +
+ " <cont4>\n" +
+ " <leaf10>abc</leaf10>"+
+ addSpace(ENCODE_TO_XML_YANG_COMMON, 8) + "\n" +
+ " </cont4>\n" +
+ " <ll4>abc</ll4>\n" +
+ " <ll4>abc</ll4>\n" +
+ " <cont3>\n" +
+ " <leaf10>abc</leaf10>\n" +
+ " </cont3>\n" +
+ " <leaf5>abc</leaf5>\n" +
+ " <list2>\n" +
+ " <leaf4>abc</leaf4>\n" +
+ " </list2>\n" +
+ " <list2>\n" +
+ " <leaf4>abc</leaf4>\n" +
+ " </list2>\n" +
+ " <leaf12>abc</leaf12>\n" +
+ " <leaf6>abc</leaf6>\n" +
+ " <list6>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </list6>\n" +
+ " <list6>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </list6>\n" +
+ "</cont2>\n";
+
+ static final String ENCODE_TO_JSON_RPC = "{\n" +
+ " \"test-yang:input\": {\n" +
+ " \"leaf30\": \"abc\",\n" +
+ " \"list10\": [\n" +
+ " {\n" +
+ " \"leaf29\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf29\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"cont15\": {\n" +
+ " \"leaf31\": \"abc\"\n" +
+ " },\n" +
+ " \"cont14\": {\n" +
+ " \"leaf28\": \"abc\"\n" +
+ " },\n" +
+ " \"cont13\": {\n" +
+ " \"list9\": [\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf28\": \"abc\"\n" +
+ " },\n" +
+ " \"ll10\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ]\n" +
+ " }\n" +
+ "}";
+
+ static final String DECODE_FROM_JSON_RPC = "{\n" +
+ " \"test-yang:output\": {\n" +
+ " \"cont16\": {\n" +
+ " \"leaf32\": \"abc\"\n" +
+ " },\n" +
+ " \"list11\": [\n" +
+ " {\n" +
+ " \"leaf33\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf33\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf34\": \"abc\",\n" +
+ " \"ll11\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"cont17\": {\n" +
+ " \"leaf35\": \"abc\"\n" +
+ " },\n" +
+ " \"cont13\": {\n" +
+ " \"cont12\": {\n" +
+ " \"leaf26\": \"abc\"\n" +
+ " },\n" +
+ " \"list9\": [\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf28\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String DECODE_ANYXML_RESPONSE = "{\n" +
+ " \"commonHeader\": {\n" +
+ " \"timestamp\": \"2019-05-18T23:42:41.658Z\",\n" +
+ " \"originatorId\": \"System\",\n" +
+ " \"requestId\": \"1234\",\n" +
+ " \"subRequestId\": \"1234-12234\",\n" +
+ " \"flags\": null\n" +
+ " },\n" +
+ " \"actionIdentifiers\": {\n" +
+ " \"blueprintName\": \"golden\",\n" +
+ " \"blueprintVersion\": \"1.0.0\",\n" +
+ " \"actionName\": \"resource-assignment\",\n" +
+ " \"mode\": \"sync\"\n" +
+ " },\n" +
+ " \"status\": {\n" +
+ " \"code\": 200,\n" +
+ " \"eventType\": \"EVENT_COMPONENT_EXECUTED\",\n" +
+ " \"timestamp\": \"2019-05-18T23:42:41.950Z\",\n" +
+ " \"errorMessage\": null,\n" +
+ " \"message\": \"success\"\n" +
+ " },\n" +
+ " \"payload\": {\n" +
+ " \"resource-assignment-response\": {\n" +
+ " \"meshed-template\": {\n" +
+ " \"vf-module-1\": \"<interface>\\n " +
+ " <description>This is the Virtual Firewall entity</" +
+ "description>\\n <vfw>10.0.101.20/24</vfw>\\n</interface>\"\n" +
+ " }\n" +
+ " }\n" +
+ " },\n" +
+ " \"stepData\": {\n" +
+ " \"name\": \"resource-assignment\",\n" +
+ " \"properties\": {\n" +
+ " \"resource-assignment-params\": null,\n" +
+ " \"status\": null\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_RPC = "<?xml version=\"1.0\" encoding" +
+ "=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<input xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <leaf30>abc</leaf30>\n" +
+ " <list10>\n" +
+ " <leaf29>abc</leaf29>\n" +
+ " </list10>\n" +
+ " <list10>\n" +
+ " <leaf29>abc</leaf29>\n" +
+ " </list10>\n" +
+ " <cont15>\n" +
+ " <leaf31>abc</leaf31>\n" +
+ " </cont15>\n" +
+ " <cont14>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " </cont14>\n" +
+ " <cont13>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " </cont13>\n" +
+ " <ll10>abc</ll10>\n" +
+ " <ll10>abc</ll10>\n" +
+ "</input>\n";
+
+ static final String DECODE_FROM_XML_RPC = "<?xml version=\"1.0\" encodi" +
+ "ng=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<output xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <cont16>\n" +
+ " <leaf32>abc</leaf32>\n" +
+ " </cont16>\n" +
+ " <list11>\n" +
+ " <leaf33>abc</leaf33>\n" +
+ " </list11>\n" +
+ " <list11>\n" +
+ " <leaf33>abc</leaf33>\n" +
+ " </list11>\n" +
+ " <leaf34>abc</leaf34>\n" +
+ " <ll11>abc</ll11>\n" +
+ " <ll11>abc</ll11>\n" +
+ " <cont17>\n" +
+ " <leaf35>abc</leaf35>\n" +
+ " </cont17>\n" +
+ " <cont13>\n" +
+ " <cont12>\n" +
+ " <leaf26>abc</leaf26>\n" +
+ " </cont12>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " </cont13>\n" +
+ "</output>";
+
+ /**
+ * Adds the specified number of space required for a req in each line.
+ *
+ * @param req request message
+ * @param i number of space
+ * @return space appended string
+ */
+ public static String addSpace(String req, int i) {
+ StringBuilder space = new StringBuilder();
+ for (int sp = 0; sp < i; sp++) {
+ space = space.append(" ");
+ }
+ return req.replaceAll("\n", "\n" + space.toString());
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java
new file mode 100644
index 000000000..1109d426c
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java
@@ -0,0 +1,762 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 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 java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.DECODE_FROM_JSON_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.DECODE_FROM_XML_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_WITH_AUG_PATH;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_YANG_AUG_POST_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_YANG_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_YANG_PUT_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_YANG_AUG_POST_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_YANG_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_YANG_PUT_ID;
+
+/**
+ * Unit test cases for identifier validation test.
+ */
+public class IdentifierValidationTest {
+
+ private Map<String, String> p;
+
+ private RestconfApiCallNode restconf;
+
+ private RestapiCallNode restApi;
+
+ private DfCaptor dfCaptor;
+
+ /**
+ * Sets up the pre-requisite for each test case.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Before
+ public void setUp() throws SvcLogicException {
+ p = new HashMap<>();
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+ restApi = new RestapiCallNode();
+ restconf = mock(RestconfApiCallNode.class);
+ dfCaptor = new DfCaptor();
+ createMethodMocks();
+ }
+
+ /**
+ * Creates method mocks using mockito for RestconfApiCallNode class.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMethodMocks() throws SvcLogicException {
+ doReturn(restApi).when(restconf).getRestapiCallNode();
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class));
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class), any(Integer.class));
+ doAnswer(dfCaptor).when(restconf).serializeRequest(
+ any(Map.class), any(YangParameters.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ doAnswer(dfCaptor).when(restconf).updateReq(
+ any(String.class), any(YangParameters.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Creates mock using mockito with input data for decoding.
+ *
+ * @param decodeData input data
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMockForDecode(String decodeData)
+ throws SvcLogicException {
+ doReturn(decodeData).when(restconf).getResponse(
+ any(SvcLogicContext.class), any(YangParameters.class),
+ any(String.class), any(HttpResponse.class));
+ doCallRealMethod().when(restconf).serializeResponse(
+ any(YangParameters.class), any(String.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYang() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operati" +
+ "ons/test_name_of_the_module:name_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters with augment in the URL.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithAugUrl() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operati" +
+ "ons/test_name_of_the_module:name_of_the_cont1/name_of_t" +
+ "he_cont2/name_of_the_cont4/test_augment_1_for_module:na" +
+ "me_of_the_cont5");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_WITH_AUG_PATH));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPut() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name_of" +
+ "_the_cont1/name_of_the_cont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPatch() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_o" +
+ "f_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name_of_" +
+ "the_cont1/name_of_the_cont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_" +
+ "the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name_of_" +
+ "the_cont1/name_of_the_cont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_AUG_POST_ID));
+ }
+
+ /**
+ * Verifies decoding of parameters from JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToJsonYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_JSON_YANG_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name" +
+ "_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYang() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of" +
+ "_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations/" +
+ "test_name_of_the_module:name_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for put operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPut() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations/" +
+ "test_name_of_the_module:name_of_the_cont1/name_of_the_cont2" +
+ "/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for patch operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPatch() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of" +
+ "_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operation" +
+ "s/test_name_of_the_module:name_of_the_cont1/name_of_the_c" +
+ "ont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_the" +
+ "_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations/" +
+ "test_name_of_the_module:name_of_the_cont1/name_of_the_cont2" +
+ "/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_AUG_POST_ID));
+ }
+
+ /**
+ * Verifies decoding of parameters from XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToXmlYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_XML_YANG_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_" +
+ "the_cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operation" +
+ "s/test_name_of_the_module:name_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, JSON respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToJsonRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_JSON_RPC_ID);
+ String inPre = "test_name_of_the_module_name_of_the_create-sfc.input.";
+ String outPre = "test_name_of_the_module_name_of_the_create-sfc" +
+ ".output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations" +
+ "/test_name_of_the_module:name_of_the_create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_RPC_ID));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, XML respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToXmlRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_XML_RPC_ID);
+ String inPre = "test_name_of_the_module_name_of_the_create-sfc.input.";
+ String outPre = "test_name_of_the_module_name_of_the_create-sfc.output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module" +
+ ":name_of_the_create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_RPC_ID));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with container,
+ * grouping and augmented YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListYang(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "name_of_the_cont3.name_of_the_leaf" +
+ "10", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_leaf1" +
+ "", "true");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_leaf2" +
+ "", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_leaf3" +
+ "", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll1[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll1[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll2[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll2[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "cont4.name_of_the_leaf11", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list4[0].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list4[1].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list5[0].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list5[1].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "leaf1", "true");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "leaf2", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "leaf3", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll1[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll1[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll2[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll2[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "cont4.name_of_the_leaf11", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list4[0].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list4[1].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list5[0].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list5[1].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list2[0].name_of_the_" +
+ "leaf4", "abc");
+ ctx.setAttribute(pre + "name_of_the_list2[1].name_of_the_" +
+ "leaf4", "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf5", "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf6", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll3[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll3[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll4[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll4[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.name_of_the_leaf10",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list6[0].name_of_the_leaf11",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list6[1].name_of_the_leaf11",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf12", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll5[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll5[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_cont5.name_of_the_leaf13",
+ "true");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_list7[0].name_of_the" +
+ "_leaf14", "test");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_list7[1].name_of_the" +
+ "_leaf14", "create");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_leaf15", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_ll6[0]",
+ "unbounded");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_ll6[1]", "8");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "cont12.name_of_the_leaf26",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_cont13.name_of_the_" +
+ "list9[0].name_of_the_leaf27",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "list9[1].name_of_the_leaf27",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "leaf28", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "ll9[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "ll9[1]", "abc");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with RPC YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListRpc(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "name_of_the_cont14.name_of_the_leaf28",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list10[0].name_of_the_leaf29",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list10[1].name_of_the_leaf29",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf30", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll10[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll10[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont15.name_of_the_leaf31",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_list9[0]" +
+ ".name_of_the_leaf27", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_list9[1]" +
+ ".name_of_the_leaf27", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_leaf28",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_ll9[0]",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_ll9[1]",
+ "abc");
+ return ctx;
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * container, grouping and augmented file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListYang(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont3.name_of" +
+ "_the_leaf10"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_cont4.name_of_the_leaf11"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list4[0].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list4[1].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list5[0].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list5[1].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_cont4.name_of_the_leaf11"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list4[0].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list4[1].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list5[0].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list5[1].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list2[0].name_of" +
+ "_the_leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list2[1].name_of" +
+ "_the_leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf5"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf6"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll3[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll3[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll4[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll4[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.name_of" +
+ "_the_leaf10"), is( "abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list6[0].name_of" +
+ "_the_leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list6[1].name_of" +
+ "_the_leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf12"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll5[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll5[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont5.name_of_the_leaf13"),
+ is("true"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_list7[0].name_of_the_leaf14"),
+ is("test"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_list7[1].name_of_the_leaf14"),
+ is("create"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_leaf15"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_ll6[0]"),
+ is("unbounded"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_ll6[1]"),
+ is("8"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13" +
+ ".name_of_the_cont12.name_of_" +
+ "the_leaf26"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_list9[0]" +
+ ".name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_list9[1]" +
+ ".name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_leaf28"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_ll9[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_ll9[1]"),
+ is("abc"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * RPC YANG file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListRpc(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont16.name_of_" +
+ "the_leaf32"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list11[0].name" +
+ "_of_the_leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list11[1].name" +
+ "_of_the_leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf34"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll11[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll11[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont17.name_of_" +
+ "the_leaf35"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_cont12.name_of_the_leaf26"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_list9[0].name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_list9[1].name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_ll9[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_ll9[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_leaf28"), is("abc"));
+ }
+
+ /**
+ * Captures the data format messages by mocking it, which can be used in
+ * testing the value.
+ *
+ * @param <String> capturing data format
+ */
+ public class DfCaptor<String> implements Answer {
+
+ private String result;
+
+ /**
+ * Returns the captured data format message.
+ *
+ * @return data format message.
+ */
+ public String getResult() {
+ return result;
+ }
+
+ @Override
+ public String answer(InvocationOnMock invocationOnMock)
+ throws Throwable {
+ result = (String) invocationOnMock.callRealMethod();
+ return result;
+ }
+ }
+
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java
new file mode 100644
index 000000000..a866f1c4a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java
@@ -0,0 +1,469 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 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 static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.addSpace;
+
+/**
+ * Unit test case utilities for identifier validation and restconf api
+ * call node.
+ */
+public final class IdentifierValidationUtilsTest {
+
+ static final String ENCODE_TO_JSON_YANG_COMMON_ID = "\n " +
+ "\"test_augment_1_for_module:name_of_the_ll6\": [\n" +
+ " \"unbounded\",\n" +
+ " \"8\"\n" +
+ " ],\n" +
+ " \"test_augment_1_for_module:name_of_the_cont13\": {\n" +
+ " \"name_of_the_cont12\": {\n" +
+ " \"name_of_the_leaf26\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf28\": \"abc\",\n" +
+ " \"name_of_the_list9\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"test_augment_1_for_module:name_of_the_list7\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf14\": \"test\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf14\": \"create\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"test_augment_1_for_module:name_of_the_leaf15\": \"abc\",\n" +
+ " \"test_augment_1_for_module:name_of_the_cont5\": {\n" +
+ " \"name_of_the_leaf13\": \"true\"\n" +
+ " }";
+
+ static final String ENCODE_TO_JSON_YANG_AUG_POST_ID = "{\n" +
+ " \"test_name_of_the_module:name_of_the_leaf10\": \"abc\"," +
+ ENCODE_TO_JSON_YANG_COMMON_ID + "\n}";
+
+ static final String ENCODE_TO_JSON_YANG_ID = "{\n" +
+ " \"test_name_of_the_module:name_of_the_cont2\": {\n" +
+ " \"name_of_the_ll4\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf5\": \"abc\",\n" +
+ " \"name_of_the_list6\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_ll5\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_ll3\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf6\": \"abc\",\n" +
+ " \"name_of_the_cont3\": {\n" +
+ " \"name_of_the_leaf10\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_list2\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf4\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf4\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_list1\": [\n" +
+ " {\n" +
+ " \"name_of_the_ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_list5\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_list4\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_leaf1\": \"true\",\n" +
+ " \"name_of_the_leaf3\": \"abc\",\n" +
+ " \"name_of_the_leaf2\": \"abc\",\n" +
+ " \"name_of_the_cont4\": {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_list5\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_list4\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_leaf1\": \"true\",\n" +
+ " \"name_of_the_leaf3\": \"abc\",\n" +
+ " \"name_of_the_leaf2\": \"abc\",\n" +
+ " \"name_of_the_cont4\": {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ]\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_cont4\": {\n" +
+ " \"name_of_the_leaf10\": \"abc\"," +
+ addSpace(ENCODE_TO_JSON_YANG_COMMON_ID,8) + "\n" +
+ " },\n" +
+ " \"name_of_the_leaf12\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_WITH_AUG_PATH = "{\n" +
+ " \"test_augment_1_for_module:name_of_the_leaf13\": \"true\"\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_YANG_PUT_ID = "{\n" +
+ " \"test_name_of_the_module:name_of_the_cont4\": {" + addSpace(
+ ENCODE_TO_JSON_YANG_COMMON_ID, 4) + ",\n" +
+ " \"name_of_the_leaf10\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_YANG_COMMON_ID = "\n" +
+ "<name_of_the_ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "test:augment:name\">unbounded</name_of_the_ll6>\n" +
+ "<name_of_the_ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "test:augment:name\">8</name_of_the_ll6>\n" +
+ "<name_of_the_cont13 xmlns=\"urn:opendaylight:params:xml:ns:ya" +
+ "ng:test:augment:name\">\n" +
+ " <name_of_the_cont12>\n" +
+ " <name_of_the_leaf26>abc</name_of_the_leaf26>\n" +
+ " </name_of_the_cont12>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ "</name_of_the_cont13>\n" +
+ "<name_of_the_list7 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:augment:name\">\n" +
+ " <name_of_the_leaf14>test</name_of_the_leaf14>\n" +
+ "</name_of_the_list7>\n" +
+ "<name_of_the_list7 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:augment:name\">\n" +
+ " <name_of_the_leaf14>create</name_of_the_leaf14>\n" +
+ "</name_of_the_list7>\n" +
+ "<name_of_the_leaf15 xmlns=\"urn:opendaylight:params:xml:ns:ya" +
+ "ng:test:augment:name\">abc</name_of_the_leaf15>\n" +
+ "<name_of_the_cont5 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:augment:name\">\n" +
+ " <name_of_the_leaf13>true</name_of_the_leaf13>\n" +
+ "</name_of_the_cont5>";
+
+ static final String ENCODE_TO_XML_YANG_AUG_POST_ID = "<?xml version=\"1" +
+ ".0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<name_of_the_leaf10 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:name\">abc</name_of_the_leaf10>" +
+ ENCODE_TO_XML_YANG_COMMON_ID + "\n";
+
+ static final String ENCODE_TO_XML_YANG_PUT_ID = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<name_of_the_cont4 xmlns=\"urn:opendaylight:params:xml:ns:yang" +
+ ":test:name\">\n" +
+ " <name_of_the_leaf10>abc</name_of_the_leaf10>" +
+ addSpace(ENCODE_TO_XML_YANG_COMMON_ID, 4) + "\n</name_of_the_co" +
+ "nt4>\n";
+
+ static final String ENCODE_TO_XML_YANG_ID= "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<name_of_the_cont2 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:name\">\n" +
+ " <name_of_the_ll4>abc</name_of_the_ll4>\n" +
+ " <name_of_the_ll4>abc</name_of_the_ll4>\n" +
+ " <name_of_the_leaf5>abc</name_of_the_leaf5>\n" +
+ " <name_of_the_list6>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_list6>\n" +
+ " <name_of_the_list6>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_list6>\n" +
+ " <name_of_the_ll5>abc</name_of_the_ll5>\n" +
+ " <name_of_the_ll5>abc</name_of_the_ll5>\n" +
+ " <name_of_the_ll3>abc</name_of_the_ll3>\n" +
+ " <name_of_the_ll3>abc</name_of_the_ll3>\n" +
+ " <name_of_the_leaf6>abc</name_of_the_leaf6>\n" +
+ " <name_of_the_cont3>\n" +
+ " <name_of_the_leaf10>abc</name_of_the_leaf10>\n" +
+ " </name_of_the_cont3>\n" +
+ " <name_of_the_list2>\n" +
+ " <name_of_the_leaf4>abc</name_of_the_leaf4>\n" +
+ " </name_of_the_list2>\n" +
+ " <name_of_the_list2>\n" +
+ " <name_of_the_leaf4>abc</name_of_the_leaf4>\n" +
+ " </name_of_the_list2>\n" +
+ " <name_of_the_list1>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_leaf1>true</name_of_the_leaf1>\n" +
+ " <name_of_the_leaf3>abc</name_of_the_leaf3>\n" +
+ " <name_of_the_leaf2>abc</name_of_the_leaf2>\n" +
+ " <name_of_the_cont4>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_cont4>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " </name_of_the_list1>\n" +
+ " <name_of_the_list1>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_leaf1>true</name_of_the_leaf1>\n" +
+ " <name_of_the_leaf3>abc</name_of_the_leaf3>\n" +
+ " <name_of_the_leaf2>abc</name_of_the_leaf2>\n" +
+ " <name_of_the_cont4>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_cont4>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " </name_of_the_list1>\n" +
+ " <name_of_the_cont4>\n" +
+ " <name_of_the_leaf10>abc</name_of_the_leaf10>" +
+ addSpace(ENCODE_TO_XML_YANG_COMMON_ID, 8) + "\n" +
+ " </name_of_the_cont4>\n" +
+ " <name_of_the_leaf12>abc</name_of_the_leaf12>\n" +
+ "</name_of_the_cont2>\n";
+
+ static final String ENCODE_TO_JSON_RPC_ID = "{\n" +
+ " \"test_name_of_the_module:input\": {\n" +
+ " \"name_of_the_cont14\": {\n" +
+ " \"name_of_the_leaf28\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_cont13\": {\n" +
+ " \"name_of_the_ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf28\": \"abc\",\n" +
+ " \"name_of_the_list9\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"name_of_the_leaf30\": \"abc\",\n" +
+ " \"name_of_the_ll10\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_list10\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf29\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf29\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_cont15\": {\n" +
+ " \"name_of_the_leaf31\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String DECODE_FROM_JSON_RPC_ID = "{\n" +
+ " \"test_name_of_the_module:output\": {\n" +
+ " \"name_of_the_cont16\": {\n" +
+ " \"name_of_the_leaf32\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_list11\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf33\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf33\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_leaf34\": \"abc\",\n" +
+ " \"name_of_the_ll11\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_cont17\": {\n" +
+ " \"name_of_the_leaf35\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_cont13\": {\n" +
+ " \"name_of_the_cont12\": {\n" +
+ " \"name_of_the_leaf26\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_list9\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf28\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_RPC_ID = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<input xmlns=\"urn:opendaylight:params:xml:ns:yang:test:name\"" +
+ ">\n" +
+ " <name_of_the_cont14>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " </name_of_the_cont14>\n" +
+ " <name_of_the_cont13>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " </name_of_the_cont13>\n" +
+ " <name_of_the_leaf30>abc</name_of_the_leaf30>\n" +
+ " <name_of_the_ll10>abc</name_of_the_ll10>\n" +
+ " <name_of_the_ll10>abc</name_of_the_ll10>\n" +
+ " <name_of_the_list10>\n" +
+ " <name_of_the_leaf29>abc</name_of_the_leaf29>\n" +
+ " </name_of_the_list10>\n" +
+ " <name_of_the_list10>\n" +
+ " <name_of_the_leaf29>abc</name_of_the_leaf29>\n" +
+ " </name_of_the_list10>\n" +
+ " <name_of_the_cont15>\n" +
+ " <name_of_the_leaf31>abc</name_of_the_leaf31>\n" +
+ " </name_of_the_cont15>\n" +
+ "</input>\n";
+
+ static final String DECODE_FROM_XML_RPC_ID = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<output xmlns=\"urn:opendaylight:params:xml:ns:yang:test:name" +
+ "\">\n" +
+ " <name_of_the_cont16>\n" +
+ " <name_of_the_leaf32>abc</name_of_the_leaf32>\n" +
+ " </name_of_the_cont16>\n" +
+ " <name_of_the_list11>\n" +
+ " <name_of_the_leaf33>abc</name_of_the_leaf33>\n" +
+ " </name_of_the_list11>\n" +
+ " <name_of_the_list11>\n" +
+ " <name_of_the_leaf33>abc</name_of_the_leaf33>\n" +
+ " </name_of_the_list11>\n" +
+ " <name_of_the_leaf34>abc</name_of_the_leaf34>\n" +
+ " <name_of_the_ll11>abc</name_of_the_ll11>\n" +
+ " <name_of_the_ll11>abc</name_of_the_ll11>\n" +
+ " <name_of_the_cont17>\n" +
+ " <name_of_the_leaf35>abc</name_of_the_leaf35>\n" +
+ " </name_of_the_cont17>\n" +
+ " <name_of_the_cont13>\n" +
+ " <name_of_the_cont12>\n" +
+ " <name_of_the_leaf26>abc</name_of_the_leaf26>\n" +
+ " </name_of_the_cont12>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " </name_of_the_cont13>\n" +
+ "</output>";
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java
new file mode 100644
index 000000000..c3a6b4ea8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java
@@ -0,0 +1,1144 @@
+/*-
+ * ============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.pnserializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertTrue;
+
+public final class PropertiesSerializerTest {
+ private SchemaContext context;
+
+ @Before
+ public void initialization() throws FileNotFoundException {
+ context = compileYangFile();
+ }
+
+ @Test
+ public void testBasicConstructs() throws SvcLogicException {
+ String uri = "test-yang:cont1/cont2";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont1.cont2.cont3.leaf10", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].leaf1", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].leaf2", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].leaf3", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll1[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll1[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll2[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll2[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].cont4.leaf11", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list4[0].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list4[1].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list5[0].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list5[1].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].leaf1", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].leaf2", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].leaf3", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll1[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll1[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll2[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll2[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].cont4.leaf11", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list4[0].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list4[1].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list5[0].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list5[1].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list2[0].leaf4", "abc");
+ params.put("test-yang_cont1.cont2.list2[1].leaf4", "abc");
+ params.put("test-yang_cont1.cont2.leaf5", "abc");
+ params.put("test-yang_cont1.cont2.leaf6", "abc");
+ params.put("test-yang_cont1.cont2.ll3[0]", "abc");
+ params.put("test-yang_cont1.cont2.ll3[1]", "abc");
+ params.put("test-yang_cont1.cont2.ll4[0]", "abc");
+ params.put("test-yang_cont1.cont2.ll4[1]", "abc");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont3"), is(true));
+ SingleInstanceNode cont3 = ((SingleInstanceNode) childNodes.get("cont3"));
+ assertThat(cont3.uri(), is("test-yang:cont1.cont2.cont3"));
+ assertThat(cont3.children().containsKey("leaf10"), is(true));
+
+ assertThat(childNodes.containsKey("list1"), is(true));
+ HolderNode list1Holder = ((ListHolderNode) childNodes.get("list1"));
+ assertThat(list1Holder.uri(), is("test-yang:cont1.cont2.list1"));
+ MultiInstanceNode list10 = ((MultiInstanceNode) list1Holder.child("0"));
+ assertThat(list10.uri(), is("test-yang:cont1.cont2.list1[0]"));
+ Map<String, DataNodeChild> list10Child = list10.children();
+ assertThat(list10Child.containsKey("leaf1"), is(true));
+ LeafNode l = ((LeafNode) list10Child.get("leaf1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].leaf1"));
+ assertThat(list10Child.containsKey("leaf2"), is(true));
+ l = ((LeafNode) list10Child.get("leaf2"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].leaf2"));
+ assertThat(list10Child.containsKey("leaf2"), is(true));
+ l = ((LeafNode) list10Child.get("leaf3"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].leaf3"));
+
+ LeafListHolderNode ll1Holder = ((LeafListHolderNode) list10Child.get("ll1"));
+ assertThat(ll1Holder.uri(), is("test-yang:cont1.cont2.list1[0].ll1"));
+ assertThat(ll1Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll1Holder.child("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll1[0]"));
+ assertThat(ll1Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll1Holder.child("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll1[1]"));
+
+ LeafListHolderNode ll2Holder = ((LeafListHolderNode) list10Child.get("ll2"));
+ assertThat(ll2Holder.uri(), is("test-yang:cont1.cont2.list1[0].ll2"));
+ assertThat(ll2Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll2Holder.child("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll2[0]"));
+ assertThat(ll2Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll2Holder.child("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll2[1]"));
+
+ SingleInstanceNode cont4 = ((SingleInstanceNode) list10Child.get("cont4"));
+ assertThat(cont4.uri(), is("test-yang:cont1.cont2.list1[0].cont4"));
+ assertThat(cont4.children().containsKey("leaf11"), is(true));
+ l = ((LeafNode) cont4.children().get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].cont4.leaf11"));
+
+ HolderNode list4Holder = ((HolderNode) list10Child.get("list4"));
+ assertThat(list4Holder.uri(), is("test-yang:cont1.cont2.list1[0].list4"));
+ Map<String, PropertiesNode> c = list4Holder.children();
+ MultiInstanceNode list40 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list40.uri(), is("test-yang:cont1.cont2.list1[0].list4[0]"));
+ assertThat(list40.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list40.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list4[0].leaf8"));
+ MultiInstanceNode list41 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list41.uri(), is("test-yang:cont1.cont2.list1[0].list4[1]"));
+ assertThat(list41.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list41.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list4[1].leaf8"));
+
+ HolderNode list5Holder = ((HolderNode) list10Child.get("list5"));
+ assertThat(list5Holder.uri(), is("test-yang:cont1.cont2.list1[0].list5"));
+ c = list5Holder.children();
+ MultiInstanceNode list50 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list50.uri(), is("test-yang:cont1.cont2.list1[0].list5[0]"));
+ assertThat(list50.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list50.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list5[0].leaf9"));
+ MultiInstanceNode list51 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list51.uri(), is("test-yang:cont1.cont2.list1[0].list5[1]"));
+ assertThat(list51.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list51.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list5[1].leaf9"));
+
+ MultiInstanceNode list11 = ((MultiInstanceNode) list1Holder.child("1"));
+ assertThat(list11.uri(), is("test-yang:cont1.cont2.list1[1]"));
+ Map<String, DataNodeChild> list11Child = list11.children();
+ assertThat(list11Child.containsKey("leaf1"), is(true));
+ l = ((LeafNode) list11Child.get("leaf1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].leaf1"));
+ assertThat(list11Child.containsKey("leaf2"), is(true));
+ l = ((LeafNode) list11Child.get("leaf2"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].leaf2"));
+ assertThat(list11Child.containsKey("leaf3"), is(true));
+ l = ((LeafNode) list11Child.get("leaf3"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].leaf3"));
+
+ ll1Holder = ((LeafListHolderNode) list11Child.get("ll1"));
+ assertThat(ll1Holder.uri(), is("test-yang:cont1.cont2.list1[1].ll1"));
+ assertThat(ll1Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll1Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll1[0]"));
+ assertThat(ll1Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll1Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll1[1]"));
+
+ ll2Holder = ((LeafListHolderNode) list11Child.get("ll2"));
+ assertThat(ll2Holder.uri(), is("test-yang:cont1.cont2.list1[1].ll2"));
+ assertThat(ll2Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll2Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll2[0]"));
+ assertThat(ll2Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll2Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll2[1]"));
+
+ cont4 = ((SingleInstanceNode) list11Child.get("cont4"));
+ assertThat(cont4.uri(), is("test-yang:cont1.cont2.list1[1].cont4"));
+ assertThat(cont4.children().containsKey("leaf11"), is(true));
+ l = ((LeafNode) cont4.children().get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].cont4.leaf11"));
+
+ list4Holder = ((HolderNode) list11Child.get("list4"));
+ assertThat(list4Holder.uri(), is("test-yang:cont1.cont2.list1[1].list4"));
+ c = list4Holder.children();
+ list40 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list40.uri(), is("test-yang:cont1.cont2.list1[1].list4[0]"));
+ assertThat(list40.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list40.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list4[0].leaf8"));
+ list41 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list41.uri(), is("test-yang:cont1.cont2.list1[1].list4[1]"));
+ assertThat(list41.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list41.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list4[1].leaf8"));
+
+ list5Holder = ((HolderNode) list11Child.get("list5"));
+ assertThat(list5Holder.uri(), is("test-yang:cont1.cont2.list1[1].list5"));
+ c = list5Holder.children();
+ list50 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list50.uri(), is("test-yang:cont1.cont2.list1[1].list5[0]"));
+ assertThat(list50.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list50.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list5[0].leaf9"));
+ list51 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list51.uri(), is("test-yang:cont1.cont2.list1[1].list5[1]"));
+ assertThat(list51.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list51.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list5[1].leaf9"));
+
+ assertThat(childNodes.containsKey("list2"), is(true));
+ HolderNode list2Holder = ((HolderNode) childNodes.get("list2"));
+ assertThat(list2Holder.uri(), is("test-yang:cont1.cont2.list2"));
+ InnerNode list20 = ((InnerNode) list2Holder.children().get("0"));
+ assertThat(list20.uri(), is("test-yang:cont1.cont2.list2[0]"));
+ assertThat(list20.children().containsKey("leaf4"), is(true));
+ l = ((LeafNode) list20.children().get("leaf4"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list2[0].leaf4"));
+ InnerNode list21 = ((InnerNode) list2Holder.children().get("1"));
+ assertThat(list21.uri(), is("test-yang:cont1.cont2.list2[1]"));
+ assertThat(list21.children().containsKey("leaf4"), is(true));
+ l = ((LeafNode) list21.children().get("leaf4"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list2[1].leaf4"));
+
+ assertThat(childNodes.containsKey("leaf5"), is(true));
+ l = ((LeafNode) childNodes.get("leaf5"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.leaf5"));
+ assertThat(childNodes.containsKey("leaf6"), is(true));
+ l = ((LeafNode) childNodes.get("leaf6"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.leaf6"));
+
+ HolderNode ll3Holder = ((HolderNode) childNodes.get("ll3"));
+ assertThat(ll3Holder.uri(), is("test-yang:cont1.cont2.ll3"));
+ assertThat(((LeafNode) ll3Holder.children().get("0")).name(), is("ll3"));
+ l = ((LeafNode) ll3Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll3[0]"));
+ assertThat(((LeafNode) ll3Holder.children().get("1")).name(), is("ll3"));
+ l = ((LeafNode) ll3Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll3[1]"));
+
+ HolderNode ll4Holder = ((HolderNode) childNodes.get("ll4"));
+ assertThat(ll4Holder.uri(), is("test-yang:cont1.cont2.ll4"));
+ assertThat(((LeafNode) ll4Holder.children().get("0")).name(), is("ll4"));
+ l = ((LeafNode) ll4Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll4[0]"));
+ assertThat(((LeafNode) ll4Holder.children().get("1")).name(), is("ll4"));
+ l = ((LeafNode) ll4Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll4[1]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testAugment() throws SvcLogicException {
+ String uri = "test-yang:cont1/cont2";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont1.cont2.cont4.leaf10", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont5.leaf13", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_list7[0].leaf14", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_list7[1].leaf14", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_leaf15", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_ll6[0]", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_ll6[1]", "abc");
+ params.put("test-yang_cont1.cont2.list6[0].leaf11", "abc");
+ params.put("test-yang_cont1.cont2.list6[1].leaf11", "abc");
+ params.put("test-yang_cont1.cont2.leaf12", "abc");
+ params.put("test-yang_cont1.cont2.ll5[0]", "abc");
+ params.put("test-yang_cont1.cont2.ll5[1]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont4"), is(true));
+ SingleInstanceNode cont4 = ((SingleInstanceNode) childNodes.get("cont4"));
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : cont4.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:cont5");
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:list7");
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:leaf15");
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:ll6");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:cont5")) {
+ assertThat(((SingleInstanceNode) pNode).children().containsKey("leaf13"), is(true));
+ LeafNode l = ((LeafNode) ((SingleInstanceNode) pNode).children().get("leaf13"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont5.leaf13"));
+ } else if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:list7")) {
+ ListHolderNode list7Holder = ((ListHolderNode) pNode);
+ MultiInstanceNode list7 = ((MultiInstanceNode) list7Holder.child("0"));
+ assertThat(list7.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[0]"));
+ Map<String, DataNodeChild> list7Child = list7.children();
+ assertThat(list7Child.containsKey("leaf14"), is(true));
+ LeafNode l = ((LeafNode) list7Child.get("leaf14"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[0].leaf14"));
+ list7 = ((MultiInstanceNode) list7Holder.child("1"));
+ assertThat(list7.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[1]"));
+ list7Child = list7.children();
+ assertThat(list7Child.containsKey("leaf14"), is(true));
+ l = ((LeafNode) list7Child.get("leaf14"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[1].leaf14"));
+ } else if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:leaf15")) {
+ LeafNode leaf15 = ((LeafNode) pNode);
+ assertThat(leaf15.name(), is("leaf15"));
+ assertThat(leaf15.uri(), is("test-yang:cont1.cont2.cont4.test-augment:leaf15"));
+ } else if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:ll6")) {
+ LeafListHolderNode ll6Holder = ((LeafListHolderNode) pNode);
+ assertThat(ll6Holder.children().containsKey("0"), is(true));
+ LeafNode l = ((LeafNode) ll6Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:ll6[0]"));
+ assertThat(ll6Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll6Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:ll6[1]"));
+ }
+ }
+ }
+ }
+ assertThat(cont4.uri(), is("test-yang:cont1.cont2.cont4"));
+ assertThat(cont4.children().containsKey("leaf10"), is(true));
+ LeafNode l = ((LeafNode) cont4.children().get("leaf10"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.leaf10"));
+
+ assertThat(childNodes.containsKey("list6"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list6"));
+ assertThat(list6Holder.uri(), is("test-yang:cont1.cont2.list6"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont1.cont2.list6[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf11"), is(true));
+ l = ((LeafNode) list6Child.get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list6[0].leaf11"));
+ list6 = ((MultiInstanceNode) list6Holder.child("1"));
+ assertThat(list6.uri(), is("test-yang:cont1.cont2.list6[1]"));
+ list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf11"), is(true));
+ l = ((LeafNode) list6Child.get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list6[1].leaf11"));
+
+ assertThat(childNodes.containsKey("leaf12"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf12"));
+ assertThat(leaf12.name(), is("leaf12"));
+ assertThat(leaf12.uri(), is("test-yang:cont1.cont2.leaf12"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll5"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont1.cont2.ll5"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll5[0]"));
+ assertThat(ll5Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll5[1]"));
+
+ Map<String, String> output = ser.decode(node);
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testChoiceCase1() throws SvcLogicException {
+ String uri = "test-yang:cont8";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont8.cont6.leaf16", "abc");
+ params.put("test-yang_cont8.list8[0].leaf18", "abc");
+ params.put("test-yang_cont8.list8[1].leaf18", "abc");
+ params.put("test-yang_cont8.leaf19", "abc");
+ params.put("test-yang_cont8.ll7[0]", "abc");
+ params.put("test-yang_cont8.ll7[1]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont6"), is(true));
+ SingleInstanceNode cont6 = ((SingleInstanceNode) childNodes.get("cont6"));
+ assertThat(cont6.uri(), is("test-yang:cont8.cont6"));
+ assertThat(cont6.children().containsKey("leaf16"), is(true));
+ LeafNode l = ((LeafNode) cont6.children().get("leaf16"));
+ assertThat(l.uri(), is("test-yang:cont8.cont6.leaf16"));
+
+ assertThat(childNodes.containsKey("list8"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list8"));
+ assertThat(list6Holder.uri(), is("test-yang:cont8.list8"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont8.list8[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf18"), is(true));
+ l = ((LeafNode) list6Child.get("leaf18"));
+ assertThat(l.uri(), is("test-yang:cont8.list8[0].leaf18"));
+ list6 = ((MultiInstanceNode) list6Holder.child("1"));
+ list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf18"), is(true));
+ l = ((LeafNode) list6Child.get("leaf18"));
+ assertThat(l.uri(), is("test-yang:cont8.list8[1].leaf18"));
+
+ assertThat(childNodes.containsKey("leaf19"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf19"));
+ assertThat(leaf12.name(), is("leaf19"));
+ assertThat(leaf12.uri(), is("test-yang:cont8.leaf19"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll7"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont8.ll7"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont8.ll7[0]"));
+ assertThat(ll5Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont8.ll7[1]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testChoiceCase2() throws SvcLogicException {
+ String uri = "test-yang:cont9";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont9.leaf20", "abc");
+ params.put("test-yang_cont9.ll8[0]", "abc");
+ params.put("test-yang_cont9.cont11.leaf25", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont11"), is(true));
+ SingleInstanceNode cont4 = ((SingleInstanceNode) childNodes.get("cont11"));
+ assertThat(cont4.uri(), is("test-yang:cont9.cont11"));
+ assertThat(cont4.children().containsKey("leaf25"), is(true));
+ LeafNode l = ((LeafNode) cont4.children().get("leaf25"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.leaf25"));
+
+ assertThat(childNodes.containsKey("leaf20"), is(true));
+ l = ((LeafNode) childNodes.get("leaf20"));
+ assertThat(l.uri(), is("test-yang:cont9.leaf20"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll8"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont9.ll8"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont9.ll8[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testChoiceCase3() throws SvcLogicException {
+ String uri = "test-yang:cont8/cont6";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont8.cont6.test-augment_leaf21", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:cont8.cont6.test-augment:leaf21");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ }
+ }
+ }
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("leaf21"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf21"));
+ assertThat(leaf12.name(), is("leaf21"));
+ assertThat(leaf12.uri(), is("test-yang:cont8.cont6.test-augment:leaf21"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping() throws SvcLogicException {
+ String uri = "test-yang:cont13";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont13.cont12.leaf26", "abc");
+ params.put("test-yang_cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_cont13.leaf28", "abc");
+ params.put("test-yang_cont13.ll9[0]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont12"), is(true));
+ SingleInstanceNode cont4 = ((SingleInstanceNode) childNodes.get("cont12"));
+ assertThat(cont4.uri(), is("test-yang:cont13.cont12"));
+ assertThat(cont4.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont4.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:cont13.cont12.leaf26"));
+
+ assertThat(childNodes.containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list9"));
+ assertThat(list6Holder.uri(), is("test-yang:cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:cont13.list9[0].leaf27"));
+
+ assertThat(childNodes.containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping2() throws SvcLogicException {
+ String uri = "test-yang:cont9/cont11";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont9.cont11.leaf25", "abc");
+ params.put("test-yang_cont9.cont11.cont13.cont12.leaf26", "abc");
+ params.put("test-yang_cont9.cont11.cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_cont9.cont11.cont13.leaf28", "abc");
+ params.put("test-yang_cont9.cont11.cont13.ll9[0]", "abc");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont13"), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) childNodes.get("cont13"));
+ assertThat(cont13.uri(), is("test-yang:cont9.cont11.cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ assertThat(cont12.uri(), is("test-yang:cont9.cont11.cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list6Holder.uri(), is("test-yang:cont9.cont11.cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont9.cont11.cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:cont9.cont11.cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont9.cont11.cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.cont13.ll9[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping3() throws SvcLogicException {
+ String uri = "test-augment:cont13";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-augment_cont13.cont12.leaf26", "abc");
+ params.put("test-augment_cont13.list9[0].leaf27", "abc");
+ params.put("test-augment_cont13.leaf28", "abc");
+ params.put("test-augment_cont13.ll9[0]", "abc");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont12"), is(true));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) childNodes.get("cont12"));
+ assertThat(cont12.uri(), is("test-augment:cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-augment:cont13.cont12.leaf26"));
+
+ assertThat(childNodes.containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list9"));
+ assertThat(list6Holder.uri(), is("test-augment:cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-augment:cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-augment:cont13.list9[0].leaf27"));
+
+ assertThat(childNodes.containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-augment:cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-augment:cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-augment:cont13.ll9[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping4() throws SvcLogicException {
+ String uri = "test-yang:cont1/cont2/cont4";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.cont12.leaf26", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.leaf28", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.ll9[0]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:cont13");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) pNode);
+ assertThat(cont13.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list6Holder.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.ll9[0]"));
+ }
+ }
+ }
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testRpcInput() throws SvcLogicException {
+ String uri = "test-yang:create-sfc";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_create-sfc.input.cont14.leaf28", "abc");
+ params.put("test-yang_create-sfc.input.list10[0].leaf29", "abc");
+ params.put("test-yang_create-sfc.input.leaf30", "abc");
+ params.put("test-yang_create-sfc.input.ll10[0]", "abc");
+ params.put("test-yang_create-sfc.input.cont15.leaf31", "abc");
+ params.put("test-yang_create-sfc.input.cont13.cont12.leaf26", "abc");
+ params.put("test-yang_create-sfc.input.cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_create-sfc.input.cont13.leaf28", "abc");
+ params.put("test-yang_create-sfc.input.cont13.ll9[0]", "abc");
+ params.put("test-yang_create-sfc.input.test-augment_leaf36", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ PropertiesNode input = childNodes.get("input");
+ assertThat(input.uri(), is("test-yang:create-sfc.input"));
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:create-sfc.input.test-augment:leaf36");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ LeafNode leaf37 = ((LeafNode) pNode);
+ assertThat(leaf37.name(), is("leaf36"));
+ assertThat(leaf37.uri(), is("test-yang:create-sfc.input.test-augment:leaf36"));
+ }
+ }
+ }
+ childNodes = ((InnerNode) input).children();
+
+ assertThat(childNodes.containsKey("cont14"), is(true));
+ SingleInstanceNode cont14 = ((SingleInstanceNode) childNodes.get("cont14"));
+ assertThat(cont14.uri(), is("test-yang:create-sfc.input.cont14"));
+ assertThat(cont14.children().containsKey("leaf28"), is(true));
+ LeafNode l = ((LeafNode) cont14.children().get("leaf28"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont14.leaf28"));
+
+ assertThat(childNodes.containsKey("list10"), is(true));
+ HolderNode list10Holder = ((ListHolderNode) childNodes.get("list10"));
+ assertThat(list10Holder.uri(), is("test-yang:create-sfc.input.list10"));
+ MultiInstanceNode list10 = ((MultiInstanceNode) list10Holder.child("0"));
+ assertThat(list10.uri(), is("test-yang:create-sfc.input.list10[0]"));
+ Map<String, DataNodeChild> list10Child = list10.children();
+ assertThat(list10Child.containsKey("leaf29"), is(true));
+ l = ((LeafNode) list10Child.get("leaf29"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.list10[0].leaf29"));
+
+ assertThat(childNodes.containsKey("leaf30"), is(true));
+ LeafNode leaf30 = ((LeafNode) childNodes.get("leaf30"));
+ assertThat(leaf30.name(), is("leaf30"));
+ assertThat(leaf30.uri(), is("test-yang:create-sfc.input.leaf30"));
+
+ LeafListHolderNode ll10Holder = ((LeafListHolderNode) childNodes.get("ll10"));
+ assertThat(ll10Holder.uri(), is("test-yang:create-sfc.input.ll10"));
+ assertThat(ll10Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll10Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.ll10[0]"));
+
+ assertThat(childNodes.containsKey("cont15"), is(true));
+ SingleInstanceNode cont15 = ((SingleInstanceNode) childNodes.get("cont15"));
+ assertThat(cont15.uri(), is("test-yang:create-sfc.input.cont15"));
+ assertThat(cont15.children().containsKey("leaf31"), is(true));
+ l = ((LeafNode) cont15.children().get("leaf31"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont15.leaf31"));
+
+ assertThat(childNodes.containsKey("cont13"), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) childNodes.get("cont13"));
+ assertThat(cont13.uri(), is("test-yang:create-sfc.input.cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.uri(), is("test-yang:create-sfc.input.cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list9Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list9Holder.uri(), is("test-yang:create-sfc.input.cont13.list9"));
+ MultiInstanceNode list9 = ((MultiInstanceNode) list9Holder.child("0"));
+ assertThat(list9.uri(), is("test-yang:create-sfc.input.cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list9.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:create-sfc.input.cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:create-sfc.input.cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont13.ll9[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testRpcOutput() throws SvcLogicException {
+ String uri = "test-yang:create-sfc";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_create-sfc.output.cont16.leaf32", "abc");
+ params.put("test-yang_create-sfc.output.list11[0].leaf33", "abc");
+ params.put("test-yang_create-sfc.output.leaf34", "abc");
+ params.put("test-yang_create-sfc.output.ll11[0]", "abc");
+ params.put("test-yang_create-sfc.output.cont17.leaf35", "abc");
+ params.put("test-yang_create-sfc.output.cont13.cont12.leaf26", "abc");
+ params.put("test-yang_create-sfc.output.cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_create-sfc.output.cont13.leaf28", "abc");
+ params.put("test-yang_create-sfc.output.cont13.ll9[0]", "abc");
+ params.put("test-yang_create-sfc.output.test-augment_leaf37", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ PropertiesNode output = childNodes.get("output");
+ assertThat(output.uri(), is("test-yang:create-sfc.output"));
+ for (Map.Entry<Object, Collection<PropertiesNode>> augmentationToChild :
+ node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> c = augmentationToChild.getValue();
+ if(!c.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:create-sfc.output.test-augment:leaf37");
+ assertThat(expectedNodes.size(), is(expectedNodes));
+ for (PropertiesNode pNode : c) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ LeafNode leaf37 = ((LeafNode) pNode);
+ assertThat(leaf37.name(), is("leaf37"));
+ assertThat(leaf37.uri(), is("test-yang:create-sfc.output.test-augment:leaf37"));
+ }
+ }
+ }
+ childNodes = ((InnerNode) output).children();
+
+ assertThat(childNodes.containsKey("cont16"), is(true));
+ SingleInstanceNode cont16 = ((SingleInstanceNode) childNodes.get("cont16"));
+ assertThat(cont16.uri(), is("test-yang:create-sfc.output.cont16"));
+ assertThat(cont16.children().containsKey("leaf32"), is(true));
+ LeafNode l = ((LeafNode) cont16.children().get("leaf32"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont16.leaf32"));
+
+ assertThat(childNodes.containsKey("list11"), is(true));
+ HolderNode list11Holder = ((ListHolderNode) childNodes.get("list11"));
+ assertThat(list11Holder.uri(), is("test-yang:create-sfc.output.list11"));
+ MultiInstanceNode list11 = ((MultiInstanceNode) list11Holder.child("0"));
+ assertThat(list11.uri(), is("test-yang:create-sfc.output.list11[0]"));
+ Map<String, DataNodeChild> list11Child = list11.children();
+ assertThat(list11Child.containsKey("leaf33"), is(true));
+ l = ((LeafNode) list11Child.get("leaf33"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.list11[0].leaf33"));
+
+ assertThat(childNodes.containsKey("leaf34"), is(true));
+ LeafNode leaf34 = ((LeafNode) childNodes.get("leaf34"));
+ assertThat(leaf34.name(), is("leaf34"));
+ assertThat(leaf34.uri(), is("test-yang:create-sfc.output.leaf34"));
+
+ LeafListHolderNode ll10Holder = ((LeafListHolderNode) childNodes.get("ll11"));
+ assertThat(ll10Holder.uri(), is("test-yang:create-sfc.output.ll11"));
+ assertThat(ll10Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll10Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.ll11[0]"));
+
+ assertThat(childNodes.containsKey("cont17"), is(true));
+ SingleInstanceNode cont17 = ((SingleInstanceNode) childNodes.get("cont17"));
+ assertThat(cont17.uri(), is("test-yang:create-sfc.output.cont17"));
+ assertThat(cont17.children().containsKey("leaf35"), is(true));
+ l = ((LeafNode) cont17.children().get("leaf35"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont17.leaf35"));
+
+ assertThat(childNodes.containsKey("cont13"), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) childNodes.get("cont13"));
+ assertThat(cont13.uri(), is("test-yang:create-sfc.output.cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.uri(), is("test-yang:create-sfc.output.cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list9Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list9Holder.uri(), is("test-yang:create-sfc.output.cont13.list9"));
+ MultiInstanceNode list9 = ((MultiInstanceNode) list9Holder.child("0"));
+ assertThat(list9.uri(), is("test-yang:create-sfc.output.cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list9.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:create-sfc.output.cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:create-sfc.output.cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont13.ll9[0]"));
+
+ Map<String, String> output1 = ser.decode(node);
+ assertThat(output1.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output1.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testContainerSameName() throws SvcLogicException {
+ String uri = "test-yang:cont18";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont18.cont18.list12[0].list12[0].leaf36", "abc");
+ params.put("test-yang_cont18.cont18.list12[0].leaf36", "hi");
+ params.put("test-yang_cont18.cont18.list12[1].list12[0].leaf36", "xyz");
+ params.put("test-yang_cont18.cont18.list12[1].list12[1].leaf36", "hey!");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont18"), is(true));
+ node = childNodes.get("cont18");
+ assertThat(node.uri(), is("test-yang:cont18.cont18"));
+ childNodes = ((InnerNode) node).children();
+
+ assertThat(childNodes.containsKey("list12"), is(true));
+ HolderNode holder = ((ListHolderNode) childNodes.get("list12"));
+ assertThat(holder.uri(), is("test-yang:cont18.cont18.list12"));
+ MultiInstanceNode node1 = ((MultiInstanceNode) holder.child("0"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[0]"));
+ Map<String, DataNodeChild> list12Child = node1.children();
+
+ assertThat(list12Child.containsKey("leaf36"), is(true));
+ LeafNode leaf = ((LeafNode) list12Child.get("leaf36"));
+ assertThat(leaf.value(), is("hi"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[0].leaf36"));
+
+ assertThat(list12Child.containsKey("list12"), is(true));
+ HolderNode holder1 = ((ListHolderNode) list12Child.get("list12"));
+ assertThat(holder1.uri(), is("test-yang:cont18.cont18.list12[0].list12"));
+ node1 = ((MultiInstanceNode) holder1.child("0"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[0].list12[0]"));
+ list12Child = node1.children();
+ assertThat(list12Child.containsKey("leaf36"), is(true));
+ leaf = ((LeafNode) list12Child.get("leaf36"));
+ assertThat(leaf.value(), is("abc"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[0].list12[0].leaf36"));
+
+ node1 = ((MultiInstanceNode) holder.child("1"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[1]"));
+ list12Child = node1.children();
+ assertThat(list12Child.containsKey("list12"), is(true));
+ holder = ((ListHolderNode) list12Child.get("list12"));
+ assertThat(holder.uri(), is("test-yang:cont18.cont18.list12[1].list12"));
+ node1 = ((MultiInstanceNode) holder.child("0"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[1].list12[0]"));
+ assertThat(node1.children().containsKey("leaf36"), is(true));
+ leaf = ((LeafNode) node1.children().get("leaf36"));
+ assertThat(leaf.value(), is("xyz"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[1].list12[0].leaf36"));
+
+ node1 = ((MultiInstanceNode) holder.child("1"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[1].list12[1]"));
+ assertThat(node1.children().containsKey("leaf36"), is(true));
+ leaf = ((LeafNode) node1.children().get("leaf36"));
+ assertThat(leaf.value(), is("hey!"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[1].list12[1].leaf36"));
+
+ Map<String, String> output1 = ser.decode(node);
+ assertThat(output1.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output1.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testPropertiesWithoutSchema() throws SvcLogicException {
+ String uri = "test-yang:cont18";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont18.leaf40", "abc");
+ params.put("leaf41", "hi");
+ params.put("test-yang_cont18.leaf41", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+ assertThat(childNodes.containsKey("leaf40"), is(true));
+ node = childNodes.get("leaf40");
+ assertThat(node.uri(), is("test-yang:cont18.leaf40"));
+ }
+
+ @Test
+ public void testIdentityRef() throws SvcLogicException {
+ String uri = "identity-test:test";
+ Map<String, String> params = new HashMap<>();
+ params.put("identity-test_test.con1.interface", "identity-types" +
+ ":physical");
+ params.put("identity-test_test.con1.interfaces.int-list[0].iden", "identity-test:Giga");
+ params.put("identity-test_test.con1.interfaces.int-list[0].available.ll[0]", "identity-types:Loopback");
+ params.put("identity-test_test.con1.interfaces.int-list[0].available.leaf1", "identity-types-second:Ethernet");
+ params.put("identity-test_test.con1.interfaces.int-list[0].available.leaf2", "identity-types-second:iden2");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+ assertThat(childNodes.containsKey("con1"), is(true));
+ node = childNodes.get("con1");
+ assertThat(node.uri(), is("identity-test:test.con1"));
+ LeafNode l = ((LeafNode) ((SingleInstanceNode) node).children().get("interface"));
+ assertThat(l.uri(), is("identity-test:test.con1.interface"));
+ assertThat(l.valueNs().moduleName(), is("identity-types"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:ns:test:json:ser"));
+
+ // identity type inside union
+ node = ((SingleInstanceNode) ((SingleInstanceNode) node).children().get("interfaces"));
+ node = ((ListHolderNode) ((SingleInstanceNode) node).children().get("int-list"));
+ node = ((MultiInstanceNode) ((ListHolderNode) node).children().get("0"));
+ l = ((LeafNode) ((MultiInstanceNode) node).children().get("iden"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].iden"));
+ assertThat(l.valueNs().moduleName(), is("identity-test"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:ns:test:json:ser"));
+
+ // leaf-list test
+ node = (SingleInstanceNode) ((MultiInstanceNode) node).children().get("available");
+ LeafListHolderNode holder = (LeafListHolderNode) ((SingleInstanceNode) node).children().get("ll");
+ l = ((LeafNode) holder.children().get("0"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.ll[0]"));
+ assertThat(l.valueNs().moduleName(), is("identity-types"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:ns:test:json:ser"));
+
+ // leaf-ref test
+ l = ((LeafNode) ((SingleInstanceNode) node).children().get("leaf1"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.leaf1"));
+ assertThat(l.valueNs().moduleName(), is("identity-types-second"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:second:ns:test:json:ser"));
+
+ // list of base identity test
+ l = ((LeafNode) ((SingleInstanceNode) node).children().get("leaf2"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.leaf2"));
+ assertThat(l.valueNs().moduleName(), is("identity-types-second"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:second:ns:test:json:ser"));
+ }
+
+ public static SchemaContext compileYangFile() throws FileNotFoundException {
+ String path = PropertiesSerializerTest.class.getResource("/yang").getPath();
+ File dir = new File(path);
+ String[] fileList = dir.list();
+ List<File> yangFiles = new ArrayList<File>();
+ if (fileList == null) {
+ throw new FileNotFoundException("/yang");
+ }
+ for (int i = 0; i < fileList.length; i++) {
+ final String fileName = fileList[i];
+ if (new File(dir, fileName).isDirectory() == false) {
+ yangFiles.add(new File(dir, fileName));
+ }
+ }
+ return YangParserTestUtils.parseYangFiles(yangFiles);
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang b/plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang
new file mode 100644
index 000000000..d7cf68f12
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang
@@ -0,0 +1,43 @@
+module execution-service {
+ yang-version 1.1;
+ namespace "cds:workflow:rest";
+ prefix "cds";
+
+ revision "2019-05-21";
+
+ container process {
+ container commonHeader {
+ leaf originatorId {
+ type string;
+ }
+ leaf requestId {
+ type string;
+ }
+ leaf subRequestId {
+ type string;
+ }
+ }
+ container actionIdentifiers {
+ leaf blueprintName {
+ type string;
+ }
+ leaf blueprintVersion {
+ type string;
+ }
+ leaf actionName {
+ type string;
+ }
+ leaf mode {
+ type string;
+ }
+ }
+ container payload {
+ leaf-list template-prefix {
+ type string;
+ }
+ container resource-assignment-request {
+ anyxml resource-assignment-properties;
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang b/plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang
new file mode 100644
index 000000000..12ef717f6
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang
@@ -0,0 +1,77 @@
+module identity-test {
+ yang-version 1.1;
+ namespace "identity:ns:test:json:ser";
+ prefix "id";
+
+ import identity-types {
+ prefix "type";
+ }
+
+ import identity-types-second {
+ prefix "sec";
+ }
+
+ revision "2013-07-15";
+
+ identity optical {
+ base type:int-type;
+ }
+
+ identity Giga {
+ base type:physical;
+ }
+
+ typedef available {
+ type identityref {
+ base "type:physical";
+ }
+ }
+
+ typedef typed{
+ type union {
+ type int32;
+ type int8;
+ type identityref {
+ base type:int-type;
+ }
+ }
+ }
+
+ container test {
+ leaf l {
+ type string;
+ }
+ container con1 {
+ leaf interface {
+ type identityref {
+ base "type:int-type";
+ }
+ }
+ container interfaces {
+ list int-list {
+ key "iden";
+ leaf iden {
+ type "id:typed";
+ }
+ container available {
+ leaf-list ll {
+ type available;
+ }
+ leaf leaf1 {
+ type leafref {
+ path "../../iden";
+ }
+ }
+
+ leaf leaf2 {
+ type identityref {
+ base type:int-type;
+ base sec:iden1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang b/plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang
new file mode 100644
index 000000000..98d6a6e60
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang
@@ -0,0 +1,25 @@
+module identity-types-second {
+ yang-version 1;
+ namespace "identity:list:second:ns:test:json:ser";
+ prefix "sec";
+
+ import identity-types {
+ prefix "type";
+ }
+
+ revision "2013-07-15";
+
+ identity virtual {
+ base type:int-type;
+ }
+
+ identity Ethernet {
+ base type:physical;
+ }
+
+ identity iden1;
+
+ identity iden2 {
+ base iden1;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang b/plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang
new file mode 100644
index 000000000..25c8fa54f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang
@@ -0,0 +1,17 @@
+module identity-types {
+ yang-version 1;
+ namespace "identity:list:ns:test:json:ser";
+ prefix "type";
+ revision "2013-07-15";
+
+ identity int-type {
+ }
+
+ identity physical {
+ base int-type;
+ }
+
+ identity Loopback {
+ base physical;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang b/plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang
new file mode 100644
index 000000000..795000d39
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang
@@ -0,0 +1,106 @@
+module test-augment {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:augment";
+ prefix "hello";
+
+ import test-yang {
+ prefix t;
+ }
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ augment "/t:cont1/t:cont2/t:cont4" {
+ container cont5 {
+ leaf leaf13 {
+ type empty;
+ }
+ }
+ list list7 {
+ leaf leaf14 {
+ type instance-identifier;
+ }
+ }
+ leaf leaf15 {
+ type string;
+ }
+ leaf-list ll6 {
+ type union {
+ type int32;
+ type enumeration {
+ enum "unbounded";
+ }
+ }
+ }
+ uses "t:g1";
+ }
+
+ uses "t:g1";
+ augment "/t:ch1/t:c1/t:cont8/t:cont6" {
+ choice ch2 {
+ case c3 {
+ leaf leaf21 {
+ type string;
+ }
+ }
+ case c4 {
+ leaf leaf22 {
+ type enumeration {
+ enum zero;
+ enum one;
+ enum seven {
+ value 7;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ augment "/t:ch1" {
+ case c5 {
+ container cont10 {
+ leaf leaf23 {
+ type string;
+ }
+ }
+ }
+ }
+
+ augment "/t:ch1/t:c1" {
+ container cont7 {
+ leaf leaf24 {
+ type string;
+ }
+ }
+ }
+
+ augment "/t:cont13/t:cont12" {
+ leaf leaf29 {
+ type string;
+ }
+ }
+
+ augment "/t:create-sfc/t:input" {
+ leaf leaf36 {
+ type bits {
+ bit angle {
+ position 0;
+ }
+ bit degree {
+ position 1;
+ }
+ bit movement {
+ position 2;
+ }
+ }
+ }
+ }
+
+ augment "/t:create-sfc/t:output" {
+ leaf leaf37 {
+ type boolean;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang b/plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang
new file mode 100644
index 000000000..b2bf06003
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang
@@ -0,0 +1,231 @@
+module test-yang {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:test";
+ prefix "hello";
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ container cont1 {
+ container cont2 {
+ container cont3 {
+ leaf leaf10 {
+ type string;
+ }
+ }
+ list list1 {
+ key "leaf1 leaf2";
+ leaf leaf1 {
+ type empty;
+ }
+ leaf leaf2 {
+ type string;
+ }
+ leaf leaf3 {
+ type string;
+ }
+ leaf-list ll1 {
+ type string;
+ }
+ leaf-list ll2 {
+ type string;
+ }
+ container cont4 {
+ leaf leaf11 {
+ type string;
+ }
+ }
+ list list4 {
+ leaf leaf8 {
+ type string;
+ }
+ }
+ list list5 {
+ leaf leaf9 {
+ type string;
+ }
+ }
+ }
+ list list2 {
+ leaf leaf4 {
+ type string;
+ }
+ }
+ leaf leaf5 {
+ type string;
+ }
+ leaf leaf6 {
+ type string;
+ }
+ leaf-list ll3 {
+ type string;
+ }
+ leaf-list ll4 {
+ type string;
+ }
+ }
+ }
+
+ augment "/cont1/cont2" {
+ container cont4 {
+ leaf leaf10 {
+ type string;
+ }
+ }
+ list list6 {
+ leaf leaf11 {
+ type string;
+ }
+ }
+ leaf leaf12 {
+ type string;
+ }
+ leaf-list ll5 {
+ type string;
+ }
+ }
+
+ choice ch1 {
+ case c1 {
+ container cont8 {
+ container cont6 {
+ leaf leaf16 {
+ type string;
+ }
+ }
+ list list8 {
+ leaf leaf18 {
+ type string;
+ }
+ }
+ leaf leaf19 {
+ type string;
+ }
+ leaf-list ll7 {
+ type string;
+ }
+ }
+ }
+ case c2 {
+ container cont9 {
+ leaf leaf20 {
+ type string;
+ }
+ leaf-list ll8 {
+ type string;
+ }
+ container cont11 {
+ choice ch3 {
+ case c1 {
+ leaf leaf25 {
+ type string;
+ }
+ uses g1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ grouping g1 {
+ container cont13 {
+ container cont12 {
+ leaf leaf26 {
+ type string;
+ }
+ }
+ list list9 {
+ leaf leaf27 {
+ type string;
+ }
+ }
+ leaf leaf28 {
+ type string;
+ }
+ leaf-list ll9 {
+ type string;
+ }
+ }
+ }
+
+ uses g1;
+
+ rpc create-sfc {
+ input {
+ container cont14 {
+ leaf leaf28 {
+ type string;
+ }
+ }
+ list list10 {
+ leaf leaf29 {
+ type string;
+ }
+ }
+ leaf leaf30 {
+ type string;
+ }
+ leaf-list ll10 {
+ type string;
+ }
+ choice ch3 {
+ case c1 {
+ container cont15 {
+ leaf leaf31 {
+ type string;
+ }
+ }
+ }
+ }
+ uses g1;
+ }
+ output {
+ container cont16 {
+ leaf leaf32 {
+ type string;
+ }
+ }
+ list list11 {
+ leaf leaf33 {
+ type string;
+ }
+ }
+ leaf leaf34 {
+ type string;
+ }
+ leaf-list ll11 {
+ type string;
+ }
+ choice ch4 {
+ case c1 {
+ container cont17 {
+ leaf leaf35 {
+ type string;
+ }
+ }
+ }
+ }
+ uses g1;
+ }
+ }
+
+ container cont18 {
+ container cont18 {
+ list list12 {
+ list list12 {
+ leaf leaf36 {
+ type string;
+ }
+ }
+ leaf leaf36 {
+ type string;
+ }
+ }
+ }
+ leaf leaf40 {
+ type string;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang b/plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang
new file mode 100644
index 000000000..d2eeea7d1
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang
@@ -0,0 +1,108 @@
+module test_augment_1_for_module {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:test:augment:name";
+ prefix "augment-name";
+
+ import test_name_of_the_module {
+ prefix aug;
+ }
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ augment "/aug:name_of_the_cont1/aug:name_of_the_cont2/aug:name_of_the_cont4" {
+ container name_of_the_cont5 {
+ leaf name_of_the_leaf13 {
+ type empty;
+ }
+ }
+ list name_of_the_list7 {
+ leaf name_of_the_leaf14 {
+ type instance-identifier;
+ }
+ }
+ leaf name_of_the_leaf15 {
+ type string;
+ }
+ leaf-list name_of_the_ll6 {
+ type union {
+ type int32;
+ type enumeration {
+ enum "unbounded";
+ }
+ }
+ }
+ uses "aug:name_of_the_g1";
+ }
+
+ uses "aug:name_of_the_g1";
+
+ augment "/aug:name_of_the_cont1/aug:name_of_the_cont2/aug:name_of_the_cont3" {
+ choice name_of_the_ch2 {
+ case name_of_the_c3 {
+ leaf name_of_the_leaf21 {
+ type string;
+ }
+ }
+ case name_of_the_c4 {
+ leaf name_of_the_leaf22 {
+ type enumeration {
+ enum zero;
+ enum one;
+ enum seven {
+ value 7;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_ch1" {
+ case name_of_the_c5 {
+ container name_of_the_cont10 {
+ leaf name_of_the_leaf23 {
+ type string;
+ }
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_ch1/aug:name_of_the_c1" {
+ container name_of_the_cont7 {
+ leaf name_of_the_leaf24 {
+ type string;
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_cont13/aug:name_of_the_cont12" {
+ leaf name_of_the_leaf29 {
+ type string;
+ }
+ }
+
+ augment "/aug:name_of_the_create-sfc/aug:input" {
+ leaf name_of_the_leaf36 {
+ type bits {
+ bit angle {
+ position 0;
+ }
+ bit degree {
+ position 1;
+ }
+ bit movement {
+ position 2;
+ }
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_create-sfc/aug:output" {
+ leaf leaf37 {
+ type boolean;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang b/plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang
new file mode 100644
index 000000000..973475ee7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang
@@ -0,0 +1,231 @@
+module test_name_of_the_module {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:test:name";
+ prefix "name";
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ container name_of_the_cont1 {
+ container name_of_the_cont2 {
+ container name_of_the_cont3 {
+ leaf name_of_the_leaf10 {
+ type string;
+ }
+ }
+ list name_of_the_list1 {
+ key "name_of_the_leaf1 name_of_the_leaf2";
+ leaf name_of_the_leaf1 {
+ type empty;
+ }
+ leaf name_of_the_leaf2 {
+ type string;
+ }
+ leaf name_of_the_leaf3 {
+ type string;
+ }
+ leaf-list name_of_the_ll1 {
+ type string;
+ }
+ leaf-list name_of_the_ll2 {
+ type string;
+ }
+ container name_of_the_cont4 {
+ leaf name_of_the_leaf11 {
+ type string;
+ }
+ }
+ list name_of_the_list4 {
+ leaf name_of_the_leaf8 {
+ type string;
+ }
+ }
+ list name_of_the_list5 {
+ leaf name_of_the_leaf9 {
+ type string;
+ }
+ }
+ }
+ list name_of_the_list2 {
+ leaf name_of_the_leaf4 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf5 {
+ type string;
+ }
+ leaf name_of_the_leaf6 {
+ type string;
+ }
+ leaf-list name_of_the_ll3 {
+ type string;
+ }
+ leaf-list name_of_the_ll4 {
+ type string;
+ }
+ }
+ }
+
+ augment "/name_of_the_cont1/name_of_the_cont2" {
+ container name_of_the_cont4 {
+ leaf name_of_the_leaf10 {
+ type string;
+ }
+ }
+ list name_of_the_list6 {
+ leaf name_of_the_leaf11 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf12 {
+ type string;
+ }
+ leaf-list name_of_the_ll5 {
+ type string;
+ }
+ }
+
+ choice name_of_the_ch1 {
+ case name_of_the_c1 {
+ container name_of_the_cont8 {
+ container name_of_the_cont6 {
+ leaf name_of_the_leaf16 {
+ type string;
+ }
+ }
+ list name_of_the_list8 {
+ leaf name_of_the_leaf18 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf19 {
+ type string;
+ }
+ leaf-list name_of_the_ll7 {
+ type string;
+ }
+ }
+ }
+ case name_of_the_c2 {
+ container name_of_the_cont9 {
+ leaf name_of_the_leaf20 {
+ type string;
+ }
+ leaf-list name_of_the_ll8 {
+ type string;
+ }
+ container name_of_the_cont11 {
+ choice name_of_the_ch3 {
+ case name_of_the_c1 {
+ leaf name_of_the_leaf25 {
+ type string;
+ }
+ uses name_of_the_g1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ grouping name_of_the_g1 {
+ container name_of_the_cont13 {
+ container name_of_the_cont12 {
+ leaf name_of_the_leaf26 {
+ type string;
+ }
+ }
+ list name_of_the_list9 {
+ leaf name_of_the_leaf27 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf28 {
+ type string;
+ }
+ leaf-list name_of_the_ll9 {
+ type string;
+ }
+ }
+ }
+
+ uses name_of_the_g1;
+
+ rpc name_of_the_create-sfc {
+ input {
+ container name_of_the_cont14 {
+ leaf name_of_the_leaf28 {
+ type string;
+ }
+ }
+ list name_of_the_list10 {
+ leaf name_of_the_leaf29 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf30 {
+ type string;
+ }
+ leaf-list name_of_the_ll10 {
+ type string;
+ }
+ choice name_of_the_ch3 {
+ case name_of_the_c1 {
+ container name_of_the_cont15 {
+ leaf name_of_the_leaf31 {
+ type string;
+ }
+ }
+ }
+ }
+ uses name_of_the_g1;
+ }
+ output {
+ container name_of_the_cont16 {
+ leaf name_of_the_leaf32 {
+ type string;
+ }
+ }
+ list name_of_the_list11 {
+ leaf name_of_the_leaf33 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf34 {
+ type string;
+ }
+ leaf-list name_of_the_ll11 {
+ type string;
+ }
+ choice name_of_the_ch4 {
+ case name_of_the_c1 {
+ container name_of_the_cont17 {
+ leaf name_of_the_leaf35 {
+ type string;
+ }
+ }
+ }
+ }
+ uses name_of_the_g1;
+ }
+ }
+
+ container name_of_the_cont18 {
+ container name_of_the_cont18 {
+ list name_of_the_list12 {
+ list name_of_the_list12 {
+ leaf name_of_the_leaf36 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf36 {
+ type string;
+ }
+ }
+ }
+ leaf name_of_the_leaf40 {
+ type string;
+ }
+ }
+} \ No newline at end of file