Fix rawtypes/hiddenField suppressions
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / ReadDataTransactionUtil.java
index a2f2c55e7bbbf968f0b2e2f6c930d478ccc30e3a..273483f48409ef710af66209faea292d610c368d 100644 (file)
@@ -26,12 +26,12 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.restconf.common.context.WriterParameters;
 import org.opendaylight.restconf.common.context.WriterParameters.WriterParametersBuilder;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfError;
-import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
 import org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationListenerAdapter;
 import org.opendaylight.restconf.nb.rfc8040.utils.mapping.RestconfMappingNodeUtil;
@@ -68,6 +68,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
@@ -92,39 +93,15 @@ public final class ReadDataTransactionUtil {
     /**
      * Parse parameters from URI request and check their types and values.
      *
-     *
      * @param identifier
      *             {@link InstanceIdentifierContext}
      * @param uriInfo
      *             URI info
-     * @param tagged
-     *             set tagged for {@link WriterParameters}
      * @return {@link WriterParameters}
      */
-    public static @NonNull WriterParameters parseUriParameters(final @NonNull InstanceIdentifierContext<?> identifier,
-            final @Nullable UriInfo uriInfo, final boolean tagged) {
-        return parseParams(identifier, uriInfo, tagged);
-    }
-
-    /**
-     * Parse parameters from URI request and check their types and values.
-     *
-     *
-     * @param identifier
-     *             {@link InstanceIdentifierContext}
-     * @param uriInfo
-     *             URI info
-     * @return {@link WriterParameters}
-     */
-    public static @NonNull WriterParameters parseUriParameters(final @NonNull InstanceIdentifierContext<?> identifier,
-                                                               final @Nullable UriInfo uriInfo) {
-        return parseParams(identifier, uriInfo, false);
-    }
-
-    private static WriterParameters parseParams(final InstanceIdentifierContext<?> identifier, final UriInfo uriInfo,
-            final boolean tagged) {
+    public static WriterParameters parseUriParameters(final InstanceIdentifierContext<?> identifier,
+                                                      final UriInfo uriInfo) {
         final WriterParametersBuilder builder = new WriterParametersBuilder();
-        builder.setTagged(tagged);
 
         if (uriInfo == null) {
             return builder.build();
@@ -145,6 +122,9 @@ public final class ReadDataTransactionUtil {
         final List<String> depth = uriInfo.getQueryParameters().getOrDefault(
                 RestconfDataServiceConstant.ReadData.DEPTH,
                 Collections.singletonList(RestconfDataServiceConstant.ReadData.UNBOUNDED));
+        final List<String> withDefaults = uriInfo.getQueryParameters().getOrDefault(
+                RestconfDataServiceConstant.ReadData.WITH_DEFAULTS,
+                Collections.emptyList());
         // fields
         final List<String> fields = uriInfo.getQueryParameters().getOrDefault(
                 RestconfDataServiceConstant.ReadData.FIELDS,
@@ -154,6 +134,7 @@ public final class ReadDataTransactionUtil {
         ParametersUtil.checkParameterCount(content, RestconfDataServiceConstant.ReadData.CONTENT);
         ParametersUtil.checkParameterCount(depth, RestconfDataServiceConstant.ReadData.DEPTH);
         ParametersUtil.checkParameterCount(fields, RestconfDataServiceConstant.ReadData.FIELDS);
+        ParametersUtil.checkParameterCount(fields, RestconfDataServiceConstant.ReadData.WITH_DEFAULTS);
 
         // check and set content
         final String contentValue = content.get(0);
@@ -190,6 +171,19 @@ public final class ReadDataTransactionUtil {
             builder.setFields(ParserFieldsParameter.parseFieldsParameter(identifier, fields.get(0)));
         }
 
+        // check and set withDefaults parameter
+        if (!withDefaults.isEmpty()) {
+            switch (withDefaults.get(0)) {
+                case RestconfDataServiceConstant.ReadData.REPORT_ALL_TAGGED_DEFAULT_VALUE:
+                    builder.setTagged(true);
+                    break;
+                case RestconfDataServiceConstant.ReadData.REPORT_ALL_DEFAULT_VALUE:
+                    break;
+                default:
+                    builder.setWithDefault(withDefaults.get(0));
+            }
+        }
+
         return builder.build();
     }
 
@@ -210,14 +204,15 @@ public final class ReadDataTransactionUtil {
     }
 
     /**
-     * Read specific type of data from data store via transaction.
+     * Read specific type of data from data store via transaction. Close {@link DOMTransactionChain} inside of object
+     * {@link TransactionVarsWrapper} provided as a parameter.
      *
      * @param valueOfContent
      *            type of data to read (config, state, all)
      * @param transactionNode
      *            {@link TransactionVarsWrapper} - wrapper for variables
      * @param withDefa
-     *            vaule of with-defaults parameter
+     *            value of with-defaults parameter
      * @param ctx
      *            schema context
      * @return {@link NormalizedNode}
@@ -241,6 +236,7 @@ public final class ReadDataTransactionUtil {
                 return readAllData(transactionNode, withDefa, ctx);
 
             default:
+                transactionNode.getTransactionChain().close();
                 throw new RestconfDocumentedException(
                         new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE,
                                 "Invalid content parameter: " + valueOfContent, null,
@@ -260,7 +256,7 @@ public final class ReadDataTransactionUtil {
      *             {@link TransactionVarsWrapper} - wrapper for variables
      * @param withDefa
      *             vaule of with-defaults parameter
-     * @param schemaContextRef
+     * @param schemaContext
      *             schema context
      * @param uriInfo
      *             uri info
@@ -268,41 +264,40 @@ public final class ReadDataTransactionUtil {
      */
     public static NormalizedNode<?, ?> readData(final String identifier, final String content,
                                                 final TransactionVarsWrapper transactionNode, final String withDefa,
-                                                final SchemaContextRef schemaContextRef, final UriInfo uriInfo) {
-        final SchemaContext schemaContext = schemaContextRef.get();
-        if (identifier.contains(STREAMS_PATH) && !identifier.contains(STREAM_PATH_PART)) {
-            createAllYangNotificationStreams(transactionNode, schemaContextRef, uriInfo);
+                                                final EffectiveModelContext schemaContext, final UriInfo uriInfo) {
+        if (identifier != null && identifier.contains(STREAMS_PATH) && !identifier.contains(STREAM_PATH_PART)) {
+            createAllYangNotificationStreams(transactionNode, schemaContext, uriInfo);
         }
         return readData(content, transactionNode, withDefa, schemaContext);
     }
 
     private static void createAllYangNotificationStreams(final TransactionVarsWrapper transactionNode,
-            final SchemaContextRef schemaContextRef, final UriInfo uriInfo) {
+            final EffectiveModelContext schemaContext, final UriInfo uriInfo) {
         final DOMDataTreeReadWriteTransaction wTx = transactionNode.getTransactionChain().newReadWriteTransaction();
-        final boolean exist = SubscribeToStreamUtil.checkExist(schemaContextRef.get(), wTx);
+        final boolean exist = SubscribeToStreamUtil.checkExist(schemaContext, wTx);
 
-        for (final NotificationDefinition notificationDefinition : schemaContextRef.get().getNotifications()) {
+        for (final NotificationDefinition notificationDefinition : schemaContext.getNotifications()) {
             final NotificationListenerAdapter notifiStreamXML =
-                    CreateStreamUtil.createYangNotifiStream(notificationDefinition, schemaContextRef,
+                    CreateStreamUtil.createYangNotifiStream(notificationDefinition, schemaContext,
                             NotificationOutputType.XML);
             final NotificationListenerAdapter notifiStreamJSON =
-                    CreateStreamUtil.createYangNotifiStream(notificationDefinition, schemaContextRef,
+                    CreateStreamUtil.createYangNotifiStream(notificationDefinition, schemaContext,
                             NotificationOutputType.JSON);
-            writeNotificationStreamToDatastore(schemaContextRef, uriInfo, wTx, exist, notifiStreamXML);
-            writeNotificationStreamToDatastore(schemaContextRef, uriInfo, wTx, exist, notifiStreamJSON);
+            writeNotificationStreamToDatastore(schemaContext, uriInfo, wTx, exist, notifiStreamXML);
+            writeNotificationStreamToDatastore(schemaContext, uriInfo, wTx, exist, notifiStreamJSON);
         }
         SubscribeToStreamUtil.submitData(wTx);
     }
 
-    private static void writeNotificationStreamToDatastore(final SchemaContextRef schemaContextRef,
+    private static void writeNotificationStreamToDatastore(final EffectiveModelContext schemaContext,
             final UriInfo uriInfo, final DOMDataTreeReadWriteTransaction readWriteTransaction, final boolean exist,
             final NotificationListenerAdapter listener) {
         final URI uri = SubscribeToStreamUtil.prepareUriByStreamName(uriInfo, listener.getStreamName());
-        final NormalizedNode mapToStreams = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
-                listener.getSchemaPath().getLastComponent(), schemaContextRef.get().getNotifications(), null,
-                listener.getOutputType(), uri,
-                SubscribeToStreamUtil.getMonitoringModule(schemaContextRef.get()), exist);
-        SubscribeToStreamUtil.writeDataToDS(schemaContextRef.get(),
+        final NormalizedNode<?, ?> mapToStreams =
+                RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
+                    listener.getSchemaPath().getLastComponent(), schemaContext.getNotifications(), null,
+                    listener.getOutputType(), uri, SubscribeToStreamUtil.getMonitoringModule(schemaContext), exist);
+        SubscribeToStreamUtil.writeDataToDS(schemaContext,
                 listener.getSchemaPath().getLastComponent().getLocalName(), readWriteTransaction, exist, mapToStreams);
     }
 
@@ -360,17 +355,17 @@ public final class ReadDataTransactionUtil {
                 final NormalizedNodeBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
                         Builders.leafBuilder((LeafSchemaNode) childSchema);
                 if (keys.contains(child.getNodeType())) {
-                    leafBuilder.withValue(((LeafNode) child).getValue());
+                    leafBuilder.withValue(((LeafNode<?>) child).getValue());
                     builder.withChild(leafBuilder.build());
                 } else {
                     if (trim) {
                         if (defaultVal == null || !defaultVal.equals(nodeVal)) {
-                            leafBuilder.withValue(((LeafNode) child).getValue());
+                            leafBuilder.withValue(((LeafNode<?>) child).getValue());
                             builder.withChild(leafBuilder.build());
                         }
                     } else {
                         if (defaultVal != null && defaultVal.equals(nodeVal)) {
-                            leafBuilder.withValue(((LeafNode) child).getValue());
+                            leafBuilder.withValue(((LeafNode<?>) child).getValue());
                             builder.withChild(leafBuilder.build());
                         }
                     }
@@ -416,12 +411,12 @@ public final class ReadDataTransactionUtil {
                         Builders.leafBuilder((LeafSchemaNode) childSchema);
                 if (trim) {
                     if (defaultVal == null || !defaultVal.equals(nodeVal)) {
-                        leafBuilder.withValue(((LeafNode) child).getValue());
+                        leafBuilder.withValue(((LeafNode<?>) child).getValue());
                         builder.withChild(leafBuilder.build());
                     }
                 } else {
                     if (defaultVal != null && defaultVal.equals(nodeVal)) {
-                        leafBuilder.withValue(((LeafNode) child).getValue());
+                        leafBuilder.withValue(((LeafNode<?>) child).getValue());
                         builder.withChild(leafBuilder.build());
                     }
                 }
@@ -432,7 +427,9 @@ public final class ReadDataTransactionUtil {
     /**
      * If is set specific {@link LogicalDatastoreType} in
      * {@link TransactionVarsWrapper}, then read this type of data from DS. If
-     * don't, we have to read all data from DS (state + config)
+     * don't, we have to read all data from DS (state + config).
+     * This method will close {@link org.opendaylight.mdsal.dom.api.DOMTransactionChain} inside of
+     * {@link TransactionVarsWrapper}.
      *
      * @param transactionNode
      *             {@link TransactionVarsWrapper} - wrapper for variables
@@ -440,19 +437,43 @@ public final class ReadDataTransactionUtil {
      */
     private static @Nullable NormalizedNode<?, ?> readDataViaTransaction(
             final @NonNull TransactionVarsWrapper transactionNode) {
+        return readDataViaTransaction(transactionNode, true);
+    }
+
+
+    /**
+     * If is set specific {@link LogicalDatastoreType} in
+     * {@link TransactionVarsWrapper}, then read this type of data from DS. If
+     * don't, we have to read all data from DS (state + config)
+     *
+     * @param transactionNode
+     *             {@link TransactionVarsWrapper} - wrapper for variables
+     * @param closeTransactionChain
+     *             If is set to true, after transaction it will close transactionChain in {@link TransactionVarsWrapper}
+     * @return {@link NormalizedNode}
+     */
+    private static @Nullable NormalizedNode<?, ?> readDataViaTransaction(
+            final @NonNull TransactionVarsWrapper transactionNode, final boolean closeTransactionChain) {
         final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
         try (DOMDataTreeReadTransaction tx = transactionNode.getTransactionChain().newReadOnlyTransaction()) {
             final FluentFuture<Optional<NormalizedNode<?, ?>>> listenableFuture = tx.read(
                 transactionNode.getLogicalDatastoreType(),
                 transactionNode.getInstanceIdentifier().getInstanceIdentifier());
-            FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
-                dataFactory);
+            if (closeTransactionChain) {
+                //Method close transactionChain inside of TransactionVarsWrapper, if is provide as a parameter.
+                FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+                        dataFactory, transactionNode.getTransactionChain());
+            } else {
+                FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+                        dataFactory);
+            }
         }
         return dataFactory.build();
     }
 
     /**
-     * Read config and state data, then map them.
+     * Read config and state data, then map them. Close {@link DOMTransactionChain} inside of object
+     * {@link TransactionVarsWrapper} provided as a parameter.
      *
      * @param transactionNode
      *            {@link TransactionVarsWrapper} - wrapper for variables
@@ -466,11 +487,12 @@ public final class ReadDataTransactionUtil {
             final String withDefa, final SchemaContext ctx) {
         // PREPARE STATE DATA NODE
         transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
-        final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode);
+        final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode, false);
 
         // PREPARE CONFIG DATA NODE
         transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
         final NormalizedNode<?, ?> configDataNode;
+        //Here will be closed transactionChain
         if (withDefa == null) {
             configDataNode = readDataViaTransaction(transactionNode);
         } else {
@@ -645,6 +667,11 @@ public final class ReadDataTransactionUtil {
             mapValueToBuilder(((LeafSetNode<Object>) configDataNode).getValue(),
                     ((LeafSetNode<Object>) stateDataNode).getValue(), builder);
             return builder.build();
+        } else if (configDataNode instanceof LeafSetEntryNode) {
+            return Builders.leafSetEntryBuilder()
+                    .withNodeIdentifier(((LeafSetEntryNode<?>) configDataNode).getIdentifier())
+                    .withValue(configDataNode.getValue())
+                    .build();
         } else if (configDataNode instanceof UnkeyedListNode) {
             final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = Builders
                     .unkeyedListBuilder().withNodeIdentifier(((UnkeyedListNode) configDataNode).getIdentifier());