Optimize Status statement declarations 88/87288/1
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 27 Jan 2020 23:40:42 +0000 (00:40 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 30 Jan 2020 10:41:50 +0000 (11:41 +0100)
As Status has low cardinality we can quite easily improve things
by sharing common instances.

JIRA: YANGTOOLS-1065
Change-Id: Ie404a65bc4a43b0d51e72f011a2aa7a5980c30df
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit f69f568356663d3583f5b2c06a5ba5c7738562fe)
(cherry picked from commit f3ec202944e53864c67990ff580295073311b5d3)

yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/Status.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/AbstractStatusEffectiveStatement.java [moved from yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/StatusEffectiveStatementImpl.java with 55% similarity]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/AbstractStatusStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/EmptyStatusEffectiveStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/EmptyStatusStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/RegularStatusEffectiveStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/RegularStatusStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/StatusStatementImpl.java [deleted file]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/StatusStatementSupport.java

index 55f5ccdcf079648fb4a0c97bb0428817e67fe8d8..17a4ec16fdd18b5ddefda6453badf1d0fa1c6a2c 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.api;
 
+import com.google.common.annotations.Beta;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 
 /**
@@ -18,16 +19,41 @@ public enum Status {
     /**
      * CURRENT means that the definition is current and valid.
      */
-    CURRENT,
+    CURRENT("current"),
     /**
      * DEPRECATED indicates an obsolete definition, but it permits new/
      * continued implementation in order to foster interoperability with
      * older/existing implementations.
      */
-    DEPRECATED,
+    DEPRECATED("deprecated"),
     /**
      * OBSOLETE means the definition is obsolete and SHOULD NOT be implemented
      * and/or can be removed from implementations.
      */
-    OBSOLETE
+    OBSOLETE("obsolete");
+
+    private final String argumentString;
+
+    Status(final String argumentString) {
+        this.argumentString = argumentString;
+    }
+
+    @Beta
+    public String getArgumentString() {
+        return argumentString;
+    }
+
+    @Beta
+    public static Status forArgumentString(final String argumentString) {
+        switch (argumentString) {
+            case "current":
+                return CURRENT;
+            case "deprecated":
+                return DEPRECATED;
+            case "obsolete":
+                return OBSOLETE;
+            default:
+                throw new IllegalArgumentException("Invalid status string '" + argumentString + "'");
+        }
+    }
 }
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -10,12 +10,12 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
-import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.DeclaredEffectiveStatementBase;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredEffectiveStatement;
 
-final class StatusEffectiveStatementImpl extends DeclaredEffectiveStatementBase<Status, StatusStatement>
+abstract class AbstractStatusEffectiveStatement
+        extends AbstractDeclaredEffectiveStatement.DefaultArgument<Status, StatusStatement>
         implements StatusEffectiveStatement {
-    StatusEffectiveStatementImpl(final StmtContext<Status, StatusStatement, ?> ctx) {
-        super(ctx);
+    AbstractStatusEffectiveStatement(final StatusStatement declared) {
+        super(declared);
     }
-}
\ No newline at end of file
+}
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/AbstractStatusStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/AbstractStatusStatement.java
new file mode 100644 (file)
index 0000000..e5d28fe
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractDeclaredStatement;
+
+abstract class AbstractStatusStatement extends AbstractDeclaredStatement<Status> implements StatusStatement {
+    private final @NonNull Status argument;
+
+    AbstractStatusStatement(final Status argument) {
+        this.argument = requireNonNull(argument);
+    }
+
+    @Override
+    public final @NonNull Status argument() {
+        return argument;
+    }
+
+    @Override
+    public final @NonNull String rawArgument() {
+        return argument.getArgumentString();
+    }
+
+    @Override
+    public final StatementDefinition statementDefinition() {
+        return YangStmtMapping.STATUS;
+    }
+}
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/EmptyStatusEffectiveStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/EmptyStatusEffectiveStatement.java
new file mode 100644 (file)
index 0000000..c00d665
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
+
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+
+final class EmptyStatusEffectiveStatement extends AbstractStatusEffectiveStatement {
+    EmptyStatusEffectiveStatement(final StatusStatement declared) {
+        super(declared);
+    }
+}
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/EmptyStatusStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/EmptyStatusStatement.java
new file mode 100644 (file)
index 0000000..d355474
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
+
+import org.opendaylight.yangtools.yang.model.api.Status;
+
+final class EmptyStatusStatement extends AbstractStatusStatement {
+    EmptyStatusStatement(final Status argument) {
+        super(argument);
+    }
+}
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/RegularStatusEffectiveStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/RegularStatusEffectiveStatement.java
new file mode 100644 (file)
index 0000000..afd7cca
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
+
+import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
+
+final class RegularStatusEffectiveStatement extends AbstractStatusEffectiveStatement {
+    private final @NonNull Object substatements;
+
+    RegularStatusEffectiveStatement(final StatusStatement declared,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        super(declared);
+        this.substatements = maskList(substatements);
+    }
+
+    @Override
+    public ImmutableList<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+        return unmaskList(substatements);
+    }
+}
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/RegularStatusStatement.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/RegularStatusStatement.java
new file mode 100644 (file)
index 0000000..3709cb7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+
+final class RegularStatusStatement extends AbstractStatusStatement {
+    private final @NonNull Object substatements;
+
+    RegularStatusStatement(final Status argument, final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+        super(argument);
+        this.substatements = maskList(substatements);
+    }
+
+    @Override
+    public Collection<? extends DeclaredStatement<?>> declaredSubstatements() {
+        return unmaskList(substatements);
+    }
+}
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/StatusStatementImpl.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/status/StatusStatementImpl.java
deleted file mode 100644 (file)
index 59ad68c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
-
-import org.opendaylight.yangtools.yang.model.api.Status;
-import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-
-final class StatusStatementImpl extends AbstractDeclaredStatement<Status> implements StatusStatement {
-    StatusStatementImpl(final StmtContext<Status, StatusStatement, ?> context) {
-        super(context);
-    }
-}
index 0928b6731b778308b42a8001318bb859492e9e83..b0e14c755fdf81e19e6e696bb2ad8f57cf719716 100644 (file)
@@ -7,22 +7,43 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.status;
 
+import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 public final class StatusStatementSupport
-        extends AbstractStatementSupport<Status, StatusStatement, StatusEffectiveStatement> {
+        extends BaseStatementSupport<Status, StatusStatement, StatusEffectiveStatement> {
     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
         .STATUS)
         .build();
     private static final StatusStatementSupport INSTANCE = new StatusStatementSupport();
 
+    /*
+     * status has low argument cardinality, hence we can reuse them in case declaration does not have any
+     * substatements (which is the usual case). Yeah, we could consider an EnumMap, but this is not too bad, either.
+     */
+    private static final @NonNull EmptyStatusStatement EMPTY_CURRENT_DECL =
+            new EmptyStatusStatement(Status.CURRENT);
+    private static final @NonNull EmptyStatusStatement EMPTY_DEPRECATED_DECL =
+            new EmptyStatusStatement(Status.DEPRECATED);
+    private static final @NonNull EmptyStatusStatement EMPTY_OBSOLETE_DECL =
+            new EmptyStatusStatement(Status.OBSOLETE);
+    private static final @NonNull EmptyStatusEffectiveStatement EMPTY_CURRENT_EFF =
+            new EmptyStatusEffectiveStatement(EMPTY_CURRENT_DECL);
+    private static final @NonNull EmptyStatusEffectiveStatement EMPTY_DEPRECATED_EFF =
+            new EmptyStatusEffectiveStatement(EMPTY_DEPRECATED_DECL);
+    private static final @NonNull EmptyStatusEffectiveStatement EMPTY_OBSOLETE_EFF =
+            new EmptyStatusEffectiveStatement(EMPTY_OBSOLETE_DECL);
+
     private StatusStatementSupport() {
         super(YangStmtMapping.STATUS);
     }
@@ -46,17 +67,6 @@ public final class StatusStatementSupport
         }
     }
 
-    @Override
-    public StatusStatement createDeclared(final StmtContext<Status, StatusStatement, ?> ctx) {
-        return new StatusStatementImpl(ctx);
-    }
-
-    @Override
-    public StatusEffectiveStatement createEffective(
-            final StmtContext<Status, StatusStatement, StatusEffectiveStatement> ctx) {
-        return new StatusEffectiveStatementImpl(ctx);
-    }
-
     @Override
     public String internArgument(final String rawArgument) {
         if ("current".equals(rawArgument)) {
@@ -74,4 +84,52 @@ public final class StatusStatementSupport
     protected SubstatementValidator getSubstatementValidator() {
         return SUBSTATEMENT_VALIDATOR;
     }
+
+    @Override
+    protected StatusStatement createDeclared(final StmtContext<Status, StatusStatement, ?> ctx,
+            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
+        return new RegularStatusStatement(ctx.coerceStatementArgument(), substatements);
+    }
+
+    @Override
+    protected StatusStatement createEmptyDeclared(final StmtContext<Status, StatusStatement, ?> ctx) {
+        final Status argument = ctx.coerceStatementArgument();
+        switch (argument) {
+            case CURRENT:
+                return EMPTY_CURRENT_DECL;
+            case DEPRECATED:
+                return EMPTY_DEPRECATED_DECL;
+            case OBSOLETE:
+                return EMPTY_OBSOLETE_DECL;
+            default:
+                throw new IllegalStateException("Unhandled argument " + argument);
+        }
+    }
+
+    @Override
+    protected StatusEffectiveStatement createEffective(
+            final StmtContext<Status, StatusStatement, StatusEffectiveStatement> ctx, final StatusStatement declared,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        return new RegularStatusEffectiveStatement(declared, substatements);
+    }
+
+    @Override
+    protected StatusEffectiveStatement createEmptyEffective(
+            final StmtContext<Status, StatusStatement, StatusEffectiveStatement> ctx, final StatusStatement declared) {
+        // Aggressively reuse effective instances which are backed by the corresponding empty declared instance, as this
+        // is the case unless there is a weird extension in use.
+        if (EMPTY_DEPRECATED_DECL.equals(declared)) {
+            // Most likely to be seen (as current is the default)
+            return EMPTY_DEPRECATED_EFF;
+        } else if (EMPTY_OBSOLETE_DECL.equals(declared)) {
+            // less likely
+            return EMPTY_OBSOLETE_EFF;
+        } else if (EMPTY_CURRENT_DECL.equals(declared)) {
+            // ... okay, why is this there? :)
+            return EMPTY_CURRENT_EFF;
+        } else {
+            return new EmptyStatusEffectiveStatement(declared);
+        }
+    }
+
 }
\ No newline at end of file