import static java.util.Objects.requireNonNull;
-import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+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;
+import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
/**
* A base class for {@link DataObject}s which are also {@link Augmentable}, backed by {@link DataObjectCodecContext}.
* @param <T> DataObject type
*/
public abstract class AugmentableCodecDataObject<T extends DataObject & Augmentable<T>>
- extends CodecDataObject<T> implements Augmentable<T>, AugmentationHolder<T> {
- @SuppressWarnings("rawtypes")
- private static final AtomicReferenceFieldUpdater<AugmentableCodecDataObject, ImmutableMap>
- CACHED_AUGMENTATIONS_UPDATER = AtomicReferenceFieldUpdater.newUpdater(AugmentableCodecDataObject.class,
- ImmutableMap.class, "cachedAugmentations");
+ extends CodecDataObject<T> implements Augmentable<T> {
+ private static final VarHandle CACHED_AUGMENTATIONS;
+
+ static {
+ try {
+ CACHED_AUGMENTATIONS = MethodHandles.lookup().findVarHandle(AugmentableCodecDataObject.class,
+ "cachedAugmentations", ImmutableMap.class);
+ } catch (ReflectiveOperationException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ // Used via VarHandle
+ @SuppressWarnings("unused")
private volatile ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> cachedAugmentations;
- protected AugmentableCodecDataObject(final DataObjectCodecContext<T, ?> context,
- final NormalizedNodeContainer<?, ?, ?> data) {
+ protected AugmentableCodecDataObject(final AbstractDataObjectCodecContext<T, ?> context,
+ final DistinctNodeContainer<?, ?> data) {
super(context, data);
}
public final <A extends Augmentation<T>> @Nullable A augmentation(final Class<A> augmentationType) {
requireNonNull(augmentationType, "Supplied augmentation must not be null.");
- final ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> aug = cachedAugmentations;
+ final var aug = acquireAugmentations();
if (aug != null) {
return (A) aug.get(augmentationType);
}
- @SuppressWarnings({"unchecked","rawtypes"})
- final Optional<DataContainerCodecContext<?, ?>> optAugCtx = codecContext().possibleStreamChild(
- (Class) augmentationType);
+ @SuppressWarnings("rawtypes")
+ final var optAugCtx = codecContext().possibleStreamChild((Class) augmentationType);
if (optAugCtx.isPresent()) {
- final DataContainerCodecContext<?, ?> augCtx = optAugCtx.get();
+ final var augCtx = (AugmentationNodeContext<A>) 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<NormalizedNode<?, ?>> augData = codecData().getChild(augCtx.getDomPathArgument());
- if (augData.isPresent()) {
- return (A) augCtx.deserialize(augData.get());
+ final var augObj = augCtx.filterFrom((DataContainerNode) codecData());
+ if (augObj != null) {
+ return augObj;
}
}
}
@Override
public final ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> augmentations() {
- ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> local = cachedAugmentations;
- if (local != null) {
- return local;
- }
-
- local = ImmutableMap.copyOf(codecContext().getAllAugmentationsFrom(codecData()));
- return CACHED_AUGMENTATIONS_UPDATER.compareAndSet(this, null, local) ? local : cachedAugmentations;
+ final ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> local = acquireAugmentations();
+ return local != null ? local : loadAugmentations();
}
- @Override
- final int codecAugmentedHashCode() {
- return 31 * super.codecAugmentedHashCode() + augmentations().hashCode();
+ private ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> acquireAugmentations() {
+ return (ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>>) 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<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentations(
- final Augmentable<?> dataObject) {
- if (dataObject instanceof AugmentationReader) {
- return ((AugmentationReader) dataObject).getAugmentations(dataObject);
- }
- return BindingReflections.getAugmentations(dataObject);
+ @SuppressWarnings("unchecked")
+ private @NonNull ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> loadAugmentations() {
+ final var ret = ImmutableMap.copyOf(codecContext().getAllAugmentationsFrom(codecData()));
+ final Object witness = CACHED_AUGMENTATIONS.compareAndExchangeRelease(this, null, ret);
+ return witness == null ? ret : (ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>>) witness;
}
}