X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frestconf%2Fimpl%2FControllerContext.xtend;h=f1d412cdb0082960aa02f93dcffbc3b5ba0ca6e3;hb=c05e8241fcef668a8d2fe00776839df56187a401;hp=d8a03e5d4fbf65c813df8576cde6e1bdc9e02efe;hpb=1c70f484cd268220d9df91d7c6377a5fdc89cd4f;p=controller.git diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend index d8a03e5d4f..f1d412cdb0 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend @@ -8,9 +8,11 @@ package org.opendaylight.controller.sal.restconf.impl import com.google.common.base.Preconditions +import com.google.common.base.Splitter import com.google.common.collect.BiMap import com.google.common.collect.FluentIterable import com.google.common.collect.HashBiMap +import com.google.common.collect.Lists import java.net.URI import java.net.URLDecoder import java.net.URLEncoder @@ -55,6 +57,8 @@ class ControllerContext implements SchemaServiceListener { val static MOUNT_MODULE = "yang-ext" val static MOUNT_NODE = "mount" public val static MOUNT = "yang-ext:mount" + val static URI_ENCODING_CHAR_SET = "ISO-8859-1" + val static URI_SLASH_PLACEHOLDER = "%2F"; @Property var SchemaContext globalSchema; @@ -96,13 +100,12 @@ class ControllerContext implements SchemaServiceListener { private def InstanceIdWithSchemaNode toIdentifier(String restconfInstance, boolean toMountPointIdentifier) { checkPreconditions - val pathArgs = restconfInstance.split("/"); + val encodedPathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance)) + val pathArgs = urlPathArgsDecode(encodedPathArgs) + pathArgs.omitFirstAndLastEmptyString if (pathArgs.empty) { return null; } - if (pathArgs.head.empty) { - pathArgs.remove(0) - } val startModule = pathArgs.head.toModuleName(); if (startModule === null) { throw new ResponseException(BAD_REQUEST, "First node in URI has to be in format \"moduleName:nodeName\"") @@ -121,6 +124,22 @@ class ControllerContext implements SchemaServiceListener { return iiWithSchemaNode } + private def omitFirstAndLastEmptyString(List list) { + if (list.empty) { + return list; + } + if (list.head.empty) { + list.remove(0) + } + if (list.empty) { + return list; + } + if (list.last.empty) { + list.remove(list.indexOf(list.last)) + } + return list; + } + private def getLatestModule(SchemaContext schema, String moduleName) { checkArgument(schema !== null); checkArgument(moduleName !== null && !moduleName.empty) @@ -176,31 +195,51 @@ class ControllerContext implements SchemaServiceListener { return mountPoint.schemaContext?.findModuleByName(module.localName, module.revision) } + def getDataNodeContainerFor(InstanceIdentifier path) { + checkPreconditions + val elements = path.path; + val startQName = elements.head.nodeType; + val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision) + var node = initialModule as DataNodeContainer; + for (element : elements) { + val potentialNode = node.childByQName(element.nodeType); + if (potentialNode === null || !potentialNode.listOrContainer) { + return null + } + node = potentialNode as DataNodeContainer + } + return node + } + def String toFullRestconfIdentifier(InstanceIdentifier path) { checkPreconditions val elements = path.path; val ret = new StringBuilder(); - val startQName = elements.get(0).nodeType; + val startQName = elements.head.nodeType; val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision) - var node = initialModule as DataSchemaNode; + var node = initialModule as DataNodeContainer; for (element : elements) { - node = node.childByQName(element.nodeType); - ret.append(element.toRestconfIdentifier(node)); + val potentialNode = node.childByQName(element.nodeType); + if (!potentialNode.listOrContainer) { + return null + } + node = potentialNode as DataNodeContainer + ret.append(element.convertToRestconfIdentifier(node)); } return ret.toString } - private def dispatch CharSequence toRestconfIdentifier(NodeIdentifier argument, DataSchemaNode node) { + private def dispatch CharSequence convertToRestconfIdentifier(NodeIdentifier argument, ContainerSchemaNode node) { '''/«argument.nodeType.toRestconfIdentifier()»''' } - private def dispatch CharSequence toRestconfIdentifier(NodeIdentifierWithPredicates argument, ListSchemaNode node) { + private def dispatch CharSequence convertToRestconfIdentifier(NodeIdentifierWithPredicates argument, ListSchemaNode node) { val nodeIdentifier = argument.nodeType.toRestconfIdentifier(); val keyValues = argument.keyValues; return '''/«nodeIdentifier»/«FOR key : node.keyDefinition SEPARATOR "/"»«keyValues.get(key).toUriString»«ENDFOR»''' } - private def dispatch CharSequence toRestconfIdentifier(PathArgument argument, DataSchemaNode node) { + private def dispatch CharSequence convertToRestconfIdentifier(PathArgument argument, DataNodeContainer node) { throw new IllegalArgumentException("Conversion of generic path argument is not supported"); } @@ -289,6 +328,10 @@ class ControllerContext implements SchemaServiceListener { return container.dataNodeChildByQName(name); } + private static dispatch def DataSchemaNode childByQName(Module container, QName name) { + return container.dataNodeChildByQName(name); + } + private static dispatch def DataSchemaNode childByQName(DataSchemaNode container, QName name) { return null; } @@ -313,7 +356,8 @@ class ControllerContext implements SchemaServiceListener { private def toUriString(Object object) { if(object === null) return ""; - return URLEncoder.encode(object.toString) +// return object.toString.replace("/",URI_SLASH_PLACEHOLDER) + return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET) } private def InstanceIdWithSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List strings, @@ -415,7 +459,7 @@ class ControllerContext implements SchemaServiceListener { } } - if (!(targetNode instanceof ListSchemaNode) && !(targetNode instanceof ContainerSchemaNode)) { + if (!targetNode.isListOrContainer) { throw new ResponseException(BAD_REQUEST,"URI has bad format. Node \"" + strings.head + "\" must be Container or List yang type.") } // Number of consumed elements @@ -538,14 +582,24 @@ class ControllerContext implements SchemaServiceListener { private def QName toQName(String name) { val module = name.toModuleName; val node = name.toNodeName; - val namespace = FluentIterable.from(globalSchema.modules.sort[o1,o2 | o1.revision.compareTo(o2.revision)]) // + val namespace = FluentIterable.from(globalSchema.modules.sort[o1,o2 | o1.revision.compareTo(o2.revision)]) .transform[QName.create(namespace,revision,it.name)].findFirst[module == localName] - ; - return QName.create(namespace,node); + if (namespace === null) { + return null + } + return QName.create(namespace, node); + } + + private def boolean isListOrContainer(DataSchemaNode node) { + return ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) } def getRpcDefinition(String name) { - return qnameToRpc.get(name.toQName) + val validName = name.toQName + if (validName === null) { + return null + } + return qnameToRpc.get(validName) } override onGlobalContextUpdated(SchemaContext context) { @@ -556,4 +610,13 @@ class ControllerContext implements SchemaServiceListener { } } + + def urlPathArgsDecode(List strings) { + val List decodedPathArgs = new ArrayList(); + for (pathArg : strings) { + decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET)) + } + return decodedPathArgs + } + }