Bump upstreams to SNAPSHOTs
[netconf.git] / restconf / restconf-common / src / main / java / org / opendaylight / restconf / common / context / InstanceIdentifierContext.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.restconf.common.context;
9
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.collect.Iterables;
15 import java.util.List;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
22 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
23 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
24 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
25 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
26 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
27
28 public abstract class InstanceIdentifierContext {
29     private static final class Root extends InstanceIdentifierContext {
30         private final @NonNull EffectiveModelContext context;
31
32         Root(final EffectiveModelContext context, final DOMMountPoint mountPoint) {
33             super(context, mountPoint);
34             this.context = requireNonNull(context);
35         }
36
37         @Override
38         public EffectiveModelContext getSchemaContext() {
39             return context;
40         }
41
42         @Override
43         public YangInstanceIdentifier getInstanceIdentifier() {
44             return YangInstanceIdentifier.empty();
45         }
46
47         @Override
48         public Inference inference() {
49             return SchemaInferenceStack.of(context).toInference();
50         }
51
52         @Override
53         InstanceIdentifierContext createWithConcapt(final List<PathArgument> concatArgs) {
54             return new DataPath(context, getMountPoint(), SchemaInferenceStack.of(context),
55                 YangInstanceIdentifier.create(concatArgs));
56         }
57     }
58
59     private static final class DataPath extends InstanceIdentifierContext {
60         private final @NonNull YangInstanceIdentifier path;
61         private final @NonNull SchemaInferenceStack stack;
62
63         private DataPath(final SchemaNode schemaNode, final DOMMountPoint mountPoint,
64                 final SchemaInferenceStack stack, final YangInstanceIdentifier path) {
65             super(schemaNode, mountPoint);
66             this.stack = requireNonNull(stack);
67             this.path = requireNonNull(path);
68         }
69
70         static @NonNull DataPath of(final EffectiveModelContext context, final YangInstanceIdentifier path,
71                 final DOMMountPoint mountPoint) {
72             final var nodeAndStack = DataSchemaContextTree.from(context).enterPath(path).orElseThrow();
73             return new DataPath(nodeAndStack.node().getDataSchemaNode(), mountPoint, nodeAndStack.stack(), path);
74         }
75
76         @Override
77         public YangInstanceIdentifier getInstanceIdentifier() {
78             return path;
79         }
80
81         @Override
82         public Inference inference() {
83             return stack.toInference();
84         }
85
86         @Override
87         @NonNull
88         InstanceIdentifierContext createWithConcapt(final List<PathArgument> concatArgs) {
89             final var newInstanceIdentifier = YangInstanceIdentifier.create(
90                 Iterables.concat(path.getPathArguments(), concatArgs));
91             return new DataPath(getSchemaNode(), getMountPoint(), stack, newInstanceIdentifier);
92         }
93     }
94
95     private static final class WithoutDataPath extends InstanceIdentifierContext {
96         private final @NonNull SchemaInferenceStack stack;
97
98         private WithoutDataPath(final SchemaNode schemaNode, final DOMMountPoint mountPoint,
99                 final SchemaInferenceStack stack) {
100             super(schemaNode, mountPoint);
101             this.stack = requireNonNull(stack);
102         }
103
104         @Override
105         public Inference inference() {
106             return stack.toInference();
107         }
108
109         @Override
110         public @Nullable YangInstanceIdentifier getInstanceIdentifier() {
111             return null;
112         }
113
114         @Override
115         InstanceIdentifierContext createWithConcapt(final List<PathArgument> concatArgs) {
116             return this;
117         }
118     }
119
120     private final @NonNull SchemaNode schemaNode;
121     private final @Nullable DOMMountPoint mountPoint;
122
123     InstanceIdentifierContext(final SchemaNode schemaNode, final DOMMountPoint mountPoint) {
124         this.schemaNode = requireNonNull(schemaNode);
125         this.mountPoint = mountPoint;
126     }
127
128     public static @NonNull InstanceIdentifierContext ofLocalRoot(final EffectiveModelContext context) {
129         return new Root(context, null);
130     }
131
132     @VisibleForTesting
133     public static @NonNull InstanceIdentifierContext ofLocalPath(final EffectiveModelContext context,
134             final YangInstanceIdentifier path) {
135         return DataPath.of(context, path, null);
136     }
137
138     // Legacy bierman02 invokeRpc()
139     public static @NonNull InstanceIdentifierContext ofRpcInput(final EffectiveModelContext context,
140             // FIXME: this this method really needed?
141             final RpcDefinition rpc, final @Nullable DOMMountPoint mountPoint) {
142         final var stack = SchemaInferenceStack.of(context);
143         stack.enterSchemaTree(rpc.getQName());
144         stack.enterSchemaTree(rpc.getInput().getQName());
145         return new WithoutDataPath(rpc, mountPoint, stack);
146     }
147
148     public static @NonNull InstanceIdentifierContext ofRpcOutput(final EffectiveModelContext context,
149             // FIXME: this this method really needed?
150             final RpcDefinition rpc, final @Nullable DOMMountPoint mountPoint) {
151         final var stack = SchemaInferenceStack.of(context);
152         stack.enterSchemaTree(rpc.getQName());
153         stack.enterSchemaTree(rpc.getOutput().getQName());
154         return new WithoutDataPath(rpc, mountPoint, stack);
155     }
156
157     // Invocations of various identifier-less details
158     public static @NonNull InstanceIdentifierContext ofStack(final SchemaInferenceStack stack) {
159         return ofStack(stack, null);
160     }
161
162     // Invocations of various identifier-less details, potentially having a mount point
163     public static @NonNull InstanceIdentifierContext ofStack(final SchemaInferenceStack stack,
164             final @Nullable DOMMountPoint mountPoint) {
165         final SchemaNode schemaNode;
166         if (!stack.isEmpty()) {
167             final var stmt = stack.currentStatement();
168             verify(stmt instanceof SchemaNode, "Unexpected statement %s", stmt);
169             schemaNode = (SchemaNode) stmt;
170         } else {
171             schemaNode = stack.getEffectiveModelContext();
172         }
173
174         return new WithoutDataPath(schemaNode, mountPoint, stack);
175     }
176
177     public static @NonNull InstanceIdentifierContext ofLocalRpcInput(final EffectiveModelContext context,
178             // FIXME: this this method really needed?
179             final RpcDefinition rpc) {
180         final var stack = SchemaInferenceStack.of(context);
181         stack.enterSchemaTree(rpc.getQName());
182         stack.enterSchemaTree(rpc.getInput().getQName());
183         return new WithoutDataPath(rpc.getInput(), null, stack);
184     }
185
186     public static @NonNull InstanceIdentifierContext ofLocalRpcOutput(final EffectiveModelContext context,
187             // FIXME: we want to re-validate this, so might as well take a QName
188             final RpcDefinition rpc) {
189         final var stack = SchemaInferenceStack.of(context);
190         stack.enterSchemaTree(rpc.getQName());
191         stack.enterSchemaTree(rpc.getOutput().getQName());
192         return new WithoutDataPath(rpc, null, stack);
193     }
194
195     public static @NonNull InstanceIdentifierContext ofPath(final SchemaInferenceStack stack,
196             final SchemaNode schemaNode, final YangInstanceIdentifier path,
197             final @Nullable DOMMountPoint mountPoint) {
198         return new DataPath(schemaNode, mountPoint, stack, path);
199     }
200
201     public static @NonNull InstanceIdentifierContext ofMountPointRoot(final DOMMountPoint mountPoint,
202             final EffectiveModelContext mountContext) {
203         return new Root(mountContext, requireNonNull(mountPoint));
204     }
205
206     @VisibleForTesting
207     public static @NonNull InstanceIdentifierContext ofMountPointPath(final DOMMountPoint mountPoint,
208             final EffectiveModelContext context, final YangInstanceIdentifier path) {
209         return DataPath.of(context, path, requireNonNull(mountPoint));
210     }
211
212     public static @NonNull InstanceIdentifierContext ofMountPointRpcOutput(final DOMMountPoint mountPoint,
213             final EffectiveModelContext mountContext, final RpcDefinition rpc) {
214         final var stack = SchemaInferenceStack.of(mountContext);
215         stack.enterSchemaTree(rpc.getQName());
216         stack.enterSchemaTree(rpc.getOutput().getQName());
217         return new WithoutDataPath(rpc, requireNonNull(mountPoint), stack);
218     }
219
220     // FIXME: what the heck are the callers of this doing?!
221     public final @NonNull InstanceIdentifierContext withConcatenatedArgs(final List<PathArgument> concatArgs) {
222         return concatArgs.isEmpty() ? this : createWithConcapt(concatArgs);
223     }
224
225     abstract @NonNull InstanceIdentifierContext createWithConcapt(List<PathArgument> concatArgs);
226
227     public final @NonNull SchemaNode getSchemaNode() {
228         return schemaNode;
229     }
230
231     public final @Nullable DOMMountPoint getMountPoint() {
232         return mountPoint;
233     }
234
235     public @NonNull EffectiveModelContext getSchemaContext() {
236         return inference().getEffectiveModelContext();
237     }
238
239     public abstract @NonNull Inference inference();
240
241     public abstract @Nullable YangInstanceIdentifier getInstanceIdentifier();
242 }