Add OrderedByAwareEffectiveStatement
[yangtools.git] / model / yang-model-ri / src / main / java / org / opendaylight / yangtools / yang / model / ri / stmt / impl / eff / AbstractLeafListEffectiveStatement.java
index 881d98b6ad267f649f96522624ea4ffcbe1229d5..d9458c7ce2763ce13469379cdc702dded46fa397 100644 (file)
@@ -7,55 +7,55 @@
  */
 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.LeafListSchemaNode;
 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.DescriptionEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafListEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafListStatement;
-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;
 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.MustConstraintMixin;
-import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.UserOrderedMixin;
+import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.UserOrderedAwareMixin;
 
 abstract class AbstractLeafListEffectiveStatement
         extends AbstractDeclaredEffectiveStatement.Default<QName, LeafListStatement>
-        implements LeafListEffectiveStatement, LeafListSchemaNode, UserOrderedMixin<QName, LeafListStatement>,
+        implements LeafListEffectiveStatement, LeafListSchemaNode,
+            UserOrderedAwareMixin<QName, LeafListStatement, LeafListEffectiveStatement>,
             DataSchemaNodeMixin<LeafListStatement>, MustConstraintMixin<QName, LeafListStatement> {
+    private static final VarHandle TYPE;
+
+    static {
+        try {
+            TYPE = MethodHandles.lookup().findVarHandle(AbstractLeafListEffectiveStatement.class, "type",
+                TypeDefinition.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
     private final @NonNull Object substatements;
-    private final @NonNull QName argument;
-    private final @NonNull TypeDefinition<?> type;
     private final int flags;
 
-    AbstractLeafListEffectiveStatement(final LeafListStatement declared, final QName argument, final int flags,
+    @SuppressWarnings("unused")
+    private volatile TypeDefinition<?> type;
+
+    AbstractLeafListEffectiveStatement(final LeafListStatement declared, final int flags,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         super(declared);
-        this.argument = requireNonNull(argument);
         this.substatements = maskList(substatements);
         this.flags = flags;
-        // TODO: lazy instantiation?
-        this.type = buildType();
     }
 
-    AbstractLeafListEffectiveStatement(final AbstractLeafListEffectiveStatement original, final QName argument,
-            final int flags) {
+    AbstractLeafListEffectiveStatement(final AbstractLeafListEffectiveStatement original, final int flags) {
         super(original);
-        this.argument = requireNonNull(argument);
-        this.substatements = original.substatements;
+        substatements = original.substatements;
         this.flags = flags;
-        // TODO: lazy instantiation?
-        this.type = buildType();
     }
 
     @Override
@@ -68,47 +68,20 @@ abstract class AbstractLeafListEffectiveStatement
         return flags;
     }
 
-    @Override
-    public final QName argument() {
-        return argument;
-    }
-
-    @Override
-    public final TypeDefinition<?> getType() {
-        return type;
-    }
-
-    @Override
-    public final boolean isUserOrdered() {
-        return userOrdered();
-    }
-
     @Override
     public final LeafListEffectiveStatement asEffectiveStatement() {
         return this;
     }
 
     @Override
-    public final String toString() {
-        return getClass().getSimpleName() + "[" + argument + "]";
+    public final TypeDefinition<?> getType() {
+        final var local = (TypeDefinition<?>) TYPE.getAcquire(this);
+        return local != null ? local : loadType();
     }
 
-    private TypeDefinition<?> buildType() {
-        final TypeEffectiveStatement<?> typeStmt = findFirstEffectiveSubstatement(TypeEffectiveStatement.class).get();
-        final ConcreteTypeBuilder<?> builder = ConcreteTypes.concreteTypeBuilder(typeStmt.getTypeDefinition(),
-            getQName());
-        for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
-            // NOTE: 'default' is omitted here on purpose
-            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;
     }
 }