From 74ef67db283874e6024413355267120c77a6095c Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 11 Jan 2024 13:05:53 +0100 Subject: [PATCH] Hide CodecContextSupplier Refactoring InstanceIdentifier.Item flushes out a problem with the class hierarchy of ChoiceNodeContextPrototype. Start off by refactoring CodecContextSupplier, introducing LazyCodecContextSupplier base class. JIRA: MDSAL-815 Change-Id: I79fe079d9fc4b0adf166c1a8b2561fb03a2f071f Signed-off-by: Robert Varga --- .../impl/AbstractDataObjectCodecContext.java | 2 +- .../dom/codec/impl/ChoiceCodecContext.java | 5 +- .../dom/codec/impl/CodecContextSupplier.java | 8 ++- .../dom/codec/impl/CodecDataObject.java | 2 +- .../impl/CommonDataObjectCodecPrototype.java | 37 +------------ .../dom/codec/impl/DataContainerAnalysis.java | 2 +- .../codec/impl/DataContainerCodecContext.java | 4 +- .../codec/impl/DataObjectCodecContext.java | 2 +- .../codec/impl/LazyCodecContextSupplier.java | 52 +++++++++++++++++++ .../dom/codec/impl/ValueNodeCodecContext.java | 2 +- 10 files changed, 67 insertions(+), 49 deletions(-) create mode 100644 binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyCodecContextSupplier.java diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java index 6748f6bb97..0afa5e63e4 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java @@ -74,7 +74,7 @@ public abstract sealed class AbstractDataObjectCodecContext choice) { choice.addYangPathArgument(arg, builder); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java index 9e55f2da29..a7ec5fabb2 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java @@ -238,7 +238,7 @@ final class ChoiceCodecContext extends CommonDataObjectCod return null; } final var caze = byYangCaseChild.get(first.name()); - return ((CaseCodecContext) caze.get()).deserialize(data); + return ((CaseCodecContext) caze.getCodecContext()).deserialize(data); } @Override @@ -288,7 +288,8 @@ final class ChoiceCodecContext extends CommonDataObjectCod } } - return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg()).get(); + return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg()) + .getCodecContext(); } /** diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecContextSupplier.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecContextSupplier.java index 1fa8b16887..c8eaea1eb7 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecContextSupplier.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecContextSupplier.java @@ -7,16 +7,14 @@ */ package org.opendaylight.mdsal.binding.dom.codec.impl; -import com.google.common.annotations.Beta; import org.eclipse.jdt.annotation.NonNullByDefault; /** * Type capture of an entity producing NodeCodecContexts. Implementations are required to perform memoization. This * interface does not form API surface and is exposed only for generated code. It can change at any time. */ -@Beta -@FunctionalInterface @NonNullByDefault -public interface CodecContextSupplier { - CodecContext get(); +sealed interface CodecContextSupplier permits LazyCodecContextSupplier, ValueNodeCodecContext { + + CodecContext getCodecContext(); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java index 173ccccd44..a32e7ea309 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java @@ -82,7 +82,7 @@ public abstract class CodecDataObject implements DataObjec protected final Object codecMember(final VarHandle handle, final CodecContextSupplier supplier) { final Object cached = handle.getAcquire(this); - return cached != null ? unmaskNull(cached) : loadMember(handle, supplier.get()); + return cached != null ? unmaskNull(cached) : loadMember(handle, supplier.getCodecContext()); } protected final @NonNull Object codecMemberOrEmpty(final @Nullable Object value, diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java index 24340e4652..ec3a2ea64c 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java @@ -9,36 +9,18 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static java.util.Objects.requireNonNull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; -abstract sealed class CommonDataObjectCodecPrototype implements CodecContextSupplier +abstract sealed class CommonDataObjectCodecPrototype + extends LazyCodecContextSupplier> permits AugmentationCodecPrototype, DataObjectCodecPrototype { - private static final VarHandle INSTANCE; - - static { - try { - INSTANCE = MethodHandles.lookup().findVarHandle(CommonDataObjectCodecPrototype.class, - "instance", CommonDataObjectCodecContext.class); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new ExceptionInInitializerError(e); - } - } - private final @NonNull T type; private final @NonNull CodecContextFactory factory; private final @NonNull Item bindingArg; - // Accessed via INSTANCE - @SuppressWarnings("unused") - @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749") - private volatile CommonDataObjectCodecContext instance; - CommonDataObjectCodecPrototype(final Item bindingArg, final T type, final CodecContextFactory factory) { this.bindingArg = requireNonNull(bindingArg); this.type = requireNonNull(type); @@ -62,19 +44,4 @@ abstract sealed class CommonDataObjectCodecPrototype get() { - final var existing = (CommonDataObjectCodecContext) INSTANCE.getAcquire(this); - return existing != null ? existing : loadInstance(); - } - - private @NonNull CommonDataObjectCodecContext loadInstance() { - final var tmp = createInstance(); - final var witness = (CommonDataObjectCodecContext) INSTANCE.compareAndExchangeRelease(this, null, tmp); - return witness == null ? tmp : witness; - } - - // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object - abstract @NonNull CommonDataObjectCodecContext createInstance(); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerAnalysis.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerAnalysis.java index 608445ea03..f6cf8b6276 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerAnalysis.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerAnalysis.java @@ -96,7 +96,7 @@ final class DataContainerAnalysis { // FIXME: It really feels like we should be specializing DataContainerCodecPrototype so as to ditch // createInstance() and then we could do an instanceof check instead. if (childProto.getType() instanceof ChoiceRuntimeType) { - final var choice = (ChoiceCodecContext) childProto.get(); + final var choice = (ChoiceCodecContext) childProto.getCodecContext(); for (var cazeChild : choice.getCaseChildrenClasses()) { byBindingArgClassBuilder.put(cazeChild, childProto); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java index 67cbc1aa3b..4dec5e68c3 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java @@ -108,7 +108,7 @@ abstract sealed class DataContainerCodecContext CommonDataObjectCodecContext streamChild(final Class childClass) { final var childProto = streamChildPrototype(requireNonNull(childClass)); - return childProto == null ? null : (CommonDataObjectCodecContext) childProto.get(); + return childProto == null ? null : (CommonDataObjectCodecContext) childProto.getCodecContext(); } abstract @Nullable CommonDataObjectCodecPrototype streamChildPrototype(@NonNull Class childClass); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java index f076958cf3..1666ec8043 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java @@ -297,7 +297,7 @@ public abstract sealed class DataObjectCodecContext {@link CodecContext} type + */ +public abstract sealed class LazyCodecContextSupplier implements CodecContextSupplier + permits CommonDataObjectCodecPrototype { + private static final VarHandle INSTANCE; + + static { + try { + INSTANCE = MethodHandles.lookup().findVarHandle(LazyCodecContextSupplier.class, "instance", + CodecContext.class); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new ExceptionInInitializerError(e); + } + } + + // Accessed via INSTANCE + @SuppressWarnings("unused") + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749") + private volatile C instance; + + @Override + public final C getCodecContext() { + final var existing = (C) INSTANCE.getAcquire(this); + return existing != null ? existing : loadInstance(); + } + + private @NonNull C loadInstance() { + final var tmp = createInstance(); + final var witness = (C) INSTANCE.compareAndExchangeRelease(this, null, tmp); + return witness == null ? tmp : witness; + } + + // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object + abstract @NonNull C createInstance(); +} diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ValueNodeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ValueNodeCodecContext.java index 2a9c533266..311ec98e9c 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ValueNodeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ValueNodeCodecContext.java @@ -53,7 +53,7 @@ abstract sealed class ValueNodeCodecContext extends CodecContext implements Code } @Override - public final CodecContext get() { + public final CodecContext getCodecContext() { return this; } -- 2.36.6