Rename StatementSource to StatementOrigin
[yangtools.git] / yang / yang-model-ri / src / main / java / org / opendaylight / yangtools / yang / model / ri / stmt / impl / eff / TypedefEffectiveStatementImpl.java
1 /*
2  * Copyright (c) 2015 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.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.MethodHandles.Lookup;
15 import java.lang.invoke.VarHandle;
16 import java.util.Collection;
17 import java.util.Map;
18 import java.util.Optional;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.yangtools.concepts.Immutable;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
26 import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
27 import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
29 import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
30 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
31 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
32 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
33 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
34 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
35 import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
36 import org.opendaylight.yangtools.yang.model.ri.type.DerivedTypeBuilder;
37 import org.opendaylight.yangtools.yang.model.ri.type.DerivedTypes;
38 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredEffectiveStatement.Default;
39 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.SchemaNodeMixin;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public final class TypedefEffectiveStatementImpl extends Default<QName, TypedefStatement>
44         implements TypedefEffectiveStatement, SchemaNodeMixin<QName, TypedefStatement> {
45     private static final Logger LOG = LoggerFactory.getLogger(TypedefEffectiveStatementImpl.class);
46
47     private static final VarHandle TYPE_DEFINITION;
48     private static final VarHandle TYPE_STATEMENT;
49
50     static {
51         final Lookup lookup = MethodHandles.lookup();
52         try {
53             TYPE_DEFINITION = lookup.findVarHandle(TypedefEffectiveStatementImpl.class, "typeDefinition",
54                 TypeDefinition.class);
55             TYPE_STATEMENT = lookup.findVarHandle(TypedefEffectiveStatementImpl.class, "typeStatement",
56                 ProxyTypeEffectiveStatement.class);
57         } catch (NoSuchFieldException | IllegalAccessException e) {
58             throw new ExceptionInInitializerError(e);
59         }
60     }
61
62     private final @NonNull Object substatements;
63     private final @NonNull Immutable path;
64     private final int flags;
65
66     // Accessed via TYPE_DEFINITION
67     @SuppressWarnings("unused")
68     private volatile TypeDefinition<?> typeDefinition;
69     // Accessed via TYPE_STATEMENT
70     @SuppressWarnings("unused")
71     private volatile ProxyTypeEffectiveStatement typeStatement;
72
73     public TypedefEffectiveStatementImpl(final TypedefStatement declared, final Immutable path, final int flags,
74             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
75         super(declared);
76         this.path = requireNonNull(path);
77         this.flags = flags;
78         this.substatements = maskList(substatements);
79     }
80
81     @Override
82     public int flags() {
83         return flags;
84     }
85
86     @Override
87     public Immutable pathObject() {
88         return path;
89     }
90
91     @Override
92     public @NonNull QName argument() {
93         return getQName();
94     }
95
96     @Override
97     public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
98         return unmaskList(substatements);
99     }
100
101     @Override
102     public TypeDefinition<?> getTypeDefinition() {
103         final TypeDefinition<?> existing = (TypeDefinition<?>) TYPE_DEFINITION.getAcquire(this);
104         return existing != null ? existing : loadTypeDefinition();
105     }
106
107     @Override
108     public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
109         final ProxyTypeEffectiveStatement local = (ProxyTypeEffectiveStatement) TYPE_STATEMENT.getAcquire(this);
110         return local != null ? local : loadTypeStatement();
111     }
112
113     private @NonNull TypeDefinition<?> loadTypeDefinition() {
114         final TypeEffectiveStatement<?> type = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
115         final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(type.getTypeDefinition(), getQName());
116
117         for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
118             if (stmt instanceof DefaultEffectiveStatement) {
119                 builder.setDefaultValue(((DefaultEffectiveStatement) stmt).argument());
120             } else if (stmt instanceof DescriptionEffectiveStatement) {
121                 builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
122             } else if (stmt instanceof ReferenceEffectiveStatement) {
123                 builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
124             } else if (stmt instanceof StatusEffectiveStatement) {
125                 builder.setStatus(((StatusEffectiveStatement)stmt).argument());
126             } else if (stmt instanceof UnitsEffectiveStatement) {
127                 builder.setUnits(((UnitsEffectiveStatement)stmt).argument());
128             } else if (stmt instanceof UnknownSchemaNode) {
129                 // FIXME: should not directly implement, I think
130                 builder.addUnknownSchemaNode((UnknownSchemaNode)stmt);
131             } else if (!(stmt instanceof TypeEffectiveStatement)) {
132                 LOG.debug("Ignoring statement {}", stmt);
133             }
134         }
135
136         final TypeDefinition<?> created = builder.build();
137         final Object witness = TYPE_DEFINITION.compareAndExchangeRelease(this, null, created);
138         return witness == null ? created : (TypeDefinition<?>) witness;
139     }
140
141     private @NonNull ProxyTypeEffectiveStatement loadTypeStatement() {
142         final ProxyTypeEffectiveStatement created = new ProxyTypeEffectiveStatement();
143         final Object witness = TYPE_STATEMENT.compareAndExchangeRelease(this, null, created);
144         return witness == null ? created : (ProxyTypeEffectiveStatement) witness;
145     }
146
147     private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
148         @Override
149         public TypeStatement getDeclared() {
150             return null;
151         }
152
153         @Override
154         public <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends V> get(final Class<N> namespace,
155                 final K identifier) {
156             return TypedefEffectiveStatementImpl.this.get(namespace, identifier);
157         }
158
159         @Override
160         public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
161             return TypedefEffectiveStatementImpl.this.getAll(namespace);
162         }
163
164         @Override
165         public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
166             return TypedefEffectiveStatementImpl.this.effectiveSubstatements();
167         }
168
169         @Override
170         public QName argument() {
171             return getQName();
172         }
173
174         @Override
175         public StatementOrigin statementOrigin() {
176             return StatementOrigin.CONTEXT;
177         }
178
179         @Override
180         public TypeDefinition<?> getTypeDefinition() {
181             return TypedefEffectiveStatementImpl.this.getTypeDefinition();
182         }
183     }
184 }