Move TypDefinition creation
[yangtools.git] / model / yang-model-ri / src / main / java / org / opendaylight / yangtools / yang / model / ri / stmt / impl / eff / AbstractLeafEffectiveStatement.java
index 08d2598319b3a2b4ea05b5f9725df0632f80e580..bd2f86a46b279c0efd99316c89bc8af6eabbd1eb 100644 (file)
@@ -7,23 +7,16 @@
  */
 package org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff;
 
-import static java.util.Objects.requireNonNull;
-
 import com.google.common.collect.ImmutableList;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.UnitsEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.ri.type.ConcreteTypeBuilder;
 import org.opendaylight.yangtools.yang.model.ri.type.ConcreteTypes;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.DataSchemaNodeMixin;
@@ -34,31 +27,34 @@ public abstract class AbstractLeafEffectiveStatement
         extends AbstractDeclaredEffectiveStatement.Default<QName, LeafStatement>
         implements LeafEffectiveStatement, LeafSchemaNode, DataSchemaNodeMixin<LeafStatement>,
             MandatoryMixin<QName, LeafStatement>, MustConstraintMixin<QName, LeafStatement> {
-    private final @NonNull Object substatements;
-    // FIXME: YANGTOOLS-1316: this seems to imply that argument.equals(declared.argument()) and we could save a field,
-    //                        except we need it in the constructors to materialize type. But if we turn it into a lazy
-    //                        field, we should be okay.
-    private final @NonNull QName argument;
-    private final @NonNull TypeDefinition<?> type;
+    private static final VarHandle TYPE;
+
+    static {
+        try {
+            TYPE = MethodHandles.lookup().findVarHandle(AbstractLeafEffectiveStatement.class, "type",
+                TypeDefinition.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
 
+    private final @NonNull Object substatements;
     private final int flags;
 
-    AbstractLeafEffectiveStatement(final LeafStatement declared, final QName argument, final int flags,
+    @SuppressWarnings("unused")
+    private volatile TypeDefinition<?> type;
+
+    AbstractLeafEffectiveStatement(final LeafStatement declared, final int flags,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         super(declared);
-        this.argument = requireNonNull(argument);
-        this.substatements = maskList(substatements);
         this.flags = flags;
-        type = buildType();
+        this.substatements = maskList(substatements);
     }
 
-    AbstractLeafEffectiveStatement(final AbstractLeafEffectiveStatement original, final QName argument,
-            final int flags) {
+    AbstractLeafEffectiveStatement(final AbstractLeafEffectiveStatement original, final int flags) {
         super(original);
-        this.argument = requireNonNull(argument);
-        substatements = original.substatements;
         this.flags = flags;
-        type = buildType();
+        substatements = original.substatements;
     }
 
     @Override
@@ -72,37 +68,19 @@ public abstract class AbstractLeafEffectiveStatement
     }
 
     @Override
-    public final QName argument() {
-        return argument;
+    public final LeafEffectiveStatement asEffectiveStatement() {
+        return this;
     }
 
     @Override
     public final TypeDefinition<?> getType() {
-        return type;
+        final var local = (TypeDefinition<?>) TYPE.getAcquire(this);
+        return local != null ? local : loadType();
     }
 
-    @Override
-    public final LeafEffectiveStatement asEffectiveStatement() {
-        return this;
-    }
-
-    private TypeDefinition<?> buildType() {
-        final TypeEffectiveStatement<?> typeStmt = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
-        final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
-            getQName());
-        for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
-            if (stmt instanceof DefaultEffectiveStatement) {
-                builder.setDefaultValue(((DefaultEffectiveStatement)stmt).argument());
-            } else if (stmt instanceof DescriptionEffectiveStatement) {
-                builder.setDescription(((DescriptionEffectiveStatement)stmt).argument());
-            } else if (stmt instanceof ReferenceEffectiveStatement) {
-                builder.setReference(((ReferenceEffectiveStatement)stmt).argument());
-            } else if (stmt instanceof StatusEffectiveStatement) {
-                builder.setStatus(((StatusEffectiveStatement)stmt).argument());
-            } else if (stmt instanceof UnitsEffectiveStatement) {
-                builder.setUnits(((UnitsEffectiveStatement)stmt).argument());
-            }
-        }
-        return builder.build();
+    private TypeDefinition<?> loadType() {
+        final var ret = ConcreteTypes.typeOf(this);
+        final var witness = (TypeDefinition<?>) TYPE.compareAndExchangeRelease(this, null, ret);
+        return witness != null ? witness : ret;
     }
 }