Bug 6935 - RPC in latest draft doesn't work - problem of parsing
[netconf.git] / restconf / sal-rest-connector / src / main / java / org / opendaylight / restconf / utils / parser / ParserIdentifier.java
index d24c3deb07336c99016c453b3810d1cf44f556d9..0ed61c60b602b8b130264f8bfc8bffca63e778d6 100644 (file)
@@ -7,14 +7,10 @@
  */
 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 javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
@@ -30,10 +26,15 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 
 /**
  * Util class for parsing identifier
@@ -48,25 +49,83 @@ public final class ParserIdentifier {
     }
 
     /**
-     * Make {@link InstanceIdentifierContext} from identifier.
+     * Make {@link InstanceIdentifierContext} from {@link String} identifier
+     * <br>
+     * For identifiers of data NOT behind mount points returned
+     * {@link InstanceIdentifierContext} is prepared with {@code null} reference of {@link DOMMountPoint} and with
+     * controller's {@link SchemaContext}.
+     * <br>
+     * For identifiers of data behind mount points returned
+     * {@link InstanceIdentifierContext} is prepared with reference of {@link DOMMountPoint} and its
+     * own {@link SchemaContext}.
      *
      * @param identifier
-     *            - path identifier
+     *           - path identifier
      * @param schemaContext
-     *            - {@link SchemaContext}
+     *           - controller schema context
+     * @param mountPointService
+     *           - mount point service
      * @return {@link InstanceIdentifierContext}
      */
-    public static InstanceIdentifierContext<?> toInstanceIdentifier(@Nullable final String identifier,
-            final SchemaContext schemaContext) {
-        final YangInstanceIdentifier deserialize;
-        if (identifier != null && identifier.contains(RestconfConstants.MOUNT)) {
-            final String mountPointId = identifier.substring(0, identifier.indexOf("/" + RestconfConstants.MOUNT));
-            deserialize = IdentifierCodec.deserialize(mountPointId, schemaContext);
+    public static InstanceIdentifierContext<?> toInstanceIdentifier(
+            final String identifier,
+            final SchemaContext schemaContext,
+            final Optional<DOMMountPointService> mountPointService) {
+        if ((identifier != null) && identifier.contains(RestconfConstants.MOUNT)) {
+            if (!mountPointService.isPresent()) {
+                throw new RestconfDocumentedException("Mount point service is not available");
+            }
+
+            final Iterator<String> pathsIt = Splitter.on("/" + RestconfConstants.MOUNT).split(identifier).iterator();
+
+            final String mountPointId = pathsIt.next();
+            final YangInstanceIdentifier mountYangInstanceIdentifier = IdentifierCodec.deserialize(
+                    mountPointId, schemaContext);
+            final Optional<DOMMountPoint> mountPoint = mountPointService.get().getMountPoint(mountYangInstanceIdentifier);
+
+            if (!mountPoint.isPresent()) {
+                throw new RestconfDocumentedException(
+                        "Mount point does not exist.", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+            }
+
+            final String pathId = pathsIt.next().replaceFirst("/", "");
+            final YangInstanceIdentifier pathYangInstanceIdentifier = IdentifierCodec.deserialize(
+                    pathId, mountPoint.get().getSchemaContext());
+
+            final DataSchemaContextNode<?> child = DataSchemaContextTree.from(
+                    mountPoint.get().getSchemaContext()).getChild(pathYangInstanceIdentifier);
+            if (child != null) {
+                return new InstanceIdentifierContext<SchemaNode>(pathYangInstanceIdentifier, child.getDataSchemaNode(),
+                        mountPoint.get(), mountPoint.get().getSchemaContext());
+            }
+            final QName rpcQName = mountYangInstanceIdentifier.getLastPathArgument().getNodeType();
+            RpcDefinition def = null;
+            for (final RpcDefinition rpcDefinition : schemaContext
+                    .findModuleByNamespaceAndRevision(rpcQName.getNamespace(), rpcQName.getRevision()).getRpcs()) {
+                if (rpcDefinition.getQName().getLocalName().equals(rpcQName.getLocalName())) {
+                    def = rpcDefinition;
+                    break;
+                }
+            }
+            return new InstanceIdentifierContext<RpcDefinition>(mountYangInstanceIdentifier, def, mountPoint.get(),
+                    mountPoint.get().getSchemaContext());
         } else {
-            deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
+            final YangInstanceIdentifier deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
+            final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
+
+            if(child != null){
+                return new InstanceIdentifierContext<SchemaNode>(deserialize, child.getDataSchemaNode(), null, schemaContext);
+            }
+            final QName rpcQName = deserialize.getLastPathArgument().getNodeType();
+            RpcDefinition def = null;
+            for (final RpcDefinition rpcDefinition : schemaContext.findModuleByNamespaceAndRevision(rpcQName.getNamespace(), rpcQName.getRevision()).getRpcs()) {
+                if (rpcDefinition.getQName().getLocalName().equals(rpcQName.getLocalName())) {
+                    def = rpcDefinition;
+                    break;
+                }
+            }
+            return new InstanceIdentifierContext<RpcDefinition>(deserialize, def, null, schemaContext);
         }
-        final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
-        return new InstanceIdentifierContext<SchemaNode>(deserialize, child.getDataSchemaNode(), null, schemaContext);
     }
 
     /**
@@ -170,12 +229,11 @@ public final class ParserIdentifier {
                 pathBuilder.append(current);
             }
             final InstanceIdentifierContext<?> point = ParserIdentifier
-                    .toInstanceIdentifier(pathBuilder.toString(), schemaContext);
-            final DOMMountPoint mountPoint = domMountPointService.getMountPoint(point.getInstanceIdentifier()).get();
+                    .toInstanceIdentifier(pathBuilder.toString(), schemaContext, Optional.of(domMountPointService));
             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);
+            final Module module = point.getMountPoint().getSchemaContext().findModuleByName(moduleName, revision);
+            return new SchemaExportContext(point.getMountPoint().getSchemaContext(), module);
         }
     }
 }