InstanceIdentifierContext does not take generics
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / PostDataTransactionUtil.java
index d5b39fd8a90b239453740e69ca24a83c78572a6a..fc066eb6fe7a671f6137bf1df121ac331f67b798 100644 (file)
@@ -18,14 +18,17 @@ import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
-import org.opendaylight.restconf.common.context.NormalizedNodeContext;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.common.errors.RestconfError;
-import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
-import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
+import org.opendaylight.restconf.nb.rfc8040.InsertParam;
+import org.opendaylight.restconf.nb.rfc8040.PointParam;
+import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
+import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.PostPutQueryParameters.Insert;
+import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfTransaction;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.IdentifierCodec;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
@@ -39,12 +42,10 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Util class to post data to DS.
- *
  */
 public final class PostDataTransactionUtil {
     private static final Logger LOG = LoggerFactory.getLogger(PostDataTransactionUtil.class);
-    // FIXME: why is this being reused from other places?
-    static final String POST_TX_TYPE = "POST";
+    private static final String POST_TX_TYPE = "POST";
 
     private PostDataTransactionUtil() {
         // Hidden on purpose
@@ -58,21 +59,19 @@ public final class PostDataTransactionUtil {
      * @param payload       data
      * @param strategy      Object that perform the actual DS operations
      * @param schemaContext reference to actual {@link EffectiveModelContext}
-     * @param point         point
-     * @param insert        insert
+     * @param params        {@link WriteDataParams}
      * @return {@link Response}
      */
-    public static Response postData(final UriInfo uriInfo, final NormalizedNodeContext payload,
+    public static Response postData(final UriInfo uriInfo, final NormalizedNodePayload payload,
                                     final RestconfStrategy strategy,
-                                    final EffectiveModelContext schemaContext, final Insert insert,
-                                    final String point) {
+                                    final EffectiveModelContext schemaContext, final WriteDataParams params) {
         final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier();
         final FluentFuture<? extends CommitInfo> future = submitData(path, payload.getData(),
-                strategy, schemaContext, insert, point);
+                strategy, schemaContext, params);
         final URI location = resolveLocation(uriInfo, path, schemaContext, payload.getData());
         final ResponseFactory dataFactory = new ResponseFactory(Status.CREATED).location(location);
         //This method will close transactionChain if any
-        FutureCallbackTx.addCallback(future, POST_TX_TYPE, dataFactory, strategy.getTransactionChain(), path);
+        FutureCallbackTx.addCallback(future, POST_TX_TYPE, dataFactory, path);
         return dataFactory.build();
     }
 
@@ -88,72 +87,72 @@ public final class PostDataTransactionUtil {
      * @return {@link FluentFuture}
      */
     private static FluentFuture<? extends CommitInfo> submitData(final YangInstanceIdentifier path,
-                                                                 final NormalizedNode<?, ?> data,
+                                                                 final NormalizedNode data,
                                                                  final RestconfStrategy strategy,
                                                                  final EffectiveModelContext schemaContext,
-                                                                 final Insert insert, final String point) {
-        strategy.prepareReadWriteExecution();
+                                                                 final WriteDataParams params) {
+        final RestconfTransaction transaction = strategy.prepareWriteExecution();
+        final InsertParam insert = params.insert();
         if (insert == null) {
-            makePost(path, data, schemaContext, strategy);
-            return strategy.commit();
+            makePost(path, data, schemaContext, transaction);
+            return transaction.commit();
         }
 
         PutDataTransactionUtil.checkListAndOrderedType(schemaContext, path);
-        final NormalizedNode<?, ?> readData;
+        final NormalizedNode readData;
         switch (insert) {
             case FIRST:
                 readData = PutDataTransactionUtil.readList(strategy, path.getParent().getParent());
-                if (readData == null || ((NormalizedNodeContainer<?, ?, ?>) readData).getValue().isEmpty()) {
-                    strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext);
-                    return strategy.commit();
+                if (readData == null || ((NormalizedNodeContainer<?>) readData).isEmpty()) {
+                    transaction.replace(path, data, schemaContext);
+                    return transaction.commit();
                 }
-                checkItemDoesNotExists(strategy, LogicalDatastoreType.CONFIGURATION, path);
-                strategy.remove(LogicalDatastoreType.CONFIGURATION, path.getParent().getParent());
-                strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext);
-                strategy.replace(LogicalDatastoreType.CONFIGURATION, path.getParent().getParent(), readData,
-                    schemaContext);
-                return strategy.commit();
+                checkItemDoesNotExists(strategy.exists(LogicalDatastoreType.CONFIGURATION, path), path);
+                transaction.remove(path.getParent().getParent());
+                transaction.replace(path, data, schemaContext);
+                transaction.replace(path.getParent().getParent(), readData, schemaContext);
+                return transaction.commit();
             case LAST:
-                makePost(path, data, schemaContext, strategy);
-                return strategy.commit();
+                makePost(path, data, schemaContext, transaction);
+                return transaction.commit();
             case BEFORE:
                 readData = PutDataTransactionUtil.readList(strategy, path.getParent().getParent());
-                if (readData == null || ((NormalizedNodeContainer<?, ?, ?>) readData).getValue().isEmpty()) {
-                    strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext);
-                    return strategy.commit();
+                if (readData == null || ((NormalizedNodeContainer<?>) readData).isEmpty()) {
+                    transaction.replace(path, data, schemaContext);
+                    return transaction.commit();
                 }
-                checkItemDoesNotExists(strategy, LogicalDatastoreType.CONFIGURATION, path);
-                insertWithPointPost(path, data, schemaContext, point,
-                    (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) readData, true, strategy);
-                return strategy.commit();
+                checkItemDoesNotExists(strategy.exists(LogicalDatastoreType.CONFIGURATION, path), path);
+                insertWithPointPost(path, data, schemaContext, params.getPoint(),
+                    (NormalizedNodeContainer<?>) readData, true, transaction);
+                return transaction.commit();
             case AFTER:
                 readData = PutDataTransactionUtil.readList(strategy, path.getParent().getParent());
-                if (readData == null || ((NormalizedNodeContainer<?, ?, ?>) readData).getValue().isEmpty()) {
-                    strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext);
-                    return strategy.commit();
+                if (readData == null || ((NormalizedNodeContainer<?>) readData).isEmpty()) {
+                    transaction.replace(path, data, schemaContext);
+                    return transaction.commit();
                 }
-                checkItemDoesNotExists(strategy, LogicalDatastoreType.CONFIGURATION, path);
-                insertWithPointPost(path, data, schemaContext, point,
-                    (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) readData, false, strategy);
-                return strategy.commit();
+                checkItemDoesNotExists(strategy.exists(LogicalDatastoreType.CONFIGURATION, path), path);
+                insertWithPointPost(path, data, schemaContext, params.getPoint(),
+                    (NormalizedNodeContainer<?>) readData, false, transaction);
+                return transaction.commit();
             default:
                 throw new RestconfDocumentedException(
                     "Used bad value of insert parameter. Possible values are first, last, before or after, but was: "
-                        + insert, RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.BAD_ATTRIBUTE);
+                        + insert, ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE);
         }
     }
 
-    private static void insertWithPointPost(final YangInstanceIdentifier path,
-                                            final NormalizedNode<?, ?> data,
-                                            final EffectiveModelContext schemaContext, final String point,
-                                            final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> readList,
-                                            final boolean before, final RestconfStrategy strategy) {
+    private static void insertWithPointPost(final YangInstanceIdentifier path, final NormalizedNode data,
+                                            final EffectiveModelContext schemaContext, final PointParam point,
+                                            final NormalizedNodeContainer<?> readList, final boolean before,
+                                            final RestconfTransaction transaction) {
         final YangInstanceIdentifier parent = path.getParent().getParent();
-        strategy.remove(LogicalDatastoreType.CONFIGURATION, parent);
-        final InstanceIdentifierContext<?> instanceIdentifier =
-            ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
+        transaction.remove(parent);
+        final InstanceIdentifierContext instanceIdentifier =
+            // FIXME: Point should be able to give us this method
+            ParserIdentifier.toInstanceIdentifier(point.value(), schemaContext, Optional.empty());
         int lastItemPosition = 0;
-        for (final NormalizedNode<?, ?> nodeChild : readList.getValue()) {
+        for (final NormalizedNode nodeChild : readList.body()) {
             if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
                 break;
             }
@@ -163,26 +162,25 @@ public final class PostDataTransactionUtil {
             lastItemPosition++;
         }
         int lastInsertedPosition = 0;
-        final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, parent);
-        strategy.merge(LogicalDatastoreType.CONFIGURATION,
-            YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
-        for (final NormalizedNode<?, ?> nodeChild : readList.getValue()) {
+        final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, parent);
+        transaction.merge(YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
+        for (final NormalizedNode nodeChild : readList.body()) {
             if (lastInsertedPosition == lastItemPosition) {
-                strategy.replace(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext);
+                transaction.replace(path, data, schemaContext);
             }
             final YangInstanceIdentifier childPath = parent.node(nodeChild.getIdentifier());
-            strategy.replace(LogicalDatastoreType.CONFIGURATION, childPath, nodeChild, schemaContext);
+            transaction.replace(childPath, nodeChild, schemaContext);
             lastInsertedPosition++;
         }
     }
 
-    private static void makePost(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data,
-                                 final SchemaContext schemaContext, final RestconfStrategy strategy) {
+    private static void makePost(final YangInstanceIdentifier path, final NormalizedNode data,
+                                 final SchemaContext schemaContext, final RestconfTransaction transaction) {
         try {
-            strategy.create(LogicalDatastoreType.CONFIGURATION, path, data, schemaContext);
+            transaction.create(path, data, schemaContext);
         } catch (RestconfDocumentedException e) {
             // close transaction if any and pass exception further
-            strategy.cancel();
+            transaction.cancel();
             throw e;
         }
     }
@@ -196,39 +194,33 @@ public final class PostDataTransactionUtil {
      * @return {@link URI}
      */
     private static URI resolveLocation(final UriInfo uriInfo, final YangInstanceIdentifier initialPath,
-                                       final EffectiveModelContext schemaContext, final NormalizedNode<?, ?> data) {
+                                       final EffectiveModelContext schemaContext, final NormalizedNode data) {
         if (uriInfo == null) {
             return null;
         }
 
         YangInstanceIdentifier path = initialPath;
         if (data instanceof MapNode) {
-            final Collection<MapEntryNode> children = ((MapNode) data).getValue();
+            final Collection<MapEntryNode> children = ((MapNode) data).body();
             if (!children.isEmpty()) {
                 path = path.node(children.iterator().next().getIdentifier());
             }
         }
 
-        return uriInfo.getBaseUriBuilder()
-                .path("data")
-                .path(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext))
-                .build();
+        return uriInfo.getBaseUriBuilder().path("data").path(IdentifierCodec.serialize(path, schemaContext)).build();
     }
 
     /**
      * Check if items do NOT already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if
      * data already exists.
      *
-     * @param strategy      Object that perform the actual DS operations
-     * @param store         Datastore
-     * @param path          Path to be checked
+     * @param isExistsFuture if checked data exists
+     * @param path           Path to be checked
      */
-    public static void checkItemDoesNotExists(final RestconfStrategy strategy,
-                                               final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-        final FluentFuture<Boolean> future = strategy.exists(store, path);
+    public static void checkItemDoesNotExists(final FluentFuture<Boolean> isExistsFuture,
+                                              final YangInstanceIdentifier path) {
         final FutureDataFactory<Boolean> response = new FutureDataFactory<>();
-
-        FutureCallbackTx.addCallback(future, POST_TX_TYPE, response);
+        FutureCallbackTx.addCallback(isExistsFuture, POST_TX_TYPE, response);
 
         if (response.result) {
             LOG.trace("Operation via Restconf was not executed because data at {} already exists", path);