import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
}
@Override
- public StructuredData getOperations(final UriInfo uriInfo) {
+ public NormalizedNodeContext getOperations(final UriInfo uriInfo) {
final Set<Module> allModules = controllerContext.getAllModules();
- return operationsFromModulesToStructuredData(allModules, null, parsePrettyPrintParameter(uriInfo));
+ return operationsFromModulesToNormalizedContext(allModules, null);
}
@Override
- public StructuredData getOperations(final String identifier, final UriInfo uriInfo) {
+ public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
Set<Module> modules = null;
DOMMountPoint mountPoint = null;
if (identifier.contains(ControllerContext.MOUNT)) {
final InstanceIdentifierContext mountPointIdentifier = controllerContext.toMountPointIdentifier(identifier);
mountPoint = mountPointIdentifier.getMountPoint();
modules = controllerContext.getAllModules(mountPoint);
+
} else {
- throw new RestconfDocumentedException(
- "URI has bad format. If operations behind mount point should be showed, URI has to end with "
- + ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+ final String errMsg = "URI has bad format. If operations behind mount point should be showed, URI has to end with ";
+ throw new RestconfDocumentedException(errMsg + ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
}
- return operationsFromModulesToStructuredData(modules, mountPoint, parsePrettyPrintParameter(uriInfo));
+ return operationsFromModulesToNormalizedContext(modules, mountPoint);
+ }
+
+ private NormalizedNodeContext operationsFromModulesToNormalizedContext(final Set<Module> modules,
+ final DOMMountPoint mountPoint) {
+
+ // FIXME find best way to change restconf-netconf yang schema for provide this functionality
+ final String errMsg = "We are not able support view operations functionality yet.";
+ throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED);
}
+ /**
+ * @deprecated method will be removed in Lithium release
+ */
+ @Deprecated
private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
final DOMMountPoint mountPoint, final boolean prettyPrint) {
final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
}
}
+ /**
+ * @deprecated method will be removed for Lithium release
+ * so, please use toStreamEntryNode method
+ *
+ * @param streamName
+ * @param streamSchemaNode
+ * @return
+ */
+ @Deprecated
private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
}
+ /**
+ * @deprecated method will be removed for Lithium release
+ * so, please use toModuleEntryNode method
+ *
+ * @param module
+ * @param moduleSchemaNode
+ * @return
+ */
+ @Deprecated
private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
return callRpc(rpc, payload, parsePrettyPrintParameter(uriInfo));
}
+ private void validateInput(final DataSchemaNode inputSchema, final NormalizedNodeContext payload) {
+ if (inputSchema != null && payload.getData() == null) {
+ // expected a non null payload
+ throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ } else if (inputSchema == null && payload.getData() != null) {
+ // 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.
+ // }
+ }
+
+ /**
+ * @deprecated method will be removed for Lithium release
+ *
+ * @param inputSchema
+ * @param payload
+ */
+ @Deprecated
private void validateInput(final DataSchemaNode inputSchema, final Node<?> payload) {
if (inputSchema != null && payload == null) {
// expected a non null payload
final YangInstanceIdentifier pathIdentifier = ((YangInstanceIdentifier) pathValue);
String streamName = null;
if (!Iterables.isEmpty(pathIdentifier.getPathArguments())) {
- final String fullRestconfIdentifier = controllerContext.toFullRestconfIdentifier(pathIdentifier);
+ final String fullRestconfIdentifier = controllerContext.toFullRestconfIdentifier(pathIdentifier, null);
LogicalDatastoreType datastore = parseEnumTypeParameter(value, LogicalDatastoreType.class,
DATASTORE_PARAM_NAME);
}
@Override
- public Response updateConfigurationData(final String identifier, final Node<?> payload) {
+ public Response updateConfigurationData(final String identifier, final NormalizedNodeContext payload) {
+ Preconditions.checkNotNull(identifier);
final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
validateInput(iiWithData.getSchemaNode(), payload);
-
- final 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());
-
+ validateListKeysEqualityInPayloadAndUri(iiWithData, payload.getData());
- YangInstanceIdentifier normalizedII;
- if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(
- iiWithData.getInstanceIdentifier());
- } else {
- normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
- }
+ final DOMMountPoint mountPoint = iiWithData.getMountPoint();
+ final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
/*
* There is a small window where another write transaction could be updating the same data
while(true) {
try {
if (mountPoint != null) {
- broker.commitConfigurationDataPut(mountPoint, normalizedII,
- datastoreNormalizedNode).checkedGet();
+ broker.commitConfigurationDataPut(mountPoint, normalizedII, payload.getData()).checkedGet();
} else {
- broker.commitConfigurationDataPut(normalizedII,
- datastoreNormalizedNode).checkedGet();
+ broker.commitConfigurationDataPut(normalizedII, payload.getData()).checkedGet();
}
break;
return Response.status(Status.OK).build();
}
+ private void validateTopLevelNodeName(final NormalizedNodeContext node,
+ final YangInstanceIdentifier identifier) {
+
+ final String payloadName = node.getData().getNodeType().getLocalName();
+ final Iterator<PathArgument> pathArguments = identifier.getReversePathArguments().iterator();
+
+ //no arguments
+ if ( ! pathArguments.hasNext()) {
+ //no "data" payload
+ if ( ! node.getData().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);
+ }
+ }
+ }
+
+ /**
+ * @deprecated method will be removed for Lithium release
+ *
+ * @param node
+ * @param identifier
+ */
+ @Deprecated
private void validateTopLevelNodeName(final Node<?> node,
final YangInstanceIdentifier identifier) {
final String payloadName = getName(node);
* if key values or key count in payload and URI isn't equal
*
*/
+ private void validateListKeysEqualityInPayloadAndUri(final InstanceIdentifierContext iiWithData,
+ final NormalizedNode<?, ?> payload) {
+ if (iiWithData.getSchemaNode() instanceof ListSchemaNode) {
+ final List<QName> keyDefinitions = ((ListSchemaNode) iiWithData.getSchemaNode()).getKeyDefinition();
+ final PathArgument lastPathArgument = iiWithData.getInstanceIdentifier().getLastPathArgument();
+ if (lastPathArgument instanceof NodeIdentifierWithPredicates) {
+ final Map<QName, Object> uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument)
+ .getKeyValues();
+ isEqualUriAndPayloadKeyValues(uriKeyValues, payload, keyDefinitions);
+ }
+ }
+ }
+
+ /**
+ * @deprecated method will be removed for Lithium release
+ *
+ * Validates whether keys in {@code payload} are equal to values of keys in {@code iiWithData} for list schema node
+ *
+ * @throws RestconfDocumentedException
+ * if key values or key count in payload and URI isn't equal
+ *
+ */
+ @Deprecated
private void validateListKeysEqualityInPayloadAndUri(final InstanceIdentifierContext iiWithData,
final CompositeNode payload) {
if (iiWithData.getSchemaNode() instanceof ListSchemaNode) {
}
}
+ private void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final NormalizedNode<?, ?> payload,
+ final List<QName> keyDefinitions) {
+ for (final QName keyDefinition : keyDefinitions) {
+ final Object uriKeyValue = uriKeyValues.get(keyDefinition);
+ // should be caught during parsing URI to InstanceIdentifier
+ if (uriKeyValue == null) {
+ final String errMsg = "Missing key " + keyDefinition + " in URI.";
+ throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+ }
+ // TODO thing about the possibility to fix
+// final List<SimpleNode<?>> payloadKeyValues = payload.getSimpleNodesByName(keyDefinition.getLocalName());
+// if (payloadKeyValues.isEmpty()) {
+// final String errMsg = "Missing key " + keyDefinition.getLocalName() + " in the message body.";
+// throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+// }
+//
+// final Object payloadKeyValue = payloadKeyValues.iterator().next().getValue();
+// if (!uriKeyValue.equals(payloadKeyValue)) {
+// final String errMsg = "The value '" + uriKeyValue + "' for key '" + keyDefinition.getLocalName() +
+// "' specified in the URI doesn't match the value '" + payloadKeyValue + "' specified in the message body. ";
+// throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+// }
+ }
+ }
+
+ /**
+ * @deprecated method will be removed for Lithium release
+ *
+ * @param uriKeyValues
+ * @param payload
+ * @param keyDefinitions
+ */
+ @Deprecated
private void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final CompositeNode payload,
final List<QName> keyDefinitions) {
for (final QName keyDefinition : keyDefinitions) {
}
@Override
- public Response createConfigurationData(final String identifier, final Node<?> payload) {
+ public Response createConfigurationData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
if (payload == null) {
throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
- final URI payloadNS = namespace(payload);
+ final URI payloadNS = payload.getData().getNodeType().getNamespace();
if (payloadNS == null) {
throw new RestconfDocumentedException(
"Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)",
ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE);
}
- InstanceIdentifierContext iiWithData = null;
- CompositeNode value = null;
- if (representsMountPointRootData(payload)) {
- // payload represents mount point data and URI represents path to the mount point
-
- if (endsWithMountPoint(identifier)) {
- throw new RestconfDocumentedException("URI has bad format. URI should be without \""
- + ControllerContext.MOUNT + "\" for POST operation.", ErrorType.PROTOCOL,
- ErrorTag.INVALID_VALUE);
- }
-
- final String completeIdentifier = addMountPointIdentifier(identifier);
- iiWithData = controllerContext.toInstanceIdentifier(completeIdentifier);
-
- value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
- } else {
- final InstanceIdentifierContext incompleteInstIdWithData = controllerContext
- .toInstanceIdentifier(identifier);
- final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
- final DOMMountPoint mountPoint = incompleteInstIdWithData.getMountPoint();
- final Module module = findModule(mountPoint, payload);
-
- final String payloadName = getName(payload);
- final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(
- parentSchema, payloadName, module.getNamespace());
- value = this.normalizeNode(payload, schemaNode, mountPoint);
-
- iiWithData = addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode,incompleteInstIdWithData.getSchemaContext());
- }
+ final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
- final NormalizedNode<?, ?> datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value,
- iiWithData.getSchemaNode());
- final DOMMountPoint mountPoint = iiWithData.getMountPoint();
- YangInstanceIdentifier normalizedII;
+ final InstanceIdentifierContext iiWithData = mountPoint != null
+ ? controllerContext.toMountPointIdentifier(identifier)
+ : controllerContext.toInstanceIdentifier(identifier);
+ final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
try {
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
- .getInstanceIdentifier());
- broker.commitConfigurationDataPost(mountPoint, normalizedII, datastoreNormalizedData);
+ broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData());
} else {
- normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
- broker.commitConfigurationDataPost(normalizedII, datastoreNormalizedData);
+ broker.commitConfigurationDataPost(normalizedII, payload.getData());
}
} catch(final RestconfDocumentedException e) {
throw e;
throw new RestconfDocumentedException("Error creating data", e);
}
- return Response.status(Status.NO_CONTENT).build();
+
+ final ResponseBuilder responseBuilder = Response.status(Status.NO_CONTENT);
+ final URI location = resolveLocation(uriInfo, "config", mountPoint, normalizedII);
+ if (location != null) {
+ responseBuilder.location(location);
+ }
+ return responseBuilder.build();
}
@Override
- public Response createConfigurationData(final Node<?> payload) {
+ public Response createConfigurationData(final NormalizedNodeContext payload, final UriInfo uriInfo) {
if (payload == null) {
throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
- final URI payloadNS = namespace(payload);
+ final URI payloadNS = payload.getData().getNodeType().getNamespace();
if (payloadNS == null) {
throw new RestconfDocumentedException(
"Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)",
ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE);
}
- final Module module = this.findModule(null, payload);
-
- final String payloadName = getName(payload);
- final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module,
- payloadName, module.getNamespace());
- final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
- final InstanceIdentifierContext iiWithData = addLastIdentifierFromData(null, value, schemaNode,ControllerContext.getInstance().getGlobalSchema());
- final NormalizedNode<?, ?> datastoreNormalizedData = compositeNodeToDatastoreNormalizedNode(value, schemaNode);
- final DOMMountPoint mountPoint = iiWithData.getMountPoint();
- YangInstanceIdentifier normalizedII;
+ final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
+ final InstanceIdentifierContext iiWithData = payload.getInstanceIdentifierContext();
+ final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
try {
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
- .getInstanceIdentifier());
- broker.commitConfigurationDataPost(mountPoint, normalizedII, datastoreNormalizedData);
+ broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData());
} else {
- normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
- broker.commitConfigurationDataPost(normalizedII, datastoreNormalizedData);
+ broker.commitConfigurationDataPost(normalizedII, payload.getData());
}
} catch(final RestconfDocumentedException e) {
throw e;
throw new RestconfDocumentedException("Error creating data", e);
}
- return Response.status(Status.NO_CONTENT).build();
+ final ResponseBuilder responseBuilder = Response.status(Status.NO_CONTENT);
+ final URI location = resolveLocation(uriInfo, "", mountPoint, normalizedII);
+ if (location != null) {
+ responseBuilder.location(location);
+ }
+ return responseBuilder.build();
+ }
+
+ private URI resolveLocation(final UriInfo uriInfo, final String uriBehindBase, final DOMMountPoint mountPoint, final YangInstanceIdentifier normalizedII) {
+ final UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+ uriBuilder.path("config");
+ try {
+ uriBuilder.path(controllerContext.toFullRestconfIdentifier(normalizedII, mountPoint));
+ } catch (final Exception e) {
+ LOG.debug("Location for instance identifier"+normalizedII+"wasn't created", e);
+ return null;
+ }
+ return uriBuilder.build();
}
@Override
return identifier + "/" + ControllerContext.MOUNT;
}
- private CompositeNode normalizeNode(final Node<?> node, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
+ /**
+ * @deprecated method will be removed in Lithium release
+ * we don't wish to use Node and CompositeNode anywhere
+ */
+ @Deprecated
+ public CompositeNode normalizeNode(final Node<?> node, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
if (schema == null) {
final String localName = node == null ? null :
node instanceof NodeWrapper ? ((NodeWrapper<?>)node).getLocalName() :
}
}
+ /**
+ * @deprecated method will be removed for Lithium release
+ *
+ * @param data
+ * @return
+ */
+ @Deprecated
private String getName(final Node<?> data) {
if (data instanceof NodeWrapper) {
return ((NodeWrapper<?>) data).getLocalName();