X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frestconf%2Fimpl%2FControllerContext.xtend;h=c2b0ae8bdbb716580b1197108d0e91168b3d6ef0;hp=daad4cff4f5cd07de7ad38d167668429eae01c7b;hb=f062dc05cc7caaf0c1811856370f1c9e2f1e5c34;hpb=ce23509536c00cb2649c36b4b64ac261946445a1 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 daad4cff4f..c2b0ae8bdb 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 @@ -1,51 +1,110 @@ package org.opendaylight.controller.sal.restconf.impl -import org.opendaylight.yangtools.yang.model.api.SchemaContext -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates +import com.google.common.collect.BiMap +import com.google.common.collect.HashBiMap import java.net.URI -import java.util.Map +import java.net.URLDecoder +import java.net.URLEncoder import java.util.HashMap +import java.util.List +import java.util.Map +import java.util.concurrent.ConcurrentHashMap +import javax.ws.rs.WebApplicationException +import javax.ws.rs.core.Response +import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener +import org.opendaylight.controller.sal.rest.impl.RestconfProvider import org.opendaylight.yangtools.yang.common.QName -import org.opendaylight.yangtools.yang.model.api.ChoiceNode -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode +import org.opendaylight.yangtools.yang.model.api.ChoiceNode import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode -import org.opendaylight.yangtools.yang.model.api.ListSchemaNode - -import java.net.URLEncoder import org.opendaylight.yangtools.yang.model.api.DataNodeContainer -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder -import java.util.List -import static com.google.common.base.Preconditions.*; -import com.google.common.collect.Collections2 -import com.google.common.collect.BiMap -import com.google.common.collect.HashBiMap +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode -import java.net.URLDecoder +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.model.api.RpcDefinition +import org.opendaylight.yangtools.yang.model.api.SchemaContext + +import static com.google.common.base.Preconditions.* + +class ControllerContext implements SchemaServiceListener { + + val static ControllerContext INSTANCE = new ControllerContext -class ControllerContext { + val static NULL_VALUE = "null" @Property SchemaContext schemas; private val BiMap uriToModuleName = HashBiMap.create(); private val Map moduleNameToUri = uriToModuleName.inverse(); + private val Map qnameToRpc = new ConcurrentHashMap(); + + + private new() { + if (INSTANCE !== null) { + throw new IllegalStateException("Already instantiated"); + } + } - public def InstanceIdentifier toInstanceIdentifier(String restconfInstance) { + static def getInstance() { + return INSTANCE + } + + private def void checkPreconditions() { + if (schemas === null) { + throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE) + .entity(RestconfProvider::NOT_INITALIZED_MSG).build()) + } + } + + public def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) { val ret = InstanceIdentifier.builder(); val pathArgs = restconfInstance.split("/"); - val first = pathArgs.get(0); - val startModule = first.toModuleName(); - val module = schemas.findModuleByNamespace(moduleNameToUri.get(startModule)); - checkArgument(module.size == 1); // Only one version supported now - ret.collectPathArguments(pathArgs, module.iterator.next); - return ret.toInstance + if (pathArgs.empty) { + return null; + } + if (pathArgs.head.empty) { + pathArgs.remove(0) + } + val schemaNode = ret.collectPathArguments(pathArgs, restconfInstance.findModule); + if (schemaNode === null) { + return null + } + new InstanceIdWithSchemaNode(ret.toInstance, schemaNode) + } + + private def findModule(String restconfInstance) { + checkPreconditions + checkNotNull(restconfInstance); + val pathArgs = restconfInstance.split("/"); + if (pathArgs.empty) { + return null; + } + val modulWithFirstYangStatement = pathArgs.filter[s|s.contains(":")].head + val startModule = modulWithFirstYangStatement.toModuleName(); + schemas.getLatestModule(startModule) + } + + private def getLatestModule(SchemaContext schema, String moduleName) { + checkNotNull(schema) + checkArgument(moduleName !== null && !moduleName.empty) + val modules = schema.modules.filter[m|m.name == moduleName] + var latestModule = modules.head + for (module : modules) { + if (module.revision.after(latestModule.revision)) { + latestModule = module + } + } + return latestModule } def String toFullRestconfIdentifier(InstanceIdentifier path) { + checkPreconditions val elements = path.path; val ret = new StringBuilder(); val startQName = elements.get(0).nodeType; @@ -72,11 +131,12 @@ class ControllerContext { throw new IllegalArgumentException("Conversion of generic path argument is not supported"); } - public def CharSequence toRestconfIdentifier(QName qname) { + def CharSequence toRestconfIdentifier(QName qname) { + checkPreconditions var module = uriToModuleName.get(qname.namespace) - if (module == null) { + if (module === null) { val moduleSchema = schemas.findModuleByNamespaceAndRevision(qname.namespace, qname.revision); - if(moduleSchema == null) throw new IllegalArgumentException() + if(moduleSchema === null) throw new IllegalArgumentException() uriToModuleName.put(qname.namespace, moduleSchema.name) module = moduleSchema.name; } @@ -129,38 +189,58 @@ class ControllerContext { } private def toUriString(Object object) { - if(object == null) return ""; + if(object === null) return ""; return URLEncoder.encode(object.toString) } - def void collectPathArguments(InstanceIdentifierBuilder builder, List strings, DataNodeContainer parentNode) { + private def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List strings, + DataNodeContainer parentNode) { checkNotNull(strings) - if (strings.length == 0) { - return; + if (strings.empty) { + return parentNode as DataSchemaNode; } - val nodeRef = strings.get(0); + val nodeRef = strings.head; - //val moduleName = nodeRef.toModuleName(); val nodeName = nodeRef.toNodeName(); - val naiveTargetNode = parentNode.getDataChildByName(nodeName); - - //var URI namespace; - var DataSchemaNode targetNode = naiveTargetNode; + val targetNode = parentNode.getDataChildByName(nodeName); + if (targetNode === null) { + val children = parentNode.childNodes + for (child : children) { + if (child instanceof ChoiceNode) { + val choice = child as ChoiceNode + for (caze : choice.cases) { + val result = builder.collectPathArguments(strings, caze as DataNodeContainer); + if (result !== null) + return result + } + } + } + return null + } + if (targetNode instanceof ChoiceNode) { + return null + } - /*if(moduleName !== null) { - namespace = moduleNameToUri.get(moduleName); - - }*/ // Number of consumed elements var consumed = 1; if (targetNode instanceof ListSchemaNode) { val listNode = targetNode as ListSchemaNode; val keysSize = listNode.keyDefinition.size - val uriKeyValues = strings.subList(1, keysSize); + + // every key has to be filled + if ((strings.length - consumed) < keysSize) { + return null; + } + val uriKeyValues = strings.subList(consumed, consumed + keysSize); val keyValues = new HashMap(); var i = 0; for (key : listNode.keyDefinition) { val uriKeyValue = uriKeyValues.get(i); + + // key value cannot be NULL + if (uriKeyValue.equals(NULL_VALUE)) { + return null + } keyValues.addKeyValue(listNode.getDataChildByName(key), uriKeyValue); i = i + 1; } @@ -172,12 +252,15 @@ class ControllerContext { builder.node(targetNode.QName); } if (targetNode instanceof DataNodeContainer) { - val remaining = strings.subList(consumed, strings.length - 1); - builder.collectPathArguments(remaining, targetNode as DataNodeContainer); + val remaining = strings.subList(consumed, strings.length); + val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer); + return result } + + return targetNode } - def void addKeyValue(HashMap map, DataSchemaNode node, String uriValue) { + private def void addKeyValue(HashMap map, DataSchemaNode node, String uriValue) { checkNotNull(uriValue); checkArgument(node instanceof LeafSchemaNode); val decoded = URLDecoder.decode(uriValue); @@ -185,7 +268,8 @@ class ControllerContext { } - def String toModuleName(String str) { + private def String toModuleName(String str) { + checkNotNull(str) if (str.contains(":")) { val args = str.split(":"); checkArgument(args.size === 2); @@ -195,7 +279,7 @@ class ControllerContext { } } - def String toNodeName(String str) { + private def String toNodeName(String str) { if (str.contains(":")) { val args = str.split(":"); checkArgument(args.size === 2); @@ -204,9 +288,28 @@ class ControllerContext { return str; } } + + public def QName toQName(String name) { + val module = name.toModuleName; + val node = name.toNodeName; + val namespace = moduleNameToUri.get(module); + return new QName(namespace,null,node); + } + + override onGlobalContextUpdated(SchemaContext context) { + this.schemas = context; + for(operation : context.operations) { + val qname = new QName(operation.QName.namespace,null,operation.QName.localName); + qnameToRpc.put(qname,operation); + } + } + + def ContainerSchemaNode getRpcOutputSchema(QName name) { + qnameToRpc.get(name)?.output; + } - public def QName toRpcQName(String name) { - - + def ContainerSchemaNode getRpcInputSchema(QName name) { + qnameToRpc.get(name)?.input; } + }