package org.opendaylight.controller.sal.restconf.impl;
import com.google.common.base.Objects;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.math.BigInteger;
import java.net.URI;
+import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.util.EmptyType;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
import org.slf4j.Logger;
}
}
+ private static class TypeDef {
+ public final TypeDefinition<? extends Object> typedef;
+ public final QName qName;
+ TypeDef(final TypeDefinition<? extends Object> typedef, final QName qName) {
+ this.typedef = typedef;
+ this.qName = qName;
+ }
+ }
private final static RestconfImpl INSTANCE = new RestconfImpl();
private static final String SCOPE_PARAM_NAME = "scope";
+ private static final String NETCONF_BASE = "urn:ietf:params:xml:ns:netconf:base:1.0";
+
+ private static final String NETCONF_BASE_PAYLOAD_NAME = "data";
+
+ private static final QName NETCONF_BASE_QNAME;
+
static {
try {
EVENT_SUBSCRIPTION_AUGMENT_REVISION = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-08");
+ NETCONF_BASE_QNAME = QName.create(QNameModule.create(new URI(NETCONF_BASE), null), NETCONF_BASE_PAYLOAD_NAME );
} catch (ParseException e) {
throw new RestconfDocumentedException(
"It wasn't possible to convert revision date of sal-remote-augment to date", ErrorType.APPLICATION,
ErrorTag.OPERATION_FAILED);
+ } catch (URISyntaxException e) {
+ throw new RestconfDocumentedException(
+ "It wasn't possible to create instance of URI class with "+NETCONF_BASE+" URI", ErrorType.APPLICATION,
+ ErrorTag.OPERATION_FAILED);
}
}
validateInput(iiWithData.getSchemaNode(), payload);
DOMMountPoint mountPoint = iiWithData.getMountPoint();
+ validateTopLevelNodeName(payload, iiWithData.getInstanceIdentifier());
final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
validateListKeysEqualityInPayloadAndUri(iiWithData, value);
final NormalizedNode<?, ?> datastoreNormalizedNode = compositeNodeToDatastoreNormalizedNode(value,
iiWithData.getSchemaNode());
+
YangInstanceIdentifier normalizedII;
if (mountPoint != null) {
normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(
return Response.status(Status.OK).build();
}
+ private void validateTopLevelNodeName(final Node<?> node,
+ final YangInstanceIdentifier identifier) {
+ final String payloadName = getName(node);
+ final Iterator<PathArgument> pathArguments = identifier.getReversePathArguments().iterator();
+
+ //no arguments
+ if (!pathArguments.hasNext()) {
+ //no "data" payload
+ if (!node.getNodeType().equals(NETCONF_BASE_QNAME)) {
+ throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument",
+ ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ }
+ //any arguments
+ } else {
+ final String identifierName = pathArguments.next().getNodeType().getLocalName();
+ if (!payloadName.equals(identifierName)) {
+ throw new RestconfDocumentedException("Payload name (" + payloadName
+ + ") is different from identifier name (" + identifierName + ")", ErrorType.PROTOCOL,
+ ErrorTag.MALFORMED_MESSAGE);
+ }
+ }
+ }
+
/**
* Validates whether keys in {@code payload} are equal to values of keys in {@code iiWithData} for list schema node
*
broker.commitConfigurationDataDelete(normalizedII).get();
}
} catch (Exception e) {
- throw new RestconfDocumentedException("Error creating data", e);
+ final Optional<Throwable> searchedException = Iterables.tryFind(Throwables.getCausalChain(e),
+ Predicates.instanceOf(ModifiedNodeDoesNotExistException.class));
+ if (searchedException.isPresent()) {
+ throw new RestconfDocumentedException("Data specified for deleting doesn't exist.", ErrorType.APPLICATION, ErrorTag.DATA_MISSING);
+ }
+ throw new RestconfDocumentedException("Error while deleting data", e);
}
-
return Response.status(Status.OK).build();
}
try {
this.normalizeNode(nodeWrap, schema, null, mountPoint);
} catch (IllegalArgumentException e) {
- throw new RestconfDocumentedException(e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+ RestconfDocumentedException restconfDocumentedException = new RestconfDocumentedException(e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+ restconfDocumentedException.addSuppressed(e);
+ throw restconfDocumentedException;
}
if (nodeWrap instanceof CompositeNodeWrapper) {
return ((CompositeNodeWrapper) nodeWrap).unwrap();
final DOMMountPoint mountPoint) {
final Object value = simpleNode.getValue();
Object inputValue = value;
- TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
- if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
- if ((value instanceof String)) {
- inputValue = new IdentityValuesDTO(simpleNode.getNamespace().toString(), (String) value, null,
- (String) value);
- } // else value is already instance of IdentityValuesDTO
+ TypeDef typeDef = this.typeDefinition(schema);
+ TypeDefinition<? extends Object> typeDefinition = typeDef != null ? typeDef.typedef : null;
+
+ // For leafrefs, extract the type it is pointing to
+ if(typeDefinition instanceof LeafrefTypeDefinition) {
+ if (schema.getQName().equals(typeDef.qName)) {
+ typeDefinition = SchemaContextUtil.getBaseTypeForLeafRef(((LeafrefTypeDefinition) typeDefinition), mountPoint == null ? this.controllerContext.getGlobalSchema() : mountPoint.getSchemaContext(), schema);
+ } else {
+ typeDefinition = SchemaContextUtil.getBaseTypeForLeafRef(((LeafrefTypeDefinition) typeDefinition), mountPoint == null ? this.controllerContext.getGlobalSchema() : mountPoint.getSchemaContext(), typeDef.qName);
+ }
+ }
+
+ if (typeDefinition instanceof IdentityrefTypeDefinition) {
+ inputValue = parseToIdentityValuesDTO(simpleNode, value, inputValue);
}
Object outputValue = inputValue;
simpleNode.setValue(outputValue);
}
+ private Object parseToIdentityValuesDTO(final SimpleNodeWrapper simpleNode, final Object value, Object inputValue) {
+ if ((value instanceof String)) {
+ inputValue = new IdentityValuesDTO(simpleNode.getNamespace().toString(), (String) value, null,
+ (String) value);
+ } // else value is already instance of IdentityValuesDTO
+ return inputValue;
+ }
+
private void normalizeCompositeNode(final CompositeNodeWrapper compositeNodeBuilder,
final DataNodeContainer schema, final DOMMountPoint mountPoint, final QName currentAugment) {
final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
}
}
- private TypeDefinition<? extends Object> _typeDefinition(final LeafSchemaNode node) {
- TypeDefinition<?> baseType = node.getType();
+ private TypeDef typeDefinition(final TypeDefinition<?> type, final QName nodeQName) {
+ TypeDefinition<?> baseType = type;
+ QName qName = nodeQName;
while (baseType.getBaseType() != null) {
+ if (baseType instanceof ExtendedType) {
+ qName = baseType.getQName();
+ }
baseType = baseType.getBaseType();
}
- return baseType;
- }
-
- private TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
- TypeDefinition<?> baseType = node.getType();
- while (baseType.getBaseType() != null) {
- baseType = baseType.getBaseType();
- }
+ return new TypeDef(baseType, qName);
- return baseType;
}
- private TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
+ private TypeDef typeDefinition(final DataSchemaNode node) {
if (node instanceof LeafListSchemaNode) {
- return typeDefinition((LeafListSchemaNode) node);
+ return typeDefinition(((LeafListSchemaNode)node).getType(), node.getQName());
} else if (node instanceof LeafSchemaNode) {
- return _typeDefinition((LeafSchemaNode) node);
+ return typeDefinition(((LeafSchemaNode)node).getType(), node.getQName());
} else if (node instanceof AnyXmlSchemaNode) {
return null;
} else {