Refactor rpc/action statements
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / EffectiveStatementMixins.java
index 3ca01d62ca7f9efeb3ff1d4d8866ab0735a73988..20f5e773a38b17c096ee0663fcfb48956861c29e 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
 
+import static com.google.common.base.Verify.verify;
+
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.Collections2;
@@ -37,6 +39,7 @@ import org.opendaylight.yangtools.yang.model.api.MustConstraintAware;
 import org.opendaylight.yangtools.yang.model.api.MustDefinition;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.NotificationNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Status;
@@ -47,6 +50,8 @@ import org.opendaylight.yangtools.yang.model.api.WhenConditionAware;
 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.DescriptionEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.WhenEffectiveStatement;
@@ -169,10 +174,7 @@ public final class EffectiveStatementMixins {
     public interface DataNodeContainerMixin<A, D extends DeclaredStatement<A>> extends DataNodeContainer, Mixin<A, D> {
         @Override
         default Set<TypeDefinition<?>> getTypeDefinitions() {
-            // TODO: the cast here is needed to work around Java 11 javac type inference issue
-            return (Set) effectiveSubstatements().stream().filter(TypedefEffectiveStatement.class::isInstance)
-                    .map(stmt -> ((TypedefEffectiveStatement) stmt).getTypeDefinition())
-                    .collect(ImmutableSet.toImmutableSet());
+            return filterTypeDefinitions(this);
         }
 
         @Override
@@ -375,7 +377,7 @@ public final class EffectiveStatementMixins {
     }
 
     /**
-     * Helper bridge for {@code anydata} and {@code anyxml} opaque data..
+     * Helper bridge for {@code anydata} and {@code anyxml} opaque data.
      *
      * @param <D> Class representing declared version of this statement.
      */
@@ -393,6 +395,44 @@ public final class EffectiveStatementMixins {
         }
     }
 
+    /**
+     * Helper bridge for {@code rpc} and {@code action} operations.
+     *
+     * @param <D> Class representing declared version of this statement.
+     */
+    public interface OperationDefinitionMixin<D extends DeclaredStatement<QName>>
+            extends SchemaNodeMixin<QName, D>, OperationDefinition {
+        @Override
+        default @NonNull QName argument() {
+            return getPath().getLastComponent();
+        }
+
+        @Override
+        default QName getQName() {
+            return argument();
+        }
+
+        @Override
+        default Set<TypeDefinition<?>> getTypeDefinitions() {
+            return filterTypeDefinitions(this);
+        }
+
+        @Override
+        default Set<GroupingDefinition> getGroupings() {
+            return filterEffectiveStatementsSet(GroupingDefinition.class);
+        }
+
+        @Override
+        default ContainerSchemaNode getInput() {
+            return findAsContainer(this, InputEffectiveStatement.class);
+        }
+
+        @Override
+        default ContainerSchemaNode getOutput() {
+            return findAsContainer(this, OutputEffectiveStatement.class);
+        }
+    }
+
     /**
      * Support interface for various mixins. Implementations are required to store 32bits worth of flags, which are
      * globally assigned to sub-interfaces -- thus providing storage for many low-cardinality properties.
@@ -507,4 +547,23 @@ public final class EffectiveStatementMixins {
             }
         }
     }
+
+    private EffectiveStatementMixins() {
+    }
+
+    static ContainerSchemaNode findAsContainer(final EffectiveStatement<?, ?> stmt,
+            final Class<? extends EffectiveStatement<QName, ?>> type) {
+        final EffectiveStatement<?, ?> statement = stmt.findFirstEffectiveSubstatement(type).get();
+        verify(statement instanceof ContainerSchemaNode, "Child statement %s is not a ContainerSchemaNode",
+            statement);
+        return (ContainerSchemaNode) statement;
+    }
+
+    static Set<TypeDefinition<?>> filterTypeDefinitions(final Mixin<?, ?> stmt) {
+        // TODO: the cast here is needed to work around Java 11 javac type inference issue
+        return (Set) stmt.effectiveSubstatements().stream()
+                .filter(TypedefEffectiveStatement.class::isInstance)
+                .map(typedef -> ((TypedefEffectiveStatement) typedef).getTypeDefinition())
+                .collect(ImmutableSet.toImmutableSet());
+    }
 }