X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb-rfc8040%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Fnb%2Frfc8040%2Frests%2Futils%2FReadDataTransactionUtil.java;h=76f0d6f1a27f72bdc0767b512a68045977cd0667;hb=01566dd41c162b950cfbbd4eca5a09482ed833c2;hp=3aeb3518b094963488e89c37bffcbc4226806630;hpb=5a78b0da75f1d2bfc90a5b2fe6c119fae94e1359;p=netconf.git diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java index 3aeb3518b0..76f0d6f1a2 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ReadDataTransactionUtil.java @@ -7,35 +7,24 @@ */ package org.opendaylight.restconf.nb.rfc8040.rests.utils; -import static org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserFieldsParameter.parseFieldsParameter; -import static org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserFieldsParameter.parseFieldsPaths; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Sets; -import com.google.common.primitives.Ints; import com.google.common.util.concurrent.ListenableFuture; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import javax.ws.rs.core.UriInfo; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; 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.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.common.errors.RestconfError.ErrorTag; -import org.opendaylight.restconf.common.errors.RestconfError.ErrorType; +import org.opendaylight.restconf.nb.rfc8040.ContentParam; +import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParam; import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy; -import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.ReadData.WithDefaults; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -53,17 +42,20 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.SystemLeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode; +import org.opendaylight.yangtools.yang.data.api.schema.UserLeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.UserMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.schema.builder.ListNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.schema.builder.NormalizedNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.schema.builder.NormalizedNodeContainerBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; @@ -81,148 +73,39 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition; * */ public final class ReadDataTransactionUtil { - private static final String READ_TYPE_TX = "READ"; - private ReadDataTransactionUtil() { - throw new UnsupportedOperationException("Util class."); - } - - /** - * Parse parameters from URI request and check their types and values. - * - * @param identifier {@link InstanceIdentifierContext} - * @param uriInfo URI info - * @return {@link WriterParameters} - */ - public static WriterParameters parseUriParameters(final InstanceIdentifierContext identifier, - final UriInfo uriInfo) { - final WriterParametersBuilder builder = new WriterParametersBuilder(); - - if (uriInfo == null) { - return builder.build(); - } - - // check only allowed parameters - checkParametersTypes(uriInfo.getQueryParameters().keySet(), - RestconfDataServiceConstant.ReadData.CONTENT, - RestconfDataServiceConstant.ReadData.DEPTH, - RestconfDataServiceConstant.ReadData.FIELDS, RestconfDataServiceConstant.ReadData.WITH_DEFAULTS); - - // read parameters from URI or set default values - final List content = uriInfo.getQueryParameters().getOrDefault( - RestconfDataServiceConstant.ReadData.CONTENT, - Collections.singletonList(RestconfDataServiceConstant.ReadData.ALL)); - final List depth = uriInfo.getQueryParameters().getOrDefault( - RestconfDataServiceConstant.ReadData.DEPTH, - Collections.singletonList(RestconfDataServiceConstant.ReadData.UNBOUNDED)); - final List withDefaults = uriInfo.getQueryParameters().getOrDefault( - RestconfDataServiceConstant.ReadData.WITH_DEFAULTS, - Collections.emptyList()); - // fields - final List fields = uriInfo.getQueryParameters().getOrDefault( - RestconfDataServiceConstant.ReadData.FIELDS, - Collections.emptyList()); - - // parameter can be in URI at most once - checkParameterCount(content, RestconfDataServiceConstant.ReadData.CONTENT); - checkParameterCount(depth, RestconfDataServiceConstant.ReadData.DEPTH); - checkParameterCount(fields, RestconfDataServiceConstant.ReadData.FIELDS); - checkParameterCount(fields, RestconfDataServiceConstant.ReadData.WITH_DEFAULTS); - - // check and set content - final String contentValue = content.get(0); - if (!contentValue.equals(RestconfDataServiceConstant.ReadData.ALL)) { - if (!contentValue.equals(RestconfDataServiceConstant.ReadData.CONFIG) - && !contentValue.equals(RestconfDataServiceConstant.ReadData.NONCONFIG)) { - throw new RestconfDocumentedException( - new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE, - "Invalid content parameter: " + contentValue, null, - "The content parameter value must be either config, nonconfig or all (default)")); - } - } - - builder.setContent(content.get(0)); - - // check and set depth - if (!depth.get(0).equals(RestconfDataServiceConstant.ReadData.UNBOUNDED)) { - final Integer value = Ints.tryParse(depth.get(0)); - - if (value == null || value < RestconfDataServiceConstant.ReadData.MIN_DEPTH - || value > RestconfDataServiceConstant.ReadData.MAX_DEPTH) { - throw new RestconfDocumentedException( - new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE, - "Invalid depth parameter: " + depth, null, - "The depth parameter must be an integer between 1 and 65535 or \"unbounded\"")); - } else { - builder.setDepth(value); - } - } - - // check and set fields - if (!fields.isEmpty()) { - if (identifier.getMountPoint() != null) { - builder.setFieldPaths(parseFieldsPaths(identifier, fields.get(0))); - } else { - builder.setFields(parseFieldsParameter(identifier, fields.get(0))); - } - } - - // check and set withDefaults parameter - if (!withDefaults.isEmpty()) { - final String str = withDefaults.get(0); - final WithDefaults val = WithDefaults.forValue(str); - if (val == null) { - throw new RestconfDocumentedException(new RestconfError(RestconfError.ErrorType.PROTOCOL, - RestconfError.ErrorTag.INVALID_VALUE, "Invalid with-defaults parameter: " + str, null, - "The with-defaults parameter must be a string in " + WithDefaults.possibleValues())); - } - - switch (val) { - case REPORT_ALL: - break; - case REPORT_ALL_TAGGED: - builder.setTagged(true); - break; - default: - builder.setWithDefault(val.value()); - } - } - return builder.build(); + // Hidden on purpose } /** * Read specific type of data from data store via transaction. Close {@link DOMTransactionChain} if any * inside of object {@link RestconfStrategy} provided as a parameter. * - * @param valueOfContent type of data to read (config, state, all) + * @param content type of data to read (config, state, all) * @param path the path to read * @param strategy {@link RestconfStrategy} - object that perform the actual DS operations * @param withDefa value of with-defaults parameter * @param ctx schema context * @return {@link NormalizedNode} */ - public static @Nullable NormalizedNode readData(final @NonNull String valueOfContent, - final @NonNull YangInstanceIdentifier path, - final @NonNull RestconfStrategy strategy, - final String withDefa, final EffectiveModelContext ctx) { - switch (valueOfContent) { - case RestconfDataServiceConstant.ReadData.CONFIG: - if (withDefa == null) { - return readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true); - } else { - return prepareDataByParamWithDef( - readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true), - path, withDefa, ctx); - } - case RestconfDataServiceConstant.ReadData.NONCONFIG: - return readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path, true); - case RestconfDataServiceConstant.ReadData.ALL: + public static @Nullable NormalizedNode readData(final @NonNull ContentParam content, + final @NonNull YangInstanceIdentifier path, + final @NonNull RestconfStrategy strategy, + final WithDefaultsParam withDefa, + final EffectiveModelContext ctx) { + // FIXME: use a switch expression when they are available, removing source of RestconfDocumentedException + switch (content) { + case ALL: return readAllData(strategy, path, withDefa, ctx); + case CONFIG: + final NormalizedNode read = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path); + return withDefa == null ? read : prepareDataByParamWithDef(read, path, withDefa, ctx); + case NONCONFIG: + return readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path); default: - strategy.close(); throw new RestconfDocumentedException( - new RestconfError(RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.INVALID_VALUE, - "Invalid content parameter: " + valueOfContent, null, + new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, + "Invalid content parameter: " + content.paramValue(), null, "The content parameter value must be either config, nonconfig or all (default)")); } } @@ -231,7 +114,7 @@ public final class ReadDataTransactionUtil { * Read specific type of data from data store via transaction with specified subtrees that should only be read. * Close {@link DOMTransactionChain} inside of object {@link RestconfStrategy} provided as a parameter. * - * @param valueOfContent type of data to read (config, state, all) + * @param content type of data to read (config, state, all) * @param path the parent path to read * @param strategy {@link RestconfStrategy} - object that perform the actual DS operations * @param withDefa value of with-defaults parameter @@ -239,91 +122,51 @@ public final class ReadDataTransactionUtil { * @param fields paths to selected subtrees which should be read, relative to to the parent path * @return {@link NormalizedNode} */ - public static @Nullable NormalizedNode readData(final @NonNull String valueOfContent, + public static @Nullable NormalizedNode readData(final @NonNull ContentParam content, final @NonNull YangInstanceIdentifier path, final @NonNull RestconfStrategy strategy, - final @Nullable String withDefa, @NonNull final EffectiveModelContext ctx, + final @Nullable WithDefaultsParam withDefa, @NonNull final EffectiveModelContext ctx, final @NonNull List fields) { - switch (valueOfContent) { - case RestconfDataServiceConstant.ReadData.CONFIG: - if (withDefa == null) { - return readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true, fields); - } else { - return prepareDataByParamWithDef( - readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true, fields), - path, withDefa, ctx); - } - case RestconfDataServiceConstant.ReadData.NONCONFIG: - return readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path, true, fields); - case RestconfDataServiceConstant.ReadData.ALL: + // FIXME: use a switch expression when they are available, removing source of RestconfDocumentedException + switch (content) { + case ALL: return readAllData(strategy, path, withDefa, ctx, fields); + case CONFIG: + final NormalizedNode read = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, + fields); + return withDefa == null ? read : prepareDataByParamWithDef(read, path, withDefa, ctx); + case NONCONFIG: + return readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path, fields); default: - strategy.close(); - throw new RestconfDocumentedException(new RestconfError(RestconfError.ErrorType.PROTOCOL, - RestconfError.ErrorTag.INVALID_VALUE, "Invalid content parameter: " + valueOfContent, null, + throw new RestconfDocumentedException(new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, + "Invalid content parameter: " + content.paramValue(), null, "The content parameter value must be either config, nonconfig or all (default)")); } } - /** - * Check if URI does not contain value for the same parameter more than once. - * - * @param parameterValues URI parameter values - * @param parameterName URI parameter name - */ - @VisibleForTesting - static void checkParameterCount(final @NonNull List parameterValues, final @NonNull String parameterName) { - if (parameterValues.size() > 1) { - throw new RestconfDocumentedException( - "Parameter " + parameterName + " can appear at most once in request URI", - ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); - } - } - - /** - * Check if URI does not contain not allowed parameters for specified operation. - * - * @param usedParameters parameters used in URI request - * @param allowedParameters allowed parameters for operation - */ - @VisibleForTesting - static void checkParametersTypes(final @NonNull Set usedParameters, - final @NonNull String... allowedParameters) { - // FIXME: there should be a speedier way to do this - final Set notAllowedParameters = Sets.newHashSet(usedParameters); - notAllowedParameters.removeAll(Sets.newHashSet(allowedParameters)); - - if (!notAllowedParameters.isEmpty()) { - throw new RestconfDocumentedException( - "Not allowed parameters for " + READ_TYPE_TX + " operation: " + notAllowedParameters, - RestconfError.ErrorType.PROTOCOL, - RestconfError.ErrorTag.INVALID_VALUE); - } - } - - private static NormalizedNode prepareDataByParamWithDef(final NormalizedNode result, - final YangInstanceIdentifier path, final String withDefa, final EffectiveModelContext ctx) { + private static NormalizedNode prepareDataByParamWithDef(final NormalizedNode result, + final YangInstanceIdentifier path, final WithDefaultsParam withDefa, final EffectiveModelContext ctx) { boolean trim; switch (withDefa) { - case "trim": + case TRIM: trim = true; break; - case "explicit": + case EXPLICIT: trim = false; break; default: - throw new RestconfDocumentedException(""); + throw new RestconfDocumentedException("Unsupported with-defaults value " + withDefa.paramValue()); } final DataSchemaContextTree baseSchemaCtxTree = DataSchemaContextTree.from(ctx); final DataSchemaNode baseSchemaNode = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); if (result instanceof ContainerNode) { final DataContainerNodeBuilder builder = - Builders.containerBuilder((ContainerSchemaNode) baseSchemaNode); + SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) baseSchemaNode); buildCont(builder, (ContainerNode) result, baseSchemaCtxTree, path, trim); return builder.build(); } else { final DataContainerNodeBuilder builder = - Builders.mapEntryBuilder((ListSchemaNode) baseSchemaNode); + SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) baseSchemaNode); buildMapEntryBuilder(builder, (MapEntryNode) result, baseSchemaCtxTree, path, trim, ((ListSchemaNode) baseSchemaNode).getKeyDefinition()); return builder.build(); @@ -334,54 +177,50 @@ public final class ReadDataTransactionUtil { final DataContainerNodeBuilder builder, final MapEntryNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier actualPath, final boolean trim, final List keys) { - for (final DataContainerChild child : result.getValue()) { + for (final DataContainerChild child : result.body()) { final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); if (child instanceof ContainerNode) { final DataContainerNodeBuilder childBuilder = - Builders.containerBuilder((ContainerSchemaNode) childSchema); + SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); buildCont(childBuilder, (ContainerNode) child, baseSchemaCtxTree, path, trim); builder.withChild(childBuilder.build()); } else if (child instanceof MapNode) { - final CollectionNodeBuilder childBuilder = - Builders.mapBuilder((ListSchemaNode) childSchema); + final CollectionNodeBuilder childBuilder = + SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim, ((ListSchemaNode) childSchema).getKeyDefinition()); builder.withChild(childBuilder.build()); } else if (child instanceof LeafNode) { final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null); - final Object nodeVal = child.getValue(); + final Object nodeVal = child.body(); final NormalizedNodeBuilder> leafBuilder = - Builders.leafBuilder((LeafSchemaNode) childSchema); - if (keys.contains(child.getNodeType())) { - leafBuilder.withValue(((LeafNode) child).getValue()); + SchemaAwareBuilders.leafBuilder((LeafSchemaNode) childSchema); + if (keys.contains(child.getIdentifier().getNodeType())) { + leafBuilder.withValue(((LeafNode) child).body()); builder.withChild(leafBuilder.build()); - } else { - if (trim) { - if (defaultVal == null || !defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); - builder.withChild(leafBuilder.build()); - } - } else { - if (defaultVal != null && defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); - builder.withChild(leafBuilder.build()); - } + } else if (trim) { + if (defaultVal == null || !defaultVal.equals(nodeVal)) { + leafBuilder.withValue(((LeafNode) child).body()); + builder.withChild(leafBuilder.build()); } + } else if (defaultVal != null && defaultVal.equals(nodeVal)) { + leafBuilder.withValue(((LeafNode) child).body()); + builder.withChild(leafBuilder.build()); } } } } - private static void buildList(final CollectionNodeBuilder builder, final MapNode result, - final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier path, final boolean trim, - final List keys) { - for (final MapEntryNode mapEntryNode : result.getValue()) { + private static void buildList(final CollectionNodeBuilder builder, + final MapNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier path, + final boolean trim, final List keys) { + for (final MapEntryNode mapEntryNode : result.body()) { final YangInstanceIdentifier actualNode = path.node(mapEntryNode.getIdentifier()); final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(actualNode).orElseThrow() .getDataSchemaNode(); final DataContainerNodeBuilder mapEntryBuilder = - Builders.mapEntryBuilder((ListSchemaNode) childSchema); + SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) childSchema); buildMapEntryBuilder(mapEntryBuilder, mapEntryNode, baseSchemaCtxTree, actualNode, trim, keys); builder.withChild(mapEntryBuilder.build()); } @@ -390,35 +229,33 @@ public final class ReadDataTransactionUtil { private static void buildCont(final DataContainerNodeBuilder builder, final ContainerNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier actualPath, final boolean trim) { - for (final DataContainerChild child : result.getValue()) { + for (final DataContainerChild child : result.body()) { final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); if (child instanceof ContainerNode) { final DataContainerNodeBuilder builderChild = - Builders.containerBuilder((ContainerSchemaNode) childSchema); + SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); buildCont(builderChild, result, baseSchemaCtxTree, actualPath, trim); builder.withChild(builderChild.build()); } else if (child instanceof MapNode) { - final CollectionNodeBuilder childBuilder = - Builders.mapBuilder((ListSchemaNode) childSchema); + final CollectionNodeBuilder childBuilder = + SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim, ((ListSchemaNode) childSchema).getKeyDefinition()); builder.withChild(childBuilder.build()); } else if (child instanceof LeafNode) { final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null); - final Object nodeVal = child.getValue(); + final Object nodeVal = child.body(); final NormalizedNodeBuilder> leafBuilder = - Builders.leafBuilder((LeafSchemaNode) childSchema); + SchemaAwareBuilders.leafBuilder((LeafSchemaNode) childSchema); if (trim) { if (defaultVal == null || !defaultVal.equals(nodeVal)) { - 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).body()); builder.withChild(leafBuilder.build()); } + } else if (defaultVal != null && defaultVal.equals(nodeVal)) { + leafBuilder.withValue(((LeafNode) child).body()); + builder.withChild(leafBuilder.build()); } } } @@ -433,11 +270,9 @@ public final class ReadDataTransactionUtil { * in {@link RestconfStrategy} if any * @return {@link NormalizedNode} */ - static @Nullable NormalizedNode readDataViaTransaction(final @NonNull RestconfStrategy strategy, - final LogicalDatastoreType store, final YangInstanceIdentifier path, - final boolean closeTransactionChain) { - final ListenableFuture>> listenableFuture = strategy.read(store, path); - return extractReadData(strategy, path, closeTransactionChain, listenableFuture); + static @Nullable NormalizedNode readDataViaTransaction(final @NonNull RestconfStrategy strategy, + final LogicalDatastoreType store, final YangInstanceIdentifier path) { + return extractReadData(strategy, path, strategy.read(store, path)); } /** @@ -452,23 +287,16 @@ public final class ReadDataTransactionUtil { * @param fields paths to selected subtrees which should be read, relative to to the parent path * @return {@link NormalizedNode} */ - private static @Nullable NormalizedNode readDataViaTransaction(final @NonNull RestconfStrategy strategy, + private static @Nullable NormalizedNode readDataViaTransaction(final @NonNull RestconfStrategy strategy, final @NonNull LogicalDatastoreType store, final @NonNull YangInstanceIdentifier path, - final boolean closeTransactionChain, final @NonNull List fields) { - final ListenableFuture>> listenableFuture = strategy.read(store, path, fields); - return extractReadData(strategy, path, closeTransactionChain, listenableFuture); + final @NonNull List fields) { + return extractReadData(strategy, path, strategy.read(store, path, fields)); } - private static NormalizedNode extractReadData(final RestconfStrategy strategy, - final YangInstanceIdentifier path, final boolean closeTransactionChain, - final ListenableFuture>> dataFuture) { + private static NormalizedNode extractReadData(final RestconfStrategy strategy, + final YangInstanceIdentifier path, final ListenableFuture> dataFuture) { final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory(); - if (closeTransactionChain) { - //Method close transactionChain if any - FutureCallbackTx.addCallback(dataFuture, READ_TYPE_TX, dataFactory, strategy, path); - } else { - FutureCallbackTx.addCallback(dataFuture, READ_TYPE_TX, dataFactory); - } + FutureCallbackTx.addCallback(dataFuture, "READ", dataFactory, path); return dataFactory.build(); } @@ -481,25 +309,16 @@ public final class ReadDataTransactionUtil { * @param ctx schema context * @return {@link NormalizedNode} */ - private static @Nullable NormalizedNode readAllData(final @NonNull RestconfStrategy strategy, - final YangInstanceIdentifier path, final String withDefa, final EffectiveModelContext ctx) { + private static @Nullable NormalizedNode readAllData(final @NonNull RestconfStrategy strategy, + final YangInstanceIdentifier path, final WithDefaultsParam withDefa, final EffectiveModelContext ctx) { // PREPARE STATE DATA NODE - final NormalizedNode stateDataNode = readDataViaTransaction( - strategy, LogicalDatastoreType.OPERATIONAL, path, false); - + final NormalizedNode stateDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path); // PREPARE CONFIG DATA NODE - final NormalizedNode configDataNode; - //Here will be closed transactionChain if any - if (withDefa == null) { - configDataNode = readDataViaTransaction( - strategy, LogicalDatastoreType.CONFIGURATION, path, true); - } else { - configDataNode = prepareDataByParamWithDef( - readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true), - path, withDefa, ctx); - } + final NormalizedNode configDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, + path); - return mergeConfigAndSTateDataIfNeeded(stateDataNode, configDataNode); + return mergeConfigAndSTateDataIfNeeded(stateDataNode, + withDefa == null ? configDataNode : prepareDataByParamWithDef(configDataNode, path, withDefa, ctx)); } /** @@ -513,29 +332,22 @@ public final class ReadDataTransactionUtil { * @param fields paths to selected subtrees which should be read, relative to to the parent path * @return {@link NormalizedNode} */ - private static @Nullable NormalizedNode readAllData(final @NonNull RestconfStrategy strategy, - final @NonNull YangInstanceIdentifier path, final @Nullable String withDefa, + private static @Nullable NormalizedNode readAllData(final @NonNull RestconfStrategy strategy, + final @NonNull YangInstanceIdentifier path, final @Nullable WithDefaultsParam withDefa, final @NonNull EffectiveModelContext ctx, final @NonNull List fields) { // PREPARE STATE DATA NODE - final NormalizedNode stateDataNode = readDataViaTransaction( - strategy, LogicalDatastoreType.OPERATIONAL, path, false, fields); + final NormalizedNode stateDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path, + fields); // PREPARE CONFIG DATA NODE - final NormalizedNode configDataNode; - //Here will be closed transactionChain if any - if (withDefa == null) { - configDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true, fields); - } else { - configDataNode = prepareDataByParamWithDef( - readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, true, fields), - path, withDefa, ctx); - } - - return mergeConfigAndSTateDataIfNeeded(stateDataNode, configDataNode); + final NormalizedNode configDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path, + fields); + return mergeConfigAndSTateDataIfNeeded(stateDataNode, + withDefa == null ? configDataNode : prepareDataByParamWithDef(configDataNode, path, withDefa, ctx)); } - private static NormalizedNode mergeConfigAndSTateDataIfNeeded(final NormalizedNode stateDataNode, - final NormalizedNode configDataNode) { + private static NormalizedNode mergeConfigAndSTateDataIfNeeded(final NormalizedNode stateDataNode, + final NormalizedNode configDataNode) { // if no data exists if (stateDataNode == null && configDataNode == null) { return null; @@ -562,8 +374,8 @@ public final class ReadDataTransactionUtil { * @param configDataNode data node of config data * @return {@link NormalizedNode} */ - private static @NonNull NormalizedNode mergeStateAndConfigData( - final @NonNull NormalizedNode stateDataNode, final @NonNull NormalizedNode configDataNode) { + private static @NonNull NormalizedNode mergeStateAndConfigData( + final @NonNull NormalizedNode stateDataNode, final @NonNull NormalizedNode configDataNode) { validateNodeMerge(stateDataNode, configDataNode); if (configDataNode instanceof RpcDefinition) { return prepareRpcData(configDataNode, stateDataNode); @@ -578,8 +390,8 @@ public final class ReadDataTransactionUtil { * @param stateDataNode data node of state data * @param configDataNode data node of config data */ - private static void validateNodeMerge(final @NonNull NormalizedNode stateDataNode, - final @NonNull NormalizedNode configDataNode) { + private static void validateNodeMerge(final @NonNull NormalizedNode stateDataNode, + final @NonNull NormalizedNode configDataNode) { final QNameModule moduleOfStateData = stateDataNode.getIdentifier().getNodeType().getModule(); final QNameModule moduleOfConfigData = configDataNode.getIdentifier().getNodeType().getModule(); if (!moduleOfStateData.equals(moduleOfConfigData)) { @@ -594,8 +406,8 @@ public final class ReadDataTransactionUtil { * @param stateDataNode data node of state data * @return {@link NormalizedNode} */ - private static @NonNull NormalizedNode prepareRpcData(final @NonNull NormalizedNode configDataNode, - final @NonNull NormalizedNode stateDataNode) { + private static @NonNull NormalizedNode prepareRpcData(final @NonNull NormalizedNode configDataNode, + final @NonNull NormalizedNode stateDataNode) { final DataContainerNodeBuilder mapEntryBuilder = ImmutableNodes .mapEntryBuilder(); mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier()); @@ -605,7 +417,9 @@ public final class ReadDataTransactionUtil { // MAP STATE DATA mapRpcDataNode(stateDataNode, mapEntryBuilder); - return ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()).addChild(mapEntryBuilder.build()).build(); + return ImmutableNodes.mapNodeBuilder(configDataNode.getIdentifier().getNodeType()) + .addChild(mapEntryBuilder.build()) + .build(); } /** @@ -614,9 +428,9 @@ public final class ReadDataTransactionUtil { * @param dataNode data node * @param mapEntryBuilder builder for mapping data */ - private static void mapRpcDataNode(final @NonNull NormalizedNode dataNode, + private static void mapRpcDataNode(final @NonNull NormalizedNode dataNode, final @NonNull DataContainerNodeBuilder mapEntryBuilder) { - ((ContainerNode) dataNode).getValue().forEach(mapEntryBuilder::addChild); + ((ContainerNode) dataNode).body().forEach(mapEntryBuilder::addChild); } /** @@ -627,22 +441,22 @@ public final class ReadDataTransactionUtil { * @return {@link NormalizedNode} */ @SuppressWarnings("unchecked") - private static @NonNull NormalizedNode prepareData(final @NonNull NormalizedNode configDataNode, - final @NonNull NormalizedNode stateDataNode) { - if (configDataNode instanceof OrderedMapNode) { - final CollectionNodeBuilder builder = Builders + private static @NonNull NormalizedNode prepareData(final @NonNull NormalizedNode configDataNode, + final @NonNull NormalizedNode stateDataNode) { + if (configDataNode instanceof UserMapNode) { + final CollectionNodeBuilder builder = Builders .orderedMapBuilder().withNodeIdentifier(((MapNode) configDataNode).getIdentifier()); mapValueToBuilder( - ((OrderedMapNode) configDataNode).getValue(), ((OrderedMapNode) stateDataNode).getValue(), builder); + ((UserMapNode) configDataNode).body(), ((UserMapNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof MapNode) { - final CollectionNodeBuilder builder = ImmutableNodes + final CollectionNodeBuilder builder = ImmutableNodes .mapNodeBuilder().withNodeIdentifier(((MapNode) configDataNode).getIdentifier()); mapValueToBuilder( - ((MapNode) configDataNode).getValue(), ((MapNode) stateDataNode).getValue(), builder); + ((MapNode) configDataNode).body(), ((MapNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof MapEntryNode) { @@ -650,7 +464,7 @@ public final class ReadDataTransactionUtil { .mapEntryBuilder().withNodeIdentifier(((MapEntryNode) configDataNode).getIdentifier()); mapValueToBuilder( - ((MapEntryNode) configDataNode).getValue(), ((MapEntryNode) stateDataNode).getValue(), builder); + ((MapEntryNode) configDataNode).body(), ((MapEntryNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof ContainerNode) { @@ -658,15 +472,15 @@ public final class ReadDataTransactionUtil { .containerBuilder().withNodeIdentifier(((ContainerNode) configDataNode).getIdentifier()); mapValueToBuilder( - ((ContainerNode) configDataNode).getValue(), ((ContainerNode) stateDataNode).getValue(), builder); + ((ContainerNode) configDataNode).body(), ((ContainerNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof AugmentationNode) { final DataContainerNodeBuilder builder = Builders .augmentationBuilder().withNodeIdentifier(((AugmentationNode) configDataNode).getIdentifier()); - mapValueToBuilder(((AugmentationNode) configDataNode).getValue(), - ((AugmentationNode) stateDataNode).getValue(), builder); + mapValueToBuilder(((AugmentationNode) configDataNode).body(), + ((AugmentationNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof ChoiceNode) { @@ -674,43 +488,43 @@ public final class ReadDataTransactionUtil { .choiceBuilder().withNodeIdentifier(((ChoiceNode) configDataNode).getIdentifier()); mapValueToBuilder( - ((ChoiceNode) configDataNode).getValue(), ((ChoiceNode) stateDataNode).getValue(), builder); + ((ChoiceNode) configDataNode).body(), ((ChoiceNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof LeafNode) { - return ImmutableNodes.leafNode(configDataNode.getNodeType(), configDataNode.getValue()); - } else if (configDataNode instanceof OrderedLeafSetNode) { - final ListNodeBuilder> builder = Builders - .orderedLeafSetBuilder().withNodeIdentifier(((OrderedLeafSetNode) configDataNode).getIdentifier()); + return ImmutableNodes.leafNode(configDataNode.getIdentifier().getNodeType(), configDataNode.body()); + } else if (configDataNode instanceof UserLeafSetNode) { + final ListNodeBuilder> builder = Builders + .orderedLeafSetBuilder().withNodeIdentifier(((UserLeafSetNode) configDataNode).getIdentifier()); - mapValueToBuilder(((OrderedLeafSetNode) configDataNode).getValue(), - ((OrderedLeafSetNode) stateDataNode).getValue(), builder); + mapValueToBuilder(((UserLeafSetNode) configDataNode).body(), + ((UserLeafSetNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof LeafSetNode) { - final ListNodeBuilder> builder = Builders + final ListNodeBuilder> builder = Builders .leafSetBuilder().withNodeIdentifier(((LeafSetNode) configDataNode).getIdentifier()); - mapValueToBuilder(((LeafSetNode) configDataNode).getValue(), - ((LeafSetNode) stateDataNode).getValue(), builder); + mapValueToBuilder(((LeafSetNode) configDataNode).body(), + ((LeafSetNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof LeafSetEntryNode) { return Builders.leafSetEntryBuilder() .withNodeIdentifier(((LeafSetEntryNode) configDataNode).getIdentifier()) - .withValue(configDataNode.getValue()) + .withValue(configDataNode.body()) .build(); } else if (configDataNode instanceof UnkeyedListNode) { final CollectionNodeBuilder builder = Builders .unkeyedListBuilder().withNodeIdentifier(((UnkeyedListNode) configDataNode).getIdentifier()); - mapValueToBuilder(((UnkeyedListNode) configDataNode).getValue(), - ((UnkeyedListNode) stateDataNode).getValue(), builder); + mapValueToBuilder(((UnkeyedListNode) configDataNode).body(), + ((UnkeyedListNode) stateDataNode).body(), builder); return builder.build(); } else if (configDataNode instanceof UnkeyedListEntryNode) { final DataContainerNodeBuilder builder = Builders .unkeyedListEntryBuilder().withNodeIdentifier(((UnkeyedListEntryNode) configDataNode).getIdentifier()); - mapValueToBuilder(((UnkeyedListEntryNode) configDataNode).getValue(), - ((UnkeyedListEntryNode) stateDataNode).getValue(), builder); + mapValueToBuilder(((UnkeyedListEntryNode) configDataNode).body(), + ((UnkeyedListEntryNode) stateDataNode).body(), builder); return builder.build(); } else { throw new RestconfDocumentedException("Unexpected node type: " + configDataNode.getClass().getName()); @@ -724,7 +538,7 @@ public final class ReadDataTransactionUtil { * @param stateData collection of state data nodes * @param builder builder */ - private static > void mapValueToBuilder( + private static void mapValueToBuilder( final @NonNull Collection configData, final @NonNull Collection stateData, final @NonNull NormalizedNodeContainerBuilder builder) { final Map configMap = configData.stream().collect( @@ -747,7 +561,7 @@ public final class ReadDataTransactionUtil { * @param stateMap map of state data nodes * @param builder - builder */ - private static > void mapDataToBuilder( + private static void mapDataToBuilder( final @NonNull Map configMap, final @NonNull Map stateMap, final @NonNull NormalizedNodeContainerBuilder builder) { configMap.entrySet().stream().filter(x -> !stateMap.containsKey(x.getKey())).forEach( @@ -765,7 +579,7 @@ public final class ReadDataTransactionUtil { * @param builder - builder */ @SuppressWarnings("unchecked") - private static > void mergeDataToBuilder( + private static void mergeDataToBuilder( final @NonNull Map configMap, final @NonNull Map stateMap, final @NonNull NormalizedNodeContainerBuilder builder) { // it is enough to process only config data because operational contains the same data