Remove SchemaPath from TypeDefinition implementations
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / typedef / 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.parser.rfc7950.stmt.typedef;
9
10 import com.google.common.collect.ImmutableList;
11 import java.lang.invoke.MethodHandles;
12 import java.lang.invoke.MethodHandles.Lookup;
13 import java.lang.invoke.VarHandle;
14 import java.util.Collection;
15 import java.util.Map;
16 import java.util.Optional;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.SchemaNodeDefaults;
21 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
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.StatementSource;
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.util.type.DerivedTypeBuilder;
37 import org.opendaylight.yangtools.yang.model.util.type.DerivedTypes;
38 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredEffectiveStatement.Default;
39 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.SchemaNodeMixin;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 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 @Nullable SchemaPath 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     TypedefEffectiveStatementImpl(final TypedefStatement declared, final SchemaPath path, final int flags,
74             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
75         super(declared);
76         this.path = 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     @Deprecated
88     public SchemaPath getPath() {
89         return SchemaNodeDefaults.throwUnsupportedIfNull(this, path);
90     }
91
92     @Override
93     public @NonNull QName argument() {
94         return getQName();
95     }
96
97     @Override
98     public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
99         return unmaskList(substatements);
100     }
101
102     @Override
103     public TypeDefinition<?> getTypeDefinition() {
104         final TypeDefinition<?> existing = (TypeDefinition<?>) TYPE_DEFINITION.getAcquire(this);
105         return existing != null ? existing : loadTypeDefinition();
106     }
107
108     @Override
109     public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
110         final ProxyTypeEffectiveStatement local = (ProxyTypeEffectiveStatement) TYPE_STATEMENT.getAcquire(this);
111         return local != null ? local : loadTypeStatement();
112     }
113
114     private @NonNull TypeDefinition<?> loadTypeDefinition() {
115         final TypeEffectiveStatement<?> type = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
116         final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(type.getTypeDefinition(), getQName());
117
118         for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
119             if (stmt instanceof DefaultEffectiveStatement) {
120                 builder.setDefaultValue(((DefaultEffectiveStatement) stmt).argument());
121             } else if (stmt instanceof DescriptionEffectiveStatement) {
122                 builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
123             } else if (stmt instanceof ReferenceEffectiveStatement) {
124                 builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
125             } else if (stmt instanceof StatusEffectiveStatement) {
126                 builder.setStatus(((StatusEffectiveStatement)stmt).argument());
127             } else if (stmt instanceof UnitsEffectiveStatement) {
128                 builder.setUnits(((UnitsEffectiveStatement)stmt).argument());
129             } else if (stmt instanceof UnknownSchemaNode) {
130                 // FIXME: should not directly implement, I think
131                 builder.addUnknownSchemaNode((UnknownSchemaNode)stmt);
132             } else if (!(stmt instanceof TypeEffectiveStatement)) {
133                 LOG.debug("Ignoring statement {}", stmt);
134             }
135         }
136
137         final TypeDefinition<?> created = builder.build();
138         final Object witness = TYPE_DEFINITION.compareAndExchangeRelease(this, null, created);
139         return witness == null ? created : (TypeDefinition<?>) witness;
140     }
141
142     private @NonNull ProxyTypeEffectiveStatement loadTypeStatement() {
143         final ProxyTypeEffectiveStatement created = new ProxyTypeEffectiveStatement();
144         final Object witness = TYPE_STATEMENT.compareAndExchangeRelease(this, null, created);
145         return witness == null ? created : (ProxyTypeEffectiveStatement) witness;
146     }
147
148     private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
149         @Override
150         public TypeStatement getDeclared() {
151             return null;
152         }
153
154         @Override
155         public <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends V> get(final Class<N> namespace,
156                 final K identifier) {
157             return TypedefEffectiveStatementImpl.this.get(namespace, identifier);
158         }
159
160         @Override
161         public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
162             return TypedefEffectiveStatementImpl.this.getAll(namespace);
163         }
164
165         @Override
166         public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
167             return TypedefEffectiveStatementImpl.this.effectiveSubstatements();
168         }
169
170         @Override
171         public String argument() {
172             return getQName().getLocalName();
173         }
174
175         @Override
176         public StatementSource getStatementSource() {
177             return StatementSource.CONTEXT;
178         }
179
180         @Override
181         public TypeDefinition<?> getTypeDefinition() {
182             return TypedefEffectiveStatementImpl.this.getTypeDefinition();
183         }
184     }
185 }