import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public interface MountInstance extends NotificationService, DataBrokerService {
Future<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input);
+
+ SchemaContext getSchemaContext();
}
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.controller.sal.core.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public interface MountProvisionInstance extends //
MountInstance,//
RpcProvisionRegistry,//
DataProviderService {
+ void setSchemaContext(SchemaContext optional);
+
}
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.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class MountPointImpl implements MountProvisionInstance {
private final InstanceIdentifier mountPath;
+ private SchemaContext schemaContext;
+
public MountPointImpl(InstanceIdentifier path) {
this.mountPath = path;
rpcs = new RpcRouterImpl("");
// NOOP
}
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ public void setSchemaContext(SchemaContext schemaContext) {
+ this.schemaContext = schemaContext;
+ }
+
class ReadWrapper implements DataReader<InstanceIdentifier, CompositeNode> {
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
SchemaService schemaService = session.getService(SchemaService.class);
listenerRegistration = schemaService.registerSchemaServiceListener(ControllerContext.getInstance());
ControllerContext.getInstance().setSchemas(schemaService.getGlobalContext());
+ ControllerContext.getInstance().setMountService(session.getService(MountService.class));
}
@Override
package org.opendaylight.controller.sal.rest.impl;
-import java.util.Set;
-
import javax.activation.UnsupportedDataTypeException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
-import org.opendaylight.controller.sal.restconf.impl.RestCodec;
-import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-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.data.impl.codec.xml.XmlDocumentUtils;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-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.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.YangNode;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
public class XmlMapper {
-
- private final Logger logger = LoggerFactory.getLogger(XmlMapper.class);
-
public Document write(CompositeNode data, DataNodeContainer schema) throws UnsupportedDataTypeException {
- Preconditions.checkNotNull(data);
- Preconditions.checkNotNull(schema);
-
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- Document doc = null;
- try {
- DocumentBuilder bob = dbf.newDocumentBuilder();
- doc = bob.newDocument();
- } catch (ParserConfigurationException e) {
- return null;
- }
-
- if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
- doc.appendChild(translateToXmlAndReturnRootElement(doc, data, schema));
- return doc;
- } else {
- throw new UnsupportedDataTypeException(
- "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
- }
- }
-
- private Element translateToXmlAndReturnRootElement(Document doc, Node<?> data, YangNode schema)
- throws UnsupportedDataTypeException {
- QName dataType = data.getNodeType();
- Element itemEl = doc.createElementNS(dataType.getNamespace().toString(), dataType.getLocalName());
- if (data instanceof SimpleNode<?>) {
- if (schema instanceof LeafListSchemaNode) {
- writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafListSchemaNode) schema).getType(), (DataSchemaNode) schema);
- } else if (schema instanceof LeafSchemaNode) {
- writeValueOfNodeByType(itemEl, (SimpleNode<?>) data, ((LeafSchemaNode) schema).getType(), (DataSchemaNode) schema);
- } else {
- Object value = data.getValue();
- if (value != null) {
- itemEl.setTextContent(String.valueOf(value));
- }
- }
- } else { // CompositeNode
- for (Node<?> child : ((CompositeNode) data).getChildren()) {
- DataSchemaNode childSchema = null;
- if(schema != null){
- childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
- if (logger.isDebugEnabled()) {
- if (childSchema == null) {
- logger.debug("Probably the data node \"" + ((child == null) ? "" : child.getNodeType().getLocalName())
- + "\" is not conform to schema");
- }
- }
- }
- itemEl.appendChild(translateToXmlAndReturnRootElement(doc, child, childSchema));
- }
- }
- return itemEl;
+ return XmlDocumentUtils.toDocument(data, schema, XmlDocumentUtils.defaultValueCodecProvider());
}
-
- private void writeValueOfNodeByType(Element element, SimpleNode<?> node, TypeDefinition<?> type, DataSchemaNode schema) {
-
- TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
-
- if (baseType instanceof IdentityrefTypeDefinition) {
- if (node.getValue() instanceof QName) {
- IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(type).serialize(node.getValue());
- IdentityValue value = valueDTO.getValuesWithNamespaces().get(0);
- String prefix = "x";
- if (value.getPrefix() != null && !value.getPrefix().isEmpty()) {
- prefix = value.getPrefix();
- }
- element.setAttribute("xmlns:" + prefix, value.getNamespace());
- element.setTextContent(prefix + ":" + value.getValue());
- } else {
- logger.debug("Value of " + baseType.getQName().getNamespace() + ":"
- + baseType.getQName().getLocalName() + " is not instance of " + QName.class + " but is " + node.getValue().getClass());
- element.setTextContent(String.valueOf(node.getValue()));
- }
- } else {
- if (node.getValue() != null) {
- String value = String.valueOf(RestCodec.from(baseType).serialize(node.getValue()));
- if (value.equals("null")) {
- value = String.valueOf(node.getValue());
- }
- element.setTextContent(value);
- }
- }
- }
-
- private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
- if (dataSchemaNode != null && node != null) {
- for (DataSchemaNode dsn : dataSchemaNode) {
- if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
- return dsn;
- } else if (dsn instanceof ChoiceNode) {
- for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
- DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
- if (foundDsn != null) {
- return foundDsn;
- }
- }
- }
- }
- }
- return null;
- }
-
}
import org.slf4j.LoggerFactory
import static com.google.common.base.Preconditions.*
+import org.opendaylight.controller.sal.core.api.mount.MountService
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
class ControllerContext implements SchemaServiceListener {
val static LOG = LoggerFactory.getLogger(ControllerContext)
val static ControllerContext INSTANCE = new ControllerContext
val static NULL_VALUE = "null"
- var SchemaContext schemas;
+ @Property
+ var SchemaContext globalSchema;
+
+ @Property
+ var MountService mountService;
private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
}
private def void checkPreconditions() {
- if (schemas === null) {
+ if (globalSchema === null) {
throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
}
}
if (pathArgs.head.empty) {
pathArgs.remove(0)
}
- val schemaNode = ret.collectPathArguments(pathArgs, restconfInstance.findModule);
+ val schemaNode = ret.collectPathArguments(pathArgs, globalSchema.findModule(pathArgs.head));
if (schemaNode === null) {
return null
}
return 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();
- return getLatestModule(startModule)
+ private static def findModule(SchemaContext context,String argument) {
+ //checkPreconditions
+ checkNotNull(argument);
+ val startModule = argument.toModuleName();
+ return context.getLatestModule(startModule)
}
- def getLatestModule(String moduleName) {
- checkPreconditions
+ static def getLatestModule(SchemaContext schema,String moduleName) {
+ checkArgument(schema != null);
checkArgument(moduleName !== null && !moduleName.empty)
- val modules = schemas.modules.filter[m|m.name == moduleName]
+ val modules = schema.modules.filter[m|m.name == moduleName]
var latestModule = modules.head
for (module : modules) {
if (module.revision.after(latestModule.revision)) {
val elements = path.path;
val ret = new StringBuilder();
val startQName = elements.get(0).nodeType;
- val initialModule = schemas.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision)
+ val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision)
var node = initialModule as DataSchemaNode;
for (element : elements) {
node = node.childByQName(element.nodeType);
checkPreconditions
var module = uriToModuleName.get(namespace)
if (module === null) {
- val moduleSchemas = schemas.findModuleByNamespace(namespace);
+ val moduleSchemas = globalSchema.findModuleByNamespace(namespace);
if(moduleSchemas === null) return null
var latestModule = moduleSchemas.head
for (m : moduleSchemas) {
def findNamespaceByModule(String module) {
var namespace = moduleNameToUri.get(module)
if (namespace === null) {
- val moduleSchemas = schemas.modules.filter[it|it.name.equals(module)]
+ val moduleSchemas = globalSchema.modules.filter[it|it.name.equals(module)]
var latestModule = moduleSchemas.head
for (m : moduleSchemas) {
if (m.revision.after(latestModule.revision)) {
checkPreconditions
var module = uriToModuleName.get(qname.namespace)
if (module === null) {
- val moduleSchema = schemas.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
+ val moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
if(moduleSchema === null) throw new IllegalArgumentException()
uriToModuleName.put(qname.namespace, moduleSchema.name)
module = moduleSchema.name;
}
val nodeRef = strings.head;
- val nodeName = nodeRef.toNodeName();
- 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
- }
- }
- }
+ val nodeName = nodeRef.toNodeName;
+ var targetNode = parentNode.findInstanceDataChild(nodeName);
+ if (targetNode instanceof ChoiceNode) {
return null
}
- if (targetNode instanceof ChoiceNode) {
+
+ if (targetNode === null) {
+ // Node is possibly in other mount point
+ val partialPath = builder.toInstance;
+ val mountPointSchema = mountService?.getMountPoint(partialPath)?.schemaContext;
+ if(mountPointSchema != null) {
+ return builder.collectPathArguments(strings, mountPointSchema.findModule(strings.head));
+ }
return null
}
+
// Number of consumed elements
var consumed = 1;
return targetNode
}
+
+ static def DataSchemaNode findInstanceDataChild(DataNodeContainer container, String name) {
+ // FIXME: Add namespace comparison
+ var potentialNode = container.getDataChildByName(name);
+ if(potentialNode.instantiatedDataSchema) {
+ return potentialNode;
+ }
+ val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten
+ for (caze : allCases) {
+ potentialNode = caze.findInstanceDataChild(name);
+ if(potentialNode != null) {
+ return potentialNode;
+ }
+ }
+ return null;
+ }
+
+ static def boolean isInstantiatedDataSchema(DataSchemaNode node) {
+ switch node {
+ LeafSchemaNode: return true
+ LeafListSchemaNode: return true
+ ContainerSchemaNode: return true
+ ListSchemaNode: return true
+ default: return false
+ }
+ }
private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue) {
checkNotNull(uriValue);
map.put(node.QName, decoded);
}
- private def String toModuleName(String str) {
+ private static def String toModuleName(String str) {
checkNotNull(str)
if (str.contains(":")) {
val args = str.split(":");
private def QName toQName(String name) {
val module = name.toModuleName;
val node = name.toNodeName;
- val namespace = FluentIterable.from(schemas.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);
}
override onGlobalContextUpdated(SchemaContext context) {
- this.schemas = context;
+ this.globalSchema = context;
for (operation : context.operations) {
val qname = operation.QName;
qnameToRpc.put(qname, operation);
import org.junit.BeforeClass;
import org.junit.Test;
+import org.mockito.Mock;
+
+import static org.mockito.Mockito.*;
+
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@BeforeClass
public static void init() throws FileNotFoundException {
- Set<Module> allModules = TestUtils.loadModules(ControllerContextTest.class.getResource("/full-versions/yangs").getPath());
+ Set<Module> allModules = TestUtils.loadModules(ControllerContextTest.class.getResource("/full-versions/yangs")
+ .getPath());
SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
controllerContext.setSchemas(schemaContext);
}
@Test
public void testToInstanceIdentifierList() throws FileNotFoundException {
- InstanceIdWithSchemaNode instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:userWithoutClass/foo");
+ InstanceIdWithSchemaNode instanceIdentifier = controllerContext
+ .toInstanceIdentifier("simple-nodes:userWithoutClass/foo");
assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "userWithoutClass");
instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:userWithoutClass/foo/full-name");
}
+ @Test
+ public void testToInstanceIdentifierMountPoint() throws FileNotFoundException {
+ try {
+ String mountPointPath = "simple-nodes:user/foo/boo";
+ String nestedPath = "simple-nodes:user/foo/boo/simple-nodes:users";
+ InstanceIdWithSchemaNode mountInstanceIdentifier = controllerContext.toInstanceIdentifier(mountPointPath);
+ assertEquals("user", mountInstanceIdentifier.getSchemaNode().getQName().getLocalName());
+
+ MountInstance mountInstance = mock(MountInstance.class);
+ MountService mountService = mock(MountService.class);
+
+ controllerContext.setMountService(mountService);
+ // when(mountService.getMountPoint(any(InstanceIdentifier.class))).thenReturn(null);
+
+ when(mountService.getMountPoint(eq(mountInstanceIdentifier.getInstanceIdentifier()))).thenReturn(
+ mountInstance);
+
+ when(mountInstance.getSchemaContext()).thenReturn(controllerContext.getGlobalSchema());
+
+ InstanceIdWithSchemaNode mountedInstanceIdentifier = controllerContext.toInstanceIdentifier(nestedPath);
+ assertEquals("users", mountedInstanceIdentifier.getSchemaNode().getQName().getLocalName());
+
+ mountedInstanceIdentifier = controllerContext.toInstanceIdentifier(mountPointPath + "/" + mountPointPath);
+ assertEquals("user", mountedInstanceIdentifier.getSchemaNode().getQName().getLocalName());
+
+ mountedInstanceIdentifier = controllerContext
+ .toInstanceIdentifier("simple-nodes:user/foo/var/simple-nodes:users");
+ assertNull(mountedInstanceIdentifier);
+
+ } finally {
+ controllerContext.setMountService(null);
+ }
+
+ }
+
@Test
public void testToInstanceIdentifierContainer() throws FileNotFoundException {
InstanceIdWithSchemaNode instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:users");
assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "users");
assertTrue(instanceIdentifier.getSchemaNode() instanceof ContainerSchemaNode);
- assertEquals(2, ((ContainerSchemaNode)instanceIdentifier.getSchemaNode()).getChildNodes().size());
+ assertEquals(2, ((ContainerSchemaNode) instanceIdentifier.getSchemaNode()).getChildNodes().size());
}
@Test
public void testToInstanceIdentifierChoice() throws FileNotFoundException {
InstanceIdWithSchemaNode instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:food/beer");
assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "beer");
-
+
instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:food/snack");
assertNull(instanceIdentifier);
-
+
instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:food/sports-arena");
assertNull(instanceIdentifier);
-
+
instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:food/snack/sports-arena");
assertNull(instanceIdentifier);
-
+
}
}
public void testReadOperationalData() throws UnsupportedEncodingException, FileNotFoundException {
String uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
+
CompositeNode loadedCompositeNode = TestUtils.loadCompositeNodeWithXmlTreeBuilder("/parts/ietf-interfaces_interfaces.xml");
when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);