Add support for overriding statement supports 79/65479/7
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 13 Nov 2017 11:51:48 +0000 (12:51 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 13 Nov 2017 16:14:31 +0000 (17:14 +0100)
If an extension needs to build a different implementation of a statement,
it needs to be able to override previous definition. Alternative is to
force users to special-case support when building a reactor, which is not
really feasible.

Add overrideSupport(), which performs a replacement operation, but requires
properly-targeted bundle.

Change-Id: Id9b527c115c7a6b815227f8dc796473803bf8a80
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/ForwardingEffectiveStatement.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/CustomCrossSourceStatementReactorBuilder.java
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ForwardingStatementSupport.java [new file with mode: 0644]
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupportBundle.java

diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/ForwardingEffectiveStatement.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/ForwardingEffectiveStatement.java
new file mode 100644 (file)
index 0000000..c373146
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.model.api.meta;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingObject;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Utility forwarding implementation of {@link EffectiveStatement} contract. This class is useful for implementing
+ * wrapped statements.
+ *
+ * @author Robert Varga
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @param <E> Effective Statement representation
+ */
+@Beta
+public abstract class ForwardingEffectiveStatement<A, D extends DeclaredStatement<A>,
+        E extends EffectiveStatement<A, D>> extends ForwardingObject implements EffectiveStatement<A, D> {
+
+    @Override
+    protected abstract E delegate();
+
+
+    @Override
+    public D getDeclared() {
+        return delegate().getDeclared();
+    }
+
+    @Override
+    public <K, V, N extends IdentifierNamespace<K, V>> V get(final Class<N> namespace, final K identifier) {
+        return delegate().get(namespace, identifier);
+    }
+
+    @Override
+    public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(final Class<N> namespace) {
+        return delegate().getAll(namespace);
+    }
+
+    @Override
+    public Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements() {
+        return delegate().effectiveSubstatements();
+    }
+
+    @Override
+    public StatementDefinition statementDefinition() {
+        return delegate().statementDefinition();
+    }
+
+    @Override
+    public A argument() {
+        return delegate().argument();
+    }
+
+    @Override
+    public StatementSource getStatementSource() {
+        return delegate().getStatementSource();
+    }
+}
index 84f32fab890d69e9e812add3cdd52f556914b0f3..d2838568a5f8188d277ffaf35b02904057c29940 100644 (file)
@@ -55,6 +55,12 @@ public class CustomCrossSourceStatementReactorBuilder implements Builder<CrossSo
         return this;
     }
 
+    public CustomCrossSourceStatementReactorBuilder overrideStatementSupport(final ModelProcessingPhase phase,
+            final StatementSupport<?, ?, ?> stmtSupport) {
+        reactorSupportBundles.get(phase).overrideSupport(stmtSupport);
+        return this;
+    }
+
     public CustomCrossSourceStatementReactorBuilder addNamespaceSupport(final ModelProcessingPhase phase,
             final NamespaceBehaviour<?, ?, ?> namespaceSupport) {
         reactorSupportBundles.get(phase).addSupport(namespaceSupport);
diff --git a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ForwardingStatementSupport.java b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/ForwardingStatementSupport.java
new file mode 100644 (file)
index 0000000..d5f53fa
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies 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.spi.meta;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ForwardingObject;
+import java.util.Optional;
+import org.opendaylight.yangtools.yang.common.QName;
+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.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+
+/**
+ * Utility forwarding implementation of {@link StatementSupport} contract. This class is useful for implementing
+ * wrapped statements.
+ *
+ * @author Robert Varga
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @param <E> Effective Statement representation
+ */
+@Beta
+public abstract class ForwardingStatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+    extends ForwardingObject implements StatementSupport<A, D, E> {
+
+    @Override
+    protected abstract StatementSupport<A, D, E> delegate();
+
+    @Override
+    public QName getStatementName() {
+        return delegate().getStatementName();
+    }
+
+    @Override
+    public QName getArgumentName() {
+        return delegate().getArgumentName();
+    }
+
+    @Override
+    public Class<? extends DeclaredStatement<?>> getDeclaredRepresentationClass() {
+        return delegate().getDeclaredRepresentationClass();
+    }
+
+    @Override
+    public Class<? extends EffectiveStatement<?, ?>> getEffectiveRepresentationClass() {
+        return delegate().getEffectiveRepresentationClass();
+    }
+
+    @Override
+    public boolean isArgumentYinElement() {
+        return delegate().isArgumentYinElement();
+    }
+
+    @Override
+    public D createDeclared(final StmtContext<A, D, ?> ctx) {
+        return delegate().createDeclared(ctx);
+    }
+
+    @Override
+    public E createEffective(final StmtContext<A, D, E> ctx) {
+        return delegate().createEffective(ctx);
+    }
+
+    @Override
+    public StatementDefinition getPublicView() {
+        return delegate().getPublicView();
+    }
+
+    @Override
+    public A parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+        return delegate().parseArgumentValue(ctx, value);
+    }
+
+    @Override
+    public void onStatementAdded(final Mutable<A, D, E> stmt) {
+        delegate().onStatementAdded(stmt);
+    }
+
+    @Override
+    public Optional<StatementSupport<?, ?, ?>> getImplicitParentFor(final StatementDefinition stmtDef) {
+        return delegate().getImplicitParentFor(stmtDef);
+    }
+
+    @Override
+    public void onPreLinkageDeclared(final Mutable<A, D, E> stmt) {
+        delegate().onPreLinkageDeclared(stmt);
+    }
+
+    @Override
+    public void onLinkageDeclared(final Mutable<A, D, E> stmt) {
+        delegate().onLinkageDeclared(stmt);
+    }
+
+    @Override
+    public void onStatementDefinitionDeclared(final Mutable<A, D, E> stmt) {
+        delegate().onStatementDefinitionDeclared(stmt);
+    }
+
+    @Override
+    public void onFullDefinitionDeclared(final Mutable<A, D, E> stmt) {
+        delegate().onFullDefinitionDeclared(stmt);
+    }
+
+    @Override
+    public boolean hasArgumentSpecificSupports() {
+        return delegate().hasArgumentSpecificSupports();
+    }
+
+    @Override
+    public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
+        return delegate().getSupportSpecificForArgument(argument);
+    }
+}
index e5a911b71fc8ca02cdb54ca45d756626adfd42af..9fd94338ef01e8ac230520f338f87ff40c04c7f7 100644 (file)
@@ -24,6 +24,8 @@ import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public final class StatementSupportBundle implements Immutable, NamespaceBehaviour.Registry {
 
@@ -157,6 +159,8 @@ public final class StatementSupportBundle implements Immutable, NamespaceBehavio
     }
 
     public static class Builder implements org.opendaylight.yangtools.concepts.Builder<StatementSupportBundle> {
+        private static final Logger LOG = LoggerFactory.getLogger(Builder.class);
+
         private final Map<QName, StatementSupport<?, ?, ?>> commonStatements = new HashMap<>();
         private final Table<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements = HashBasedTable
                 .create();
@@ -170,13 +174,13 @@ public final class StatementSupportBundle implements Immutable, NamespaceBehavio
             this.supportedVersions = ImmutableSet.copyOf(supportedVersions);
         }
 
-        public Builder addSupport(final StatementSupport<?, ?, ?> definition) {
-            final QName identifier = definition.getStatementName();
+        public Builder addSupport(final StatementSupport<?, ?, ?> support) {
+            final QName identifier = support.getStatementName();
+            checkNoParentDefinition(identifier);
+
             checkState(!commonStatements.containsKey(identifier),
                     "Statement %s already defined in common statement bundle.", identifier);
-            checkState(parent.getCommonStatementDefinition(identifier) == null,
-                    "Statement %s already defined.", identifier);
-            commonStatements.put(identifier, definition);
+            commonStatements.put(identifier, support);
             return this;
         }
 
@@ -198,8 +202,7 @@ public final class StatementSupportBundle implements Immutable, NamespaceBehavio
                     "Statement %s already defined in common statement bundle.", identifier);
             checkState(!versionSpecificStatements.contains(version, identifier),
                     "Statement %s already defined for version %s.", identifier, version);
-            checkState(parent.getCommonStatementDefinition(identifier) == null,
-                    "Statement %s already defined in parent's common statement bundle.", identifier);
+            checkNoParentDefinition(identifier);
             checkState(parent.getVersionSpecificStatementDefinition(version, identifier) == null,
                     "Statement %s already defined for version %s in parent's statement bundle.", identifier, version);
             versionSpecificStatements.put(version, identifier, definition);
@@ -215,11 +218,26 @@ public final class StatementSupportBundle implements Immutable, NamespaceBehavio
             return this;
         }
 
+        public Builder overrideSupport(final StatementSupport<?, ?, ?> support) {
+            final QName identifier = support.getStatementName();
+            checkNoParentDefinition(identifier);
+
+            final StatementSupport<?, ?, ?> previousSupport = commonStatements.replace(identifier, support);
+            checkState(previousSupport != null, "Statement %s was not previously defined", identifier);
+            LOG.debug("Changed statement {} support from {} to {}", identifier, previousSupport, support);
+            return this;
+        }
+
         @Override
         public StatementSupportBundle build() {
             Preconditions.checkState(parent != null, "Parent must not be null");
             return new StatementSupportBundle(parent, supportedVersions, ImmutableMap.copyOf(commonStatements),
                     ImmutableMap.copyOf(namespaces), ImmutableTable.copyOf(versionSpecificStatements));
         }
+
+        private void checkNoParentDefinition(final QName identifier) {
+            checkState(parent.getCommonStatementDefinition(identifier) == null,
+                    "Statement %s is defined in parent's common statement bundle", identifier);
+        }
     }
 }