2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.ImmutableMap;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.lang.invoke.MethodHandles;
15 import java.lang.invoke.VarHandle;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.yang.binding.Augmentable;
20 import org.opendaylight.yangtools.yang.binding.Augmentation;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
25 * A base class for {@link DataObject}s which are also {@link Augmentable}, backed by {@link DataObjectCodecContext}.
26 * While this class is public, it not part of API surface and is an implementation detail. The only reason for it being
27 * public is that it needs to be accessible by code generated at runtime.
29 * @param <T> DataObject type
31 public abstract class AugmentableCodecDataObject<T extends DataObject & Augmentable<T>>
32 extends CodecDataObject<T> implements Augmentable<T> {
33 private static final VarHandle CACHED_AUGMENTATIONS;
37 CACHED_AUGMENTATIONS = MethodHandles.lookup().findVarHandle(AugmentableCodecDataObject.class,
38 "cachedAugmentations", ImmutableMap.class);
39 } catch (ReflectiveOperationException e) {
40 throw new ExceptionInInitializerError(e);
45 @SuppressWarnings("unused")
46 @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
47 private volatile ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> cachedAugmentations;
49 protected AugmentableCodecDataObject(final AbstractDataObjectCodecContext<T, ?> context,
50 final DataContainerNode data) {
54 @SuppressWarnings("unchecked")
56 public final <A extends Augmentation<T>> @Nullable A augmentation(final Class<A> augmentationType) {
57 requireNonNull(augmentationType, "Supplied augmentation must not be null.");
59 final var aug = acquireAugmentations();
61 return (A) aug.get(augmentationType);
64 @SuppressWarnings("rawtypes")
65 final var augCtx = (AugmentationCodecContext<A>) codecContext().streamChild((Class) augmentationType);
66 // Due to binding specification not representing grouping instantiations we can end up having the same
67 // augmentation applied to a grouping multiple times. While these augmentations have the same shape, they are
68 // still represented by distinct binding classes and therefore we need to make sure the result matches
69 // the augmentation the user is requesting -- otherwise a strict receiver would end up with a cryptic
70 // ClassCastException.
71 if (augCtx != null && augmentationType.isAssignableFrom(augCtx.getBindingClass())) {
72 final var augObj = augCtx.filterFrom(codecData());
81 public final ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> augmentations() {
82 final var local = acquireAugmentations();
83 return local != null ? local : loadAugmentations();
86 private ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> acquireAugmentations() {
87 return (ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>>) CACHED_AUGMENTATIONS.getAcquire(this);
90 @SuppressWarnings("unchecked")
91 private @NonNull ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>> loadAugmentations() {
92 @SuppressWarnings("rawtypes")
93 final Map extracted = codecContext().getAllAugmentationsFrom(codecData());
94 final var ret = ImmutableMap.<Class<? extends Augmentation<T>>, Augmentation<T>>copyOf(extracted);
95 final Object witness = CACHED_AUGMENTATIONS.compareAndExchangeRelease(this, null, ret);
96 return witness == null ? ret : (ImmutableMap<Class<? extends Augmentation<T>>, Augmentation<T>>) witness;