adc6a6fc70e601731e5855421e088456e7bb79a7
[yangtools.git] / model / yang-model-ri / src / main / java / org / opendaylight / yangtools / yang / model / ri / stmt / impl / eff / UndeclaredLeafEffectiveStatement.java
1 /*
2  * Copyright (c) 2021 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.yangtools.yang.model.ri.stmt.impl.eff;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ImmutableList;
13 import java.lang.invoke.MethodHandles;
14 import java.lang.invoke.VarHandle;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
18 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
19 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
20 import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
22 import org.opendaylight.yangtools.yang.model.ri.type.ConcreteTypes;
23 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractUndeclaredEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.DataSchemaNodeMixin;
25 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.MandatoryMixin;
26 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.MustConstraintMixin;
27
28 public final class UndeclaredLeafEffectiveStatement extends AbstractUndeclaredEffectiveStatement<QName, LeafStatement>
29         implements LeafEffectiveStatement, LeafSchemaNode, DataSchemaNodeMixin<LeafStatement>,
30                    MandatoryMixin<QName, LeafStatement>, MustConstraintMixin<QName, LeafStatement> {
31     private static final VarHandle TYPE;
32
33     static {
34         try {
35             TYPE = MethodHandles.lookup().findVarHandle(UndeclaredLeafEffectiveStatement.class, "type",
36                 TypeDefinition.class);
37         } catch (NoSuchFieldException | IllegalAccessException e) {
38             throw new ExceptionInInitializerError(e);
39         }
40     }
41
42     private final @NonNull Object substatements;
43     private final @NonNull QName argument;
44     private final int flags;
45
46     @SuppressWarnings("unused")
47     private volatile TypeDefinition<?> type;
48
49     public UndeclaredLeafEffectiveStatement(final QName argument, final int flags,
50             final ImmutableList<? extends @NonNull EffectiveStatement<?, ?>> substatements) {
51         this.argument = requireNonNull(argument);
52         this.flags = flags;
53         this.substatements = maskList(substatements);
54     }
55
56     public UndeclaredLeafEffectiveStatement(final UndeclaredLeafEffectiveStatement original, final QName argument,
57             final int flags) {
58         this.argument = requireNonNull(argument);
59         this.flags = flags;
60         substatements = original.substatements;
61     }
62
63     @Override
64     public QName argument() {
65         return argument;
66     }
67
68     @Override
69     public int flags() {
70         return flags;
71     }
72
73     @Override
74     public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
75         return unmaskList(substatements);
76     }
77
78     @Override
79     public LeafEffectiveStatement asEffectiveStatement() {
80         return this;
81     }
82
83     @Override
84     public TypeDefinition<?> getType() {
85         final var local = (TypeDefinition<?>) TYPE.getAcquire(this);
86         return local != null ? local : loadType();
87     }
88
89     private TypeDefinition<?> loadType() {
90         final var ret = ConcreteTypes.typeOf(this);
91         final var witness = (TypeDefinition<?>) TYPE.compareAndExchangeRelease(this, null, ret);
92         return witness != null ? witness : ret;
93     }
94 }