[ONOS-5769] Implement encodeYdtToCompositeProtocolFormat() for JSON codec
Change-Id: Ifb68a25ae6bc3ba10e7d983d694b132a23785890
diff --git a/protocols/restconf/client/ctl/BUCK b/protocols/restconf/client/ctl/BUCK
index 0a78565..445e4b8b 100644
--- a/protocols/restconf/client/ctl/BUCK
+++ b/protocols/restconf/client/ctl/BUCK
@@ -13,6 +13,7 @@
'//protocols/rest/api:onos-protocols-rest-api',
'//apps/yms/api:onos-apps-yms-api',
'//protocols/restconf/server/utils:onos-protocols-restconf-server-utils',
+ '//providers/ietfte/utils:onos-providers-ietfte-utils',
]
osgi_jar_with_tests (
diff --git a/protocols/restconf/client/ctl/pom.xml b/protocols/restconf/client/ctl/pom.xml
index 32d2681..f4912b3 100644
--- a/protocols/restconf/client/ctl/pom.xml
+++ b/protocols/restconf/client/ctl/pom.xml
@@ -78,6 +78,12 @@
<version>${project.version}</version>
<type>bundle</type>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-ietfte-provider-utils</artifactId>
+ <version>${project.version}</version>
+ <type>bundle</type>
+ </dependency>
</dependencies>
<build>
diff --git a/protocols/restconf/client/ctl/src/main/java/org/onosproject/protocol/restconf/ctl/JsonYdtCodec.java b/protocols/restconf/client/ctl/src/main/java/org/onosproject/protocol/restconf/ctl/JsonYdtCodec.java
index dfb7294..6fda6cd 100644
--- a/protocols/restconf/client/ctl/src/main/java/org/onosproject/protocol/restconf/ctl/JsonYdtCodec.java
+++ b/protocols/restconf/client/ctl/src/main/java/org/onosproject/protocol/restconf/ctl/JsonYdtCodec.java
@@ -19,9 +19,12 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.io.IOUtils;
import org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils;
+import org.onosproject.provider.te.utils.YangCompositeEncodingImpl;
import org.onosproject.yms.ych.YangCompositeEncoding;
import org.onosproject.yms.ych.YangDataTreeCodec;
+import org.onosproject.yms.ych.YangResourceIdentifierType;
import org.onosproject.yms.ydt.YdtBuilder;
+import org.onosproject.yms.ydt.YdtContext;
import org.onosproject.yms.ydt.YmsOperationType;
import org.onosproject.yms.ymsm.YmsService;
import org.slf4j.Logger;
@@ -30,6 +33,10 @@
import java.io.IOException;
import java.io.InputStream;
+import static org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils.convertYdtToJson;
+import static org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils.findTopNodeInCompositeYdt;
+import static org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils.getJsonNameFromYdtNode;
+import static org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils.getUriInCompositeYdt;
import static org.onosproject.yms.ydt.YdtContextOperationType.NONE;
@@ -38,6 +45,7 @@
*/
public class JsonYdtCodec implements YangDataTreeCodec {
private static final String RESTCONF_ROOT = "restconf/data";
+ private static final String EMPTY_JSON_OBJECT = "{}";
protected final YmsService ymsService;
@@ -48,23 +56,28 @@
}
@Override
- public String encodeYdtToProtocolFormat(YdtBuilder ydtBuilder) {
- String json = ParserUtils.convertYdtToJson(ydtBuilder.getRootNode().getName(),
- ydtBuilder.getRootNode(),
- ymsService.getYdtWalker())
- .textValue();
- return json;
+ public String encodeYdtToProtocolFormat(YdtBuilder builder) {
+ return convertYdtToJson(getJsonNameFromYdtNode(builder.getRootNode()),
+ builder.getRootNode(),
+ ymsService.getYdtWalker()).textValue();
}
@Override
- public YangCompositeEncoding encodeYdtToCompositeProtocolFormat(YdtBuilder ydtBuilder) {
- // Mainly for POST/PUT operation.
- // YdtBuilder/YdtContext has YdtContextType NONE for URI,
- // YdtContextType CREATE/MERGE/REPLACE for Resource data.
+ public YangCompositeEncoding encodeYdtToCompositeProtocolFormat(YdtBuilder builder) {
+ String uriString = getUriInCompositeYdt(builder);
+ YdtContext topNode = findTopNodeInCompositeYdt(builder);
+ if (topNode != null) {
+ ObjectNode objectNode = convertYdtToJson(getJsonNameFromYdtNode(topNode),
+ topNode,
+ ymsService.getYdtWalker());
+ return new YangCompositeEncodingImpl(YangResourceIdentifierType.URI,
+ uriString,
+ objectNode.toString());
+ }
- // TODO: Implement this method in Release Ibis for TE Tunnel.
-
- return null;
+ return new YangCompositeEncodingImpl(YangResourceIdentifierType.URI,
+ uriString,
+ EMPTY_JSON_OBJECT);
}
@Override
diff --git a/protocols/restconf/server/utils/BUCK b/protocols/restconf/server/utils/BUCK
index d1410c0..dde27c3 100644
--- a/protocols/restconf/server/utils/BUCK
+++ b/protocols/restconf/server/utils/BUCK
@@ -1,6 +1,7 @@
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//apps/yms/api:onos-apps-yms-api',
+ '//apps/yms/app:onos-apps-yms-app',
]
osgi_jar_with_tests (
diff --git a/protocols/restconf/server/utils/pom.xml b/protocols/restconf/server/utils/pom.xml
index daed4ac..b94c198 100644
--- a/protocols/restconf/server/utils/pom.xml
+++ b/protocols/restconf/server/utils/pom.xml
@@ -18,10 +18,15 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-yms</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/DefaultJsonBuilder.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/DefaultJsonBuilder.java
index 654fff9..90a28b2 100644
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/DefaultJsonBuilder.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/DefaultJsonBuilder.java
@@ -144,7 +144,7 @@
case NUMBER:
case POJO:
case STRING:
- log.debug("Unimplemented node type {}", nodeType);
+ log.trace("Unimplemented node type {}", nodeType);
break;
default:
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java
index cf4e690..0ba2da0 100755
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/JsonToYdtListener.java
@@ -100,7 +100,7 @@
case MISSING:
case NULL:
case POJO:
- log.debug("Unimplemented node type {}", nodeType);
+ log.trace("Unimplemented node type {}", nodeType);
break;
default:
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java
index d02ee97..87a3d51 100644
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/ParserUtils.java
@@ -22,6 +22,8 @@
import org.onosproject.protocol.restconf.server.utils.exceptions.JsonParseException;
import org.onosproject.protocol.restconf.server.utils.parser.api.JsonBuilder;
import org.onosproject.protocol.restconf.server.utils.parser.api.NormalizedYangNode;
+import org.onosproject.yms.app.ydt.YdtExtendedContext;
+import org.onosproject.yms.app.ydt.YdtSingleInstanceLeafNode;
import org.onosproject.yms.ydt.YdtBuilder;
import org.onosproject.yms.ydt.YdtContext;
import org.onosproject.yms.ydt.YdtContextOperationType;
@@ -47,6 +49,7 @@
private static final String EQUAL = "=";
private static final String COMMA = ",";
private static final String COLON = ":";
+ private static final String SLASH = "/";
private static final String URI_ENCODING_CHAR_SET = "ISO-8859-1";
private static final String ERROR_LIST_MSG = "List/Leaf-list node should be " +
"in format \"nodeName=key\"or \"nodeName=instance-value\"";
@@ -393,4 +396,187 @@
return moduleName;
}
+
+ /**
+ * Extracts the URI from the given YANG Data Tree (YDT). The URI is
+ * presented in string format. If no URI is found in the YDT, an
+ * empty string is returned.
+ *
+ * @param ydtBuilder the YDT from which the URI is extracted
+ * @return URI
+ */
+ public static String getUriInCompositeYdt(YdtBuilder ydtBuilder) {
+ checkNotNull(ydtBuilder, "ydt cannot be null");
+
+ StringBuilder uriBuilder = new StringBuilder();
+ YdtContext ydtNode = ydtBuilder.getRootNode().getFirstChild();
+ String currModuleName = null;
+
+ boolean isLastNodeInUri = false;
+ int levelNum = 0;
+ while (((YdtExtendedContext) ydtNode).getYdtContextOperationType() == NONE ||
+ isLastNodeInUri) {
+ currModuleName = addNodeToUri(ydtNode, currModuleName,
+ levelNum, uriBuilder);
+
+ if (ydtNode.getYdtType() == YdtType.MULTI_INSTANCE_NODE) {
+ if (isLastNodeInUri) {
+ addKeyNodeToUri(ydtNode, uriBuilder);
+ break;
+ }
+
+ YdtContext firstChild = ydtNode.getFirstChild();
+ YdtContext lastChild = ydtNode.getLastChild();
+ if ((firstChild.getYdtType() == YdtType.SINGLE_INSTANCE_LEAF_VALUE_NODE) &&
+ ((YdtSingleInstanceLeafNode) firstChild).isKeyLeaf()) {
+ currModuleName = addNodeToUri(firstChild,
+ currModuleName,
+ levelNum,
+ uriBuilder);
+ ydtNode = lastChild;
+ } else {
+ currModuleName = addNodeToUri(lastChild,
+ currModuleName,
+ levelNum,
+ uriBuilder);
+ ydtNode = firstChild;
+ }
+ } else {
+ ydtNode = ydtNode.getFirstChild();
+ }
+
+ if (isLastNodeInUri) {
+ break;
+ }
+
+ if (((YdtExtendedContext) ydtNode).getYdtContextOperationType() != NONE) {
+ isLastNodeInUri = true;
+ }
+
+ levelNum++;
+ }
+
+ return uriBuilder.toString();
+ }
+
+ /**
+ * Finds the key leaf node from the given multi-instance YDT node and
+ * appends the key value to the given URI string.
+ * <p>
+ * If no key leaf node is found, then the given URI is unchanged.
+ *
+ * @param ydtNode YDT node under which the key leaf node is found
+ * @param uriBuilder URI
+ */
+ private static void addKeyNodeToUri(YdtContext ydtNode,
+ StringBuilder uriBuilder) {
+ YdtContext child = ydtNode.getFirstChild();
+
+ while (child != null) {
+ if (child.getYdtType() == YdtType.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
+ if (((YdtSingleInstanceLeafNode) child).isKeyLeaf()) {
+ uriBuilder.append(EQUAL).append(ydtNode.getValue());
+ break;
+ }
+ }
+ child = child.getNextSibling();
+ }
+ }
+
+ /**
+ * Extracts the path segment from a given YANG Data Tree (YDT) node and
+ * appends it to the given URI string.
+ *
+ * @param ydtNode YDT node from which the URI segment is extracted
+ * @param currModuleName current YANG module name in URI
+ * @param ydtNodeDepth depth of the YDT node's position in the tree
+ * @param uriBuilder URI to which the URI segment appends
+ * @return YANG module name extracted from the YDT node
+ */
+ private static String addNodeToUri(YdtContext ydtNode,
+ String currModuleName,
+ int ydtNodeDepth,
+ StringBuilder uriBuilder) {
+ YdtType nodeType = ydtNode.getYdtType();
+
+ /*
+ * The given YDT node is the root of the YDT. Only the module name
+ * needs to be extracted and added to URI.
+ */
+ if (ydtNodeDepth == 0) {
+ String moduleName = ydtNode.getModuleNameAsNameSpace();
+ uriBuilder.append(moduleName);
+ return moduleName;
+ }
+
+ if (ydtNodeDepth == 1) {
+ String moduleName = ydtNode.getModuleNameAsNameSpace();
+ uriBuilder.append(COLON);
+ uriBuilder.append(ydtNode.getName());
+ return moduleName;
+ }
+
+ if (nodeType == YdtType.SINGLE_INSTANCE_LEAF_VALUE_NODE &&
+ ((YdtSingleInstanceLeafNode) ydtNode).isKeyLeaf()) {
+ uriBuilder.append(EQUAL).append(ydtNode.getValue());
+ return currModuleName;
+ } else {
+ uriBuilder.append(SLASH);
+ }
+
+ String moduleName = ydtNode.getModuleNameAsNameSpace();
+
+ if (currModuleName == null || !currModuleName.equals(moduleName)) {
+ uriBuilder.append(moduleName).append(COLON);
+ }
+
+ uriBuilder.append(ydtNode.getName());
+
+ return moduleName;
+ }
+
+ /**
+ * Retrieves the top data node of the subtree from the given composite
+ * YANG Data Tree (YDT) which contains both the URI path and the data
+ * subtree to which the URI points.
+ * <p>
+ * A null is returned if no data subtree is found.
+ *
+ * @param ydtBuilder the given YDT
+ * @return the top data node of the data subtree.
+ */
+ public static YdtContext findTopNodeInCompositeYdt(YdtBuilder ydtBuilder) {
+ checkNotNull(ydtBuilder, "ydt cannot be null");
+
+ YdtContext ydtNode = ydtBuilder.getRootNode().getFirstChild();
+ YdtContextOperationType opType = ((YdtExtendedContext) ydtNode).getYdtContextOperationType();
+ while (opType == NONE) {
+ if (ydtNode.getYdtType() == YdtType.MULTI_INSTANCE_NODE) {
+ YdtContext firstChild = ydtNode.getFirstChild();
+ YdtContext lastChild = ydtNode.getLastChild();
+ if (firstChild.getYdtType() == YdtType.SINGLE_INSTANCE_LEAF_VALUE_NODE &&
+ ((YdtSingleInstanceLeafNode) firstChild).isKeyLeaf()) {
+ ydtNode = lastChild;
+ } else {
+ ydtNode = firstChild;
+ }
+ } else {
+ ydtNode = ydtNode.getFirstChild();
+ }
+
+ if (((YdtExtendedContext) ydtNode).getYdtContextOperationType() != NONE) {
+ // We found last node
+ break;
+ }
+
+ if (ydtNode == null) {
+ // There is no more node to find in YDT
+ return null;
+ }
+
+ opType = ((YdtExtendedContext) ydtNode).getYdtContextOperationType();
+ }
+
+ return ydtNode;
+ }
}
diff --git a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java
index eeee124..9479d97 100644
--- a/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java
+++ b/protocols/restconf/server/utils/src/main/java/org/onosproject/protocol/restconf/server/utils/parser/json/YdtToJsonListener.java
@@ -81,6 +81,8 @@
case MULTI_INSTANCE_LEAF_VALUE_NODE:
jsonBuilder.addNodeWithSetTopHalf(name, ydtContext.getValueSet());
break;
+ case LOGICAL_ROOT_NODE:
+ break;
default:
throw new YdtParseException("unknown Ydt type " +
ydtContext.getYdtType());
@@ -116,6 +118,8 @@
case MULTI_INSTANCE_LEAF_VALUE_NODE:
jsonBuilder.addNodeBottomHalf(JsonNodeType.ARRAY);
break;
+ case LOGICAL_ROOT_NODE:
+ break;
default:
throw new YdtParseException("Unknown Ydt type " +
ydtContext.getYdtType());