From 0a4a9179882447a97a7ee95d256f615affaa656d Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 4 Jun 2023 23:47:46 +0200 Subject: [PATCH] Split out NotificationCodecContext.Prototype Notifications require a special context, split them out and guard against re-instantiation. Change-Id: I7eede21b2aeab92c02ae451a4c5e341361563bca Signed-off-by: Robert Varga --- .../impl/DataContainerCodecPrototype.java | 7 ------- .../codec/impl/NotificationCodecContext.java | 21 +++++++++++++++++-- .../codec/impl/SchemaRootCodecContext.java | 21 +++++++++++-------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java index e446c7bdf2..4fcbf16d5d 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java @@ -16,7 +16,6 @@ import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.dom.codec.api.CommonDataObjectCodecTreeNode.ChildAddressabilitySummary; import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory; import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType; -import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType; import org.opendaylight.mdsal.binding.runtime.api.RuntimeType; import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; @@ -161,12 +160,6 @@ abstract sealed class DataContainerCodecPrototype(bindingArg, createIdentifier(type), type, factory); } - static DataContainerCodecPrototype from(final Class augClass, - final NotificationRuntimeType schema, final CodecContextFactory factory) { - return new DataObjectCodecPrototype<>(augClass, NodeIdentifier.create(schema.statement().argument()), schema, - factory); - } - private static @NonNull NodeIdentifier createIdentifier(final CompositeRuntimeType type) { final Object arg = type.statement().argument(); verify(arg instanceof QName, "Unexpected type %s argument %s", type, arg); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java index b8cd98075d..9bae0af94c 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java @@ -39,6 +39,7 @@ import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType; import org.opendaylight.yangtools.yang.binding.BaseNotification; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.EventInstantAware; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -68,9 +69,9 @@ final class NotificationCodecContext private final MethodHandle eventProxy; - NotificationCodecContext(final Class key, final NotificationRuntimeType schema, + NotificationCodecContext(final Class notificationClass, final NotificationRuntimeType type, final CodecContextFactory factory) { - super(DataContainerCodecPrototype.from(key, schema, factory)); + super(new Prototype<>(notificationClass, type, factory)); final Class bindingClass = getBindingClass(); final Class awareClass = CodecPackage.EVENT_AWARE.generateClass(factory().getLoader(), bindingClass, @@ -121,6 +122,22 @@ final class NotificationCodecContext return deserialize(normalizedNode); } + /** + * Prototype for a {@code notiofication}. This class only exists because DataContainerCodecContext requires a + * prototype. + */ + private static final class Prototype + extends DataObjectCodecPrototype { + Prototype(final Class cls, final NotificationRuntimeType type, final CodecContextFactory factory) { + super(cls, NodeIdentifier.create(type.statement().argument()), type, factory); + } + + @Override + DataContainerCodecContext createInstance() { + throw new UnsupportedOperationException("Should never be invoked"); + } + } + private enum ConstructorImplementation implements Implementation { INSTANCE; diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java index b190aad2b2..133c75f254 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/SchemaRootCodecContext.java @@ -114,14 +114,15 @@ final class SchemaRootCodecContext extends DataContainerCo .build(new CacheLoader, NotificationCodecContext>() { @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 QName qname = BindingReflections.findQName(key); - final RuntimeType child = getType().schemaTreeChild(qname); - checkArgument(child instanceof NotificationRuntimeType, "Supplied %s is not valid notification", - key); - return new NotificationCodecContext<>(key, (NotificationRuntimeType) child, factory()); + final var qname = BindingReflections.findQName(key); + if (getType().schemaTreeChild(qname) instanceof NotificationRuntimeType type) { + return new NotificationCodecContext<>(key, type, factory()); + } + throw new IllegalArgumentException("Supplied " + key + " is not valid notification"); } }); @@ -214,10 +215,12 @@ final class SchemaRootCodecContext extends DataContainerCo CacheBuilder.newBuilder().build(new CacheLoader<>() { @Override public NotificationCodecContext load(final Absolute key) { - final Class cls = factory().getRuntimeContext().getClassForSchema(key); - checkArgument(Notification.class.isAssignableFrom(cls), "Path %s does not represent a notification", - key); - return getNotificationImpl(cls); + final var cls = factory().getRuntimeContext().getClassForSchema(key); + try { + return getNotificationImpl(cls.asSubclass(Notification.class)); + } catch (ClassCastException e) { + throw new IllegalArgumentException("Path " + key + " does not represent a notification", e); + } } }); -- 2.36.6