24340e46527227816b59f5efb9a5d575a4d349f4
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / CommonDataObjectCodecPrototype.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import java.lang.invoke.MethodHandles;
14 import java.lang.invoke.VarHandle;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
17 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19
20 abstract sealed class CommonDataObjectCodecPrototype<T extends CompositeRuntimeType> implements CodecContextSupplier
21         permits AugmentationCodecPrototype, DataObjectCodecPrototype {
22     private static final VarHandle INSTANCE;
23
24     static {
25         try {
26             INSTANCE = MethodHandles.lookup().findVarHandle(CommonDataObjectCodecPrototype.class,
27                 "instance", CommonDataObjectCodecContext.class);
28         } catch (NoSuchFieldException | IllegalAccessException e) {
29             throw new ExceptionInInitializerError(e);
30         }
31     }
32
33     private final @NonNull T type;
34     private final @NonNull CodecContextFactory factory;
35     private final @NonNull Item<?> bindingArg;
36
37     // Accessed via INSTANCE
38     @SuppressWarnings("unused")
39     @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
40     private volatile CommonDataObjectCodecContext<?, T> instance;
41
42     CommonDataObjectCodecPrototype(final Item<?> bindingArg, final T type, final CodecContextFactory factory) {
43         this.bindingArg = requireNonNull(bindingArg);
44         this.type = requireNonNull(type);
45         this.factory = requireNonNull(factory);
46     }
47
48     final @NonNull T getType() {
49         return type;
50     }
51
52     final @NonNull CodecContextFactory getFactory() {
53         return factory;
54     }
55
56     final @NonNull Class<?> getBindingClass() {
57         return bindingArg.getType();
58     }
59
60     final @NonNull Item<?> getBindingArg() {
61         return bindingArg;
62     }
63
64     abstract @NonNull NodeIdentifier getYangArg();
65
66     @Override
67     public final CommonDataObjectCodecContext<?, T> get() {
68         final var existing = (CommonDataObjectCodecContext<?, T>) INSTANCE.getAcquire(this);
69         return existing != null ? existing : loadInstance();
70     }
71
72     private @NonNull CommonDataObjectCodecContext<?, T> loadInstance() {
73         final var tmp = createInstance();
74         final var witness = (CommonDataObjectCodecContext<?, T>) INSTANCE.compareAndExchangeRelease(this, null, tmp);
75         return witness == null ? tmp : witness;
76     }
77
78     // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
79     abstract @NonNull CommonDataObjectCodecContext<?, T> createInstance();
80 }