Merge "Bug 3864: Notify netconf monitoring about changes in session"
[netconf.git] / restconf / sal-rest-connector / src / main / java / org / opendaylight / restconf / rest / impl / services / RestconfModulesServiceImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.restconf.rest.impl.services;
9
10 import com.google.common.base.Preconditions;
11 import java.util.Collections;
12 import java.util.Set;
13 import javax.ws.rs.core.UriInfo;
14 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
15 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
16 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
17 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
18 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
19 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
20 import org.opendaylight.restconf.Draft11;
21 import org.opendaylight.restconf.rest.api.schema.context.SchemaContextHandler;
22 import org.opendaylight.restconf.rest.api.services.RestconfModulesService;
23 import org.opendaylight.restconf.utils.RestconfConstants;
24 import org.opendaylight.restconf.utils.mapping.RestconfMappingNodeUtil;
25 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
26 import org.opendaylight.restconf.utils.schema.context.RestconfSchemaUtil;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
31 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
33 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.Module;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Implementation of {@link RestconfModulesService}
43  */
44 public class RestconfModulesServiceImpl implements RestconfModulesService {
45
46     private static final Logger LOG = LoggerFactory.getLogger(RestconfModulesServiceImpl.class);
47     private final SchemaContextHandler schemaContextHandler;
48
49     /**
50      * Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}
51      *
52      * @param schemaContextHandler
53      *            - handling schema context
54      */
55     public RestconfModulesServiceImpl(final SchemaContextHandler schemaContextHandler) {
56         this.schemaContextHandler = schemaContextHandler;
57     }
58
59     @Override
60     public NormalizedNodeContext getModules(final UriInfo uriInfo) {
61         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
62         return getModules(schemaContextRef.getModules(), schemaContextRef, null);
63     }
64
65     @Override
66     public NormalizedNodeContext getModules(final String identifier, final UriInfo uriInfo) {
67         Preconditions.checkNotNull(identifier);
68         if (!identifier.contains(RestconfConstants.MOUNT)) {
69             final String errMsg = "URI has bad format. If modules behind mount point should be showed,"
70                     + " URI has to end with " + RestconfConstants.MOUNT;
71             LOG.debug(errMsg + " for " + identifier);
72             throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
73         }
74         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
75         final DOMMountPoint mountPoint = ParserIdentifier.toInstanceIdentifier(identifier).getMountPoint();
76         return getModules(schemaContextRef.getModules(mountPoint), schemaContextRef, mountPoint);
77     }
78
79
80     @Override
81     public NormalizedNodeContext getModule(final String identifier, final UriInfo uriInfo) {
82         Preconditions.checkNotNull(identifier);
83         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.getSchemaContext());
84         final QName moduleQname = ParserIdentifier.makeQNameFromIdentifier(identifier);
85         Module module = null;
86         DOMMountPoint mountPoint = null;
87         if (identifier.contains(RestconfConstants.MOUNT)) {
88             mountPoint = ParserIdentifier.toInstanceIdentifier(identifier).getMountPoint();
89             module = schemaContextRef.findModuleInMountPointByQName(mountPoint, moduleQname);
90         } else {
91             module = schemaContextRef.findModuleByQName(moduleQname);
92         }
93
94         if (module == null) {
95             final String errMsg = "Module with name '" + moduleQname.getLocalName() + "' and revision '"
96                     + moduleQname.getRevision() + "' was not found.";
97             LOG.debug(errMsg);
98             throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT);
99         }
100
101         final Set<Module> modules = Collections.singleton(module);
102         final MapNode moduleMap = RestconfMappingNodeUtil
103                 .restconfMappingNode(schemaContextRef.getRestconfModule(), modules);
104         final DataSchemaNode moduleSchemaNode = RestconfSchemaUtil.getRestconfSchemaNode(
105                 schemaContextRef.getRestconfModule(), Draft11.RestconfModule.MODULE_LIST_SCHEMA_NODE);
106         Preconditions.checkState(moduleSchemaNode instanceof ListSchemaNode);
107         return new NormalizedNodeContext(
108                 new InstanceIdentifierContext<>(null, moduleSchemaNode, mountPoint, schemaContextRef.get()), moduleMap);
109         }
110
111     /**
112      * Get {@link NormalizedNodeContext} from set of modules. Used by
113      * {@link #getModules(UriInfo)} and {@link #getModules(String, UriInfo)}
114      *
115      * @param modules
116      *            - all modules
117      * @param schemaContextRef
118      *            - schema context reference
119      * @param mountPoint
120      *            - mount point
121      * @return {@link NormalizedNodeContext}
122      */
123     private NormalizedNodeContext getModules(final Set<Module> modules, final SchemaContextRef schemaContextRef,
124             final DOMMountPoint mountPoint) {
125         final Module restconfModule = schemaContextRef.getRestconfModule();
126         Preconditions.checkNotNull(restconfModule);
127
128         final MapNode mapNodes = RestconfMappingNodeUtil.restconfMappingNode(restconfModule, modules);
129         final DataSchemaNode schemaNode = RestconfSchemaUtil.getRestconfSchemaNode(restconfModule,
130                 Draft11.RestconfModule.MODULES_CONTAINER_SCHEMA_NODE);
131         Preconditions.checkState(schemaNode instanceof ContainerSchemaNode);
132         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> modulContainerSchemaNodeBuilder = Builders
133                 .containerBuilder((ContainerSchemaNode) schemaNode);
134         modulContainerSchemaNodeBuilder.withChild(mapNodes);
135
136         return new NormalizedNodeContext(
137                 new InstanceIdentifierContext<>(null, schemaNode, mountPoint, schemaContextRef.get()),
138                 modulContainerSchemaNodeBuilder.build());
139     }
140 }