X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Fserver%2Fspi%2FApiPathNormalizer.java;h=8505e0486352bc1dd93ca1810d534d606afff1e3;hb=76b38ec7221f507106a99b7b0e0a95c78e124559;hp=5cae3c8e6b527a1bd49db212a2971dc3537adcd8;hpb=32fad0d2b1161304ff9a9d18ea2f4e72dff591d5;p=netconf.git diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/ApiPathNormalizer.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/ApiPathNormalizer.java index 5cae3c8e6b..8505e04863 100644 --- a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/ApiPathNormalizer.java +++ b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/spi/ApiPathNormalizer.java @@ -11,17 +11,24 @@ import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; +import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.NonNullByDefault; import org.opendaylight.restconf.api.ApiPath; import org.opendaylight.restconf.api.ApiPath.ListInstance; +import org.opendaylight.restconf.api.ApiPath.Step; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; import org.opendaylight.restconf.nb.rfc8040.Insert.PointNormalizer; +import org.opendaylight.restconf.server.api.DatabindAware; import org.opendaylight.restconf.server.api.DatabindContext; -import org.opendaylight.restconf.server.spi.ApiPathNormalizer.OperationPath.Rpc; +import org.opendaylight.restconf.server.api.DatabindPath; +import org.opendaylight.restconf.server.api.DatabindPath.Action; +import org.opendaylight.restconf.server.api.DatabindPath.Data; +import org.opendaylight.restconf.server.api.DatabindPath.InstanceReference; +import org.opendaylight.restconf.server.api.DatabindPath.Rpc; import org.opendaylight.yangtools.yang.common.ErrorTag; import org.opendaylight.yangtools.yang.common.ErrorType; import org.opendaylight.yangtools.yang.common.QName; @@ -30,100 +37,42 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; import org.opendaylight.yangtools.yang.data.util.DataSchemaContext; import org.opendaylight.yangtools.yang.data.util.DataSchemaContext.PathMixin; import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; -import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition; import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; -import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference; /** - * Deserializer for {@link String} to {@link YangInstanceIdentifier} for restconf. + * Utility for normalizing {@link ApiPath}s. An {@link ApiPath} can represent a number of different constructs, as + * denoted to in the {@link DatabindPath} interface hierarchy. + * + *
+ * This process is governed by
+ * RFC8040, section 3.5.3. The URI provides the
+ * equivalent of NETCONF XML filter encoding, with data values being escaped RFC7891 strings.
*/
-public final class ApiPathNormalizer implements PointNormalizer {
- @NonNullByDefault
- public sealed interface Path {
-
- Inference inference();
- }
-
- @NonNullByDefault
- public sealed interface InstanceReference extends Path {
-
- YangInstanceIdentifier instance();
- }
-
- @NonNullByDefault
- public record DataPath(Inference inference, YangInstanceIdentifier instance, DataSchemaContext schema)
- implements InstanceReference {
- public DataPath {
- requireNonNull(inference);
- requireNonNull(instance);
- requireNonNull(schema);
- }
- }
-
- @NonNullByDefault
- public sealed interface OperationPath extends Path {
-
- InputEffectiveStatement inputStatement();
-
- record Action(Inference inference, YangInstanceIdentifier instance, ActionEffectiveStatement action)
- implements OperationPath, InstanceReference {
- public Action {
- requireNonNull(inference);
- requireNonNull(action);
- requireNonNull(instance);
- }
-
- @Override
- public InputEffectiveStatement inputStatement() {
- return action.input();
- }
- }
-
- record Rpc(Inference inference, RpcEffectiveStatement rpc) implements OperationPath {
- public Rpc {
- requireNonNull(inference);
- requireNonNull(rpc);
- }
-
- @Override
- public InputEffectiveStatement inputStatement() {
- return rpc.input();
- }
- }
- }
-
- private final @NonNull ApiPathInstanceIdentifierCodec instanceIdentifierCodec;
- private final @NonNull EffectiveModelContext modelContext;
+public final class ApiPathNormalizer implements DatabindAware, PointNormalizer {
private final @NonNull DatabindContext databind;
public ApiPathNormalizer(final DatabindContext databind) {
this.databind = requireNonNull(databind);
- modelContext = databind.modelContext();
- instanceIdentifierCodec = new ApiPathInstanceIdentifierCodec(databind);
}
- public @NonNull Path normalizePath(final ApiPath apiPath) {
+ @Override
+ public DatabindContext databind() {
+ return databind;
+ }
+
+ public @NonNull DatabindPath normalizePath(final ApiPath apiPath) {
final var it = apiPath.steps().iterator();
if (!it.hasNext()) {
- return new DataPath(Inference.ofDataTreePath(modelContext), YangInstanceIdentifier.of(),
- databind.schemaTree().getRoot());
+ return new Data(databind);
}
// First step is somewhat special:
@@ -131,18 +80,20 @@ public final class ApiPathNormalizer implements PointNormalizer {
// - it has to consider RPCs, for which we need SchemaContext
//
// We therefore peel that first iteration here and not worry about those details in further iterations
- var step = it.next();
- final var firstModule = step.module();
+ final var firstStep = it.next();
+ final var firstModule = firstStep.module();
if (firstModule == null) {
throw new RestconfDocumentedException(
- "First member must use namespace-qualified form, '" + step.identifier() + "' does not",
+ "First member must use namespace-qualified form, '" + firstStep.identifier() + "' does not",
ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
var namespace = resolveNamespace(firstModule);
+ var step = firstStep;
var qname = step.identifier().bindTo(namespace);
// We go through more modern APIs here to get this special out of the way quickly
+ final var modelContext = databind.modelContext();
final var optRpc = modelContext.findModuleStatement(namespace).orElseThrow()
.findSchemaTreeNode(RpcEffectiveStatement.class, qname);
if (optRpc.isPresent()) {
@@ -161,12 +112,22 @@ public final class ApiPathNormalizer implements PointNormalizer {
final var stack = SchemaInferenceStack.of(modelContext);
final var stmt = stack.enterSchemaTree(rpc.argument());
verify(rpc.equals(stmt), "Expecting %s, inferred %s", rpc, stmt);
- return new OperationPath.Rpc(stack.toInference(), rpc);
+ return new Rpc(databind, stack.toInference(), rpc);
}
- final var stack = SchemaInferenceStack.of(modelContext);
- final var path = new ArrayList