We are passing around EffectiveModelContext like there's no tomorrow.
Let us just bind it to a RestconfStrategy instance.
This allows us to simplify methods all over the place, reducing
cognitive load while navigating them.
JIRA: NETCONF-773
Change-Id: Ibaeb7b865c894c6eaadf65de11147b912534cf93
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
/**
* A request to a resource identified by the URL path.
*/
record ResourceRequest(
@NonNull RestconfStrategy strategy,
- @NonNull EffectiveModelContext modelContext,
@NonNull YangInstanceIdentifier path,
@NonNull NormalizedNode data) {
ResourceRequest {
requireNonNull(strategy);
- requireNonNull(modelContext);
requireNonNull(path);
requireNonNull(data);
}
import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
import java.net.URI;
import java.time.Clock;
import java.time.LocalDateTime;
public final class RestconfDataServiceImpl {
private static final Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss");
+ private static final VarHandle LOCAL_STRATEGY;
+
+ static {
+ try {
+ LOCAL_STRATEGY = MethodHandles.lookup()
+ .findVarHandle(RestconfDataServiceImpl.class, "localStrategy", RestconfStrategy.class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
private final RestconfStreamsSubscriptionService delegRestconfSubscrService;
private final DatabindProvider databindProvider;
- private final MdsalRestconfStrategy restconfStrategy;
private final DOMMountPointService mountPointService;
private final SubscribeToStreamUtil streamUtils;
private final DOMActionService actionService;
private final DOMDataBroker dataBroker;
private final ListenersBroker listenersBroker = ListenersBroker.getInstance();
+ @SuppressWarnings("unused")
+ private volatile RestconfStrategy localStrategy;
+
public RestconfDataServiceImpl(final DatabindProvider databindProvider,
final DOMDataBroker dataBroker, final DOMMountPointService mountPointService,
final RestconfStreamsSubscriptionService delegRestconfSubscrService,
final DOMActionService actionService, final StreamsConfiguration configuration) {
this.databindProvider = requireNonNull(databindProvider);
this.dataBroker = requireNonNull(dataBroker);
- restconfStrategy = new MdsalRestconfStrategy(dataBroker);
this.mountPointService = requireNonNull(mountPointService);
this.delegRestconfSubscrService = requireNonNull(delegRestconfSubscrService);
this.actionService = requireNonNull(actionService);
final var queryParams = QueryParams.newQueryParameters(readParams, instanceIdentifier);
final var fieldPaths = queryParams.fieldPaths();
- final var strategy = getRestconfStrategy(mountPoint);
+ // FIXME:the model context should be coming from instanceIdentifier!
+ final var strategy = getRestconfStrategy(schemaContextRef, mountPoint);
final NormalizedNode node;
if (fieldPaths != null && !fieldPaths.isEmpty()) {
node = strategy.readData(readParams.content(), instanceIdentifier.getInstanceIdentifier(),
- readParams.withDefaults(), instanceIdentifier.getSchemaContext(), fieldPaths);
+ readParams.withDefaults(), fieldPaths);
} else {
node = strategy.readData(readParams.content(), instanceIdentifier.getInstanceIdentifier(),
- readParams.withDefaults(), instanceIdentifier.getSchemaContext());
+ readParams.withDefaults());
}
// FIXME: this is utter craziness, refactor it properly!
final var req = bindResourceRequest(identifier, body);
return switch (
- req.strategy().putData(req.path(), req.data(), req.modelContext(), insert)) {
+ req.strategy().putData(req.path(), req.data(), insert)) {
// Note: no Location header, as it matches the request path
case CREATED -> Response.status(Status.CREATED).build();
case REPLACED -> Response.noContent().build();
private Response postData(final Inference inference, final YangInstanceIdentifier parentPath, final ChildBody body,
final UriInfo uriInfo, final @Nullable DOMMountPoint mountPoint) {
final var insert = QueryParams.parseInsert(uriInfo);
- final var strategy = getRestconfStrategy(mountPoint);
- final var context = inference.getEffectiveModelContext();
+ final var modelContext = inference.getEffectiveModelContext();
+ final var strategy = getRestconfStrategy(modelContext, mountPoint);
var path = parentPath;
final var payload = body.toPayload(path, inference);
final var data = payload.body();
path = path.node(arg);
}
- strategy.postData(path, data, context, insert);
- return Response.created(resolveLocation(uriInfo, path, context, data)).build();
+ strategy.postData(path, data, insert);
+ return Response.created(resolveLocation(uriInfo, path, modelContext, data)).build();
}
/**
@Suspended final AsyncResponse ar) {
final var instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
databindProvider.currentContext().modelContext(), mountPointService);
- final var strategy = getRestconfStrategy(instanceIdentifier.getMountPoint());
+ final var strategy = getRestconfStrategy(instanceIdentifier.getSchemaContext(),
+ instanceIdentifier.getMountPoint());
Futures.addCallback(strategy.delete(instanceIdentifier.getInstanceIdentifier()), new FutureCallback<>() {
@Override
*/
private void plainPatchData(final @Nullable String identifier, final ResourceBody body, final AsyncResponse ar) {
final var req = bindResourceRequest(identifier, body);
- final var future = req.strategy().merge(req.path(), req.data(), req.modelContext());
+ final var future = req.strategy().merge(req.path(), req.data());
Futures.addCallback(future, new FutureCallback<>() {
@Override
final var path = context.getInstanceIdentifier();
final var data = body.toNormalizedNode(path, inference, context.getSchemaNode());
- return new ResourceRequest(getRestconfStrategy(context.getMountPoint()), inference.getEffectiveModelContext(),
+ return new ResourceRequest(getRestconfStrategy(inference.getEffectiveModelContext(), context.getMountPoint()),
path, data);
}
@VisibleForTesting
- @NonNull PatchStatusContext yangPatchData(final @NonNull EffectiveModelContext context,
+ @NonNull PatchStatusContext yangPatchData(final @NonNull EffectiveModelContext modelContext,
final @NonNull PatchContext patch, final @Nullable DOMMountPoint mountPoint) {
- return getRestconfStrategy(mountPoint).patchData(patch, context);
+ return getRestconfStrategy(modelContext, mountPoint).patchData(patch);
}
private static @NonNull PatchContext parsePatchBody(final @NonNull EffectiveModelContext context,
}
@VisibleForTesting
- RestconfStrategy getRestconfStrategy(final DOMMountPoint mountPoint) {
+ @NonNull RestconfStrategy getRestconfStrategy(final EffectiveModelContext modelContext,
+ final @Nullable DOMMountPoint mountPoint) {
if (mountPoint == null) {
- return restconfStrategy;
+ return localStrategy(modelContext);
+ }
+
+ final var ret = RestconfStrategy.forMountPoint(modelContext, mountPoint);
+ if (ret == null) {
+ final var mountId = mountPoint.getIdentifier();
+ LOG.warn("Mount point {} does not expose a suitable access interface", mountId);
+ throw new RestconfDocumentedException("Could not find a supported access interface in mount point "
+ + mountId);
+ }
+ return ret;
+ }
+
+ private @NonNull RestconfStrategy localStrategy(final EffectiveModelContext modelContext) {
+ final var local = (RestconfStrategy) LOCAL_STRATEGY.getAcquire(this);
+ if (local != null && modelContext.equals(local.modelContext())) {
+ return local;
}
- return RestconfStrategy.forMountPoint(mountPoint).orElseThrow(() -> {
- LOG.warn("Mount point {} does not expose a suitable access interface", mountPoint.getIdentifier());
- return new RestconfDocumentedException("Could not find a supported access interface in mount point "
- + mountPoint.getIdentifier());
- });
+ final var created = new MdsalRestconfStrategy(modelContext, dataBroker);
+ LOCAL_STRATEGY.setRelease(this, created);
+ return created;
}
/**
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
/**
* Implementation of RESTCONF operations using {@link DOMTransactionChain} and related concepts.
public final class MdsalRestconfStrategy extends RestconfStrategy {
private final DOMDataBroker dataBroker;
- public MdsalRestconfStrategy(final DOMDataBroker dataBroker) {
+ public MdsalRestconfStrategy(final EffectiveModelContext modelContext, final DOMDataBroker dataBroker) {
+ super(modelContext);
this.dataBroker = requireNonNull(dataBroker);
}
@Override
RestconfTransaction prepareWriteExecution() {
- return new MdsalRestconfTransaction(dataBroker);
+ return new MdsalRestconfTransaction(modelContext(), dataBroker);
}
@Override
private DOMDataTreeReadWriteTransaction rwTx;
- MdsalRestconfTransaction(final DOMDataBroker dataBroker) {
+ MdsalRestconfTransaction(final EffectiveModelContext modelContext, final DOMDataBroker dataBroker) {
+ super(modelContext);
rwTx = dataBroker.newReadWriteTransaction();
}
}
@Override
- void createImpl(final YangInstanceIdentifier path, final NormalizedNode data, final EffectiveModelContext context) {
+ void createImpl(final YangInstanceIdentifier path, final NormalizedNode data) {
if (data instanceof MapNode || data instanceof LeafSetNode) {
- final var emptySubTree = ImmutableNodes.fromInstanceId(context, path);
+ final var emptySubTree = ImmutableNodes.fromInstanceId(modelContext, path);
merge(YangInstanceIdentifier.of(emptySubTree.name()), emptySubTree);
- ensureParentsByMerge(path, context);
+ ensureParentsByMerge(path);
final var children = ((DistinctNodeContainer<?, ?>) data).body();
final var check = BatchedExistenceCheck.start(verifyNotNull(rwTx), CONFIGURATION, path, children);
checkExistence(path, check);
} else {
RestconfStrategy.checkItemDoesNotExists(verifyNotNull(rwTx).exists(CONFIGURATION, path), path);
- ensureParentsByMerge(path, context);
+ ensureParentsByMerge(path);
verifyNotNull(rwTx).put(CONFIGURATION, path, data);
}
}
@Override
- void replaceImpl(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context) {
+ void replaceImpl(final YangInstanceIdentifier path, final NormalizedNode data) {
if (data instanceof MapNode || data instanceof LeafSetNode) {
- final var emptySubtree = ImmutableNodes.fromInstanceId(context, path);
+ final var emptySubtree = ImmutableNodes.fromInstanceId(modelContext, path);
merge(YangInstanceIdentifier.of(emptySubtree.name()), emptySubtree);
- ensureParentsByMerge(path, context);
+ ensureParentsByMerge(path);
for (var child : ((NormalizedNodeContainer<?>) data).body()) {
final var childPath = path.node(child.name());
verifyNotNull(rwTx).put(CONFIGURATION, childPath, child);
}
} else {
- ensureParentsByMerge(path, context);
+ ensureParentsByMerge(path);
verifyNotNull(rwTx).put(CONFIGURATION, path, data);
}
}
import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
/**
* Implementation of RESTCONF operations on top of a raw NETCONF backend.
public final class NetconfRestconfStrategy extends RestconfStrategy {
private final NetconfDataTreeService netconfService;
- public NetconfRestconfStrategy(final NetconfDataTreeService netconfService) {
+ public NetconfRestconfStrategy(final EffectiveModelContext modelContext,
+ final NetconfDataTreeService netconfService) {
+ super(modelContext);
this.netconfService = requireNonNull(netconfService);
}
@Override
RestconfTransaction prepareWriteExecution() {
- return new NetconfRestconfTransaction(netconfService);
+ return new NetconfRestconfTransaction(modelContext(), netconfService);
}
@Override
private volatile boolean isLocked = false;
- NetconfRestconfTransaction(final NetconfDataTreeService netconfService) {
+ NetconfRestconfTransaction(final EffectiveModelContext modelContext, final NetconfDataTreeService netconfService) {
+ super(modelContext);
this.netconfService = requireNonNull(netconfService);
+
final var lockResult = netconfService.lock();
Futures.addCallback(lockResult, new FutureCallback<DOMRpcResult>() {
@Override
}
@Override
- void createImpl(final YangInstanceIdentifier path, final NormalizedNode data, final EffectiveModelContext context) {
+ void createImpl(final YangInstanceIdentifier path, final NormalizedNode data) {
if (data instanceof MapNode || data instanceof LeafSetNode) {
- final var emptySubTree = ImmutableNodes.fromInstanceId(context, path);
+ final var emptySubTree = ImmutableNodes.fromInstanceId(modelContext, path);
merge(YangInstanceIdentifier.of(emptySubTree.name()), emptySubTree);
for (var child : ((NormalizedNodeContainer<?>) data).body()) {
}
@Override
- void replaceImpl(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context) {
+ void replaceImpl(final YangInstanceIdentifier path, final NormalizedNode data) {
if (data instanceof MapNode || data instanceof LeafSetNode) {
- final var emptySubTree = ImmutableNodes.fromInstanceId(context, path);
+ final var emptySubTree = ImmutableNodes.fromInstanceId(modelContext, path);
merge(YangInstanceIdentifier.of(emptySubTree.name()), emptySubTree);
for (var child : ((NormalizedNodeContainer<?>) data).body()) {
private static final Logger LOG = LoggerFactory.getLogger(RestconfStrategy.class);
- RestconfStrategy() {
- // Hidden on purpose
+ private final @NonNull EffectiveModelContext modelContext;
+
+ RestconfStrategy(final EffectiveModelContext modelContext) {
+ this.modelContext = requireNonNull(modelContext);
}
/**
* Look up the appropriate strategy for a particular mount point.
*
+ * @param modelContext {@link EffectiveModelContext} of target mount point
* @param mountPoint Target mount point
* @return A strategy, or null if the mount point does not expose a supported interface
- * @throws NullPointerException if {@code mountPoint} is null
+ * @throws NullPointerException if any argument is {@code null}
*/
- public static Optional<RestconfStrategy> forMountPoint(final DOMMountPoint mountPoint) {
- final Optional<RestconfStrategy> netconf = mountPoint.getService(NetconfDataTreeService.class)
- .map(NetconfRestconfStrategy::new);
- if (netconf.isPresent()) {
- return netconf;
+ public static @Nullable RestconfStrategy forMountPoint(final EffectiveModelContext modelContext,
+ final DOMMountPoint mountPoint) {
+ final var netconfService = mountPoint.getService(NetconfDataTreeService.class);
+ if (netconfService.isPresent()) {
+ return new NetconfRestconfStrategy(modelContext, netconfService.orElseThrow());
+ }
+ final var dataBroker = mountPoint.getService(DOMDataBroker.class);
+ if (dataBroker.isPresent()) {
+ return new MdsalRestconfStrategy(modelContext, dataBroker.orElseThrow());
}
+ return null;
+ }
- return mountPoint.getService(DOMDataBroker.class).map(MdsalRestconfStrategy::new);
+ public final @NonNull EffectiveModelContext modelContext() {
+ return modelContext;
}
/**
* @param path the data object path
* @return a ListenableFuture containing the result of the read
*/
- abstract ListenableFuture<Optional<NormalizedNode>> read(LogicalDatastoreType store,
- YangInstanceIdentifier path);
+ abstract ListenableFuture<Optional<NormalizedNode>> read(LogicalDatastoreType store, YangInstanceIdentifier path);
/**
* Read data selected using fields from the datastore.
* @param fields paths to selected fields relative to parent path
* @return a ListenableFuture containing the result of the read
*/
- abstract ListenableFuture<Optional<NormalizedNode>> read(LogicalDatastoreType store,
- YangInstanceIdentifier path, List<YangInstanceIdentifier> fields);
+ abstract ListenableFuture<Optional<NormalizedNode>> read(LogicalDatastoreType store, YangInstanceIdentifier path,
+ List<YangInstanceIdentifier> fields);
/**
* Check if data already exists in the configuration datastore.
*
* @param path Path to merge
* @param data Data to merge
- * @param context Corresponding EffectiveModelContext
* @return A {@link RestconfFuture}
* @throws NullPointerException if any argument is {@code null}
*/
- public final @NonNull RestconfFuture<Empty> merge(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context) {
+ public final @NonNull RestconfFuture<Empty> merge(final YangInstanceIdentifier path, final NormalizedNode data) {
final var ret = new SettableRestconfFuture<Empty>();
- merge(ret, requireNonNull(path), requireNonNull(data), requireNonNull(context));
+ merge(ret, requireNonNull(path), requireNonNull(data));
return ret;
}
- private void merge(final @NonNull SettableRestconfFuture<Empty> future,
- final @NonNull YangInstanceIdentifier path, final @NonNull NormalizedNode data,
- final @NonNull EffectiveModelContext context) {
+ private void merge(final @NonNull SettableRestconfFuture<Empty> future, final @NonNull YangInstanceIdentifier path,
+ final @NonNull NormalizedNode data) {
final var tx = prepareWriteExecution();
// FIXME: this method should be further specialized to eliminate this call -- it is only needed for MD-SAL
- tx.ensureParentsByMerge(path, context);
+ tx.ensureParentsByMerge(path);
tx.merge(path, data);
Futures.addCallback(tx.commit(), new FutureCallback<CommitInfo>() {
@Override
*
* @param path path of data
* @param data data
- * @param context reference to {@link EffectiveModelContext}
* @param insert {@link Insert}
* @return A {@link CreateOrReplaceResult}
*/
- public @NonNull CreateOrReplaceResult putData(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context, final @Nullable Insert insert) {
+ public final @NonNull CreateOrReplaceResult putData(final YangInstanceIdentifier path, final NormalizedNode data,
+ final @Nullable Insert insert) {
final var exists = TransactionUtil.syncAccess(exists(path), path);
final ListenableFuture<? extends CommitInfo> commitFuture;
if (insert != null) {
final var parentPath = path.coerceParent();
- checkListAndOrderedType(context, parentPath);
- commitFuture = insertAndCommitPut(path, data, insert, parentPath, context);
+ checkListAndOrderedType(parentPath);
+ commitFuture = insertAndCommitPut(path, data, insert, parentPath);
} else {
- commitFuture = replaceAndCommit(prepareWriteExecution(), path, data, context);
+ commitFuture = replaceAndCommit(prepareWriteExecution(), path, data);
}
TransactionUtil.syncCommit(commitFuture, "PUT", path);
}
private ListenableFuture<? extends CommitInfo> insertAndCommitPut(final YangInstanceIdentifier path,
- final NormalizedNode data, final @NonNull Insert insert, final YangInstanceIdentifier parentPath,
- final EffectiveModelContext context) {
+ final NormalizedNode data, final @NonNull Insert insert, final YangInstanceIdentifier parentPath) {
final var tx = prepareWriteExecution();
return switch (insert.insert()) {
case FIRST -> {
final var readData = tx.readList(parentPath);
if (readData == null || readData.isEmpty()) {
- yield replaceAndCommit(tx, path, data, context);
+ yield replaceAndCommit(tx, path, data);
}
tx.remove(parentPath);
- tx.replace(path, data, context);
- tx.replace(parentPath, readData, context);
+ tx.replace(path, data);
+ tx.replace(parentPath, readData);
yield tx.commit();
}
- case LAST -> replaceAndCommit(tx, path, data, context);
+ case LAST -> replaceAndCommit(tx, path, data);
case BEFORE -> {
final var readData = tx.readList(parentPath);
if (readData == null || readData.isEmpty()) {
- yield replaceAndCommit(tx, path, data, context);
+ yield replaceAndCommit(tx, path, data);
}
- insertWithPointPut(tx, path, data, verifyNotNull(insert.point()), readData, true, context);
+ insertWithPointPut(tx, path, data, verifyNotNull(insert.point()), readData, true);
yield tx.commit();
}
case AFTER -> {
final var readData = tx.readList(parentPath);
if (readData == null || readData.isEmpty()) {
- yield replaceAndCommit(tx, path, data, context);
+ yield replaceAndCommit(tx, path, data);
}
- insertWithPointPut(tx, path, data, verifyNotNull(insert.point()), readData, false, context);
+ insertWithPointPut(tx, path, data, verifyNotNull(insert.point()), readData, false);
yield tx.commit();
}
};
}
- private static void insertWithPointPut(final RestconfTransaction tx, final YangInstanceIdentifier path,
+ private void insertWithPointPut(final RestconfTransaction tx, final YangInstanceIdentifier path,
final NormalizedNode data, final @NonNull PointParam point, final NormalizedNodeContainer<?> readList,
- final boolean before, final EffectiveModelContext context) {
+ final boolean before) {
tx.remove(path.getParent());
- final var pointArg = YangInstanceIdentifierDeserializer.create(context, point.value()).path
+ // FIXME: this should have happened sooner
+ final var pointArg = YangInstanceIdentifierDeserializer.create(modelContext, point.value()).path
.getLastPathArgument();
int lastItemPosition = 0;
for (var nodeChild : readList.body()) {
lastItemPosition++;
}
int lastInsertedPosition = 0;
- final var emptySubtree = ImmutableNodes.fromInstanceId(context, path.getParent());
+ final var emptySubtree = ImmutableNodes.fromInstanceId(modelContext, path.getParent());
tx.merge(YangInstanceIdentifier.of(emptySubtree.name()), emptySubtree);
for (var nodeChild : readList.body()) {
if (lastInsertedPosition == lastItemPosition) {
- tx.replace(path, data, context);
+ tx.replace(path, data);
}
final var childPath = path.coerceParent().node(nodeChild.name());
- tx.replace(childPath, nodeChild, context);
+ tx.replace(childPath, nodeChild);
lastInsertedPosition++;
}
}
private static ListenableFuture<? extends CommitInfo> replaceAndCommit(final RestconfTransaction tx,
- final YangInstanceIdentifier path, final NormalizedNode data, final EffectiveModelContext context) {
- tx.replace(path, data, context);
+ final YangInstanceIdentifier path, final NormalizedNode data) {
+ tx.replace(path, data);
return tx.commit();
}
- private static DataSchemaNode checkListAndOrderedType(final EffectiveModelContext ctx,
- final YangInstanceIdentifier path) {
- final var dataSchemaNode = DataSchemaContextTree.from(ctx).findChild(path).orElseThrow().dataSchemaNode();
+ private DataSchemaNode checkListAndOrderedType(final YangInstanceIdentifier path) {
+ // FIXME: we have this available in InstanceIdentifierContext
+ final var dataSchemaNode = DataSchemaContextTree.from(modelContext).findChild(path).orElseThrow()
+ .dataSchemaNode();
final String message;
if (dataSchemaNode instanceof ListSchemaNode listSchema) {
*
* @param path path
* @param data data
- * @param context reference to actual {@link EffectiveModelContext}
* @param insert {@link Insert}
*/
public final void postData(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context, final @Nullable Insert insert) {
+ final @Nullable Insert insert) {
final ListenableFuture<? extends CommitInfo> future;
if (insert != null) {
final var parentPath = path.coerceParent();
- checkListAndOrderedType(context, parentPath);
- future = insertAndCommitPost(path, data, insert, parentPath, context);
+ checkListAndOrderedType(parentPath);
+ future = insertAndCommitPost(path, data, insert, parentPath);
} else {
- future = createAndCommit(prepareWriteExecution(), path, data, context);
+ future = createAndCommit(prepareWriteExecution(), path, data);
}
TransactionUtil.syncCommit(future, "POST", path);
}
private ListenableFuture<? extends CommitInfo> insertAndCommitPost(final YangInstanceIdentifier path,
- final NormalizedNode data, final @NonNull Insert insert, final YangInstanceIdentifier parent,
- final EffectiveModelContext context) {
+ final NormalizedNode data, final @NonNull Insert insert, final YangInstanceIdentifier parent) {
final var grandParent = parent.coerceParent();
final var tx = prepareWriteExecution();
case FIRST -> {
final var readData = tx.readList(grandParent);
if (readData == null || readData.isEmpty()) {
- tx.replace(path, data, context);
+ tx.replace(path, data);
} else {
checkItemDoesNotExists(exists(path), path);
tx.remove(grandParent);
- tx.replace(path, data, context);
- tx.replace(grandParent, readData, context);
+ tx.replace(path, data);
+ tx.replace(grandParent, readData);
}
yield tx.commit();
}
- case LAST -> createAndCommit(tx, path, data, context);
+ case LAST -> createAndCommit(tx, path, data);
case BEFORE -> {
final var readData = tx.readList(grandParent);
if (readData == null || readData.isEmpty()) {
- tx.replace(path, data, context);
+ tx.replace(path, data);
} else {
checkItemDoesNotExists(exists(path), path);
- insertWithPointPost(tx, path, data, verifyNotNull(insert.point()), readData, grandParent, true,
- context);
+ insertWithPointPost(tx, path, data, verifyNotNull(insert.point()), readData, grandParent, true);
}
yield tx.commit();
}
case AFTER -> {
final var readData = tx.readList(grandParent);
if (readData == null || readData.isEmpty()) {
- tx.replace(path, data, context);
+ tx.replace(path, data);
} else {
checkItemDoesNotExists(exists(path), path);
- insertWithPointPost(tx, path, data, verifyNotNull(insert.point()), readData, grandParent, false,
- context);
+ insertWithPointPost(tx, path, data, verifyNotNull(insert.point()), readData, grandParent, false);
}
yield tx.commit();
}
/**
* Process edit operations of one {@link PatchContext}.
*
- * @param patch Patch context to be processed
- * @param context Global schema context
+ * @param patch Patch context to be processed
* @return {@link PatchStatusContext}
*/
- public final @NonNull PatchStatusContext patchData(final PatchContext patch, final EffectiveModelContext context) {
+ public final @NonNull PatchStatusContext patchData(final PatchContext patch) {
final var editCollection = new ArrayList<PatchStatusEntity>();
final var tx = prepareWriteExecution();
switch (patchEntity.getOperation()) {
case Create:
try {
- tx.create(targetNode, patchEntity.getNode(), context);
+ tx.create(targetNode, patchEntity.getNode());
editCollection.add(new PatchStatusEntity(editId, true, null));
} catch (RestconfDocumentedException e) {
editCollection.add(new PatchStatusEntity(editId, false, e.getErrors()));
break;
case Merge:
try {
- tx.ensureParentsByMerge(targetNode, context);
+ tx.ensureParentsByMerge(targetNode);
tx.merge(targetNode, patchEntity.getNode());
editCollection.add(new PatchStatusEntity(editId, true, null));
} catch (RestconfDocumentedException e) {
break;
case Replace:
try {
- tx.replace(targetNode, patchEntity.getNode(), context);
+ tx.replace(targetNode, patchEntity.getNode());
editCollection.add(new PatchStatusEntity(editId, true, null));
} catch (RestconfDocumentedException e) {
editCollection.add(new PatchStatusEntity(editId, false, e.getErrors()));
TransactionUtil.syncCommit(tx.commit(), "PATCH", null);
} catch (RestconfDocumentedException e) {
// if errors occurred during transaction commit then patch failed and global errors are reported
- return new PatchStatusContext(context, patchId, List.copyOf(editCollection), false, e.getErrors());
+ return new PatchStatusContext(modelContext, patchId, List.copyOf(editCollection), false, e.getErrors());
}
- return new PatchStatusContext(context, patchId, List.copyOf(editCollection), true, null);
+ return new PatchStatusContext(modelContext, patchId, List.copyOf(editCollection), true, null);
} else {
tx.cancel();
- return new PatchStatusContext(context, patchId, List.copyOf(editCollection), false, null);
+ return new PatchStatusContext(modelContext, patchId, List.copyOf(editCollection), false, null);
}
}
- private static void insertWithPointPost(final RestconfTransaction tx, final YangInstanceIdentifier path,
+ private void insertWithPointPost(final RestconfTransaction tx, final YangInstanceIdentifier path,
final NormalizedNode data, final PointParam point, final NormalizedNodeContainer<?> readList,
- final YangInstanceIdentifier grandParentPath, final boolean before, final EffectiveModelContext context) {
+ final YangInstanceIdentifier grandParentPath, final boolean before) {
tx.remove(grandParentPath);
- final var pointArg = YangInstanceIdentifierDeserializer.create(context, point.value()).path
+ // FIXME: this should have happened sooner
+ final var pointArg = YangInstanceIdentifierDeserializer.create(modelContext, point.value()).path
.getLastPathArgument();
int lastItemPosition = 0;
for (var nodeChild : readList.body()) {
lastItemPosition++;
}
int lastInsertedPosition = 0;
- final var emptySubtree = ImmutableNodes.fromInstanceId(context, grandParentPath);
+ final var emptySubtree = ImmutableNodes.fromInstanceId(modelContext, grandParentPath);
tx.merge(YangInstanceIdentifier.of(emptySubtree.name()), emptySubtree);
for (var nodeChild : readList.body()) {
if (lastInsertedPosition == lastItemPosition) {
- tx.replace(path, data, context);
+ tx.replace(path, data);
}
final YangInstanceIdentifier childPath = grandParentPath.node(nodeChild.name());
- tx.replace(childPath, nodeChild, context);
+ tx.replace(childPath, nodeChild);
lastInsertedPosition++;
}
}
private static ListenableFuture<? extends CommitInfo> createAndCommit(final RestconfTransaction tx,
- final YangInstanceIdentifier path, final NormalizedNode data, final EffectiveModelContext context) {
+ final YangInstanceIdentifier path, final NormalizedNode data) {
try {
- tx.create(path, data, context);
+ tx.create(path, data);
} catch (RestconfDocumentedException e) {
// close transaction if any and pass exception further
tx.cancel();
* 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 content type of data to read (config, state, all)
- * @param path the path to read
- * @param defaultsMode value of with-defaults parameter
- * @param ctx schema context
+ * @param content type of data to read (config, state, all)
+ * @param path the path to read
+ * @param defaultsMode value of with-defaults parameter
* @return {@link NormalizedNode}
*/
public @Nullable NormalizedNode readData(final @NonNull ContentParam content,
- final @NonNull YangInstanceIdentifier path, final WithDefaultsParam defaultsMode,
- final EffectiveModelContext ctx) {
+ final @NonNull YangInstanceIdentifier path, final WithDefaultsParam defaultsMode) {
return switch (content) {
case ALL -> {
// PREPARE STATE DATA NODE
final var configDataNode = readDataViaTransaction(LogicalDatastoreType.CONFIGURATION, path);
yield mergeConfigAndSTateDataIfNeeded(stateDataNode, defaultsMode == null ? configDataNode
- : prepareDataByParamWithDef(configDataNode, path, defaultsMode.mode(), ctx));
+ : prepareDataByParamWithDef(configDataNode, path, defaultsMode.mode()));
}
case CONFIG -> {
final var read = readDataViaTransaction(LogicalDatastoreType.CONFIGURATION, path);
- yield defaultsMode == null ? read : prepareDataByParamWithDef(read, path, defaultsMode.mode(), ctx);
+ yield defaultsMode == null ? read
+ : prepareDataByParamWithDef(read, path, defaultsMode.mode());
}
case NONCONFIG -> readDataViaTransaction(LogicalDatastoreType.OPERATIONAL, path);
};
* 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 content type of data to read (config, state, all)
- * @param path the parent path to read
- * @param withDefa value of with-defaults parameter
- * @param ctx schema context
- * @param fields paths to selected subtrees which should be read, relative to to the parent path
+ * @param content type of data to read (config, state, all)
+ * @param path the parent path to read
+ * @param withDefa value of with-defaults parameter
+ * @param fields paths to selected subtrees which should be read, relative to to the parent path
* @return {@link NormalizedNode}
*/
public @Nullable NormalizedNode readData(final @NonNull ContentParam content,
final @NonNull YangInstanceIdentifier path, final @Nullable WithDefaultsParam withDefa,
- final @NonNull EffectiveModelContext ctx, final @NonNull List<YangInstanceIdentifier> fields) {
+ final @NonNull List<YangInstanceIdentifier> fields) {
return switch (content) {
case ALL -> {
// PREPARE STATE DATA NODE
final var configDataNode = readDataViaTransaction(LogicalDatastoreType.CONFIGURATION, path, fields);
yield mergeConfigAndSTateDataIfNeeded(stateDataNode, withDefa == null ? configDataNode
- : prepareDataByParamWithDef(configDataNode, path, withDefa.mode(), ctx));
+ : prepareDataByParamWithDef(configDataNode, path, withDefa.mode()));
}
case CONFIG -> {
final var read = readDataViaTransaction(LogicalDatastoreType.CONFIGURATION, path, fields);
- yield withDefa == null ? read : prepareDataByParamWithDef(read, path, withDefa.mode(), ctx);
+ yield withDefa == null ? read : prepareDataByParamWithDef(read, path, withDefa.mode());
}
case NONCONFIG -> readDataViaTransaction(LogicalDatastoreType.OPERATIONAL, path, fields);
};
return TransactionUtil.syncAccess(read(store, path, fields), path).orElse(null);
}
- private static NormalizedNode prepareDataByParamWithDef(final NormalizedNode readData,
- final YangInstanceIdentifier path, final WithDefaultsMode defaultsMode, final EffectiveModelContext ctx) {
+ private NormalizedNode prepareDataByParamWithDef(final NormalizedNode readData, final YangInstanceIdentifier path,
+ final WithDefaultsMode defaultsMode) {
final boolean trim = switch (defaultsMode) {
case Trim -> true;
case Explicit -> false;
"Unsupported with-defaults value " + defaultsMode.getName());
};
- final var ctxNode = DataSchemaContextTree.from(ctx).findChild(path).orElseThrow();
+ // FIXME: we have this readily available in InstanceIdentifierContext
+ final var ctxNode = DataSchemaContextTree.from(modelContext).findChild(path).orElseThrow();
if (readData instanceof ContainerNode container) {
final var builder = Builders.containerBuilder().withNodeIdentifier(container.name());
buildCont(builder, container.body(), ctxNode, trim);
configMap.entrySet().stream().filter(x -> stateMap.containsKey(x.getKey())).forEach(
y -> builder.addChild((T) prepareData(y.getValue(), stateMap.get(y.getKey()))));
}
-
}
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
abstract class RestconfTransaction {
private static final Logger LOG = LoggerFactory.getLogger(RestconfTransaction.class);
- RestconfTransaction() {
- // Hidden on purpose
+ final @NonNull EffectiveModelContext modelContext;
+
+ RestconfTransaction(final EffectiveModelContext modelContext) {
+ this.modelContext = requireNonNull(modelContext);
}
/**
*
* @param path the data object path
* @param data the data object to be merged to the specified path
- * @param context static view of compiled yang files
*/
- final void create(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context) {
+ final void create(final YangInstanceIdentifier path, final NormalizedNode data) {
LOG.trace("Create {}", path);
LOG.trace(Markers.confidential(), "Create as {}", data.prettyTree());
- createImpl(requireNonNull(path), data, requireNonNull(context));
+ createImpl(requireNonNull(path), data);
}
- abstract void createImpl(@NonNull YangInstanceIdentifier path, @NonNull NormalizedNode data,
- @NonNull EffectiveModelContext context);
+ abstract void createImpl(@NonNull YangInstanceIdentifier path, @NonNull NormalizedNode data);
/**
* Replace a piece of data at the specified path.
*
* @param path the data object path
* @param data the data object to be merged to the specified path
- * @param context static view of compiled yang files
*/
- final void replace(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext context) {
+ final void replace(final YangInstanceIdentifier path, final NormalizedNode data) {
LOG.trace("Replace {}", path);
LOG.trace(Markers.confidential(), "Replace with {}", data.prettyTree());
- replaceImpl(requireNonNull(path), data, requireNonNull(context));
+ replaceImpl(requireNonNull(path), data);
}
- abstract void replaceImpl(@NonNull YangInstanceIdentifier path, @NonNull NormalizedNode data,
- @NonNull EffectiveModelContext context);
-
+ abstract void replaceImpl(@NonNull YangInstanceIdentifier path, @NonNull NormalizedNode data);
final @Nullable NormalizedNodeContainer<?> readList(final YangInstanceIdentifier path) {
return (NormalizedNodeContainer<?>) TransactionUtil.syncAccess(read(path), path).orElse(null);
* Merge parents of data.
*
* @param path path of data
- * @param context {@link SchemaContext}
*/
// FIXME: this method should only be invoked in MdsalRestconfStrategy, and even then only if we are crossing
// an implicit list.
- final void ensureParentsByMerge(final YangInstanceIdentifier path, final EffectiveModelContext context) {
+ final void ensureParentsByMerge(final YangInstanceIdentifier path) {
final var normalizedPathWithoutChildArgs = new ArrayList<PathArgument>();
YangInstanceIdentifier rootNormalizedPath = null;
}
merge(rootNormalizedPath,
- ImmutableNodes.fromInstanceId(context, YangInstanceIdentifier.of(normalizedPathWithoutChildArgs)));
+ ImmutableNodes.fromInstanceId(modelContext, YangInstanceIdentifier.of(normalizedPathWithoutChildArgs)));
}
}
import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.yang.patch.Edit.Operation;
import org.opendaylight.yangtools.yang.common.ErrorTag;
@Test
public void testGetRestconfStrategy() {
- RestconfStrategy restconfStrategy = dataService.getRestconfStrategy(mountPoint);
+ var restconfStrategy = dataService.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint);
assertTrue(restconfStrategy instanceof MdsalRestconfStrategy);
doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
- restconfStrategy = dataService.getRestconfStrategy(mountPoint);
+ restconfStrategy = dataService.getRestconfStrategy(JUKEBOX_SCHEMA, mountPoint);
assertTrue(restconfStrategy instanceof NetconfRestconfStrategy);
}
}
new NodeIdentifier(QName.create("ns", "2016-02-28", "container"));
@Mock
- private EffectiveModelContext mockSchemaContext;
+ EffectiveModelContext mockSchemaContext;
@Mock
private UriInfo uriInfo;
@Test
public final void testPostContainerData() {
- testPostContainerDataStrategy().postData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA, null);
+ testPostContainerDataStrategy().postData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
}
abstract @NonNull RestconfStrategy testPostContainerDataStrategy();
@Test
public final void testPostListData() {
testPostListDataStrategy(BAND_ENTRY, PLAYLIST_IID.node(BAND_ENTRY.name())).postData(PLAYLIST_IID, PLAYLIST,
- JUKEBOX_SCHEMA, null);
+ null);
}
abstract @NonNull RestconfStrategy testPostListDataStrategy(MapEntryNode entryNode, YangInstanceIdentifier node);
final var domException = new DOMException((short) 414, "Post request failed");
RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
- () -> testPostDataFailStrategy(domException).postData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA, null));
+ () -> testPostDataFailStrategy(domException).postData(JUKEBOX_IID, EMPTY_JUKEBOX, null));
assertEquals(1, ex.getErrors().size());
assertThat(ex.getErrors().get(0).getErrorInfo(), containsString(domException.getMessage()));
}
@Test
public final void testPatchContainerData() {
- testPatchContainerDataStrategy().merge(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA).getOrThrow();
+ testPatchContainerDataStrategy().merge(JUKEBOX_IID, EMPTY_JUKEBOX).getOrThrow();
}
abstract @NonNull RestconfStrategy testPatchContainerDataStrategy();
@Test
public final void testPatchLeafData() {
- testPatchLeafDataStrategy().merge(GAP_IID, GAP_LEAF, JUKEBOX_SCHEMA).getOrThrow();
+ testPatchLeafDataStrategy().merge(GAP_IID, GAP_LEAF).getOrThrow();
}
abstract @NonNull RestconfStrategy testPatchLeafDataStrategy();
@Test
public final void testPatchListData() {
- testPatchListDataStrategy().merge(JUKEBOX_IID, JUKEBOX_WITH_PLAYLIST, JUKEBOX_SCHEMA).getOrThrow();
+ testPatchListDataStrategy().merge(JUKEBOX_IID, JUKEBOX_WITH_PLAYLIST).getOrThrow();
}
abstract @NonNull RestconfStrategy testPatchListDataStrategy();
@Test
public final void testDeleteNonexistentData() {
final var patchStatusContext = deleteNonexistentDataTestStrategy().patchData(new PatchContext("patchD",
- List.of(new PatchEntity("edit", Operation.Delete, CREATE_AND_DELETE_TARGET))), JUKEBOX_SCHEMA);
+ List.of(new PatchEntity("edit", Operation.Delete, CREATE_AND_DELETE_TARGET))));
assertFalse(patchStatusContext.ok());
}
* @param strategy {@link RestconfStrategy} - wrapper for variables
* @return {@link NormalizedNode}
*/
- private @Nullable NormalizedNode readData(final @NonNull ContentParam content,
+ private static @Nullable NormalizedNode readData(final @NonNull ContentParam content,
final YangInstanceIdentifier path, final @NonNull RestconfStrategy strategy) {
- return strategy.readData(content, path, null, mockSchemaContext);
+ return strategy.readData(content, path, null);
}
private static void patch(final PatchContext patchContext, final RestconfStrategy strategy, final boolean failed) {
- final var patchStatusContext = strategy.patchData(patchContext, JUKEBOX_SCHEMA);
+ final var patchStatusContext = strategy.patchData(patchContext);
for (var entity : patchStatusContext.editCollection()) {
if (failed) {
assertTrue("Edit " + entity.getEditId() + " failed", entity.isOk());
// assert that data to delete exists
when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
.thenReturn(immediateTrueFluentFuture());
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
// assert that data to delete does NOT exist
when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
.thenReturn(immediateFalseFluentFuture());
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doReturn(immediateFailedFluentFuture(domException)).when(readWrite).commit();
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Test
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- new MdsalRestconfStrategy(mockDataBroker).putData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA, null);
+ new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
}
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- new MdsalRestconfStrategy(mockDataBroker).putData(GAP_IID, GAP_LEAF, JUKEBOX_SCHEMA, null);
+ new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker).putData(GAP_IID, GAP_LEAF, null);
verify(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
}
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- new MdsalRestconfStrategy(mockDataBroker).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, JUKEBOX_SCHEMA, null);
+ new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
}
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
RestconfStrategy testPatchContainerDataStrategy() {
doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
RestconfStrategy testPatchLeafDataStrategy() {
doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
RestconfStrategy testPatchListDataStrategy() {
doReturn(readWrite).when(mockDataBroker).newReadWriteTransaction();
doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, PLAYER_IID);
doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
CREATE_AND_DELETE_TARGET);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
RestconfStrategy testPatchMergePutContainerStrategy() {
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
RestconfStrategy deleteNonexistentDataTestStrategy() {
doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
CREATE_AND_DELETE_TARGET);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(JUKEBOX_SCHEMA, mockDataBroker);
}
@Override
doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.CONFIGURATION, PATH);
doReturn(immediateFluentFuture(Optional.empty())).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_2);
doReturn(immediateFluentFuture(Optional.empty())).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_2);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH_2);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.CONFIGURATION, PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.CONFIGURATION, PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, PATH);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_3);
doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_3);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_3);
doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_3);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, PATH_3);
doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, PATH_3);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
.read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Override
RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
doReturn(read).when(mockDataBroker).newReadOnlyTransaction();
doReturn(immediateFluentFuture(Optional.empty())).when(read).read(LogicalDatastoreType.CONFIGURATION, PATH_2);
- return new MdsalRestconfStrategy(mockDataBroker);
+ return new MdsalRestconfStrategy(mockSchemaContext, mockDataBroker);
}
@Test
doReturn(immediateFluentFuture(Optional.of(data))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, path);
- assertEquals(data, new MdsalRestconfStrategy(mockDataBroker).readData(ContentParam.ALL, path,
- WithDefaultsParam.TRIM, MODULES_SCHEMA));
+ assertEquals(data, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker).readData(ContentParam.ALL, path,
+ WithDefaultsParam.TRIM));
}
@Test
doReturn(immediateFluentFuture(Optional.of(data))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, path);
- assertEquals(data, new MdsalRestconfStrategy(mockDataBroker).readData(ContentParam.ALL, path,
- WithDefaultsParam.TRIM, MODULES_SCHEMA));
+ assertEquals(data, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker).readData(ContentParam.ALL, path,
+ WithDefaultsParam.TRIM));
}
@Test
doReturn(immediateFluentFuture(Optional.of(content))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, path);
- assertEquals(content, new MdsalRestconfStrategy(mockDataBroker).readData(ContentParam.ALL, path,
- WithDefaultsParam.TRIM, MODULES_SCHEMA));
+ assertEquals(content, new MdsalRestconfStrategy(MODULES_SCHEMA, mockDataBroker).readData(ContentParam.ALL, path,
+ WithDefaultsParam.TRIM));
}
}
@Override
RestconfStrategy testDeleteDataStrategy() {
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
doReturn(Futures.immediateFailedFuture(new TransactionCommitFailedException(
"Commit of transaction " + this + " failed", new NetconfDocumentedException("id",
ErrorType.RPC, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR)))).when(netconfService).commit();
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.create(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
RestconfStrategy testPostListDataStrategy(final MapEntryNode entryNode, final YangInstanceIdentifier node) {
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
+ // FIXME: exact match
.merge(any(), any(), any(), any());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).create(
LogicalDatastoreType.CONFIGURATION, node, entryNode, Optional.empty());
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
RestconfStrategy testPostDataFailStrategy(final DOMException domException) {
doReturn(immediateFailedFluentFuture(domException)).when(netconfService)
+ // FIXME: exact match
.create(any(), any(), any(), any());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
RestconfStrategy testPatchContainerDataStrategy() {
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).merge(any(), any(),any(),
any());
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.merge(any(), any(), any(), any());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.merge(any(), any(),any(),any());
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Test
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
- new NetconfRestconfStrategy(netconfService).putData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
verify(netconfService).lock();
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
- new NetconfRestconfStrategy(netconfService).putData(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
- new NetconfRestconfStrategy(netconfService).putData(GAP_IID, GAP_LEAF, JUKEBOX_SCHEMA, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(GAP_IID, GAP_LEAF, null);
verify(netconfService).getConfig(GAP_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
}
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
- new NetconfRestconfStrategy(netconfService).putData(GAP_IID, GAP_LEAF, JUKEBOX_SCHEMA, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(GAP_IID, GAP_LEAF, null);
verify(netconfService).getConfig(GAP_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
}
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
- new NetconfRestconfStrategy(netconfService).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, JUKEBOX_SCHEMA, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
- new NetconfRestconfStrategy(netconfService).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, JUKEBOX_SCHEMA, null);
+ new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService).putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
verify(netconfService).getConfig(JUKEBOX_IID);
verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.remove(LogicalDatastoreType.CONFIGURATION, ARTIST_IID);
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
+ // FIXME: exact match
.replace(any(), any(), any(), any());
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
.create(LogicalDatastoreType.CONFIGURATION, PLAYER_IID, EMPTY_JUKEBOX, Optional.empty());
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
RestconfStrategy testPatchMergePutContainerStrategy() {
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
.when(netconfService).commit();
doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
.delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService);
}
@Override
@Override
RestconfStrategy readDataConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(PATH);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readDataNonConfigTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readContainerDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readListDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(netconfService).get(PATH_3);
doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(netconfService).getConfig(PATH_3);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readOrderedListDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(netconfService).get(PATH_3);
doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(netconfService).getConfig(PATH_3);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readUnkeyedListDataAllTestStrategy() {
doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(netconfService).get(PATH_3);
doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(netconfService).getConfig(PATH_3);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
.get(LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(netconfService)
.getConfig(LEAF_SET_NODE_PATH);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
.get(LEAF_SET_NODE_PATH);
doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(netconfService)
.getConfig(LEAF_SET_NODE_PATH);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
@Override
RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
- return new NetconfRestconfStrategy(netconfService);
+ return new NetconfRestconfStrategy(mockSchemaContext, netconfService);
}
}