Split out yang-model-ri
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / typedef / TypedefEffectiveStatementImpl.java
index 8ab0ae3ad4149d707671d758273e186c35706c0e..c243097be60d870117ca76d1ff1bf9da4f8b5382 100644 (file)
@@ -7,17 +7,22 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.typedef;
 
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.VarHandle;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
 import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
@@ -28,34 +33,90 @@ import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.util.type.DerivedTypeBuilder;
-import org.opendaylight.yangtools.yang.model.util.type.DerivedTypes;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveSchemaNode;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.model.ri.type.DerivedTypeBuilder;
+import org.opendaylight.yangtools.yang.model.ri.type.DerivedTypes;
+import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredEffectiveStatement.Default;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.SchemaNodeMixin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class TypedefEffectiveStatementImpl extends AbstractEffectiveSchemaNode<TypedefStatement> implements
-        TypedefEffectiveStatement {
+final class TypedefEffectiveStatementImpl extends Default<QName, TypedefStatement>
+        implements TypedefEffectiveStatement, SchemaNodeMixin<QName, TypedefStatement> {
     private static final Logger LOG = LoggerFactory.getLogger(TypedefEffectiveStatementImpl.class);
 
-    private final @NonNull TypeDefinition<?> typeDefinition;
+    private static final VarHandle TYPE_DEFINITION;
+    private static final VarHandle TYPE_STATEMENT;
+
+    static {
+        final Lookup lookup = MethodHandles.lookup();
+        try {
+            TYPE_DEFINITION = lookup.findVarHandle(TypedefEffectiveStatementImpl.class, "typeDefinition",
+                TypeDefinition.class);
+            TYPE_STATEMENT = lookup.findVarHandle(TypedefEffectiveStatementImpl.class, "typeStatement",
+                ProxyTypeEffectiveStatement.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    private final @NonNull Object substatements;
+    private final @NonNull Immutable path;
+    private final int flags;
+
+    // Accessed via TYPE_DEFINITION
+    @SuppressWarnings("unused")
+    private volatile TypeDefinition<?> typeDefinition;
+    // Accessed via TYPE_STATEMENT
+    @SuppressWarnings("unused")
+    private volatile ProxyTypeEffectiveStatement typeStatement;
+
+    TypedefEffectiveStatementImpl(final TypedefStatement declared, final Immutable path, final int flags,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        super(declared);
+        this.path = requireNonNull(path);
+        this.flags = flags;
+        this.substatements = maskList(substatements);
+    }
+
+    @Override
+    public int flags() {
+        return flags;
+    }
 
-    private volatile TypeEffectiveStatement<TypeStatement> typeStatement;
+    @Override
+    public Immutable pathObject() {
+        return path;
+    }
 
-    TypedefEffectiveStatementImpl(final StmtContext<QName, TypedefStatement, ?> ctx) {
-        super(ctx);
+    @Override
+    public @NonNull QName argument() {
+        return getQName();
+    }
+
+    @Override
+    public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+        return unmaskList(substatements);
+    }
+
+    @Override
+    public TypeDefinition<?> getTypeDefinition() {
+        final TypeDefinition<?> existing = (TypeDefinition<?>) TYPE_DEFINITION.getAcquire(this);
+        return existing != null ? existing : loadTypeDefinition();
+    }
+
+    @Override
+    public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
+        final ProxyTypeEffectiveStatement local = (ProxyTypeEffectiveStatement) TYPE_STATEMENT.getAcquire(this);
+        return local != null ? local : loadTypeStatement();
+    }
+
+    private @NonNull TypeDefinition<?> loadTypeDefinition() {
+        final TypeEffectiveStatement<?> type = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
+        final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(type.getTypeDefinition(), getQName());
 
-        final TypeEffectiveStatement<?> typeEffectiveStmt = firstSubstatementOfType(TypeEffectiveStatement.class);
-        final DerivedTypeBuilder<?> builder = DerivedTypes.derivedTypeBuilder(typeEffectiveStmt.getTypeDefinition(),
-            ctx.getSchemaPath().get());
-        String dflt = null;
         for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
             if (stmt instanceof DefaultEffectiveStatement) {
-                dflt = ((DefaultEffectiveStatement) stmt).argument();
-                builder.setDefaultValue(dflt);
+                builder.setDefaultValue(((DefaultEffectiveStatement) stmt).argument());
             } else if (stmt instanceof DescriptionEffectiveStatement) {
                 builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
             } else if (stmt instanceof ReferenceEffectiveStatement) {
@@ -67,40 +128,20 @@ final class TypedefEffectiveStatementImpl extends AbstractEffectiveSchemaNode<Ty
             } else if (stmt instanceof UnknownSchemaNode) {
                 // FIXME: should not directly implement, I think
                 builder.addUnknownSchemaNode((UnknownSchemaNode)stmt);
-            } else {
-                if (!(stmt instanceof TypeEffectiveStatement)) {
-                    LOG.debug("Ignoring statement {}", stmt);
-                }
+            } else if (!(stmt instanceof TypeEffectiveStatement)) {
+                LOG.debug("Ignoring statement {}", stmt);
             }
         }
 
-        SourceException.throwIf(
-            EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(ctx.getRootVersion(), typeEffectiveStmt, dflt),
-            ctx.getStatementSourceReference(),
-            "Typedef '%s' has default value '%s' marked with an if-feature statement.", ctx.getStatementArgument(),
-            dflt);
-
-        typeDefinition = builder.build();
-    }
-
-    @Override
-    public TypeDefinition<?> getTypeDefinition() {
-        return typeDefinition;
+        final TypeDefinition<?> created = builder.build();
+        final Object witness = TYPE_DEFINITION.compareAndExchangeRelease(this, null, created);
+        return witness == null ? created : (TypeDefinition<?>) witness;
     }
 
-    @Override
-    public TypeEffectiveStatement<TypeStatement> asTypeEffectiveStatement() {
-        TypeEffectiveStatement<TypeStatement> ret = typeStatement;
-        if (ret == null) {
-            synchronized (this) {
-                ret = typeStatement;
-                if (ret == null) {
-                    typeStatement = ret = new ProxyTypeEffectiveStatement();
-                }
-            }
-        }
-
-        return ret;
+    private @NonNull ProxyTypeEffectiveStatement loadTypeStatement() {
+        final ProxyTypeEffectiveStatement created = new ProxyTypeEffectiveStatement();
+        final Object witness = TYPE_STATEMENT.compareAndExchangeRelease(this, null, created);
+        return witness == null ? created : (ProxyTypeEffectiveStatement) witness;
     }
 
     private final class ProxyTypeEffectiveStatement implements TypeEffectiveStatement<TypeStatement> {
@@ -125,11 +166,6 @@ final class TypedefEffectiveStatementImpl extends AbstractEffectiveSchemaNode<Ty
             return TypedefEffectiveStatementImpl.this.effectiveSubstatements();
         }
 
-        @Override
-        public StatementDefinition statementDefinition() {
-            return YangStmtMapping.TYPE;
-        }
-
         @Override
         public String argument() {
             return getQName().getLocalName();