<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
<version>${yang.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-model-util</artifactId>
+ <version>${yang.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
import java.util.Set;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import com.google.common.collect.Lists;
}
} else if (childType.isJsonArray()) {
if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
- parent.addValue(new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), null));
+ parent.addValue(new EmptyNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName)));
} else {
for (JsonElement childOfChildType : childType.getAsJsonArray()) {
import javax.xml.stream.events.XMLEvent;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.yangtools.yang.data.api.Node;
public class XmlReader {
return false;
}
- private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement)
+ private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
throws XMLStreamException {
checkArgument(startElement != null, "Start Element cannot be NULL!");
String data = null;
}
}
}
-
+ if(data == null) {
+ return new EmptyNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
+ }
return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
}
public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
return unwrap().entrySet();
}
-
}
import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
class ControllerContext implements SchemaServiceListener {
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;
+ val decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded)
map.put(node.QName, decoded);
-
}
private def String toModuleName(String str) {
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl;
+
+import java.net.URI;
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+
+import com.google.common.base.Preconditions;
+
+public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void> {
+
+ private Node<?> unwrapped;
+
+ private String localName;
+ private URI namespace;
+ private QName name;
+
+ private boolean composite;
+
+ public boolean isComposite() {
+ return composite;
+ }
+
+ public void setComposite(boolean composite) {
+ this.composite = composite;
+ }
+
+ public EmptyNodeWrapper(URI namespace, String localName) {
+ this.localName = Preconditions.checkNotNull(localName);
+ this.namespace = namespace;
+ }
+
+ @Override
+ public void setQname(QName name) {
+ Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
+ this.name = name;
+ }
+
+ @Override
+ public String getLocalName() {
+ if (unwrapped != null) {
+ return unwrapped.getNodeType().getLocalName();
+ }
+ return localName;
+ }
+
+ @Override
+ public URI getNamespace() {
+ if (unwrapped != null) {
+ return unwrapped.getNodeType().getNamespace();
+ }
+ return namespace;
+ }
+
+ @Override
+ public void setNamespace(URI namespace) {
+ Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
+ this.namespace = namespace;
+ }
+
+ @Override
+ public Node<?> unwrap() {
+ if (unwrapped == null) {
+ if (name == null) {
+ Preconditions.checkNotNull(namespace);
+ name = new QName(namespace, localName);
+ }
+ if(composite) {
+ unwrapped = NodeFactory.createImmutableCompositeNode(name, null, Collections.<Node<?>>emptyList(),null);
+ } else {
+ unwrapped = NodeFactory.createImmutableSimpleNode(name, null, null);
+ }
+ namespace = null;
+ localName = null;
+ name = null;
+ }
+ return unwrapped;
+ }
+
+ @Override
+ public QName getNodeType() {
+ return unwrap().getNodeType();
+ }
+
+ @Override
+ public CompositeNode getParent() {
+ return unwrap().getParent();
+ }
+
+ @Override
+ public Void getValue() {
+ return null;
+ }
+
+ @Override
+ public QName getKey() {
+ return unwrap().getKey();
+ }
+
+ @Override
+ public Void setValue(Void value) {
+ return null;
+ }
+
+}
import org.opendaylight.yangtools.yang.model.api.ChoiceNode
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
class RestconfImpl implements RestconfService {
override createConfigurationData(String identifier, CompositeNode payload) {
val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
- val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+ val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
switch status.result {
case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
override updateConfigurationData(String identifier, CompositeNode payload) {
val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
- val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
+ val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
switch status.result {
case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
if (rpc === null) {
throw new ResponseException(Response.Status.NOT_FOUND, "RPC does not exist.");
}
- val value = resolveNodeNamespaceBySchema(payload, rpc.input)
+ val value = normalizeNode(payload, rpc.input)
val List<Node<?>> input = new ArrayList
input.add(value)
val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
return identifierWithSchemaNode
}
- private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
+ private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
if (node instanceof CompositeNodeWrapper) {
- addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
+ normalizeNode(node as CompositeNodeWrapper, schema,null)
return (node as CompositeNodeWrapper).unwrap()
}
return node
}
- private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
+ private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema,QName previousAugment) {
if (schema === null) {
throw new ResponseException(Response.Status.BAD_REQUEST,
"Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
}
- val moduleName = controllerContext.findModuleByNamespace(schema.QName.namespace);
- if (nodeBuilder.namespace === null || nodeBuilder.namespace == schema.QName.namespace ||
+ var validQName = schema.QName
+ var currentAugment = previousAugment;
+ if(schema.augmenting) {
+ currentAugment = schema.QName
+ } else if(previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
+ validQName = QName.create(currentAugment,schema.QName.localName);
+ }
+ val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
+ if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
nodeBuilder.namespace.path == moduleName) {
- nodeBuilder.qname = schema.QName
+ nodeBuilder.qname = validQName
} else {
throw new ResponseException(Response.Status.BAD_REQUEST,
"Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
" should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
nodeBuilder.localName + " should be " + moduleName + ".");
}
+
if (nodeBuilder instanceof CompositeNodeWrapper) {
val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
for (child : children) {
- addNamespaceToNodeFromSchemaRecursively(child,
- findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes))
+ normalizeNode(child,
+ findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),currentAugment)
+ }
+ } else if (nodeBuilder instanceof SimpleNodeWrapper) {
+ val simpleNode = (nodeBuilder as SimpleNodeWrapper)
+ val stringValue = simpleNode.value as String;
+
+ val objectValue = TypeDefinitionAwareCodec.from(schema.typeDefinition)?.deserialize(stringValue);
+ simpleNode.setValue(objectValue)
+ } else if (nodeBuilder instanceof EmptyNodeWrapper) {
+ val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
+ if(schema instanceof LeafSchemaNode) {
+ emptyNodeBuilder.setComposite(false);
+ } else if(schema instanceof ContainerSchemaNode) {
+ // FIXME: Add presence check
+ emptyNodeBuilder.setComposite(true);
}
}
}
+ private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
+ node.type
+ }
+
+ private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
+ node.type
+ }
+
+
private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
for (schema : schemas) {
if (schema instanceof ChoiceNode) {
}
}
} else {
- return schemas.findFirst[n|n.QName.localName.equals(localName)]
+ val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
+ if(result !== null) {
+ return result;
+
+ }
}
}
return null
import com.google.common.base.Preconditions;
-public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<String> {
+public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
- private SimpleNode<String> simpleNode;
+ private SimpleNode<?> simpleNode;
private String localName;
- private String value;
+ private Object value;
private URI namespace;
private QName name;
- public SimpleNodeWrapper(String localName, String value) {
+ public SimpleNodeWrapper(String localName, Object value) {
this.localName = Preconditions.checkNotNull(localName);
this.value = value;
}
}
@Override
- public SimpleNode<String> unwrap() {
+ public SimpleNode<Object> unwrap() {
if (simpleNode == null) {
if (name == null) {
Preconditions.checkNotNull(namespace);
localName = null;
name = null;
}
- return simpleNode;
+ return (SimpleNode<Object>) simpleNode;
}
@Override
}
@Override
- public String getValue() {
+ public Object getValue() {
return unwrap().getValue();
}
}
@Override
- public MutableSimpleNode<String> asMutable() {
+ public MutableSimpleNode<Object> asMutable() {
return unwrap().asMutable();
}
}
@Override
- public String setValue(String value) {
+ public Object setValue(Object value) {
return unwrap().setValue(value);
}
+
}
SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getChildren().get(0);
assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString());
assertEquals("lf111", cont11_lf111.getNodeType().getLocalName());
- assertEquals("100", cont11_lf111.getValue());
+ assertEquals((short) 100, cont11_lf111.getValue());
// :lst1_2
}
SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getChildren().get(0);
assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString());
assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName());
- assertEquals("100", cont1_lf11.getValue());
+ assertEquals((short) 100, cont1_lf11.getValue());
}
private CompositeNode compositeContainerFromXml(String xmlPath, boolean dummyNamespaces) {