package org.opendaylight.controller.sal.restconf.impl
import com.google.common.collect.BiMap
+import com.google.common.collect.FluentIterable
import com.google.common.collect.HashBiMap
import java.net.URI
import java.net.URLDecoder
import java.util.concurrent.ConcurrentHashMap
import javax.ws.rs.core.Response
import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.controller.sal.rest.impl.RestUtil
import org.opendaylight.controller.sal.rest.impl.RestconfProvider
import org.opendaylight.yangtools.yang.common.QName
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
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.data.impl.codec.TypeDefinitionAwareCodec
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 org.opendaylight.yangtools.yang.model.api.RpcDefinition
import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
+import org.slf4j.LoggerFactory
import static com.google.common.base.Preconditions.*
class ControllerContext implements SchemaServiceListener {
-
+ val static LOG = LoggerFactory.getLogger(ControllerContext)
val static ControllerContext INSTANCE = new ControllerContext
-
val static NULL_VALUE = "null"
var SchemaContext schemas;
private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
- private val Map<QName,RpcDefinition> qnameToRpc = new ConcurrentHashMap();
-
+ private val Map<QName, RpcDefinition> qnameToRpc = new ConcurrentHashMap();
private new() {
if (INSTANCE !== null) {
static def getInstance() {
return INSTANCE
}
-
+
private def void checkPreconditions() {
if (schemas === null) {
throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
return getLatestModule(startModule)
}
- private def getLatestModule(String moduleName) {
+ def getLatestModule(String moduleName) {
checkPreconditions
checkArgument(moduleName !== null && !moduleName.empty)
val modules = schemas.modules.filter[m|m.name == moduleName]
private def dispatch CharSequence toRestconfIdentifier(PathArgument argument, DataSchemaNode node) {
throw new IllegalArgumentException("Conversion of generic path argument is not supported");
}
-
+
def findModuleByNamespace(URI namespace) {
checkPreconditions
var module = uriToModuleName.get(namespace)
if (module === null) {
val moduleSchemas = schemas.findModuleByNamespace(namespace);
- if(moduleSchemas === null) throw new IllegalArgumentException()
+ if(moduleSchemas === null) return null
var latestModule = moduleSchemas.head
for (m : moduleSchemas) {
if (m.revision.after(latestModule.revision)) {
latestModule = m
}
}
- if(latestModule === null) throw new IllegalArgumentException()
+ if(latestModule === null) return null
uriToModuleName.put(namespace, latestModule.name)
module = latestModule.name;
}
return module
}
+ def findNamespaceByModule(String module) {
+ var namespace = moduleNameToUri.get(module)
+ if (namespace === null) {
+ val moduleSchemas = schemas.modules.filter[it|it.name.equals(module)]
+ var latestModule = moduleSchemas.head
+ for (m : moduleSchemas) {
+ if (m.revision.after(latestModule.revision)) {
+ latestModule = m
+ }
+ }
+ if(latestModule === null) return null
+ namespace = latestModule.namespace
+ uriToModuleName.put(namespace, latestModule.name)
+ }
+ return namespace
+ }
+
def CharSequence toRestconfIdentifier(QName qname) {
checkPreconditions
var module = uriToModuleName.get(qname.namespace)
private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue) {
checkNotNull(uriValue);
checkArgument(node instanceof LeafSchemaNode);
- val decoded = URLDecoder.decode(uriValue);
+ val urlDecoded = URLDecoder.decode(uriValue);
+ val typedef = (node as LeafSchemaNode).type;
+
+ var decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded)
+ if(decoded === null) {
+ var baseType = RestUtil.resolveBaseTypeFrom(typedef)
+ if(baseType instanceof IdentityrefTypeDefinition) {
+ decoded = toQName(urlDecoded)
+ }
+ }
map.put(node.QName, decoded);
-
}
private def String toModuleName(String str) {
return str;
}
}
-
+
private def QName toQName(String name) {
val module = name.toModuleName;
val node = name.toNodeName;
- val namespace = moduleNameToUri.get(module);
- return new QName(namespace,null,node);
+ val namespace = FluentIterable.from(schemas.modules.sort[o1,o2 | o1.revision.compareTo(o2.revision)]) //
+ .transform[QName.create(namespace,revision,it.name)].findFirst[module == localName]
+ ;
+ return QName.create(namespace,node);
}
-
+
def getRpcDefinition(String name) {
return qnameToRpc.get(name.toQName)
}
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);
+ for (operation : context.operations) {
+ val qname = operation.QName;
+ qnameToRpc.put(qname, operation);
}
}
-
+
}