BUG-6964: reuse StatementDefinitionNamespace 17/47617/3
authorRobert Varga <rovarga@cisco.com>
Mon, 24 Oct 2016 19:04:29 +0000 (21:04 +0200)
committerAnil Belur <abelur@linuxfoundation.org>
Sun, 30 Oct 2016 11:41:48 +0000 (11:41 +0000)
Instead of performing two lookups, cache the extension's
statement in the source's maps, so it behaves just like
any other statement.

Change-Id: Ie71bedeefb57f5fc1575515cccf56f03ad373117
Signed-off-by: Robert Varga <rovarga@cisco.com>
(cherry picked from commit a961d73abd6afcb10b778b04cf8d394a9f4342df)

yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementDefinitionNamespace.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/QNameToStatementDefinitionMap.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ExtensionStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ModelDefinedStatementDefinition.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ModelDefinedStatementSupport.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/UnknownEffectiveStatementBase.java

index a4efa4ce1f8a3e3873fa9ccaccf88d1d331b868e..16741f34e8616173db3c87da6a672b26f8941b42 100644 (file)
@@ -19,6 +19,6 @@ import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
  * @author Robert Varga
  */
 @Beta
-public interface StatementDefinitionNamespace extends IdentifierNamespace<QName, StatementDefinition> {
+public interface StatementDefinitionNamespace extends IdentifierNamespace<QName, StatementSupport<?, ?, ?>> {
 
 }
index 287964969dabdf82f2fdb618c9ba886998c6f426..20c79c3926c8894556c7a6abbba0fb46c4378828 100644 (file)
@@ -14,13 +14,14 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 
 public class QNameToStatementDefinitionMap implements QNameToStatementDefinition {
 
-    private Map<QName, StatementDefinition> qNameToStmtDefMap = new HashMap<>();
-    private Map<QName, StatementDefinition> qNameWithoutRevisionToStmtDefMap = new HashMap<>();
+    private final Map<QName, StatementSupport<?, ?, ?>> qNameToStmtDefMap = new HashMap<>();
+    private final Map<QName, StatementSupport<?, ?, ?>> qNameWithoutRevisionToStmtDefMap = new HashMap<>();
 
-    public void put(QName qName, StatementDefinition stDef) {
+    public void put(final QName qName, final StatementSupport<?, ?, ?> stDef) {
         qNameToStmtDefMap.put(qName, stDef);
 
         final QName norev;
@@ -34,7 +35,7 @@ public class QNameToStatementDefinitionMap implements QNameToStatementDefinition
 
     @Nullable
     @Override
-    public StatementDefinition get(@Nonnull QName identifier) {
+    public StatementSupport<?, ?, ?> get(@Nonnull final QName identifier) {
         return qNameToStmtDefMap.get(identifier);
     }
 
index 9c4416fc7db9bc4a5b05938b5d8a6ffbe2f14777..ed32ec142d4e11a9fee2833a6c1a9d1c2fdf06b8 100644 (file)
@@ -30,8 +30,6 @@ 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.meta.IdentifierNamespace;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
-import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ImportedNamespaceContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
@@ -41,7 +39,6 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Namesp
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementDefinitionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
@@ -103,7 +100,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         this.source = Preconditions.checkNotNull(source);
     }
 
-    public boolean isEnabledSemanticVersioning(){
+    boolean isEnabledSemanticVersioning(){
         return currentContext.isEnabledSemanticVersioning();
     }
 
@@ -111,31 +108,28 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return inProgressPhase;
     }
 
-    StatementDefinitionContext<?, ?, ?> getDefinition(final QName name) {
-        return currentContext.getStatementDefinition(name);
-    }
-
     ContextBuilder<?, ?, ?> createDeclaredChild(final StatementContextBase<?, ?, ?> current, final QName name,
                                                 final StatementSourceReference ref) {
-        StatementDefinitionContext<?, ?, ?> def = getDefinition(name);
+        StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(name);
 
         if (def == null) {
-            // unknown-stmts (from import, include or local-scope)
-            if (qNameToStmtDefMap.get(name) != null) {
-                final StatementDefinition extension = currentContext.getFromNamespace(
-                    StatementDefinitionNamespace.class, name);
-                SourceException.throwIfNull(extension, current.getStatementSourceReference(), "Extension %s not found",
-                    name);
-
-                def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition(extension));
+            final StatementSupport<?, ?, ?> extension = qNameToStmtDefMap.get(name);
+            if (extension != null) {
+                def = new StatementDefinitionContext<>(extension);
             } else {
                 // type-body-stmts
                 def = resolveTypeBodyStmts(name.getLocalName());
             }
         } else if (current != null && current.definition().getRepresentingClass().equals(UnknownStatementImpl.class)) {
-            // FIXME: What's going on here?
+            /*
+             * This code wraps statements encountered inside an extension so they do not get confused with regular
+             * statements.
+             *
+             * FIXME: BUG-7037: re-evaluate whether this is really needed, as this is a very expensive way of making
+             *        this work. We really should be peeking into the extension definition to find these nodes,
+             *        as otherwise we are not reusing definitions nor support for these nodes.
+             */
             final QName qName = Utils.qNameFromArgument(current, name.getLocalName());
-
             def = new StatementDefinitionContext<>(new UnknownStatementImpl.Definition(
                 new ModelDefinedStatementDefinition(qName)));
         }
@@ -210,6 +204,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         if (potentialLocal != null) {
             return potentialLocal;
         }
+
         for (final NamespaceStorageNode importedSource : importedNamespaces) {
             final V potential = importedSource.getFromLocalStorage(type, key);
             if (potential != null) {
@@ -223,7 +218,6 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
         final Map<K, V> potentialLocal = getRoot().getAllFromLocalStorage(type);
-
         if (potentialLocal != null) {
             return potentialLocal;
         }
@@ -269,7 +263,6 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return hasProgressed ? PhaseCompletionProgress.PROGRESS : PhaseCompletionProgress.NO_PROGRESS;
     }
 
-
     private static boolean tryToProgress(final Collection<ModifierImpl> currentPhaseModifiers) {
         boolean hasProgressed = false;
 
@@ -282,7 +275,6 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         }
 
         return hasProgressed;
-
     }
 
     ModelActionBuilder newInferenceAction(final ModelProcessingPhase phase) {
@@ -381,23 +373,28 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
 
     private QNameToStatementDefinition stmtDef() {
         // regular YANG statements and extension supports added
-        final ImmutableMap<QName, StatementSupport<?, ?, ?>> definitions = currentContext.getSupportsForPhase(
-                inProgressPhase).getDefinitions();
+        final Map<QName, StatementSupport<?, ?, ?>> definitions = currentContext.getSupportsForPhase(inProgressPhase)
+                .getDefinitions();
         for (final Entry<QName, StatementSupport<?, ?, ?>> entry : definitions.entrySet()) {
             qNameToStmtDefMap.put(entry.getKey(), entry.getValue());
         }
 
         // extensions added
         if (inProgressPhase.equals(ModelProcessingPhase.FULL_DECLARATION)) {
-            final Map<QName, StmtContext<?, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>>> extensions =
-                    currentContext.getAllFromNamespace(ExtensionNamespace.class);
+            final Map<QName, StatementSupport<?, ?, ?>> extensions = currentContext.getAllFromNamespace(
+                StatementDefinitionNamespace.class);
             if (extensions != null) {
-                for (final Entry<QName, StmtContext<?, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>>> extension :
-                    extensions.entrySet()) {
-                    if(qNameToStmtDefMap.get(extension.getKey()) == null) {
-                        qNameToStmtDefMap.put((extension.getKey()),
-                        (StatementDefinition) ((StatementContextBase<?, ?, ?>) extension.getValue()).definition()
-                        .getFactory());
+                for (final Entry<QName, StatementSupport<?, ?, ?>> e : extensions.entrySet()) {
+                    final StatementDefinition previous = qNameToStmtDefMap.get(e.getKey());
+                    if (previous != null) {
+                        LOG.debug("Source {} already defines statement {} as {}", source, e.getKey(), previous);
+                        if (!(previous instanceof StatementSupport)) {
+                            LOG.warn("Source {} statement for {} definition {} is not a StatementSupport", source,
+                                e.getKey(), previous);
+                        }
+                    } else {
+                        qNameToStmtDefMap.put(e.getKey(), e.getValue());
+                        LOG.debug("Source {} defined statement {} as {}", source, e.getKey(), e.getValue());
                     }
                 }
             }
index 7b4d4c25bc339fd5d255c36d0bf56dd7564b689a..955428120476daea5babc429a3f1ee757e00cbc9 100644 (file)
@@ -86,9 +86,9 @@ public class ExtensionStatementImpl extends AbstractDeclaredStatement<QName> imp
                 YinElementStatement.class);
 
             stmt.addToNs(StatementDefinitionNamespace.class, stmt.getStatementArgument(),
-                new ModelDefinedStatementDefinition(stmt.getStatementArgument(),
+                new ModelDefinedStatementSupport(new ModelDefinedStatementDefinition(stmt.getStatementArgument(),
                     argument != null ? argument.getStatementArgument() : null,
-                    yinElement != null ? yinElement.getStatementArgument() : false));
+                            yinElement != null ? yinElement.getStatementArgument() : false)));
         }
 
         @Override
index 1b496e603fe79acc9907ace8afbf3541b72203e2..fb36187d84b62c786d9c0ac569ccdb38dd233f6d 100644 (file)
@@ -18,6 +18,10 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.UnknownEffectiveStatementImpl;
 
+/**
+ * Public definition for statements declared by extensions. This class is instantiated for every extension that is seen
+ * to be declared in a model.
+ */
 @Beta
 public final class ModelDefinedStatementDefinition implements StatementDefinition {
     private final QName statementName;
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ModelDefinedStatementSupport.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ModelDefinedStatementSupport.java
new file mode 100644 (file)
index 0000000..8f4842f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.stmt.rfc6020;
+
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+/**
+ * StatementSupport for statements defined via YANG extensions. This is implemented by piggy-backing
+ * to a {@link UnknownStatementImpl.Definition}.
+ *
+ * @author Robert Varga
+ */
+public final class ModelDefinedStatementSupport extends AbstractStatementSupport<String,
+        UnknownStatement<String>, EffectiveStatement<String, UnknownStatement<String>>> {
+    private final UnknownStatementImpl.Definition definition;
+
+    ModelDefinedStatementSupport(final ModelDefinedStatementDefinition publicDefinition) {
+        super(publicDefinition);
+        this.definition = new UnknownStatementImpl.Definition(publicDefinition);
+    }
+
+    @Override
+    public UnknownStatement<String> createDeclared(final StmtContext<String, UnknownStatement<String>, ?> ctx) {
+        return definition.createDeclared(ctx);
+    }
+
+    @Override
+    public EffectiveStatement<String, UnknownStatement<String>> createEffective(
+            final StmtContext<String, UnknownStatement<String>, EffectiveStatement<String, UnknownStatement<String>>> ctx) {
+        return definition.createEffective(ctx);
+    }
+
+    @Override
+    public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) throws SourceException {
+        return definition.parseArgumentValue(ctx, value);
+    }
+}
index 1a281b55cfe06467b14f2cb9cd7f68ab08a50792..8d0653d8ac1f47d6229665477db92f7152a63c94 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
 import java.util.List;
@@ -19,8 +20,8 @@ import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
 import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 
 public abstract class UnknownEffectiveStatementBase<A> extends AbstractEffectiveDocumentedNode<A, UnknownStatement<A>>
         implements UnknownSchemaNode {
@@ -33,7 +34,7 @@ public abstract class UnknownEffectiveStatementBase<A> extends AbstractEffective
     private final QName nodeType;
     private final String nodeParameter;
 
-    public UnknownEffectiveStatementBase(final StmtContext<A, UnknownStatement<A>, ?> ctx) {
+    protected UnknownEffectiveStatementBase(final StmtContext<A, UnknownStatement<A>, ?> ctx) {
         super(ctx);
 
         final StmtContext<?, ExtensionStatement, EffectiveStatement<QName, ExtensionStatement>> extensionInit = ctx
@@ -43,7 +44,10 @@ public abstract class UnknownEffectiveStatementBase<A> extends AbstractEffective
             extension = null;
             nodeType = ctx.getPublicDefinition().getArgumentName();
         } else {
-            extension = (ExtensionEffectiveStatementImpl) extensionInit.buildEffective();
+            final EffectiveStatement<QName, ExtensionStatement> effective = extensionInit.buildEffective();
+            Preconditions.checkState(effective instanceof ExtensionDefinition,
+                "Statement %s is not an ExtensionDefinition", effective);
+            extension = (ExtensionDefinition) extensionInit.buildEffective();
             nodeType = null;
         }