Bug 5526 - Implementations of services 49/35949/51
authorJakub Toth <jatoth@cisco.com>
Fri, 22 Apr 2016 09:49:40 +0000 (11:49 +0200)
committerJakub Toth <jatoth@cisco.com>
Thu, 5 May 2016 17:07:31 +0000 (17:07 +0000)
  * used soft reference for schema context for holding the current schema
  * util classes for static methodes and constants for implementations
    of services

Change-Id: I5ddccc91feaf3ebfd7f8b40c2f954c4506995622
Signed-off-by: Jakub Toth <jatoth@cisco.com>
13 files changed:
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/Draft11ServicesWrapperImpl.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfModulesServiceImpl.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfOperationsServiceImpl.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfSchemaServiceImpl.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfStreamsServiceImpl.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/SchemaContextRef.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/RestconfConstants.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingNodeConstants.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingNodeUtil.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingStreamConstants.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/parser/ParserIdentifier.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/schema/context/RestconfSchemaUtil.java [new file with mode: 0644]
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/validation/RestconfValidation.java [new file with mode: 0644]

diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/Draft11ServicesWrapperImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/Draft11ServicesWrapperImpl.java
new file mode 100644 (file)
index 0000000..375788a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.rest.impl.services;
+
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
+import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.restconf.rest.api.schema.context.SchemaContextHandler;
+import org.opendaylight.restconf.rest.api.services.Draft11ServicesWrapper;
+import org.opendaylight.restconf.rest.api.services.RestconfModulesService;
+import org.opendaylight.restconf.rest.api.services.RestconfOperationsService;
+import org.opendaylight.restconf.rest.api.services.RestconfStreamsService;
+import org.opendaylight.restconf.rest.api.services.schema.RestconfSchemaService;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Implementation of {@link Draft11ServicesWrapper}
+ *
+ */
+public class Draft11ServicesWrapperImpl implements Draft11ServicesWrapper {
+
+    private final RestconfModulesService delegRestModSer;
+    private final RestconfOperationsService delegRestOpsSer;
+    private final RestconfStreamsService delegRestStrsSer;
+    private final RestconfSchemaService delegRestSchSer;
+
+    /**
+     * Creating delegates to all implemented services
+     *
+     * @param schemaContextHandler
+     *            - for handling {@link SchemaContext}
+     */
+    public Draft11ServicesWrapperImpl(final SchemaContextHandler schemaContextHandler) {
+        this.delegRestModSer = new RestconfModulesServiceImpl(schemaContextHandler);
+        this.delegRestOpsSer = new RestconfOperationsServiceImpl(schemaContextHandler);
+        this.delegRestStrsSer = new RestconfStreamsServiceImpl(schemaContextHandler);
+        this.delegRestSchSer = new RestconfSchemaServiceImpl(schemaContextHandler);
+    }
+
+    @Override
+    public NormalizedNodeContext getModules(final UriInfo uriInfo) {
+        return this.delegRestModSer.getModules(uriInfo);
+    }
+
+    @Override
+    public NormalizedNodeContext getModules(final String identifier, final UriInfo uriInfo) {
+        return this.delegRestModSer.getModules(identifier, uriInfo);
+    }
+
+    @Override
+    public NormalizedNodeContext getModule(final String identifier, final UriInfo uriInfo) {
+        return this.delegRestModSer.getModules(identifier, uriInfo);
+    }
+
+    @Override
+    public NormalizedNodeContext getOperations(final UriInfo uriInfo) {
+        return this.delegRestOpsSer.getOperations(uriInfo);
+    }
+
+    @Override
+    public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
+        return this.delegRestOpsSer.getOperations(identifier, uriInfo);
+    }
+
+    @Override
+    public NormalizedNodeContext getAvailableStreams(final UriInfo uriInfo) {
+        return this.delegRestStrsSer.getAvailableStreams(uriInfo);
+    }
+
+    @Override
+    public SchemaExportContext getSchema(final String mountAndModuleId) {
+        return this.delegRestSchSer.getSchema(mountAndModuleId);
+    }
+
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfModulesServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfModulesServiceImpl.java
new file mode 100644 (file)
index 0000000..8ff0b02
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.rest.impl.services;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.Set;
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.netconf.sal.restconf.impl.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.Draft11;
+import org.opendaylight.restconf.rest.api.schema.context.SchemaContextHandler;
+import org.opendaylight.restconf.rest.api.services.RestconfModulesService;
+import org.opendaylight.restconf.utils.RestconfConstants;
+import org.opendaylight.restconf.utils.mapping.RestconfMappingNodeUtil;
+import org.opendaylight.restconf.utils.parser.ParserIdentifier;
+import org.opendaylight.restconf.utils.schema.context.RestconfSchemaUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of {@link RestconfModulesService}
+ */
+public class RestconfModulesServiceImpl implements RestconfModulesService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(RestconfModulesServiceImpl.class);
+    private final SchemaContextHandler schemaContextHandler;
+
+    /**
+     * Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}
+     *
+     * @param schemaContextHandler
+     *            - handling schema context
+     */
+    public RestconfModulesServiceImpl(final SchemaContextHandler schemaContextHandler) {
+        this.schemaContextHandler = schemaContextHandler;
+    }
+
+    @Override
+    public NormalizedNodeContext getModules(final UriInfo uriInfo) {
+        final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
+        return getModules(schemaContextRef.getModules(), schemaContextRef, null);
+    }
+
+    @Override
+    public NormalizedNodeContext getModules(final String identifier, final UriInfo uriInfo) {
+        Preconditions.checkNotNull(identifier);
+        if (!identifier.contains(RestconfConstants.MOUNT)) {
+            final String errMsg = "URI has bad format. If modules behind mount point should be showed,"
+                    + " URI has to end with " + RestconfConstants.MOUNT;
+            LOG.debug(errMsg + " for " + identifier);
+            throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+        }
+        final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
+        final DOMMountPoint mountPoint = ParserIdentifier.toInstanceIdentifier(identifier).getMountPoint();
+        return getModules(schemaContextRef.getModules(mountPoint), schemaContextRef, mountPoint);
+    }
+
+
+    @Override
+    public NormalizedNodeContext getModule(final String identifier, final UriInfo uriInfo) {
+        Preconditions.checkNotNull(identifier);
+        final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
+        final QName moduleQname = ParserIdentifier.makeQNameFromIdentifier(identifier);
+        Module module = null;
+        DOMMountPoint mountPoint = null;
+        if (identifier.contains(RestconfConstants.MOUNT)) {
+            mountPoint = ParserIdentifier.toInstanceIdentifier(identifier).getMountPoint();
+            module = schemaContextRef.findModuleInMountPointByQName(mountPoint, moduleQname);
+        } else {
+            module = schemaContextRef.findModuleByQName(moduleQname);
+        }
+
+        if (module == null) {
+            final String errMsg = "Module with name '" + moduleQname.getLocalName() + "' and revision '"
+                    + moduleQname.getRevision() + "' was not found.";
+            LOG.debug(errMsg);
+            throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
+        }
+
+        final Set<Module> modules = Collections.singleton(module);
+        final MapNode moduleMap = RestconfMappingNodeUtil
+                .restconfMappingNode(schemaContextRef.getRestconfModule(), modules);
+        final DataSchemaNode moduleSchemaNode = RestconfSchemaUtil.getRestconfSchemaNode(
+                schemaContextRef.getRestconfModule(), Draft11.RestconfModule.MODULE_LIST_SCHEMA_NODE);
+        Preconditions.checkState(moduleSchemaNode instanceof ListSchemaNode);
+        return new NormalizedNodeContext(
+                new InstanceIdentifierContext<>(null, moduleSchemaNode, mountPoint, schemaContextRef.get()), moduleMap);
+        }
+
+    /**
+     * Get {@link NormalizedNodeContext} from set of modules. Used by
+     * {@link #getModules(UriInfo)} and {@link #getModules(String, UriInfo)}
+     *
+     * @param modules
+     *            - all modules
+     * @param schemaContextRef
+     *            - schema context reference
+     * @param mountPoint
+     *            - mount point
+     * @return {@link NormalizedNodeContext}
+     */
+    private NormalizedNodeContext getModules(final Set<Module> modules, final SchemaContextRef schemaContextRef,
+            final DOMMountPoint mountPoint) {
+        final Module restconfModule = schemaContextRef.getRestconfModule();
+        Preconditions.checkNotNull(restconfModule);
+
+        final MapNode mapNodes = RestconfMappingNodeUtil.restconfMappingNode(restconfModule, modules);
+        final DataSchemaNode schemaNode = RestconfSchemaUtil.getRestconfSchemaNode(restconfModule,
+                Draft11.RestconfModule.MODULES_CONTAINER_SCHEMA_NODE);
+        Preconditions.checkState(schemaNode instanceof ContainerSchemaNode);
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> modulContainerSchemaNodeBuilder = Builders
+                .containerBuilder((ContainerSchemaNode) schemaNode);
+        modulContainerSchemaNodeBuilder.withChild(mapNodes);
+
+        return new NormalizedNodeContext(
+                new InstanceIdentifierContext<>(null, schemaNode, mountPoint, schemaContextRef.get()),
+                modulContainerSchemaNodeBuilder.build());
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfOperationsServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfOperationsServiceImpl.java
new file mode 100644 (file)
index 0000000..09a3530
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.rest.impl.services;
+
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.restconf.rest.api.schema.context.SchemaContextHandler;
+import org.opendaylight.restconf.rest.api.services.RestconfOperationsService;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Implementation of {@link RestconfOperationsService}
+ *
+ */
+public class RestconfOperationsServiceImpl implements RestconfOperationsService {
+
+    private final SchemaContextHandler schemaContextHandler;
+
+    /**
+     * Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}
+     *
+     * @param schemaContextHandler
+     *            - handling schema context
+     */
+    public RestconfOperationsServiceImpl(final SchemaContextHandler schemaContextHandler) {
+        this.schemaContextHandler = schemaContextHandler;
+    }
+
+    @Override
+    public NormalizedNodeContext getOperations(final UriInfo uriInfo) {
+        throw new RestconfDocumentedException("Not yet implemented.", new UnsupportedOperationException());
+    }
+
+
+    @Override
+    public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
+        throw new RestconfDocumentedException("Not yet implemented.", new UnsupportedOperationException());
+    }
+
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfSchemaServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfSchemaServiceImpl.java
new file mode 100644 (file)
index 0000000..bf30b76
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.rest.impl.services;
+
+import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
+import org.opendaylight.restconf.rest.api.schema.context.SchemaContextHandler;
+import org.opendaylight.restconf.rest.api.services.schema.RestconfSchemaService;
+import org.opendaylight.restconf.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Implementation of {@link RestconfSchemaService}.
+ *
+ */
+public class RestconfSchemaServiceImpl implements RestconfSchemaService {
+
+    private final SchemaContextHandler schemaContextHandler;
+
+    /**
+     * Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}
+     * .
+     *
+     * @param schemaContextHandler
+     *            - handling schema context
+     */
+    public RestconfSchemaServiceImpl(final SchemaContextHandler schemaContextHandler) {
+        this.schemaContextHandler = schemaContextHandler;
+    }
+
+    @Override
+    public SchemaExportContext getSchema(final String identifier) {
+        final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
+        return ParserIdentifier.toSchemaExportContextFromIdentifier(schemaContextRef.get(), identifier);
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfStreamsServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/RestconfStreamsServiceImpl.java
new file mode 100644 (file)
index 0000000..1b63652
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.rest.impl.services;
+
+import com.google.common.base.Preconditions;
+import java.util.Set;
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.netconf.sal.streams.listeners.Notificator;
+import org.opendaylight.restconf.Draft11;
+import org.opendaylight.restconf.rest.api.schema.context.SchemaContextHandler;
+import org.opendaylight.restconf.rest.api.services.RestconfStreamsService;
+import org.opendaylight.restconf.utils.mapping.RestconfMappingNodeUtil;
+import org.opendaylight.restconf.utils.schema.context.RestconfSchemaUtil;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Implementation of {@link RestconfStreamsService}
+ *
+ */
+public class RestconfStreamsServiceImpl implements RestconfStreamsService {
+
+    private final SchemaContextHandler schemaContextHandler;
+
+    /**
+     * Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}
+     * .
+     *
+     * @param schemaContextHandler
+     *            - handling schema context
+     */
+    public RestconfStreamsServiceImpl(final SchemaContextHandler schemaContextHandler) {
+        this.schemaContextHandler = schemaContextHandler;
+    }
+
+    @Override
+    public NormalizedNodeContext getAvailableStreams(final UriInfo uriInfo) {
+        final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
+        final Set<String> availableStreams = Notificator.getStreamNames();
+
+        final DataSchemaNode streamListSchemaNode = RestconfSchemaUtil.getRestconfSchemaNode(
+                schemaContextRef.getRestconfModule(), Draft11.MonitoringModule.STREAM_LIST_SCHEMA_NODE);
+        Preconditions.checkState(streamListSchemaNode instanceof ListSchemaNode);
+        final CollectionNodeBuilder<MapEntryNode, MapNode> listStreamBuilder = Builders
+                .mapBuilder((ListSchemaNode) streamListSchemaNode);
+
+        for (final String streamValue : availableStreams) {
+            listStreamBuilder.withChild(RestconfMappingNodeUtil.toStreamEntryNode(streamValue, streamListSchemaNode));
+        }
+
+        final DataSchemaNode streamContSchemaNode = RestconfSchemaUtil.getRestconfSchemaNode(
+                schemaContextRef.getRestconfModule(), Draft11.MonitoringModule.STREAMS_CONTAINER_SCHEMA_NODE);
+        Preconditions.checkState(streamContSchemaNode instanceof ContainerSchemaNode);
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> streamsContainerBuilder = Builders
+                .containerBuilder((ContainerSchemaNode) streamContSchemaNode);
+
+        streamsContainerBuilder.withChild(listStreamBuilder.build());
+
+        return new NormalizedNodeContext(
+                new InstanceIdentifierContext<>(null, streamContSchemaNode, null, schemaContextRef.get()),
+                streamsContainerBuilder.build());
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/SchemaContextRef.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/rest/impl/services/SchemaContextRef.java
new file mode 100644 (file)
index 0000000..b4a385e
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.rest.impl.services;
+
+import java.lang.ref.SoftReference;
+import java.net.URI;
+import java.util.Date;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.restconf.Draft11;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * This class creates {@link SoftReference} of actual {@link SchemaContext}
+ * object and even if the {@link SchemaContext} changes, this will be sticks
+ * reference to the old {@link SchemaContext} and provides work with the old
+ * {@link SchemaContext}.
+ *
+ */
+final class SchemaContextRef {
+
+    private final SoftReference<SchemaContext> schemaContextRef;
+
+    /**
+     * Create {@link SoftReference} of actual {@link SchemaContext}
+     *
+     * @param schemaContext
+     *            - actual {@link SchemaContext}
+     */
+    public SchemaContextRef(final SchemaContext schemaContext) {
+        this.schemaContextRef = new SoftReference<SchemaContext>(schemaContext);
+    }
+
+    /**
+     * Get {@link SchemaContext} from reference
+     *
+     * @return {@link SchemaContext}
+     */
+    public SchemaContext get() {
+        return this.schemaContextRef.get();
+    }
+
+    /**
+     * Get all modules like {@link Set} of {@link Module} from
+     * {@link SchemaContext}
+     *
+     * @return {@link Set} of {@link Module}
+     */
+    public Set<Module> getModules() {
+        return get().getModules();
+    }
+
+    /**
+     * Get all modules like {@link Set} of {@link Module} from
+     * {@link SchemaContext} of {@link DOMMountPoint}
+     *
+     * @param mountPoint
+     *            - mount point
+     *
+     * @return {@link Set} of {@link Module}
+     */
+    public Set<Module> getModules(final DOMMountPoint mountPoint) {
+        final SchemaContext schemaContext = mountPoint == null ? null : mountPoint.getSchemaContext();
+        return schemaContext == null ? null : schemaContext.getModules();
+    }
+
+    /**
+     * Get {@link Module} by ietf-restconf qname from
+     * {@link Draft09.RestconfModule}
+     *
+     * @return {@link Module}
+     */
+    public Module getRestconfModule() {
+        return this.findModuleByNamespaceAndRevision(Draft11.RestconfModule.IETF_RESTCONF_QNAME.getNamespace(),
+                Draft11.RestconfModule.IETF_RESTCONF_QNAME.getRevision());
+    }
+
+    /**
+     * Find {@link Module} in {@link SchemaContext} by {@link URI} and
+     * {@link Date}
+     *
+     * @param namespace
+     *            - namespace of module
+     * @param revision
+     *            - revision of module
+     * @return {@link Module}
+     */
+    public Module findModuleByNamespaceAndRevision(final URI namespace, final Date revision) {
+        return this.get().findModuleByNamespaceAndRevision(namespace, revision);
+    }
+
+
+    /**
+     * Find {@link Module} in {@link SchemaContext} of {@link DOMMountPoint} by
+     * {@link QName} of {@link Module}
+     *
+     * @param mountPoint
+     *            - mount point
+     * @param qname
+     *            - {@link QName} of module
+     * @return {@link Module}
+     */
+    public Module findModuleInMountPointByQName(final DOMMountPoint mountPoint, final QName moduleQname) {
+        final SchemaContext schemaContext = mountPoint == null ? null : mountPoint.getSchemaContext();
+        return schemaContext == null ? null
+                : schemaContext.findModuleByName(moduleQname.getLocalName(), moduleQname.getRevision());
+    }
+
+    /**
+     * Find {@link Module} in {@link SchemaContext} by {@link QName}
+     *
+     * @param moduleQname
+     *            - {@link QName} of module
+     * @return {@link Module}
+     */
+    public Module findModuleByQName(final QName moduleQname) {
+        return this.findModuleByNameAndRevision(moduleQname.getLocalName(), moduleQname.getRevision());
+    }
+
+    /**
+     * Find {@link Module} in {@link SchemaContext} by {@link String} localName
+     * and {@link Date} revision.
+     *
+     * @param localName
+     *            - local name of module
+     * @param revision
+     *            - revision of module
+     * @return {@link Module}
+     */
+    public Module findModuleByNameAndRevision(final String localName, final Date revision) {
+        return this.get().findModuleByName(localName, revision);
+    }
+
+}
index d9888a962bf1007e0f5ae1ce9a9c9ad1cfbddf7a..bef0be9dfccc1d2b379a20c783f0dbf401cc5cb9 100644 (file)
@@ -7,16 +7,21 @@
  */
 package org.opendaylight.restconf.utils;
 
+import com.google.common.base.Splitter;
+import java.text.SimpleDateFormat;
+
 /**
  * Util class for Restconf constants.
  *
  */
-public class RestconfConstants {
+public final class RestconfConstants {
 
     public static final String XML = "+xml";
     public static final String JSON = "+json";
-
+    public static final String MOUNT = "yang-ext:mount";
     public static final String IDENTIFIER = "identifier";
+    public static final SimpleDateFormat REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+    public static final Splitter SLASH_SPLITTER = Splitter.on("/");
 
     private RestconfConstants() {
         throw new UnsupportedOperationException("Util class");
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingNodeConstants.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingNodeConstants.java
new file mode 100644 (file)
index 0000000..6938af4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.utils.mapping;
+
+/**
+ * Util class for constants of mapping node
+ *
+ */
+public final class RestconfMappingNodeConstants {
+
+    public static final String NAME = "name";
+    public static final String REVISION = "revision";
+    public static final String NAMESPACE = "namespace";
+    public static final String FEATURE = "feature";
+    public static final String DESCRIPTION = "description";
+    public static final String REPLAY_SUPPORT = "replay-support";
+    public static final String REPLAY_LOG = "replay-log-creation-time";
+    public static final String EVENTS = "events";
+
+    private RestconfMappingNodeConstants() {
+        throw new UnsupportedOperationException("Util class.");
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingNodeUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingNodeUtil.java
new file mode 100644 (file)
index 0000000..939f3ac
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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.utils.mapping;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Set;
+import org.opendaylight.restconf.Draft11;
+import org.opendaylight.restconf.utils.RestconfConstants;
+import org.opendaylight.restconf.utils.schema.context.RestconfSchemaUtil;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+/**
+ * Util class for mapping nodes
+ *
+ */
+public final class RestconfMappingNodeUtil {
+
+    private RestconfMappingNodeUtil() {
+        throw new UnsupportedOperationException("Util class");
+    }
+
+    /**
+     * Mapping {@link Module} from {@link Set} of {@link Module} to
+     * {@link ListSchemaNode} of {@link Module} list.
+     *
+     * @param restconfModule
+     *            - restconf module
+     * @param modules
+     *            - all modules
+     * @return {@link MapNode}
+     */
+    public static MapNode restconfMappingNode(final Module restconfModule, final Set<Module> modules) {
+        final DataSchemaNode modulListSchemaNode = RestconfSchemaUtil.getRestconfSchemaNode(restconfModule,
+                Draft11.RestconfModule.MODULE_LIST_SCHEMA_NODE);
+        Preconditions.checkState(modulListSchemaNode instanceof ListSchemaNode);
+
+        final CollectionNodeBuilder<MapEntryNode, MapNode> listModuleBuilder = Builders
+                .mapBuilder((ListSchemaNode) modulListSchemaNode);
+        for (final Module module : modules) {
+            listModuleBuilder.withChild(toModuleEntryNode(module, modulListSchemaNode));
+        }
+        return listModuleBuilder.build();
+    }
+
+    /**
+     * Mapping {@link MapEntryNode} entries of {@link Module} to
+     * {@link ListSchemaNode}.
+     *
+     * @param module
+     *            - module for mapping
+     * @param modulListSchemaNode
+     *            - mapped {@link DataSchemaNode}
+     * @return {@link MapEntryNode}
+     */
+    private static MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode modulListSchemaNode) {
+        final ListSchemaNode listSchemaNode = (ListSchemaNode) modulListSchemaNode;
+        final Collection<DataSchemaNode> childListSchemaNode = listSchemaNode.getChildNodes();
+        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> moduleNodeValues = Builders
+                .mapEntryBuilder(listSchemaNode);
+
+        // MODULE NAME SCHEMA NODE
+        fillListWithLeaf(listSchemaNode, moduleNodeValues, RestconfMappingNodeConstants.NAME, module.getName());
+
+        // MODULE REVISION SCHEMA NODE
+        fillListWithLeaf(listSchemaNode, moduleNodeValues, RestconfMappingNodeConstants.REVISION,
+                RestconfConstants.REVISION_FORMAT.format(module.getRevision()));
+
+        // MODULE NAMESPACE SCHEMA NODE
+        fillListWithLeaf(listSchemaNode, moduleNodeValues, RestconfMappingNodeConstants.NAMESPACE,
+                module.getNamespace().toString());
+
+        // MODULE FEATURES SCHEMA NODES
+        final DataSchemaNode schemaNode = RestconfSchemaUtil.findSchemaNodeInCollection(childListSchemaNode,
+                RestconfMappingNodeConstants.FEATURE);
+        Preconditions.checkState(schemaNode instanceof LeafListSchemaNode);
+        final ListNodeBuilder<Object, LeafSetEntryNode<Object>> featureBuilder = Builders
+                .leafSetBuilder((LeafListSchemaNode) schemaNode);
+        for (final FeatureDefinition feature : module.getFeatures()) {
+            featureBuilder.withChild(Builders.leafSetEntryBuilder((LeafListSchemaNode) schemaNode)
+                    .withValue(feature.getQName().getLocalName()).build());
+        }
+        moduleNodeValues.withChild(featureBuilder.build());
+
+        return moduleNodeValues.build();
+    }
+
+    /**
+     * Mapping {@link MapEntryNode} stream entries of stream to
+     * {@link ListSchemaNode}
+     *
+     * @param streamName
+     *            - stream name
+     * @param streamListSchemaNode
+     *            - mapped {@link DataSchemaNode}
+     * @return {@link MapEntryNode}
+     */
+    public static MapEntryNode toStreamEntryNode(final String streamName, final DataSchemaNode streamListSchemaNode) {
+        Preconditions.checkState(streamListSchemaNode instanceof ListSchemaNode);
+        final ListSchemaNode listStreamSchemaNode = (ListSchemaNode) streamListSchemaNode;
+        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamNodeValues = Builders
+                .mapEntryBuilder(listStreamSchemaNode);
+
+        // STREAM NAME
+        fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.NAME, streamName);
+
+        // STREAM DESCRIPTION
+        fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.DESCRIPTION,
+                RestconfMappingStreamConstants.DESCRIPTION);
+
+        // STREAM REPLAY_SUPPORT
+        fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.REPLAY_SUPPORT,
+                RestconfMappingStreamConstants.REPLAY_SUPPORT);
+
+        // STREAM REPLAY_LOG
+        fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.REPLAY_LOG,
+                RestconfMappingStreamConstants.REPLAY_LOG);
+
+        // STREAM EVENTS
+        fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.EVENTS,
+                RestconfMappingStreamConstants.EVENTS);
+
+        return streamNodeValues.build();
+    }
+
+    /**
+     * Method for filling {@link ListSchemaNode} with {@link LeafSchemaNode}
+     *
+     * @param listStreamSchemaNode
+     *            - {@link ListSchemaNode}
+     * @param streamNodeValues
+     *            - filled {@link DataContainerNodeAttrBuilder}
+     * @param nameSchemaNode
+     *            - name of mapped leaf
+     * @param value
+     *            - value for mapped node
+     */
+    private static void fillListWithLeaf(
+            final ListSchemaNode listStreamSchemaNode,
+            final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamNodeValues,
+            final String nameSchemaNode, final Object value) {
+        final DataSchemaNode schemaNode = RestconfSchemaUtil
+                .findSchemaNodeInCollection(listStreamSchemaNode.getChildNodes(), nameSchemaNode);
+        Preconditions.checkState(schemaNode instanceof LeafSchemaNode);
+        streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) schemaNode).withValue(value).build());
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingStreamConstants.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/mapping/RestconfMappingStreamConstants.java
new file mode 100644 (file)
index 0000000..912dac4
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.utils.mapping;
+
+/**
+ * Util class for mapping entry stream
+ *
+ */
+public final class RestconfMappingStreamConstants {
+
+    public static final String DESCRIPTION = "DESCRIPTION_PLACEHOLDER";
+    public static final Boolean REPLAY_SUPPORT = Boolean.valueOf(true);
+    public static final String REPLAY_LOG = "";
+    public static final String EVENTS = "";
+
+    private RestconfMappingStreamConstants() {
+        throw new UnsupportedOperationException("Util class");
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/parser/ParserIdentifier.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/parser/ParserIdentifier.java
new file mode 100644 (file)
index 0000000..355b9a3
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.utils.parser;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+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.utils.RestconfConstants;
+import org.opendaylight.restconf.utils.validation.RestconfValidation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util class for parsing identifier
+ *
+ */
+public final class ParserIdentifier {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ParserIdentifier.class);
+
+    public static InstanceIdentifierContext<?> toInstanceIdentifier(final String identifier) {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    /**
+     * Make a {@link QName} from identifier
+     *
+     * @param identifier
+     *            - path parameter
+     * @return {@link QName}
+     */
+    public static QName makeQNameFromIdentifier(final String identifier) {
+        final int mountIndex = identifier.indexOf(RestconfConstants.MOUNT);
+        String moduleNameAndRevision = "";
+        if (mountIndex >= 0) {
+            moduleNameAndRevision = identifier.substring(mountIndex + RestconfConstants.MOUNT.length());
+        } else {
+            moduleNameAndRevision = identifier;
+        }
+
+        final Splitter splitter = Splitter.on("/").omitEmptyStrings();
+        final Iterable<String> split = splitter.split(moduleNameAndRevision);
+        final List<String> pathArgs = Lists.<String> newArrayList(split);
+        if (pathArgs.size() < 2) {
+            LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' " + identifier);
+            throw new RestconfDocumentedException(
+                    "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'", ErrorType.PROTOCOL,
+                    ErrorTag.INVALID_VALUE);
+        }
+
+        try {
+            final String moduleName = pathArgs.get(0);
+            final String revision = pathArgs.get(1);
+            final Date moduleRevision = RestconfConstants.REVISION_FORMAT.parse(revision);
+
+            return QName.create(null, moduleRevision, moduleName);
+        } catch (final ParseException e) {
+            LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' " + identifier);
+            throw new RestconfDocumentedException("URI has bad format. It should be \'moduleName/yyyy-MM-dd\'",
+                    ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+        }
+    }
+
+    /**
+     * Parsing {@link Module} module by {@link String} module name and
+     * {@link Date} revision and from the parsed module create
+     * {@link SchemaExportContext}
+     *
+     * @param schemaContext
+     *            - {@link SchemaContext}
+     * @param identifier
+     *            - path parameter
+     * @return {@link SchemaExportContext}
+     */
+    public static SchemaExportContext toSchemaExportContextFromIdentifier(final SchemaContext schemaContext,
+            final String identifier) {
+        final Iterable<String> pathComponents = RestconfConstants.SLASH_SPLITTER.split(identifier);
+        final Iterator<String> componentIter = pathComponents.iterator();
+        if (!Iterables.contains(pathComponents, RestconfConstants.MOUNT)) {
+            final String moduleName = RestconfValidation.validateAndGetModulName(componentIter);
+            final Date revision = RestconfValidation.validateAndGetRevision(componentIter);
+            final Module module = schemaContext.findModuleByName(moduleName, revision);
+            return new SchemaExportContext(schemaContext, module);
+        } else {
+            final StringBuilder pathBuilder = new StringBuilder();
+            while (componentIter.hasNext()) {
+                final String current = componentIter.next();
+                if (pathBuilder.length() != 0) {
+                    pathBuilder.append("/");
+                }
+                pathBuilder.append(current);
+                if (RestconfConstants.MOUNT.equals(current)) {
+                    break;
+                }
+            }
+            final InstanceIdentifierContext<?> mountPoint = ParserIdentifier
+                    .toInstanceIdentifier(pathBuilder.toString());
+            final String moduleName = RestconfValidation.validateAndGetModulName(componentIter);
+            final Date revision = RestconfValidation.validateAndGetRevision(componentIter);
+            final Module module = mountPoint.getSchemaContext().findModuleByName(moduleName, revision);
+            return new SchemaExportContext(mountPoint.getSchemaContext(), module);
+        }
+    }
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/schema/context/RestconfSchemaUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/schema/context/RestconfSchemaUtil.java
new file mode 100644 (file)
index 0000000..fbeb7d9
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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.utils.schema.context;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Set;
+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.Draft11;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+/**
+ * Util class for finding {@link DataSchemaNode}.
+ *
+ */
+public final class RestconfSchemaUtil {
+
+    private RestconfSchemaUtil() {
+        throw new UnsupportedOperationException("Util class");
+    }
+
+    /**
+     * Get {@link DataSchemaNode} from {@link Module} Restconf module by
+     * {@link String} schema node name.
+     *
+     * @param restconfModule
+     *            - restconf module
+     * @param schemaNodeName
+     *            - schema node name
+     * @return {@link DataSchemaNode}
+     */
+    public static DataSchemaNode getRestconfSchemaNode(final Module restconfModule, final String schemaNodeName) {
+
+        final Set<GroupingDefinition> groupings = restconfModule.getGroupings();
+        final GroupingDefinition restGroup = findSchemaNodeInCollection(groupings,
+                Draft11.RestconfModule.RESTCONF_GROUPING_SCHEMA_NODE);
+        final Collection<DataSchemaNode> childNodes = restGroup.getChildNodes();
+        final DataSchemaNode restCont = childNodes.iterator().next();
+
+        return findSchemaNode(restCont, schemaNodeName);
+    }
+
+    /**
+     * Find specific {@link DataSchemaNode} child in {@link DataNodeContainer}
+     * by {@link String} schema node name.
+     *
+     * @param restCont
+     *            - restconf container
+     * @param schemaNodeName
+     *            - schema node name
+     * @return {@link DataSchemaNode}
+     */
+    private static DataSchemaNode findSchemaNode(final DataSchemaNode restCont, final String schemaNodeName) {
+        switch (schemaNodeName) {
+            //MODULES
+            case Draft11.RestconfModule.MODULE_LIST_SCHEMA_NODE:
+                final DataSchemaNode moduleListSchNode = findSchemaNodeInCollection(
+                        ((DataNodeContainer) findSchemaNode(restCont,
+                                Draft11.RestconfModule.MODULES_CONTAINER_SCHEMA_NODE)).getChildNodes(),
+                        Draft11.RestconfModule.MODULE_LIST_SCHEMA_NODE);
+                Preconditions.checkNotNull(moduleListSchNode);
+                return moduleListSchNode;
+            case Draft11.RestconfModule.MODULES_CONTAINER_SCHEMA_NODE:
+                final DataSchemaNode modulesContSchNode = findSchemaNodeInCollection(((DataNodeContainer) restCont).getChildNodes(),
+                        Draft11.RestconfModule.MODULES_CONTAINER_SCHEMA_NODE);
+                Preconditions.checkNotNull(modulesContSchNode);
+                return modulesContSchNode;
+
+            //STREAMS
+            case Draft11.MonitoringModule.STREAM_LIST_SCHEMA_NODE:
+                final DataSchemaNode streamListSchNode = findSchemaNodeInCollection(
+                        ((DataNodeContainer) findSchemaNode(restCont,
+                                Draft11.MonitoringModule.STREAMS_CONTAINER_SCHEMA_NODE)).getChildNodes(),
+                        Draft11.MonitoringModule.STREAM_LIST_SCHEMA_NODE);
+                Preconditions.checkNotNull(streamListSchNode);
+                return streamListSchNode;
+            case Draft11.MonitoringModule.STREAMS_CONTAINER_SCHEMA_NODE:
+                final DataSchemaNode streamsContSchNode = findSchemaNodeInCollection(
+                        ((DataNodeContainer) restCont).getChildNodes(),
+                        Draft11.MonitoringModule.STREAMS_CONTAINER_SCHEMA_NODE);
+                Preconditions.checkNotNull(streamsContSchNode);
+                return streamsContSchNode;
+            default:
+                throw new RestconfDocumentedException("Schema node " + schemaNodeName + " does not exist in module.",
+                        ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+        }
+    }
+
+    /**
+     * Find child of {@link SchemaNode} in {@link Collection} by {@link String}
+     * schema node name.
+     *
+     * @param <T>
+     *            - child of SchemaNode
+     * @param collection
+     *            - child of node
+     * @param schemaNodeName
+     *            - schema node name
+     * @return {@link SchemaNode}
+     */
+    public static <T extends SchemaNode> T findSchemaNodeInCollection(final Collection<T> collection,
+            final String schemaNodeName) {
+        for (final T child : collection) {
+            if (child.getQName().getLocalName().equals(schemaNodeName)) {
+                return child;
+            }
+        }
+        throw new RestconfDocumentedException("Schema node " + schemaNodeName + " does not exist in module.",
+                ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+    }
+
+}
diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/validation/RestconfValidation.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/utils/validation/RestconfValidation.java
new file mode 100644 (file)
index 0000000..d688a8f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.utils.validation;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Iterator;
+import org.opendaylight.netconf.md.sal.rest.common.RestconfValidationUtils;
+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.yangtools.yang.common.SimpleDateFormatUtil;
+
+/**
+ * Util class for validations
+ *
+ */
+public final class RestconfValidation {
+
+    private RestconfValidation() {
+        throw new UnsupportedOperationException("Util class.");
+    }
+
+    /**
+     * Validation and parsing of revision.
+     *
+     * @param revisionDate
+     *            - iterator
+     * @return {@link Date}
+     */
+    public static Date validateAndGetRevision(final Iterator<String> revisionDate) {
+        RestconfValidationUtils.checkDocumentedError(revisionDate.hasNext(), ErrorType.PROTOCOL,
+                ErrorTag.INVALID_VALUE, "Revision date must be supplied.");
+        try {
+            return SimpleDateFormatUtil.getRevisionFormat().parse(revisionDate.next());
+        } catch (final ParseException e) {
+            throw new RestconfDocumentedException("Supplied revision is not in expected date format YYYY-mm-dd", e);
+        }
+    }
+
+    /**
+     * Validation of name.
+     *
+     * @param moduleName
+     *            - iterator
+     * @return {@link String}
+     */
+    public static String validateAndGetModulName(final Iterator<String> moduleName) {
+        RestconfValidationUtils.checkDocumentedError(moduleName.hasNext(), ErrorType.PROTOCOL,
+                ErrorTag.INVALID_VALUE, "Module name must be supplied.");
+        return moduleName.next();
+    }
+
+}