From: Jakub Toth Date: Wed, 5 Oct 2016 12:56:08 +0000 (+0200) Subject: Bug 6848 - repackage providers for jersey+create xml X-Git-Tag: release/carbon~181 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=f3a63a5aa4a59f3dd47f0e62ea900416e4a37811;p=netconf.git Bug 6848 - repackage providers for jersey+create xml and json reader for restconf draft17 *fix tests *rename tests part from draft11 to draft17 Change-Id: I1315bb693eccc34c78f07ea0acbf45f6ff972455 Signed-off-by: Jakub Toth --- diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java index caa4726d5c..49072d8339 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/AbstractIdentifierAwareJaxRsProvider.java @@ -17,7 +17,7 @@ import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; /** * @deprecated This class will be replaced by - * {@link org.opendaylight.restconf.utils.patch.AbstractIdentifierAwareJaxRsProvider} + * {@link org.opendaylight.restconf.jersey.providers.AbstractIdentifierAwareJaxRsProvider} */ @Deprecated public class AbstractIdentifierAwareJaxRsProvider { @@ -45,4 +45,8 @@ public class AbstractIdentifierAwareJaxRsProvider { protected boolean isPost() { return POST.equals(this.request.getMethod()); } + + Request getRequest() { + return this.request; + } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonNormalizedNodeBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonNormalizedNodeBodyReader.java index ea51998d9f..373dbb5adc 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonNormalizedNodeBodyReader.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonNormalizedNodeBodyReader.java @@ -70,7 +70,14 @@ public class JsonNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsPr final MultivaluedMap httpHeaders, final InputStream entityStream) throws IOException, WebApplicationException { try { - return readFrom(getInstanceIdentifierContext(), entityStream, isPost()); + if(getUriInfo().getAbsolutePath().getPath().contains("restconf/16")){ + final org.opendaylight.restconf.jersey.providers.JsonNormalizedNodeBodyReader jsonReaderNewRest = + new org.opendaylight.restconf.jersey.providers.JsonNormalizedNodeBodyReader(); + jsonReaderNewRest.injectParams(getUriInfo(), getRequest()); + return jsonReaderNewRest.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream); + } else { + return readFrom(getInstanceIdentifierContext(), entityStream, isPost()); + } } catch (final Exception e) { propagateExceptionAs(e); return null; // no-op diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonToPATCHBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonToPATCHBodyReader.java index 75240378cb..ffb47bd352 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonToPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/JsonToPATCHBodyReader.java @@ -52,7 +52,7 @@ import org.slf4j.LoggerFactory; /** * @deprecated This class will be replaced by - * {@link org.opendaylight.restconf.utils.patch.JsonToPATCHBodyReader} + * {@link org.opendaylight.restconf.jersey.providers.JsonToPATCHBodyReader} */ @Deprecated @Provider diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java index 63fe1a6ffb..0830904924 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/StringModuleInstanceIdentifierCodec.java @@ -19,7 +19,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; /** * @deprecated This class will be replaced by - * {@link org.opendaylight.restconf.utils.patch.StringModuleInstanceIdentifierCodec} + * {@link org.opendaylight.restconf.jersey.providers.StringModuleInstanceIdentifierCodec} */ @Deprecated public final class StringModuleInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec { diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlNormalizedNodeBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlNormalizedNodeBodyReader.java index 72f86c6d05..37baa231e7 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlNormalizedNodeBodyReader.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlNormalizedNodeBodyReader.java @@ -34,8 +34,6 @@ 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.Draft17; -import org.opendaylight.restconf.utils.RestconfConstants; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils; @@ -55,10 +53,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.xml.sax.SAXException; @Provider @Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML, - Draft17.MediaTypes.DATA + RestconfConstants.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + MediaType.APPLICATION_XML, MediaType.TEXT_XML }) public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsProvider implements MessageBodyReader { private final static Logger LOG = LoggerFactory.getLogger(XmlNormalizedNodeBodyReader.class); @@ -94,22 +93,14 @@ public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsPro final MultivaluedMap httpHeaders, final InputStream entityStream) throws IOException, WebApplicationException { try { - final InstanceIdentifierContext path = getInstanceIdentifierContext(); - - if (entityStream.available() < 1) { - // represent empty nopayload input - return new NormalizedNodeContext(path, null); - } - - final DocumentBuilder dBuilder; - try { - dBuilder = BUILDERFACTORY.newDocumentBuilder(); - } catch (final ParserConfigurationException e) { - throw new RuntimeException("Failed to parse XML document", e); + if (getUriInfo().getAbsolutePath().getPath().contains("restconf/16")) { + final org.opendaylight.restconf.jersey.providers.XmlNormalizedNodeBodyReader xmlReaderNewRest = + new org.opendaylight.restconf.jersey.providers.XmlNormalizedNodeBodyReader(); + xmlReaderNewRest.injectParams(getUriInfo(), getRequest()); + return xmlReaderNewRest.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream); + } else { + return readFrom(entityStream); } - final Document doc = dBuilder.parse(entityStream); - - return parse(path,doc); } catch (final RestconfDocumentedException e){ throw e; } catch (final Exception e) { @@ -120,6 +111,25 @@ public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsPro } } + private NormalizedNodeContext readFrom(final InputStream entityStream) throws IOException, SAXException { + final InstanceIdentifierContext path = getInstanceIdentifierContext(); + + if (entityStream.available() < 1) { + // represent empty nopayload input + return new NormalizedNodeContext(path, null); + } + + final DocumentBuilder dBuilder; + try { + dBuilder = BUILDERFACTORY.newDocumentBuilder(); + } catch (final ParserConfigurationException e) { + throw new RuntimeException("Failed to parse XML document", e); + } + final Document doc = dBuilder.parse(entityStream); + + return parse(path,doc); + } + private NormalizedNodeContext parse(final InstanceIdentifierContext pathContext,final Document doc) { final List elements = Collections.singletonList(doc.getDocumentElement()); diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlToPATCHBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlToPATCHBodyReader.java index 7c82d01d9a..d203de59ed 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlToPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/rest/impl/XmlToPATCHBodyReader.java @@ -59,7 +59,7 @@ import org.w3c.dom.NodeList; /** * @deprecated This class will be replaced by - * {@link org.opendaylight.restconf.utils.patch.XmlToPATCHBodyReader} + * {@link org.opendaylight.restconf.jersey.providers.XmlToPATCHBodyReader} */ @Deprecated @Provider diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestconfApplication.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestconfApplication.java index e9585f4c4a..14b8082055 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestconfApplication.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestconfApplication.java @@ -21,8 +21,8 @@ import org.opendaylight.netconf.sal.rest.impl.PATCHXmlBodyWriter; import org.opendaylight.netconf.sal.rest.impl.RestconfDocumentedExceptionMapper; import org.opendaylight.netconf.sal.rest.impl.XmlNormalizedNodeBodyReader; import org.opendaylight.restconf.common.wrapper.services.ServicesWrapperImpl; -import org.opendaylight.restconf.utils.patch.JsonToPATCHBodyReader; -import org.opendaylight.restconf.utils.patch.XmlToPATCHBodyReader; +import org.opendaylight.restconf.jersey.providers.JsonToPATCHBodyReader; +import org.opendaylight.restconf.jersey.providers.XmlToPATCHBodyReader; public class RestconfApplication extends Application { diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/AbstractIdentifierAwareJaxRsProvider.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/AbstractIdentifierAwareJaxRsProvider.java similarity index 86% rename from restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/AbstractIdentifierAwareJaxRsProvider.java rename to restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/AbstractIdentifierAwareJaxRsProvider.java index 3fed78d523..bcf95f7b64 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/AbstractIdentifierAwareJaxRsProvider.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/AbstractIdentifierAwareJaxRsProvider.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.restconf.utils.patch; +package org.opendaylight.restconf.jersey.providers; import javax.ws.rs.core.Context; import javax.ws.rs.core.Request; @@ -42,4 +42,12 @@ public class AbstractIdentifierAwareJaxRsProvider { protected boolean isPost() { return POST.equals(this.request.getMethod()); } + + void setUriInfo(final UriInfo uriInfo) { + this.uriInfo = uriInfo; + } + + void setRequest(final Request request) { + this.request = request; + } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/JsonNormalizedNodeBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/JsonNormalizedNodeBodyReader.java new file mode 100644 index 0000000000..4fa9576856 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/JsonNormalizedNodeBodyReader.java @@ -0,0 +1,160 @@ +/* + * 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.jersey.providers; + +import com.google.common.collect.Iterables; +import com.google.gson.stream.JsonReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.Provider; +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.Draft17; +import org.opendaylight.restconf.utils.RestconfConstants; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult; +import org.opendaylight.yangtools.yang.data.impl.schema.ResultAlreadySetException; +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.model.util.SchemaContextUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Provider +@Consumes({ Draft17.MediaTypes.DATA + RestconfConstants.JSON, MediaType.APPLICATION_JSON }) +public class JsonNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsProvider implements MessageBodyReader { + + private final static Logger LOG = LoggerFactory.getLogger(JsonNormalizedNodeBodyReader.class); + + @Override + public boolean isReadable(final Class type, final Type genericType, final Annotation[] annotations, + final MediaType mediaType) { + return true; + } + + @Override + public NormalizedNodeContext readFrom(final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final InputStream entityStream) throws IOException, + WebApplicationException { + try { + return readFrom(getInstanceIdentifierContext(), entityStream, isPost()); + } catch (final Exception e) { + propagateExceptionAs(e); + return null; + } + } + + private static void propagateExceptionAs(final Exception e) throws RestconfDocumentedException { + if(e instanceof RestconfDocumentedException) { + throw (RestconfDocumentedException)e; + } + + if(e instanceof ResultAlreadySetException) { + LOG.debug("Error parsing json input:", e); + + throw new RestconfDocumentedException("Error parsing json input: Failed to create new parse result data. " + + "Are you creating multiple resources/subresources in POST request?"); + } + + LOG.debug("Error parsing json input", e); + + throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL, + ErrorTag.MALFORMED_MESSAGE, e); + } + + private static NormalizedNodeContext readFrom(final InstanceIdentifierContext path, final InputStream entityStream, + final boolean isPost) throws IOException { + if (entityStream.available() < 1) { + return new NormalizedNodeContext(path, null); + } + final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder); + + final SchemaNode parentSchema; + if(isPost) { + parentSchema = path.getSchemaNode(); + } else if(path.getSchemaNode() instanceof SchemaContext) { + parentSchema = path.getSchemaContext(); + } else { + if (SchemaPath.ROOT.equals(path.getSchemaNode().getPath().getParent())) { + parentSchema = path.getSchemaContext(); + } else { + parentSchema = SchemaContextUtil.findDataSchemaNode(path.getSchemaContext(), path.getSchemaNode().getPath().getParent()); + } + } + + final JsonParserStream jsonParser = JsonParserStream.create(writer, path.getSchemaContext(), parentSchema); + final JsonReader reader = new JsonReader(new InputStreamReader(entityStream)); + jsonParser.parse(reader); + + NormalizedNode result = resultHolder.getResult(); + final List iiToDataList = new ArrayList<>(); + InstanceIdentifierContext newIIContext; + + while ((result instanceof AugmentationNode) || (result instanceof ChoiceNode)) { + final Object childNode = ((DataContainerNode) result).getValue().iterator().next(); + if (isPost) { + iiToDataList.add(result.getIdentifier()); + } + result = (NormalizedNode) childNode; + } + + if (isPost) { + if (result instanceof MapEntryNode) { + iiToDataList.add(new YangInstanceIdentifier.NodeIdentifier(result.getNodeType())); + iiToDataList.add(result.getIdentifier()); + } else { + iiToDataList.add(result.getIdentifier()); + } + } else { + if (result instanceof MapNode) { + result = Iterables.getOnlyElement(((MapNode) result).getValue()); + } + } + + final YangInstanceIdentifier fullIIToData = YangInstanceIdentifier.create(Iterables.concat( + path.getInstanceIdentifier().getPathArguments(), iiToDataList)); + + newIIContext = new InstanceIdentifierContext<>(fullIIToData, path.getSchemaNode(), path.getMountPoint(), + path.getSchemaContext()); + + return new NormalizedNodeContext(newIIContext, result); + } + + public void injectParams(final UriInfo uriInfo, final Request request) { + setUriInfo(uriInfo); + setRequest(request); + } +} + diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/JsonToPATCHBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/JsonToPATCHBodyReader.java similarity index 99% rename from restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/JsonToPATCHBodyReader.java rename to restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/JsonToPATCHBodyReader.java index ac50c47ce0..b0f50a6aa0 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/JsonToPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/JsonToPATCHBodyReader.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.restconf.utils.patch; +package org.opendaylight.restconf.jersey.providers; import static org.opendaylight.netconf.sal.restconf.impl.PATCHEditOperation.isPatchOperationWithValue; diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/StringModuleInstanceIdentifierCodec.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/StringModuleInstanceIdentifierCodec.java similarity index 97% rename from restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/StringModuleInstanceIdentifierCodec.java rename to restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/StringModuleInstanceIdentifierCodec.java index bc10c795aa..06f006cf9f 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/StringModuleInstanceIdentifierCodec.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/StringModuleInstanceIdentifierCodec.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.restconf.utils.patch; +package org.opendaylight.restconf.jersey.providers; import com.google.common.base.Preconditions; import java.net.URI; diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlNormalizedNodeBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlNormalizedNodeBodyReader.java new file mode 100644 index 0000000000..8ea2f92541 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlNormalizedNodeBodyReader.java @@ -0,0 +1,246 @@ +/* + * 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.jersey.providers; + +import com.google.common.collect.Iterables; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.Provider; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +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.Draft17; +import org.opendaylight.restconf.utils.RestconfConstants; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +@Provider +@Consumes({ Draft17.MediaTypes.DATA + RestconfConstants.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML }) +public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsProvider implements MessageBodyReader { + + private final static Logger LOG = LoggerFactory.getLogger(XmlNormalizedNodeBodyReader.class); + private static final DocumentBuilderFactory BUILDERFACTORY; + + static { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try { + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature("http://xml.org/sax/features/external-general-entities", false); + factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + factory.setXIncludeAware(false); + factory.setExpandEntityReferences(false); + } catch (final ParserConfigurationException e) { + throw new ExceptionInInitializerError(e); + } + factory.setNamespaceAware(true); + factory.setCoalescing(true); + factory.setIgnoringElementContentWhitespace(true); + factory.setIgnoringComments(true); + BUILDERFACTORY = factory; + } + + @Override + public boolean isReadable(final Class type, final Type genericType, final Annotation[] annotations, + final MediaType mediaType) { + return true; + } + + @Override + public NormalizedNodeContext readFrom(final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final InputStream entityStream) throws IOException, + WebApplicationException { + try { + final InstanceIdentifierContext path = getInstanceIdentifierContext(); + + if (entityStream.available() < 1) { + // represent empty nopayload input + return new NormalizedNodeContext(path, null); + } + + final DocumentBuilder dBuilder; + try { + dBuilder = BUILDERFACTORY.newDocumentBuilder(); + } catch (final ParserConfigurationException e) { + throw new RuntimeException("Failed to parse XML document", e); + } + final Document doc = dBuilder.parse(entityStream); + + return parse(path,doc); + } catch (final RestconfDocumentedException e){ + throw e; + } catch (final Exception e) { + LOG.debug("Error parsing xml input", e); + + throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL, + ErrorTag.MALFORMED_MESSAGE); + } + } + + private NormalizedNodeContext parse(final InstanceIdentifierContext pathContext,final Document doc) { + + final List elements = Collections.singletonList(doc.getDocumentElement()); + final SchemaNode schemaNodeContext = pathContext.getSchemaNode(); + DataSchemaNode schemaNode; + boolean isRpc = false; + if (schemaNodeContext instanceof RpcDefinition) { + schemaNode = ((RpcDefinition) schemaNodeContext).getInput(); + isRpc = true; + } else if (schemaNodeContext instanceof DataSchemaNode) { + schemaNode = (DataSchemaNode) schemaNodeContext; + } else { + throw new IllegalStateException("Unknown SchemaNode"); + } + + final String docRootElm = doc.getDocumentElement().getLocalName(); + final String docRootNamespace = doc.getDocumentElement().getNamespaceURI(); + final List iiToDataList = new ArrayList<>(); + InstanceIdentifierContext outIIContext; + + + final DomToNormalizedNodeParserFactory parserFactory = + DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, pathContext.getSchemaContext()); + + if (isPost() && !isRpc) { + final Deque foundSchemaNodes = findPathToSchemaNodeByName(schemaNode, docRootElm, docRootNamespace); + if (foundSchemaNodes.isEmpty()) { + throw new IllegalStateException(String.format("Child \"%s\" was not found in parent schema node \"%s\"", + docRootElm, schemaNode.getQName())); + } + while (!foundSchemaNodes.isEmpty()) { + final Object child = foundSchemaNodes.pop(); + if (child instanceof AugmentationSchema) { + final AugmentationSchema augmentSchemaNode = (AugmentationSchema) child; + iiToDataList.add(SchemaUtils.getNodeIdentifierForAugmentation(augmentSchemaNode)); + } else if (child instanceof DataSchemaNode) { + schemaNode = (DataSchemaNode) child; + iiToDataList.add(new YangInstanceIdentifier.NodeIdentifier(schemaNode.getQName())); + } + } + } + + NormalizedNode parsed = null; + + if (schemaNode instanceof ContainerSchemaNode) { + parsed = parserFactory.getContainerNodeParser().parse(Collections.singletonList(doc.getDocumentElement()), (ContainerSchemaNode) schemaNode); + } else if(schemaNode instanceof ListSchemaNode) { + final ListSchemaNode casted = (ListSchemaNode) schemaNode; + parsed = parserFactory.getMapEntryNodeParser().parse(elements, casted); + if (isPost()) { + iiToDataList.add(parsed.getIdentifier()); + } + } + + final YangInstanceIdentifier fullIIToData = YangInstanceIdentifier.create(Iterables.concat( + pathContext.getInstanceIdentifier().getPathArguments(), iiToDataList)); + + outIIContext = new InstanceIdentifierContext<>(fullIIToData, pathContext.getSchemaNode(), pathContext.getMountPoint(), + pathContext.getSchemaContext()); + + return new NormalizedNodeContext(outIIContext, parsed); + } + + private static Deque findPathToSchemaNodeByName(final DataSchemaNode schemaNode, final String elementName, + final String namespace) { + final Deque result = new ArrayDeque<>(); + final ArrayList choiceSchemaNodes = new ArrayList<>(); + final Collection children = ((DataNodeContainer) schemaNode).getChildNodes(); + for (final DataSchemaNode child : children) { + if (child instanceof ChoiceSchemaNode) { + choiceSchemaNodes.add((ChoiceSchemaNode) child); + } else if (child.getQName().getLocalName().equalsIgnoreCase(elementName) + && child.getQName().getNamespace().toString().equalsIgnoreCase(namespace)) { + // add child to result + result.push(child); + + // find augmentation + if (child.isAugmenting()) { + final AugmentationSchema augment = findCorrespondingAugment(schemaNode, child); + if (augment != null) { + result.push(augment); + } + } + + // return result + return result; + } + } + + for (final ChoiceSchemaNode choiceNode : choiceSchemaNodes) { + for (final ChoiceCaseNode caseNode : choiceNode.getCases()) { + final Deque resultFromRecursion = findPathToSchemaNodeByName(caseNode, elementName, namespace); + if (!resultFromRecursion.isEmpty()) { + resultFromRecursion.push(choiceNode); + if (choiceNode.isAugmenting()) { + final AugmentationSchema augment = findCorrespondingAugment(schemaNode, choiceNode); + if (augment != null) { + resultFromRecursion.push(augment); + } + } + return resultFromRecursion; + } + } + } + return result; + } + + private static AugmentationSchema findCorrespondingAugment(final DataSchemaNode parent, final DataSchemaNode child) { + if ((parent instanceof AugmentationTarget) && !(parent instanceof ChoiceSchemaNode)) { + for (final AugmentationSchema augmentation : ((AugmentationTarget) parent).getAvailableAugmentations()) { + final DataSchemaNode childInAugmentation = augmentation.getDataChildByName(child.getQName()); + if (childInAugmentation != null) { + return augmentation; + } + } + } + return null; + } + + public void injectParams(final UriInfo uriInfo, final Request request) { + setRequest(request); + setUriInfo(uriInfo); + } +} + diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/XmlToPATCHBodyReader.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlToPATCHBodyReader.java similarity index 99% rename from restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/XmlToPATCHBodyReader.java rename to restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlToPATCHBodyReader.java index 599f7c1a94..1f6d5632a9 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/patch/XmlToPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/jersey/providers/XmlToPATCHBodyReader.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.restconf.utils.patch; +package org.opendaylight.restconf.jersey.providers; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java index 5184d38e58..22c667b35e 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java @@ -11,8 +11,8 @@ package org.opendaylight.controller.sal.rest.impl.test.providers; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - import java.lang.reflect.Field; +import java.net.URI; import java.util.Collections; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedHashMap; @@ -42,7 +42,7 @@ public abstract class AbstractBodyReaderTest { requestField = AbstractIdentifierAwareJaxRsProvider.class .getDeclaredField("request"); requestField.setAccessible(true); - mediaType = getMediaType(); + this.mediaType = getMediaType(); } protected abstract MediaType getMediaType(); @@ -52,10 +52,8 @@ public abstract class AbstractBodyReaderTest { return TestRestconfUtils.loadSchemaContext(yangPath, schemaContext); } - protected static void mockBodyReader( - final String identifier, final T normalizedNodeProvider, - final boolean isPost) throws NoSuchFieldException, - SecurityException, IllegalArgumentException, IllegalAccessException { + protected static void mockBodyReader(final String identifier, + final T normalizedNodeProvider, final boolean isPost) throws Exception { final UriInfo uriInfoMock = mock(UriInfo.class); final MultivaluedMap pathParm = new MultivaluedHashMap<>(1); @@ -66,6 +64,7 @@ public abstract class AbstractBodyReaderTest { when(uriInfoMock.getPathParameters()).thenReturn(pathParm); when(uriInfoMock.getPathParameters(false)).thenReturn(pathParm); when(uriInfoMock.getPathParameters(true)).thenReturn(pathParm); + when(uriInfoMock.getAbsolutePath()).thenReturn(new URI("restconf")); uriField.set(normalizedNodeProvider, uriInfoMock); final Request request = mock(Request.class); diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft11AbstractBodyReaderTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17AbstractBodyReaderTest.java similarity index 95% rename from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft11AbstractBodyReaderTest.java rename to restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17AbstractBodyReaderTest.java index c88d1fb840..dc33cf25c5 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft11AbstractBodyReaderTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17AbstractBodyReaderTest.java @@ -24,17 +24,17 @@ import org.opendaylight.netconf.sal.rest.api.RestconfConstants; import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.netconf.sal.restconf.impl.PATCHContext; -import org.opendaylight.restconf.utils.patch.AbstractIdentifierAwareJaxRsProvider; +import org.opendaylight.restconf.jersey.providers.AbstractIdentifierAwareJaxRsProvider; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -public abstract class Draft11AbstractBodyReaderTest { +public abstract class Draft17AbstractBodyReaderTest { protected final static ControllerContext controllerContext = ControllerContext.getInstance(); protected final MediaType mediaType; private static Field uriField; private static Field requestField; - public Draft11AbstractBodyReaderTest() throws NoSuchFieldException, + public Draft17AbstractBodyReaderTest() throws NoSuchFieldException, SecurityException { uriField = AbstractIdentifierAwareJaxRsProvider.class .getDeclaredField("uriInfo"); diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17JsonBodyReaderTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17JsonBodyReaderTest.java new file mode 100644 index 0000000000..e49f1e8de3 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17JsonBodyReaderTest.java @@ -0,0 +1,173 @@ +/** + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; +import org.opendaylight.restconf.jersey.providers.JsonNormalizedNodeBodyReader; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; +import com.google.common.collect.Sets; + +public class Draft17JsonBodyReaderTest extends Draft17AbstractBodyReaderTest { + + private final JsonNormalizedNodeBodyReader jsonBodyReader; + private static SchemaContext schemaContext; + + private static final QNameModule INSTANCE_IDENTIFIER_MODULE_QNAME = initializeInstanceIdentifierModule(); + + private static QNameModule initializeInstanceIdentifierModule() { + try { + return QNameModule.create(URI.create("instance:identifier:module"), + new SimpleDateFormat("yyyy-MM-dd").parse("2014-01-17")); + } catch (final ParseException e) { + throw new Error(e); + } + } + + public Draft17JsonBodyReaderTest() throws NoSuchFieldException, SecurityException { + super(); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() + throws NoSuchFieldException, SecurityException, FileNotFoundException, SourceException, ReactorException { + final Collection testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/modules")); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = TestRestconfUtils.parseYangSources(testFiles); + controllerContext.setSchemas(schemaContext); + } + + @Test + public void moduleDataTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.jsonBodyReader, false); + final InputStream inputStream = Draft17JsonBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/json/jsondata.json"); + final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPutTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final DataSchemaNode dataSchemaNodeOnPath = ((DataNodeContainer) dataSchemaNode).getDataChildByName(cont1QName); + final String uri = "instance-identifier-module:cont/cont1"; + mockBodyReader(uri, this.jsonBodyReader, false); + final InputStream inputStream = Draft17JsonBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/json/json_sub_container.json"); + final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNodeOnPath, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.jsonBodyReader, true); + final InputStream inputStream = Draft17JsonBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/json/json_sub_container.json"); + final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModuleByNamespace(new URI("augment:module")).iterator().next(); + final QName contAugmentQName = QName.create(augmentModule.getQNameModule(), "cont-augment"); + final YangInstanceIdentifier.AugmentationIdentifier augII = new YangInstanceIdentifier.AugmentationIdentifier( + Sets.newHashSet(contAugmentQName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(augII) + .node(contAugmentQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.jsonBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/json/json_augment_container.json"); + final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerChoiceAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModuleByNamespace(new URI("augment:module")).iterator().next(); + final QName augmentChoice1QName = QName.create(augmentModule.getQNameModule(), "augment-choice1"); + final QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final QName containerQName = QName.create(augmentChoice1QName, "case-choice-case-container1"); + final YangInstanceIdentifier.AugmentationIdentifier augChoice1II = new YangInstanceIdentifier.AugmentationIdentifier( + Sets.newHashSet(augmentChoice1QName)); + final YangInstanceIdentifier.AugmentationIdentifier augChoice2II = new YangInstanceIdentifier.AugmentationIdentifier( + Sets.newHashSet(augmentChoice2QName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(augChoice1II) + .node(augmentChoice1QName).node(augChoice2II).node(augmentChoice2QName).node(containerQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.jsonBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/json/json_augment_choice_container.json"); + final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + private void checkExpectValueNormalizeNodeContext(final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext, final YangInstanceIdentifier dataNodeIdent) { + assertEquals(dataSchemaNode, nnContext.getInstanceIdentifierContext().getSchemaNode()); + assertEquals(dataNodeIdent, nnContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(NormalizedNodes.findNode(nnContext.getData(), dataNodeIdent)); + } +} \ No newline at end of file diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17XmlBodyReaderTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17XmlBodyReaderTest.java new file mode 100644 index 0000000000..a183ead0c8 --- /dev/null +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/Draft17XmlBodyReaderTest.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.io.InputStream; +import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collection; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; +import org.opendaylight.restconf.jersey.providers.XmlNormalizedNodeBodyReader; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import com.google.common.collect.Sets; + +public class Draft17XmlBodyReaderTest extends Draft17AbstractBodyReaderTest { + + private final XmlNormalizedNodeBodyReader xmlBodyReader; + private static SchemaContext schemaContext; + private static final QNameModule INSTANCE_IDENTIFIER_MODULE_QNAME = initializeInstanceIdentifierModule(); + + private static QNameModule initializeInstanceIdentifierModule() { + try { + return QNameModule.create(URI.create("instance:identifier:module"), + new SimpleDateFormat("yyyy-MM-dd").parse("2014-01-17")); + } catch (final ParseException e) { + throw new Error(e); + } + } + + public Draft17XmlBodyReaderTest() throws NoSuchFieldException, SecurityException { + super(); + this.xmlBodyReader = new XmlNormalizedNodeBodyReader(); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws Exception { + final Collection testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/modules")); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = TestRestconfUtils.parseYangSources(testFiles); + controllerContext.setSchemas(schemaContext); + } + + @Test + public void moduleDataTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.xmlBodyReader, false); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xmldata.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPutTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final DataSchemaNode dataSchemaNodeOnPath = ((DataNodeContainer) dataSchemaNode).getDataChildByName(cont1QName); + final String uri = "instance-identifier-module:cont/cont1"; + mockBodyReader(uri, this.xmlBodyReader, false); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNodeOnPath, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.xmlBodyReader, true); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModuleByNamespace(new URI("augment:module")).iterator().next(); + final QName contAugmentQName = QName.create(augmentModule.getQNameModule(), "cont-augment"); + final YangInstanceIdentifier.AugmentationIdentifier augII = new YangInstanceIdentifier.AugmentationIdentifier( + Sets.newHashSet(contAugmentQName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(augII) + .node(contAugmentQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.xmlBodyReader, true); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xml_augment_container.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerChoiceAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModuleByNamespace(new URI("augment:module")).iterator().next(); + final QName augmentChoice1QName = QName.create(augmentModule.getQNameModule(), "augment-choice1"); + final QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final QName containerQName = QName.create(augmentChoice1QName, "case-choice-case-container1"); + final YangInstanceIdentifier.AugmentationIdentifier augChoice1II = new YangInstanceIdentifier.AugmentationIdentifier( + Sets.newHashSet(augmentChoice1QName)); + final YangInstanceIdentifier.AugmentationIdentifier augChoice2II = new YangInstanceIdentifier.AugmentationIdentifier( + Sets.newHashSet(augmentChoice2QName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(augChoice1II) + .node(augmentChoice1QName).node(augChoice2II).node(augmentChoice2QName).node(containerQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, this.xmlBodyReader, true); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xml_augment_choice_container.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + private void checkExpectValueNormalizeNodeContext(final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext, final YangInstanceIdentifier dataNodeIdent) { + assertEquals(dataSchemaNode, nnContext.getInstanceIdentifierContext().getSchemaNode()); + assertEquals(dataNodeIdent, nnContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(NormalizedNodes.findNode(nnContext.getData(), dataNodeIdent)); + } + + /** + * Test when container with the same name is placed in two modules + * (foo-module and bar-module). Namespace must be used to distinguish + * between them to find correct one. Check if container was found not only + * according to its name but also by correct namespace used in payload. + */ + @Test + public void findFooContainerUsingNamespaceTest() throws Exception { + mockBodyReader("", this.xmlBodyReader, true); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xmlDataFindFooContainer.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + + // check return value + checkNormalizedNodeContext(returnValue); + // check if container was found both according to its name and namespace + assertEquals("Not correct container found, name was ignored", "foo-bar-container", + returnValue.getData().getNodeType().getLocalName()); + assertEquals("Not correct container found, namespace was ignored", "foo:module", + returnValue.getData().getNodeType().getNamespace().toString()); + } + + /** + * Test when container with the same name is placed in two modules + * (foo-module and bar-module). Namespace must be used to distinguish + * between them to find correct one. Check if container was found not only + * according to its name but also by correct namespace used in payload. + */ + @Test + public void findBarContainerUsingNamespaceTest() throws Exception { + mockBodyReader("", this.xmlBodyReader, true); + final InputStream inputStream = Draft17XmlBodyReaderTest.class + .getResourceAsStream("/instanceidentifier/xml/xmlDataFindBarContainer.xml"); + final NormalizedNodeContext returnValue = this.xmlBodyReader.readFrom(null, null, null, this.mediaType, null, + inputStream); + + // check return value + checkNormalizedNodeContext(returnValue); + // check if container was found both according to its name and namespace + assertEquals("Not correct container found, name was ignored", "foo-bar-container", + returnValue.getData().getNodeType().getLocalName()); + assertEquals("Not correct container found, namespace was ignored", "bar:module", + returnValue.getData().getNodeType().getNamespace().toString()); + } +} diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft11JsonPATCHBodyReader.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17JsonPATCHBodyReader.java similarity index 97% rename from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft11JsonPATCHBodyReader.java rename to restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17JsonPATCHBodyReader.java index f49251319a..c8c0f19423 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft11JsonPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17JsonPATCHBodyReader.java @@ -18,15 +18,15 @@ import org.junit.BeforeClass; import org.junit.Test; import org.opendaylight.netconf.sal.restconf.impl.PATCHContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; -import org.opendaylight.restconf.utils.patch.JsonToPATCHBodyReader; +import org.opendaylight.restconf.jersey.providers.JsonToPATCHBodyReader; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -public class TestDraft11JsonPATCHBodyReader extends Draft11AbstractBodyReaderTest { +public class TestDraft17JsonPATCHBodyReader extends Draft17AbstractBodyReaderTest { private final JsonToPATCHBodyReader jsonPATCHBodyReader; private static SchemaContext schemaContext; - public TestDraft11JsonPATCHBodyReader() throws NoSuchFieldException, SecurityException { + public TestDraft17JsonPATCHBodyReader() throws NoSuchFieldException, SecurityException { super(); jsonPATCHBodyReader = new JsonToPATCHBodyReader(); } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft11XmlPATCHBodyReader.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17XmlPATCHBodyReader.java similarity index 97% rename from restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft11XmlPATCHBodyReader.java rename to restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17XmlPATCHBodyReader.java index e8d60ca2b4..f05b693131 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft11XmlPATCHBodyReader.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestDraft17XmlPATCHBodyReader.java @@ -17,15 +17,15 @@ import org.junit.BeforeClass; import org.junit.Test; import org.opendaylight.netconf.sal.restconf.impl.PATCHContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; -import org.opendaylight.restconf.utils.patch.XmlToPATCHBodyReader; +import org.opendaylight.restconf.jersey.providers.XmlToPATCHBodyReader; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -public class TestDraft11XmlPATCHBodyReader extends Draft11AbstractBodyReaderTest { +public class TestDraft17XmlPATCHBodyReader extends Draft17AbstractBodyReaderTest { private final XmlToPATCHBodyReader xmlPATCHBodyReader; private static SchemaContext schemaContext; - public TestDraft11XmlPATCHBodyReader() throws NoSuchFieldException, SecurityException { + public TestDraft17XmlPATCHBodyReader() throws NoSuchFieldException, SecurityException { super(); xmlPATCHBodyReader = new XmlToPATCHBodyReader(); } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonIdentityrefToNnTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonIdentityrefToNnTest.java index 7649c833d2..a639fef4a4 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonIdentityrefToNnTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonIdentityrefToNnTest.java @@ -10,16 +10,12 @@ package org.opendaylight.controller.sal.restconf.impl.json.to.nn.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.IOException; import java.io.InputStream; - -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; - import org.junit.BeforeClass; import org.junit.Test; -import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; import org.opendaylight.controller.sal.rest.impl.test.providers.AbstractBodyReaderTest; +import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -32,7 +28,7 @@ public class JsonIdentityrefToNnTest extends AbstractBodyReaderTest { public JsonIdentityrefToNnTest() throws NoSuchFieldException, SecurityException { super(); - jsonBodyReader = new JsonNormalizedNodeBodyReader(); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); } @BeforeClass @@ -43,22 +39,20 @@ public class JsonIdentityrefToNnTest extends AbstractBodyReaderTest { } @Test - public void jsonIdentityrefToNn() throws NoSuchFieldException, - SecurityException, IllegalArgumentException, - IllegalAccessException, WebApplicationException, IOException { + public void jsonIdentityrefToNn() throws Exception { - String uri = "identityref-module:cont"; - mockBodyReader(uri, jsonBodyReader, false); - InputStream inputStream = this.getClass().getResourceAsStream( + final String uri = "identityref-module:cont"; + mockBodyReader(uri, this.jsonBodyReader, false); + final InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/identityref/json/data.json"); - NormalizedNodeContext normalizedNodeContext = jsonBodyReader.readFrom( - null, null, null, mediaType, null, inputStream); + final NormalizedNodeContext normalizedNodeContext = this.jsonBodyReader.readFrom( + null, null, null, this.mediaType, null, inputStream); assertEquals("cont", normalizedNodeContext.getData().getNodeType() .getLocalName()); - String dataTree = NormalizedNodes.toStringTree(normalizedNodeContext + final String dataTree = NormalizedNodes.toStringTree(normalizedNodeContext .getData()); assertTrue(dataTree.contains("cont1")); @@ -74,7 +68,6 @@ public class JsonIdentityrefToNnTest extends AbstractBodyReaderTest { @Override protected MediaType getMediaType() { - // TODO Auto-generated method stub return null; } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonLeafrefToNnTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonLeafrefToNnTest.java index d3b65350ed..d44cb15945 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonLeafrefToNnTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonLeafrefToNnTest.java @@ -9,17 +9,12 @@ package org.opendaylight.controller.sal.restconf.impl.json.to.nn.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; - -import java.io.IOException; import java.io.InputStream; - -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; - import org.junit.BeforeClass; import org.junit.Test; -import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; import org.opendaylight.controller.sal.rest.impl.test.providers.AbstractBodyReaderTest; +import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -31,7 +26,7 @@ public class JsonLeafrefToNnTest extends AbstractBodyReaderTest { public JsonLeafrefToNnTest() throws NoSuchFieldException, SecurityException { super(); - jsonBodyReader = new JsonNormalizedNodeBodyReader(); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); } @BeforeClass @@ -42,28 +37,25 @@ public class JsonLeafrefToNnTest extends AbstractBodyReaderTest { } @Test - public void jsonIdentityrefToNormalizeNode() throws NoSuchFieldException, - SecurityException, IllegalArgumentException, - IllegalAccessException, WebApplicationException, IOException { + public void jsonIdentityrefToNormalizeNode() throws Exception { - String uri = "leafref-module:cont"; - mockBodyReader(uri, jsonBodyReader, false); - InputStream inputStream = this.getClass().getResourceAsStream( + final String uri = "leafref-module:cont"; + mockBodyReader(uri, this.jsonBodyReader, false); + final InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/leafref/json/data.json"); - NormalizedNodeContext normalizedNodeContext = jsonBodyReader.readFrom( - null, null, null, mediaType, null, inputStream); + final NormalizedNodeContext normalizedNodeContext = this.jsonBodyReader.readFrom( + null, null, null, this.mediaType, null, inputStream); assertEquals("cont", normalizedNodeContext.getData().getNodeType() .getLocalName()); - String dataTree = NormalizedNodes.toStringTree(normalizedNodeContext + final String dataTree = NormalizedNodes.toStringTree(normalizedNodeContext .getData()); assertTrue(dataTree.contains("lf2 121")); } @Override protected MediaType getMediaType() { - // TODO Auto-generated method stub return null; } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonToNnTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonToNnTest.java index a5fd92375f..3672a3c130 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonToNnTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/nn/test/JsonToNnTest.java @@ -12,17 +12,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - import java.io.IOException; import java.io.InputStream; - import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; - -import org.junit.Ignore; import org.junit.Test; -import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; import org.opendaylight.controller.sal.rest.impl.test.providers.AbstractBodyReaderTest; +import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; @@ -42,25 +38,23 @@ public class JsonToNnTest extends AbstractBodyReaderTest { controllerContext.setSchemas(schemaContext); } - //TODO unignore once yangtools bug is fixed @Test - @Ignore - public void simpleListTest() { + public void simpleListTest() throws Exception { simpleTest("/json-to-nn/simple-list.json", "/json-to-nn/simple-list-yang/1", "lst", "simple-list-yang1"); } @Test - public void simpleContainerTest() { + public void simpleContainerTest() throws Exception { simpleTest("/json-to-nn/simple-container.json", "/json-to-nn/simple-container-yang", "cont", "simple-container-yang"); } @Test - public void multipleItemsInLeafListTest() { + public void multipleItemsInLeafListTest() throws Exception { - initialize("/json-to-nn/simple-list-yang/1", schemaContext); + initialize("/json-to-nn/simple-list-yang/1", this.schemaContext); final NormalizedNodeContext normalizedNodeContext = prepareNNC( "/json-to-nn/multiple-leaflist-items.json", @@ -75,8 +69,8 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void multipleItemsInListTest() { - initialize("/json-to-nn/simple-list-yang/3", schemaContext); + public void multipleItemsInListTest() throws Exception { + initialize("/json-to-nn/simple-list-yang/3", this.schemaContext); final NormalizedNodeContext normalizedNodeContext = prepareNNC( "/json-to-nn/multiple-items-in-list.json", @@ -90,8 +84,8 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void nullArrayToSimpleNodeWithNullValueTest() { - initialize("/json-to-nn/simple-list-yang/4", schemaContext); + public void nullArrayToSimpleNodeWithNullValueTest() throws Exception { + initialize("/json-to-nn/simple-list-yang/4", this.schemaContext); final NormalizedNodeContext normalizedNodeContext = prepareNNC( "/json-to-nn/array-with-null.json", "array-with-null-yang:cont"); @@ -107,13 +101,11 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void incorrectTopLevelElementsTest() throws WebApplicationException, - IOException, NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { + public void incorrectTopLevelElementsTest() throws Exception { - jsonBodyReader = new JsonNormalizedNodeBodyReader(); - initialize("/json-to-nn/simple-list-yang/1", schemaContext); - mockBodyReader("simple-list-yang1:lst", jsonBodyReader, false); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); + initialize("/json-to-nn/simple-list-yang/1", this.schemaContext); + mockBodyReader("simple-list-yang1:lst", this.jsonBodyReader, false); InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/wrong-top-level1.json"); @@ -122,7 +114,7 @@ public class JsonToNnTest extends AbstractBodyReaderTest { RestconfDocumentedException exception = null; try { - jsonBodyReader.readFrom(null, null, null, mediaType, null, + this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream); } catch (final RestconfDocumentedException e) { exception = e; @@ -137,7 +129,7 @@ public class JsonToNnTest extends AbstractBodyReaderTest { "/json-to-nn/wrong-top-level2.json"); exception = null; try { - jsonBodyReader.readFrom(null, null, null, mediaType, null, + this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream); } catch (final RestconfDocumentedException e) { exception = e; @@ -152,7 +144,7 @@ public class JsonToNnTest extends AbstractBodyReaderTest { "/json-to-nn/wrong-top-level3.json"); exception = null; try { - jsonBodyReader.readFrom(null, null, null, mediaType, null, + this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream); } catch (final RestconfDocumentedException e) { exception = e; @@ -166,11 +158,9 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void emptyDataReadTest() throws WebApplicationException, - IOException, NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { + public void emptyDataReadTest() throws Exception { - initialize("/json-to-nn/simple-list-yang/4", schemaContext); + initialize("/json-to-nn/simple-list-yang/4", this.schemaContext); final NormalizedNodeContext normalizedNodeContext = prepareNNC( "/json-to-nn/empty-data.json", "array-with-null-yang:cont"); @@ -186,14 +176,14 @@ public class JsonToNnTest extends AbstractBodyReaderTest { assertTrue(dataTree.contains("lflst2 45")); - jsonBodyReader = new JsonNormalizedNodeBodyReader(); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); RestconfDocumentedException exception = null; - mockBodyReader("array-with-null-yang:cont", jsonBodyReader, false); + mockBodyReader("array-with-null-yang:cont", this.jsonBodyReader, false); final InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/empty-data.json1"); try { - jsonBodyReader.readFrom(null, null, null, mediaType, null, + this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream); } catch (final RestconfDocumentedException e) { exception = e; @@ -204,23 +194,17 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void testJsonBlankInput() throws NoSuchFieldException, - SecurityException, IllegalArgumentException, - IllegalAccessException, WebApplicationException, IOException { - initialize("/json-to-nn/simple-list-yang/4", schemaContext); + public void testJsonBlankInput() throws Exception { + initialize("/json-to-nn/simple-list-yang/4", this.schemaContext); final NormalizedNodeContext normalizedNodeContext = prepareNNC("", "array-with-null-yang:cont"); assertNull(normalizedNodeContext); } - //TODO unignore once yangtools bug is fixed @Test - @Ignore - public void notSupplyNamespaceIfAlreadySupplied() - throws WebApplicationException, IOException, NoSuchFieldException, - SecurityException, IllegalArgumentException, IllegalAccessException { + public void notSupplyNamespaceIfAlreadySupplied()throws Exception { - initialize("/json-to-nn/simple-list-yang/1", schemaContext); + initialize("/json-to-nn/simple-list-yang/1", this.schemaContext); final String uri = "simple-list-yang1" + ":" + "lst"; @@ -230,12 +214,12 @@ public class JsonToNnTest extends AbstractBodyReaderTest { verifyNormaluizedNodeContext(normalizedNodeContext, "lst"); - mockBodyReader("simple-list-yang2:lst", jsonBodyReader, false); + mockBodyReader("simple-list-yang2:lst", this.jsonBodyReader, false); final InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/simple-list.json"); try { - jsonBodyReader.readFrom(null, null, null, mediaType, null, + this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream); fail("NormalizedNodeContext should not be create because of different namespace"); } catch (final RestconfDocumentedException e) { @@ -245,9 +229,9 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void dataAugmentedTest() { + public void dataAugmentedTest() throws Exception { - initialize("/common/augment/yang", schemaContext); + initialize("/common/augment/yang", this.schemaContext); NormalizedNodeContext normalizedNodeContext = prepareNNC( "/common/augment/json/dataa.json", "main:cont"); @@ -274,9 +258,9 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } private void simpleTest(final String jsonPath, final String yangPath, - final String topLevelElementName, final String moduleName) { + final String topLevelElementName, final String moduleName) throws Exception { - initialize(yangPath, schemaContext); + initialize(yangPath, this.schemaContext); final String uri = moduleName + ":" + topLevelElementName; @@ -286,10 +270,10 @@ public class JsonToNnTest extends AbstractBodyReaderTest { verifyNormaluizedNodeContext(normalizedNodeContext, topLevelElementName); } - private NormalizedNodeContext prepareNNC(final String jsonPath, final String uri) { - jsonBodyReader = new JsonNormalizedNodeBodyReader(); + private NormalizedNodeContext prepareNNC(final String jsonPath, final String uri) throws Exception { + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); try { - mockBodyReader(uri, jsonBodyReader, false); + mockBodyReader(uri, this.jsonBodyReader, false); } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { // TODO Auto-generated catch block @@ -300,8 +284,8 @@ public class JsonToNnTest extends AbstractBodyReaderTest { NormalizedNodeContext normalizedNodeContext = null; try { - normalizedNodeContext = jsonBodyReader.readFrom(null, null, null, - mediaType, null, inputStream); + normalizedNodeContext = this.jsonBodyReader.readFrom(null, null, null, + this.mediaType, null, inputStream); } catch (WebApplicationException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -340,12 +324,10 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void unsupportedDataFormatTest() throws NoSuchFieldException, - SecurityException, IllegalArgumentException, - IllegalAccessException, WebApplicationException, IOException { - jsonBodyReader = new JsonNormalizedNodeBodyReader(); - initialize("/json-to-nn/simple-list-yang/1", schemaContext); - mockBodyReader("simple-list-yang1:lst", jsonBodyReader, false); + public void unsupportedDataFormatTest() throws Exception { + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); + initialize("/json-to-nn/simple-list-yang/1", this.schemaContext); + mockBodyReader("simple-list-yang1:lst", this.jsonBodyReader, false); final InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/unsupported-json-format.json"); @@ -353,7 +335,7 @@ public class JsonToNnTest extends AbstractBodyReaderTest { RestconfDocumentedException exception = null; try { - jsonBodyReader.readFrom(null, null, null, mediaType, null, + this.jsonBodyReader.readFrom(null, null, null, this.mediaType, null, inputStream); } catch (final RestconfDocumentedException e) { exception = e; @@ -365,19 +347,17 @@ public class JsonToNnTest extends AbstractBodyReaderTest { } @Test - public void invalidUriCharacterInValue() throws NoSuchFieldException, - SecurityException, IllegalArgumentException, - IllegalAccessException, WebApplicationException, IOException { + public void invalidUriCharacterInValue() throws Exception { - jsonBodyReader = new JsonNormalizedNodeBodyReader(); - initialize("/json-to-nn/simple-list-yang/4", schemaContext); - mockBodyReader("array-with-null-yang:cont", jsonBodyReader, false); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(); + initialize("/json-to-nn/simple-list-yang/4", this.schemaContext); + mockBodyReader("array-with-null-yang:cont", this.jsonBodyReader, false); final InputStream inputStream = this.getClass().getResourceAsStream( "/json-to-nn/invalid-uri-character-in-value.json"); - final NormalizedNodeContext normalizedNodeContext = jsonBodyReader.readFrom( - null, null, null, mediaType, null, inputStream); + final NormalizedNodeContext normalizedNodeContext = this.jsonBodyReader.readFrom( + null, null, null, this.mediaType, null, inputStream); assertNotNull(normalizedNodeContext); assertEquals("cont", normalizedNodeContext.getData().getNodeType() @@ -391,7 +371,6 @@ public class JsonToNnTest extends AbstractBodyReaderTest { @Override protected MediaType getMediaType() { - // TODO Auto-generated method stub return null; }