X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-codec%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fcodec%2Fimpl%2FBindingCodecContext.java;h=1547e7d0a9654c430d69b7f8c3abc5851ad3fd68;hb=3b18d17d6882c14b0f3542717e3ca539c0bc9593;hp=08997deaf3537cc4e48645d2a4422ce129c458eb;hpb=fdcf549686105e2baf76a06e94a2da5ba0f73544;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java index 08997deaf3..1547e7d0a9 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java @@ -38,7 +38,6 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.ServiceLoader; import java.util.concurrent.ExecutionException; -import java.util.function.Function; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.kohsuke.MetaInfServices; @@ -63,9 +62,10 @@ import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.DataRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType; -import org.opendaylight.mdsal.binding.runtime.api.RpcRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.OutputRuntimeType; import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.util.ClassLoaderUtils; @@ -85,9 +85,7 @@ import org.opendaylight.yangtools.yang.binding.OpaqueObject; import org.opendaylight.yangtools.yang.binding.RpcInput; import org.opendaylight.yangtools.yang.binding.RpcOutput; import org.opendaylight.yangtools.yang.binding.YangData; -import org.opendaylight.yangtools.yang.binding.contract.Naming; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.common.YangDataName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; @@ -106,13 +104,10 @@ import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolde import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode; import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; -import org.opendaylight.yangtools.yang.model.api.ContainerLike; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.TypeAware; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; @@ -156,10 +151,10 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri return new DataContainerSerializer(BindingCodecContext.this, streamers.get(key)); } }); - private final LoadingCache, DataContainerCodecContext> childrenByClass = + private final LoadingCache, DataContainerCodecContext> childrenByClass = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override - public DataContainerCodecContext load(final Class key) { + public DataContainerCodecContext load(final Class key) { final var childSchema = context.getTypes().bindingChild(JavaTypeName.create(key)); if (childSchema instanceof ContainerLikeRuntimeType containerLike) { if (childSchema instanceof ContainerRuntimeType container @@ -182,15 +177,15 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri }); // FIXME: this could also be a leaf! - private final LoadingCache> childrenByDomArg = + private final LoadingCache> childrenByDomArg = CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override - public DataContainerCodecContext load(final QName qname) throws ClassNotFoundException { + public DataContainerCodecContext load(final QName qname) throws ClassNotFoundException { final var type = context.getTypes(); final var child = type.schemaTreeChild(qname); if (child == null) { final var module = qname.getModule(); - if (context.getEffectiveModelContext().findModule(module).isEmpty()) { + if (context.modelContext().findModule(module).isEmpty()) { throw new MissingSchemaException( "Module " + module + " is not present in current schema context."); } @@ -275,15 +270,13 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri .build(new CacheLoader<>() { @Override public NotificationCodecContext load(final Class key) { - // FIXME: sharpen check to an Notification.class - checkArgument(key.isInterface(), "Supplied class must be interface."); - - // TODO: we should be able to work with bindingChild() instead of schemaTreeChild() here - final var qname = BindingReflections.findQName(key); - if (context.getTypes().schemaTreeChild(qname) instanceof NotificationRuntimeType type) { - return new NotificationCodecContext<>(key, type, BindingCodecContext.this); + final var runtimeType = context.getTypes().bindingChild(JavaTypeName.create(key)); + if (runtimeType instanceof NotificationRuntimeType notification) { + return new NotificationCodecContext<>(key, notification, BindingCodecContext.this); + } if (runtimeType != null) { + throw new IllegalArgumentException(key + " maps to unexpected " + runtimeType); } - throw new IllegalArgumentException("Supplied " + key + " is not valid notification"); + throw new IllegalArgumentException(key + " is not a known class"); } }); private final LoadingCache> notificationsByPath = @@ -303,62 +296,17 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override public ContainerLikeCodecContext load(final Class key) { - final Function> lookup; - if (RpcInput.class.isAssignableFrom(key)) { - lookup = RpcRuntimeType::input; - } else if (RpcOutput.class.isAssignableFrom(key)) { - lookup = RpcRuntimeType::output; + final var runtimeType = context.getTypes().findSchema(JavaTypeName.create(key)) + .orElseThrow(() -> new IllegalArgumentException(key + " is not a known class")); + if (RpcInput.class.isAssignableFrom(key) && runtimeType instanceof InputRuntimeType input) { + // FIXME: accurate type + return new ContainerLikeCodecContext(key, input, BindingCodecContext.this); + } else if (RpcOutput.class.isAssignableFrom(key) && runtimeType instanceof OutputRuntimeType output) { + // FIXME: accurate type + return new ContainerLikeCodecContext(key, output, BindingCodecContext.this); } else { - throw new IllegalArgumentException(key + " does not represent an RPC container"); + throw new IllegalArgumentException(key + " maps to unexpected " + runtimeType); } - - final QName qname = BindingReflections.findQName(key); - final QNameModule qnameModule = qname.getModule(); - final Module module = context.getEffectiveModelContext().findModule(qnameModule) - .orElseThrow(() -> new IllegalArgumentException("Failed to find module for " + qnameModule)); - final String className = Naming.getClassName(qname); - - for (var potential : module.getRpcs()) { - final QName potentialQName = potential.getQName(); - /* - * Check if rpc and class represents data from same module and then checks if rpc local name - * produces same class name as class name appended with Input/Output based on QName associated - * with binding class. - * - * FIXME: Rework this to have more precise logic regarding Binding Specification. - */ - if (key.getSimpleName().equals(Naming.getClassName(potentialQName) + className)) { - final ContainerLike schema = getRpcDataSchema(potential, qname); - checkArgument(schema != null, "Schema for %s does not define input / output.", potentialQName); - - final var runtimeType = context.getTypes().schemaTreeChild(potentialQName); - if (runtimeType instanceof RpcRuntimeType rpcType) { - // FIXME: accurate type - return new ContainerLikeCodecContext(key, lookup.apply(rpcType), BindingCodecContext.this); - } - throw new IllegalArgumentException("Cannot find runtime type for " + key); - } - } - - throw new IllegalArgumentException("Supplied class " + key + " is not valid RPC class."); - } - - /** - * Returns RPC input or output schema based on supplied QName. - * - * @param rpc RPC Definition - * @param qname input or output QName with namespace same as RPC - * @return input or output schema. Returns null if RPC does not have input/output specified. - */ - private static @Nullable ContainerLike getRpcDataSchema(final @NonNull RpcDefinition rpc, - final @NonNull QName qname) { - requireNonNull(rpc, "Rpc Schema must not be null"); - return switch (requireNonNull(qname, "QName must not be null").getLocalName()) { - case "input" -> rpc.getInput(); - case "output" -> rpc.getOutput(); - default -> throw new IllegalArgumentException( - "Supplied qname " + qname + " does not represent rpc input or output."); - }; } }); private final LoadingCache> rpcDataByPath = @@ -478,12 +426,12 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri return new BindingToNormalizedStreamWriter(getActionCodec(action).output(), domWriter); } - @NonNull DataContainerCodecContext getCodecContextNode(final InstanceIdentifier binding, + @NonNull DataContainerCodecContext getCodecContextNode(final InstanceIdentifier binding, final List builder) { final var it = binding.getPathArguments().iterator(); final var arg = it.next(); - DataContainerCodecContext current; + DataContainerCodecContext current; final var caseType = arg.getCaseType(); if (caseType.isPresent()) { final @NonNull Class type = caseType.orElseThrow(); @@ -701,7 +649,7 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri final Class valueType = method.getReturnType(); final ValueCodec codec = getCodec(valueType, leafSchema.getType()); valueNode = LeafNodeCodecContext.of(leafSchema, codec, method.getName(), valueType, - context.getEffectiveModelContext()); + context.modelContext()); } else if (schema instanceof LeafListSchemaNode leafListSchema) { final Optional optType = ClassLoaderUtils.getFirstGenericParameter( method.getGenericReturnType());