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=6a74a24661bd80ba433b8f13ea1305ff893f67b2;hb=9f23891d96e635e1cd30c699f9b72b9336fc9d06;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..6a74a24661 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,17 @@ 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +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,81 +29,70 @@ 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") + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749") + 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); - if (optAugCtx.isPresent()) { - final DataContainerCodecContext augCtx = optAugCtx.get(); - // 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()); - } + @SuppressWarnings("rawtypes") + final var augCtx = (AugmentationCodecContext) codecContext().streamChild((Class) augmentationType); + // 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 (augCtx != null && augmentationType.isAssignableFrom(augCtx.getBindingClass())) { + final var augObj = augCtx.filterFrom(codecData()); + if (augObj != null) { + return augObj; } } return null; } @Override - public final Map>, 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; } }