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%2FAugmentableCodecDataObject.java;h=5791d5f817e1e7ebb96fa46c10932dc44a708c25;hb=d98a73e49bee3edaf8991fc5578bea23d91a304e;hp=43edeadb86a597cab8533ecf1a868b759533e87a;hpb=49b411fd05d076a363c1c86dca881387f453487f;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java index 43edeadb86..5791d5f817 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java @@ -9,21 +9,16 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static java.util.Objects.requireNonNull; -import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.collect.ImmutableClassToInstanceMap; +import com.google.common.collect.ImmutableMap; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.opendaylight.mdsal.binding.dom.codec.util.AugmentationReader; -import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections; import org.opendaylight.yangtools.yang.binding.Augmentable; import org.opendaylight.yangtools.yang.binding.Augmentation; -import org.opendaylight.yangtools.yang.binding.AugmentationHolder; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; /** * A base class for {@link DataObject}s which are also {@link Augmentable}, backed by {@link DataObjectCodecContext}. @@ -33,44 +28,50 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; * @param DataObject type */ public abstract class AugmentableCodecDataObject> - extends CodecDataObject implements Augmentable, AugmentationHolder { - private final @NonNull DataObjectCodecContext context; + extends CodecDataObject implements Augmentable { + private static final VarHandle CACHED_AUGMENTATIONS; - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater - CACHED_AUGMENTATIONS_UPDATER = AtomicReferenceFieldUpdater.newUpdater(AugmentableCodecDataObject.class, - ImmutableClassToInstanceMap.class, "cachedAugmentations"); - private volatile ImmutableClassToInstanceMap> cachedAugmentations; + static { + try { + CACHED_AUGMENTATIONS = MethodHandles.lookup().findVarHandle(AugmentableCodecDataObject.class, + "cachedAugmentations", ImmutableMap.class); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } - public AugmentableCodecDataObject(final DataObjectCodecContext context, - final NormalizedNodeContainer data) { - super(data); - this.context = requireNonNull(context, "Context must not be null"); + // Used via VarHandle + @SuppressWarnings("unused") + private volatile ImmutableMap>, Augmentation> cachedAugmentations; + + protected AugmentableCodecDataObject(final AbstractDataObjectCodecContext context, + final DataContainerNode data) { + super(context, data); } + @SuppressWarnings("unchecked") @Override public final > @Nullable A augmentation(final Class augmentationType) { requireNonNull(augmentationType, "Supplied augmentation must not be null."); - final ImmutableClassToInstanceMap> aug = cachedAugmentations; + final var aug = acquireAugmentations(); if (aug != null) { - return aug.getInstance(augmentationType); + return (A) aug.get(augmentationType); } - @SuppressWarnings({"unchecked","rawtypes"}) - final Optional> optAugCtx = context.possibleStreamChild( - (Class) augmentationType); + @SuppressWarnings("rawtypes") + final var optAugCtx = codecContext().possibleStreamChild((Class) augmentationType); if (optAugCtx.isPresent()) { - final DataContainerCodecContext augCtx = optAugCtx.get(); + final var augCtx = (AugmentationNodeContext) optAugCtx.orElseThrow(); // Due to binding specification not representing grouping instantiations we can end up having the same // augmentation applied to a grouping multiple times. While these augmentations have the same shape, they // are still represented by distinct binding classes and therefore we need to make sure the result matches // the augmentation the user is requesting -- otherwise a strict receiver would end up with a cryptic // ClassCastException. if (augmentationType.isAssignableFrom(augCtx.getBindingClass())) { - final Optional> augData = codecData().getChild(augCtx.getDomPathArgument()); - if (augData.isPresent()) { - return (A) augCtx.deserialize(augData.get()); + final var augObj = augCtx.filterFrom(codecData()); + if (augObj != null) { + return augObj; } } } @@ -78,36 +79,21 @@ public abstract class AugmentableCodecDataObject>, Augmentation> augmentations() { - ImmutableClassToInstanceMap> local = cachedAugmentations; - if (local != null) { - return local; - } - - local = ImmutableClassToInstanceMap.copyOf(context.getAllAugmentationsFrom(codecData())); - return CACHED_AUGMENTATIONS_UPDATER.compareAndSet(this, null, local) ? local : cachedAugmentations; + public final ImmutableMap>, Augmentation> augmentations() { + final var local = acquireAugmentations(); + return local != null ? local : loadAugmentations(); } - @Override - final int codecAugmentedHashCode() { - return 31 * super.codecAugmentedHashCode() + augmentations().hashCode(); + private ImmutableMap>, Augmentation> acquireAugmentations() { + return (ImmutableMap>, Augmentation>) CACHED_AUGMENTATIONS.getAcquire(this); } - @Override - final boolean codecAugmentedEquals(final T other) { - return super.codecAugmentedEquals(other) && augmentations().equals(getAllAugmentations(other)); - } - - @Override - final ToStringHelper codecAugmentedFillToString(final ToStringHelper helper) { - return super.codecAugmentedFillToString(helper).add("augmentations", augmentations()); - } - - private static Map>, Augmentation> getAllAugmentations( - final Augmentable dataObject) { - if (dataObject instanceof AugmentationReader) { - return ((AugmentationReader) dataObject).getAugmentations(dataObject); - } - return BindingReflections.getAugmentations(dataObject); + @SuppressWarnings("unchecked") + private @NonNull ImmutableMap>, Augmentation> loadAugmentations() { + @SuppressWarnings("rawtypes") + final Map extracted = codecContext().getAllAugmentationsFrom(codecData()); + final var ret = ImmutableMap.>, Augmentation>copyOf(extracted); + final Object witness = CACHED_AUGMENTATIONS.compareAndExchangeRelease(this, null, ret); + return witness == null ? ret : (ImmutableMap>, Augmentation>) witness; } }