--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
*/
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");
--- /dev/null
+/*
+ * 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.");
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}