Further optimize OrderedBy effective statement dispatch
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / AbstractEffectiveDocumentedNode.java
index d99e7d87a3801e6fc16016d33e0ce25bcdadc2e2..0d217c24888eb2636b8f872333dee56a8b73997d 100644 (file)
@@ -7,23 +7,40 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
 
-import java.util.Optional;
+import com.google.common.collect.ImmutableList;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
 import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionEffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
+// FIXME: 5.0.0: rename to AbstractEffectiveDocumentedNodeWithStatus
 public abstract class AbstractEffectiveDocumentedNode<A, D extends DeclaredStatement<A>>
-        extends DeclaredEffectiveStatementBase<A, D> implements DocumentedNode.WithStatus {
+        extends AbstractEffectiveDocumentedNodeWithoutStatus<A, D> implements DocumentedNode.WithStatus {
+    private static final VarHandle UNKNOWN_NODES;
+
+    static {
+        try {
+            UNKNOWN_NODES = MethodHandles.lookup().findVarHandle(AbstractEffectiveDocumentedNode.class,
+                "unknownNodes", ImmutableList.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
 
-    private final String description;
-    private final String reference;
     private final @NonNull Status status;
 
+    @SuppressWarnings("unused")
+    private volatile ImmutableList<UnknownSchemaNode> unknownNodes;
+
     /**
      * Constructor.
      *
@@ -32,23 +49,32 @@ public abstract class AbstractEffectiveDocumentedNode<A, D extends DeclaredState
      */
     protected AbstractEffectiveDocumentedNode(final StmtContext<A, D, ?> ctx) {
         super(ctx);
-        description = findFirstEffectiveSubstatementArgument(DescriptionEffectiveStatement.class).orElse(null);
-        reference = findFirstEffectiveSubstatementArgument(ReferenceEffectiveStatement.class).orElse(null);
         status = findFirstEffectiveSubstatementArgument(StatusEffectiveStatement.class).orElse(Status.CURRENT);
     }
 
     @Override
-    public final Optional<String> getDescription() {
-        return Optional.ofNullable(description);
+    public final Status getStatus() {
+        return status;
     }
 
     @Override
-    public final Optional<String> getReference() {
-        return Optional.ofNullable(reference);
+    public final Collection<? extends UnknownSchemaNode> getUnknownSchemaNodes() {
+        final ImmutableList<UnknownSchemaNode> existing =
+                (ImmutableList<UnknownSchemaNode>) UNKNOWN_NODES.getAcquire(this);
+        return existing != null ? existing : loadUnknownSchemaNodes();
     }
 
-    @Override
-    public final Status getStatus() {
-        return status;
+    @SuppressWarnings("unchecked")
+    private @NonNull ImmutableList<UnknownSchemaNode> loadUnknownSchemaNodes() {
+        final List<UnknownSchemaNode> init = new ArrayList<>();
+        for (EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
+            if (stmt instanceof UnknownSchemaNode) {
+                init.add((UnknownSchemaNode) stmt);
+            }
+        }
+
+        final ImmutableList<UnknownSchemaNode> computed = ImmutableList.copyOf(init);
+        final Object witness = UNKNOWN_NODES.compareAndExchangeRelease(this, null, computed);
+        return witness == null ? computed : (ImmutableList<UnknownSchemaNode>) witness;
     }
 }