From: Jakub Toth Date: Mon, 4 Jul 2016 10:47:24 +0000 (+0200) Subject: Bug 5553 - Impl get operations X-Git-Tag: release/carbon~243 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=a8f0f0bc9a3a27bdf012c5321882c96ef7de46f4;p=netconf.git Bug 5553 - Impl get operations *package protected impl of container, leaf and module *fix for new restconf part too Change-Id: I1e3e1eb1a52158278992df871ba6690dd3b7c640 Signed-off-by: Jakub Toth --- diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ContainerSchemaNodeImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ContainerSchemaNodeImpl.java new file mode 100644 index 0000000000..d589f94d3e --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ContainerSchemaNodeImpl.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.restconf.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UsesNode; + +/** + * Special case only use by GET restconf/operations (since moment of pre-Beryllium Yang + * parser and yang model API removal) to build and use fake container for module + */ +class ContainerSchemaNodeImpl implements ContainerSchemaNode { + + List child = new ArrayList<>(); + private final QName qname = QName.create(ModuleImpl.moduleQName, "operations"); + private final SchemaPath path = SchemaPath.create(true, this.qname); + + @Override + public Set> getTypeDefinitions() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Collection getChildNodes() { + return this.child; + } + + @Override + public Set getGroupings() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public DataSchemaNode getDataChildByName(final QName name) { + for (final DataSchemaNode node : this.child) { + if (node.getQName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + this.qname); + } + + @Override + public DataSchemaNode getDataChildByName(final String name) { + for (final DataSchemaNode node : this.child) { + if (node.getQName().getLocalName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + this.qname); + } + + @Override + public Set getUses() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Set getAvailableAugmentations() { + return new HashSet<>(); + } + + @Override + public boolean isAugmenting() { + return false; + } + + @Override + public boolean isAddedByUses() { + return false; + } + + @Override + public boolean isConfiguration() { + return false; + } + + @Override + public ConstraintDefinition getConstraints() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public QName getQName() { + return this.qname; + } + + @Override + public SchemaPath getPath() { + return this.path; + } + + @Override + public List getUnknownSchemaNodes() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getReference() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Status getStatus() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean isPresenceContainer() { + throw new UnsupportedOperationException("Not supported."); + } + + /** + * Adding new schema node to this container + * + * @param fakeLeaf + * - fake schema leaf node + */ + public void addNodeChild(final DataSchemaNode fakeLeaf) { + this.child.add(fakeLeaf); + } +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/LeafSchemaNodeImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/LeafSchemaNodeImpl.java new file mode 100644 index 0000000000..f36b5fc565 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/LeafSchemaNodeImpl.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.restconf.impl; + +import java.util.List; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.util.type.BaseTypes; + +/** + * Special case only use by GET restconf/operations (since moment of old Yang + * parser and old yang model API removal) to build and use fake leaf like child + * in container + * + */ +class LeafSchemaNodeImpl implements LeafSchemaNode { + + private final SchemaPath path; + private final QName qname; + + /** + * Base values for fake leaf schema node + * + * @param basePath + * - schema path + * @param qname + * - qname + */ + LeafSchemaNodeImpl(final SchemaPath basePath, final QName qname) { + this.path = basePath.createChild(qname); + this.qname = qname; + } + + @Override + public boolean isAugmenting() { + return true; + } + + @Override + public boolean isAddedByUses() { + return false; + } + + @Override + public boolean isConfiguration() { + return false; + } + + @Override + public ConstraintDefinition getConstraints() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public QName getQName() { + return this.qname; + } + + @Override + public SchemaPath getPath() { + return this.path; + } + + @Override + public List getUnknownSchemaNodes() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getReference() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Status getStatus() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TypeDefinition getType() { + return BaseTypes.emptyType(); + } + + @Override + public String getDefault() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getUnits() { + throw new UnsupportedOperationException("Not supported."); + } + +} + diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ModuleImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ModuleImpl.java new file mode 100644 index 0000000000..a88917dc9e --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/ModuleImpl.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.restconf.impl; + +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Deviation; +import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition; +import org.opendaylight.yangtools.yang.model.api.FeatureDefinition; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.ModuleImport; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UsesNode; + +/** + * Special case only use by GET restconf/operations (since moment of old Yang + * parser and old yang model API removal) to build and use fake module to create + * new schema context + * + */ +class ModuleImpl implements Module { + + private final List listChild = new ArrayList<>(); + static QNameModule moduleQName; + static { + Date date = null; + try { + date = SimpleDateFormatUtil.getRevisionFormat().parse("2016-06-28"); + } catch (final ParseException e) { + throw new RestconfDocumentedException("Problem while parsing revision.", e); + } + try { + moduleQName = QNameModule.create(new URI("urn:ietf:params:xml:ns:yang:ietf-restconf"), date); + } catch (final URISyntaxException e) { + throw new RestconfDocumentedException("Problem while creating URI.", e); + } + } + + /** + * Set container for this module + * + * @param fakeContSchNode + * - fake container schema node + * + */ + public ModuleImpl(final ContainerSchemaNode fakeContSchNode) { + this.listChild.add(fakeContSchNode); + } + + @Override + public Set> getTypeDefinitions() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Collection getChildNodes() { + return this.listChild; + } + + @Override + public Set getGroupings() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public DataSchemaNode getDataChildByName(final QName name) { + for (final DataSchemaNode node : this.listChild) { + if (node.getQName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + ModuleImpl.moduleQName); + } + + @Override + public DataSchemaNode getDataChildByName(final String name) { + for (final DataSchemaNode node : this.listChild) { + if (node.getQName().getLocalName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + ModuleImpl.moduleQName); + } + + @Override + public Set getUses() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getModuleSourcePath() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public QNameModule getQNameModule() { + return moduleQName; + } + + @Override + public String getName() { + return "ietf-restconf"; + } + + @Override + public URI getNamespace() { + return moduleQName.getNamespace(); + } + + @Override + public Date getRevision() { + return moduleQName.getRevision(); + } + + @Override + public String getPrefix() { + return "restconf"; + } + + @Override + public String getYangVersion() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getReference() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getOrganization() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getContact() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getImports() { + return new HashSet<>(); + } + + @Override + public Set getSubmodules() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getFeatures() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getNotifications() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getAugmentations() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getRpcs() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getDeviations() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getIdentities() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public List getExtensionSchemaNodes() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public List getUnknownSchemaNodes() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getSource() { + throw new UnsupportedOperationException("Not supported operations."); + } + +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java index be2e5edd6e..095df06586 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java @@ -30,6 +30,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -71,6 +72,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; @@ -95,6 +97,7 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -320,9 +323,48 @@ public class RestconfImpl implements RestconfService { return operationsFromModulesToNormalizedContext(modules, mountPoint); } + /** + * Special case only for GET restconf/operations use (since moment of pre-Beryllium + * Yang parser and Yang model API removal). The method is creating fake + * schema context with fake module and fake data by use own implementations + * of schema nodes and module. + * + * @param modules + * - set of modules for get RPCs from every module + * @param mountPoint + * - mount point, if in use otherwise null + * @return {@link NormalizedNodeContext} + */ private NormalizedNodeContext operationsFromModulesToNormalizedContext(final Set modules, final DOMMountPoint mountPoint) { - throw new UnsupportedOperationException(); + + final ContainerSchemaNodeImpl fakeCont = new ContainerSchemaNodeImpl(); + final List> listRpcNodes = new ArrayList<>(); + for (final Module m : modules) { + for (final RpcDefinition rpc : m.getRpcs()) { + + final LeafSchemaNode fakeLeaf = new LeafSchemaNodeImpl(fakeCont.getPath(), + QName.create(ModuleImpl.moduleQName, m.getName() + ":" + rpc.getQName().getLocalName())); + fakeCont.addNodeChild(fakeLeaf); + listRpcNodes.add(Builders.leafBuilder(fakeLeaf).build()); + } + } + final ContainerSchemaNode fakeContSchNode = fakeCont; + final DataContainerNodeAttrBuilder containerBuilder = Builders + .containerBuilder(fakeContSchNode); + + for (final LeafNode rpcNode : listRpcNodes) { + containerBuilder.withChild(rpcNode); + } + + final Module fakeModule = new ModuleImpl(fakeContSchNode); + + final Set fakeModules = new HashSet<>(); + fakeModules.add(fakeModule); + final SchemaContext fakeSchemaCtx = EffectiveSchemaContext.resolveSchemaContext(fakeModules); + final InstanceIdentifierContext instanceIdentifierContext = new InstanceIdentifierContext<>( + null, fakeContSchNode, mountPoint, fakeSchemaCtx); + return new NormalizedNodeContext(instanceIdentifierContext, containerBuilder.build()); } private Module getRestconfModule() { @@ -465,12 +507,6 @@ public class RestconfImpl implements RestconfService { // did not expect any input throw new RestconfDocumentedException("No input expected.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); } - // else - // { - // TODO: Validate "mandatory" and "config" values here??? Or should those be - // those be - // validate in a more central location inside MD-SAL core. - // } } private CheckedFuture invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) { @@ -1173,11 +1209,6 @@ public class RestconfImpl implements RestconfService { return result; } - public BigInteger getOperationalReceived() { - // TODO Auto-generated method stub - return null; - } - private MapNode makeModuleMapNode(final Set modules) { Preconditions.checkNotNull(modules); final Module restconfModule = getRestconfModule(); diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ContainerSchemaNodeImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ContainerSchemaNodeImpl.java new file mode 100644 index 0000000000..cf85579121 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ContainerSchemaNodeImpl.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.restconf.rest.services.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UsesNode; + +/** + * Special case only use by GET restconf/operations (since moment of old Yang + * parser and old yang model API removal) to build and use fake container for + * module + * + */ +class ContainerSchemaNodeImpl implements ContainerSchemaNode { + + List child = new ArrayList<>(); + private final QName qname = QName.create(ModuleImpl.moduleQName, "operations"); + private final SchemaPath path = SchemaPath.create(true, this.qname); + + @Override + public Set> getTypeDefinitions() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Collection getChildNodes() { + return this.child; + } + + @Override + public Set getGroupings() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public DataSchemaNode getDataChildByName(final QName name) { + for (final DataSchemaNode node : this.child) { + if (node.getQName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + this.qname); + } + + @Override + public DataSchemaNode getDataChildByName(final String name) { + for (final DataSchemaNode node : this.child) { + if (node.getQName().getLocalName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + this.qname); + } + + @Override + public Set getUses() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Set getAvailableAugmentations() { + return new HashSet<>(); + } + + @Override + public boolean isAugmenting() { + return false; + } + + @Override + public boolean isAddedByUses() { + return false; + } + + @Override + public boolean isConfiguration() { + return false; + } + + @Override + public ConstraintDefinition getConstraints() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public QName getQName() { + return this.qname; + } + + @Override + public SchemaPath getPath() { + return this.path; + } + + @Override + public List getUnknownSchemaNodes() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getReference() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Status getStatus() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean isPresenceContainer() { + throw new UnsupportedOperationException("Not supported."); + } + + /** + * Adding new schema node to this container + * + * @param fakeLeaf + * - fake schema leaf node + */ + public void addNodeChild(final DataSchemaNode fakeLeaf) { + this.child.add(fakeLeaf); + } +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/LeafSchemaNodeImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/LeafSchemaNodeImpl.java new file mode 100644 index 0000000000..13a3190896 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/LeafSchemaNodeImpl.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.restconf.rest.services.impl; + +import java.util.List; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.Status; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.util.type.BaseTypes; + +/** + * Special case only use by GET restconf/operations (since moment of old Yang + * parser and old yang model API removal) to build and use fake leaf like child + * in container + * + */ +class LeafSchemaNodeImpl implements LeafSchemaNode { + + private final SchemaPath path; + private final QName qname; + + /** + * Base values for fake leaf schema node + * + * @param basePath + * - schema path + * @param qname + * - qname + */ + LeafSchemaNodeImpl(final SchemaPath basePath, final QName qname) { + this.path = basePath.createChild(qname); + this.qname = qname; + } + + @Override + public boolean isAugmenting() { + return true; + } + + @Override + public boolean isAddedByUses() { + return false; + } + + @Override + public boolean isConfiguration() { + return false; + } + + @Override + public ConstraintDefinition getConstraints() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public QName getQName() { + return this.qname; + } + + @Override + public SchemaPath getPath() { + return this.path; + } + + @Override + public List getUnknownSchemaNodes() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getReference() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Status getStatus() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TypeDefinition getType() { + return BaseTypes.emptyType(); + } + + @Override + public String getDefault() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public String getUnits() { + throw new UnsupportedOperationException("Not supported."); + } + +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ModuleImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ModuleImpl.java new file mode 100644 index 0000000000..f66b6e9c72 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/ModuleImpl.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.restconf.rest.services.impl; + +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Deviation; +import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition; +import org.opendaylight.yangtools.yang.model.api.FeatureDefinition; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.ModuleImport; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; +import org.opendaylight.yangtools.yang.model.api.UsesNode; + +/** + * Special case only use by GET restconf/operations (since moment of old Yang + * parser and old yang model API removal) to build and use fake module to create + * new schema context + * + */ +class ModuleImpl implements Module { + + private final List listChild = new ArrayList<>(); + static QNameModule moduleQName; + static { + Date date = null; + try { + date = SimpleDateFormatUtil.getRevisionFormat().parse("2016-06-28"); + } catch (final ParseException e) { + throw new RestconfDocumentedException("Problem while parsing revision.", e); + } + try { + moduleQName = QNameModule.create(new URI("urn:ietf:params:xml:ns:yang:ietf-restconf"), date); + } catch (final URISyntaxException e) { + throw new RestconfDocumentedException("Problem while creating URI.", e); + } + } + + /** + * Set container for this module + * + * @param fakeContSchNode + * - fake container schema node + * + */ + public ModuleImpl(final ContainerSchemaNode fakeContSchNode) { + this.listChild.add(fakeContSchNode); + } + + @Override + public Set> getTypeDefinitions() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Collection getChildNodes() { + return this.listChild; + } + + @Override + public Set getGroupings() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public DataSchemaNode getDataChildByName(final QName name) { + for (final DataSchemaNode node : this.listChild) { + if (node.getQName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + ModuleImpl.moduleQName); + } + + @Override + public DataSchemaNode getDataChildByName(final String name) { + for (final DataSchemaNode node : this.listChild) { + if (node.getQName().getLocalName().equals(name)) { + return node; + } + } + throw new RestconfDocumentedException(name + " is not in child of " + ModuleImpl.moduleQName); + } + + @Override + public Set getUses() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getModuleSourcePath() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public QNameModule getQNameModule() { + return moduleQName; + } + + @Override + public String getName() { + return "ietf-restconf"; + } + + @Override + public URI getNamespace() { + return moduleQName.getNamespace(); + } + + @Override + public Date getRevision() { + return moduleQName.getRevision(); + } + + @Override + public String getPrefix() { + return "restconf"; + } + + @Override + public String getYangVersion() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getDescription() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getReference() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getOrganization() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getContact() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getImports() { + return new HashSet<>(); + } + + @Override + public Set getSubmodules() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getFeatures() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getNotifications() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getAugmentations() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getRpcs() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getDeviations() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public Set getIdentities() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public List getExtensionSchemaNodes() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public List getUnknownSchemaNodes() { + throw new UnsupportedOperationException("Not supported operations."); + } + + @Override + public String getSource() { + throw new UnsupportedOperationException("Not supported operations."); + } + +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceImpl.java index fec4c3f659..bddd086bd7 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceImpl.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceImpl.java @@ -7,13 +7,38 @@ */ package org.opendaylight.restconf.rest.services.impl; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import javax.ws.rs.core.UriInfo; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; +import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; +import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; +import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; +import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; +import org.opendaylight.restconf.common.references.SchemaContextRef; import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler; import org.opendaylight.restconf.handlers.SchemaContextHandler; import org.opendaylight.restconf.rest.services.api.RestconfOperationsService; +import org.opendaylight.restconf.utils.RestconfConstants; +import org.opendaylight.restconf.utils.parser.ParserIdentifier; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Implementation of {@link RestconfOperationsService} @@ -21,6 +46,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; */ public class RestconfOperationsServiceImpl implements RestconfOperationsService { + private static final Logger LOG = LoggerFactory.getLogger(RestconfOperationsServiceImpl.class); + private final SchemaContextHandler schemaContextHandler; private final DOMMountPointServiceHandler domMountPointServiceHandler; @@ -40,13 +67,71 @@ public class RestconfOperationsServiceImpl implements RestconfOperationsService @Override public NormalizedNodeContext getOperations(final UriInfo uriInfo) { - throw new RestconfDocumentedException("Not yet implemented.", new UnsupportedOperationException()); + final SchemaContextRef ref = new SchemaContextRef(this.schemaContextHandler.get()); + return getOperations(ref.getModules(), null); } - @Override public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) { - throw new RestconfDocumentedException("Not yet implemented.", new UnsupportedOperationException()); + Set modules = null; + DOMMountPoint mountPoint = null; + final SchemaContextRef ref = new SchemaContextRef(this.schemaContextHandler.get()); + if (identifier.contains(RestconfConstants.MOUNT)) { + final InstanceIdentifierContext mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(identifier, + ref.get()); + mountPoint = mountPointIdentifier.getMountPoint(); + modules = ref.getModules(mountPoint); + + } else { + final String errMsg = "URI has bad format. If operations behind mount point should be showed, URI has to end with "; + LOG.debug(errMsg + ControllerContext.MOUNT + " for " + identifier); + throw new RestconfDocumentedException(errMsg + ControllerContext.MOUNT, ErrorType.PROTOCOL, + ErrorTag.INVALID_VALUE); + } + + return getOperations(modules, mountPoint); + } + + /** + * Special case only for GET restconf/operations use (since moment of old + * Yang parser and old Yang model API removal). The method is creating fake + * schema context with fake module and fake data by use own implementations + * of schema nodes and module. + * + * @param modules + * - set of modules for get RPCs from every module + * @param mountPoint + * - mount point, if in use otherwise null + * @return {@link NormalizedNodeContext} + */ + private static NormalizedNodeContext getOperations(final Set modules, final DOMMountPoint mountPoint) { + final ContainerSchemaNodeImpl fakeCont = new ContainerSchemaNodeImpl(); + final List> listRpcNodes = new ArrayList<>(); + for (final Module m : modules) { + for (final RpcDefinition rpc : m.getRpcs()) { + + final LeafSchemaNode fakeLeaf = new LeafSchemaNodeImpl(fakeCont.getPath(), + QName.create(ModuleImpl.moduleQName, m.getName() + ":" + rpc.getQName().getLocalName())); + fakeCont.addNodeChild(fakeLeaf); + listRpcNodes.add(Builders.leafBuilder(fakeLeaf).build()); + } + } + final ContainerSchemaNode fakeContSchNode = fakeCont; + final DataContainerNodeAttrBuilder containerBuilder = Builders + .containerBuilder(fakeContSchNode); + + for (final LeafNode rpcNode : listRpcNodes) { + containerBuilder.withChild(rpcNode); + } + + final Module fakeModule = new ModuleImpl(fakeContSchNode); + + final Set fakeModules = new HashSet<>(); + fakeModules.add(fakeModule); + final SchemaContext fakeSchemaCtx = EffectiveSchemaContext.resolveSchemaContext(fakeModules); + final InstanceIdentifierContext instanceIdentifierContext = new InstanceIdentifierContext<>( + null, fakeContSchNode, mountPoint, fakeSchemaCtx); + return new NormalizedNodeContext(instanceIdentifierContext, containerBuilder.build()); } } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceTest.java new file mode 100644 index 0000000000..eea5db5d55 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/rest/services/impl/RestconfOperationsServiceTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.restconf.rest.services.impl; + +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.core.UriInfo; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; +import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler; +import org.opendaylight.restconf.handlers.SchemaContextHandler; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public class RestconfOperationsServiceTest { + + @Mock + private DOMMountPointService domMountPointService; + + @Mock + private UriInfo uriInfo; + + private SchemaContext schemaContext; + private SchemaContextHandler schemaContextHandler; + private DOMMountPointServiceHandler domMountPointServiceHandler; + + private static final List listOfRpcsNames = new ArrayList<>(); + + @Before + public void init() throws Exception { + MockitoAnnotations.initMocks(this); + this.schemaContext = TestRestconfUtils.loadSchemaContext("/modules"); + this.schemaContextHandler = new SchemaContextHandler(); + this.schemaContextHandler.onGlobalContextUpdated(this.schemaContext); + this.domMountPointServiceHandler = new DOMMountPointServiceHandler(this.domMountPointService); + listOfRpcsNames.add("module2:dummy-rpc2-module2"); + listOfRpcsNames.add("module2:dummy-rpc1-module2"); + listOfRpcsNames.add("module1:dummy-rpc2-module1"); + listOfRpcsNames.add("module1:dummy-rpc1-module1"); + } + + @Test + public void getOperationsTest() { + final RestconfOperationsServiceImpl oper = new RestconfOperationsServiceImpl(this.schemaContextHandler, this.domMountPointServiceHandler); + final NormalizedNodeContext operations = oper.getOperations(this.uriInfo); + final ContainerNode data = (ContainerNode) operations.getData(); + Assert.assertTrue( + data.getNodeType().getNamespace().toString().equals("urn:ietf:params:xml:ns:yang:ietf-restconf")); + Assert.assertTrue(data.getNodeType().getLocalName().equals("operations")); + for (final DataContainerChild dataContainerChild : data.getValue()) { + Assert.assertTrue(dataContainerChild.getNodeType().getNamespace().toString() + .equals("urn:ietf:params:xml:ns:yang:ietf-restconf")); + Assert.assertTrue(listOfRpcsNames.contains(dataContainerChild.getNodeType().getLocalName())); + Assert.assertTrue(dataContainerChild.getValue() == null); + } + + } +}