def7a91d9b3ee0559209cc633462ba2a3a2cb174
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / StructuralContainerCodecContext.java
1 /*
2  * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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 java.lang.invoke.MethodHandles;
11 import java.lang.invoke.VarHandle;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType;
14 import org.opendaylight.yangtools.yang.binding.DataObject;
15 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
16 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
17
18 /**
19  * A {@link ContainerLikeCodecContext} specialized for {@code container}s which do not have a presence statement.
20  */
21 final class StructuralContainerCodecContext<D extends DataObject> extends ContainerLikeCodecContext<D> {
22     private static final VarHandle EMPTY_OBJECT;
23
24     static {
25         try {
26             EMPTY_OBJECT = MethodHandles.lookup().findVarHandle(StructuralContainerCodecContext.class,
27                 "emptyObject", DataObject.class);
28         } catch (NoSuchFieldException | IllegalAccessException e) {
29             throw new ExceptionInInitializerError(e);
30         }
31     }
32
33     @SuppressWarnings("unused")
34     private volatile D emptyObject;
35
36     StructuralContainerCodecContext(final Class<D> cls, final ContainerRuntimeType type,
37             final CodecContextFactory factory) {
38         this(new StructuralContainerCodecPrototype(Item.of(cls), type, factory));
39     }
40
41     StructuralContainerCodecContext(final StructuralContainerCodecPrototype prototype) {
42         super(prototype);
43     }
44
45     @NonNull D emptyObject() {
46         final var local = (D) EMPTY_OBJECT.getAcquire(this);
47         return local != null ? local : loadEmptyObject();
48     }
49
50     private @NonNull D loadEmptyObject() {
51         final var local = createBindingProxy(
52             Builders.containerBuilder().withNodeIdentifier(getDomPathArgument()).build());
53         final var witness = (D) EMPTY_OBJECT.compareAndExchangeRelease(this, null, local);
54         return witness != null ? witness : local;
55     }
56 }