Make CopyHistory implement CopyableNode
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / EffectiveStatementMixins.java
index e16d066b49207e6d002b90ccf3fd1d9a79e0d285..3eb78f0488bd4a1d2a9dba1b1488f9ae7b061c3c 100644 (file)
@@ -11,11 +11,13 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import java.util.Collection;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.concepts.Mutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
@@ -53,10 +55,12 @@ import org.opendaylight.yangtools.yang.model.api.stmt.ErrorMessageEffectiveState
 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.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.WhenEffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.CopyHistory;
-import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression.QualifiedBound;
 
 /**
@@ -68,7 +72,7 @@ public final class EffectiveStatementMixins {
     // Marker interface requiring all mixins to be derived from EffectiveStatement.
     private interface Mixin<A, D extends DeclaredStatement<A>> extends EffectiveStatement<A, D> {
         @SuppressWarnings("unchecked")
-        default <T> @NonNull Collection<? extends T> filterEffectiveStatements(final Class<T> type) {
+        default <T> @NonNull Collection<? extends @NonNull T> filterEffectiveStatements(final Class<T> type) {
             // Yeah, this is not nice, but saves one transformation
             return (Collection<? extends T>) Collections2.filter(effectiveSubstatements(), type::isInstance);
         }
@@ -97,6 +101,7 @@ public final class EffectiveStatementMixins {
     public interface AddedByUsesMixin<A, D extends DeclaredStatement<A>>
             extends EffectiveStatementWithFlags<A, D>, AddedByUsesAware {
         @Override
+        @Deprecated
         default boolean isAddedByUses() {
             return (flags() & FlagsBuilder.ADDED_BY_USES) != 0;
         }
@@ -138,7 +143,7 @@ public final class EffectiveStatementMixins {
      */
     public interface MustConstraintMixin<A, D extends DeclaredStatement<A>> extends Mixin<A, D>, MustConstraintAware {
         @Override
-        default Collection<? extends MustDefinition> getMustConstraints() {
+        default Collection<? extends @NonNull MustDefinition> getMustConstraints() {
             return filterEffectiveStatements(MustDefinition.class);
         }
     }
@@ -151,6 +156,7 @@ public final class EffectiveStatementMixins {
      */
     public interface CopyableMixin<A, D extends DeclaredStatement<A>> extends AddedByUsesMixin<A, D>, CopyableNode {
         @Override
+        @Deprecated
         default boolean isAugmenting() {
             return (flags() & FlagsBuilder.AUGMENTING) != 0;
         }
@@ -193,8 +199,18 @@ public final class EffectiveStatementMixins {
     public interface DataSchemaNodeMixin<A, D extends DeclaredStatement<A>>
             extends DataSchemaNode, CopyableMixin<A, D>, SchemaNodeMixin<A, D>, WhenConditionMixin<A, D> {
         @Override
-        default boolean isConfiguration() {
-            return (flags() & FlagsBuilder.CONFIGURATION) != 0;
+        default Optional<Boolean> effectiveConfig() {
+            final int fl = flags() & FlagsBuilder.MASK_CONFIG;
+            switch (fl) {
+                case FlagsBuilder.CONFIG_FALSE:
+                    return Optional.of(Boolean.FALSE);
+                case FlagsBuilder.CONFIG_TRUE:
+                    return Optional.of(Boolean.TRUE);
+                case FlagsBuilder.CONFIG_UNDEF:
+                    return Optional.empty();
+                default:
+                    throw new IllegalStateException("Unhandled effective config flags " + fl);
+            }
         }
     }
 
@@ -381,8 +397,8 @@ public final class EffectiveStatementMixins {
         }
 
         @Override
-        default boolean isConfiguration() {
-            return false;
+        default Optional<Boolean> effectiveConfig() {
+            return Optional.empty();
         }
 
         default String defaultToString() {
@@ -417,12 +433,12 @@ public final class EffectiveStatementMixins {
         }
 
         @Override
-        default Collection<? extends TypeDefinition<?>> getTypeDefinitions() {
+        default Collection<? extends @NonNull TypeDefinition<?>> getTypeDefinitions() {
             return filterTypeDefinitions(this);
         }
 
         @Override
-        default Collection<? extends GroupingDefinition> getGroupings() {
+        default Collection<? extends @NonNull GroupingDefinition> getGroupings() {
             return filterEffectiveStatements(GroupingDefinition.class);
         }
 
@@ -454,14 +470,13 @@ public final class EffectiveStatementMixins {
 
         @NonNullByDefault
         final class FlagsBuilder implements Mutable {
-            // We still have 24 flags remaining
+            // We still have 23 flags remaining
             static final int STATUS_CURRENT       = 0x0001;
             static final int STATUS_DEPRECATED    = 0x0002;
             static final int STATUS_OBSOLETE      = 0x0003;
             static final int MASK_STATUS          = 0x0003;
 
-            static final int CONFIGURATION        = 0x0004;
-            static final int MANDATORY            = 0x0008;
+            static final int MANDATORY            = 0x0004;
 
             static final int AUGMENTING           = 0x0010;
             static final int ADDED_BY_USES        = 0x0020;
@@ -470,32 +485,27 @@ public final class EffectiveStatementMixins {
             static final int USER_ORDERED         = 0x0040;
             static final int PRESENCE             = 0x0080;
 
+            static final int CONFIG_UNDEF         = 0x0100;
+            static final int CONFIG_FALSE         = 0x0200;
+            static final int CONFIG_TRUE          = 0x0300;
+            static final int MASK_CONFIG          = CONFIG_TRUE;
+
             private int flags;
 
-            public FlagsBuilder setConfiguration(final boolean config) {
-                if (config) {
-                    flags |= CONFIGURATION;
+            public FlagsBuilder setConfiguration(final @Nullable Boolean config) {
+                final int fl;
+                if (config != null) {
+                    fl = config ? CONFIG_TRUE : CONFIG_FALSE;
                 } else {
-                    flags &= ~CONFIGURATION;
+                    fl = CONFIG_UNDEF;
                 }
+                flags = flags & ~MASK_CONFIG | fl;
                 return this;
             }
 
             public FlagsBuilder setHistory(final CopyHistory history) {
-                int bits;
-                if (history.contains(CopyType.ADDED_BY_USES_AUGMENTATION)) {
-                    bits = AUGMENTING | ADDED_BY_USES;
-                } else {
-                    bits = 0;
-                    if (history.contains(CopyType.ADDED_BY_AUGMENTATION)) {
-                        bits |= AUGMENTING;
-                    }
-                    if (history.contains(CopyType.ADDED_BY_USES)) {
-                        bits |= ADDED_BY_USES;
-                    }
-                }
-
-                flags = flags & ~MASK_HISTORY | bits;
+                flags = flags & ~MASK_HISTORY
+                    | (history.isAugmenting() ? AUGMENTING : 0) | (history.isAddedByUses() ? ADDED_BY_USES : 0);
                 return this;
             }
 
@@ -556,12 +566,21 @@ public final class EffectiveStatementMixins {
     }
 
     static <T extends ContainerLike> T findAsContainer(final EffectiveStatement<?, ?> stmt,
-            final Class<? extends EffectiveStatement<QName, ?>> type, Class<T> target) {
+            final Class<? extends EffectiveStatement<QName, ?>> type, final Class<T> target) {
         return target.cast(stmt.findFirstEffectiveSubstatement(type).get());
     }
 
-    static Collection<? extends TypeDefinition<?>> filterTypeDefinitions(final Mixin<?, ?> stmt) {
+    static Collection<? extends @NonNull TypeDefinition<?>> filterTypeDefinitions(final Mixin<?, ?> stmt) {
         return Collections2.transform(stmt.filterEffectiveStatements(TypedefEffectiveStatement.class),
             TypedefEffectiveStatement::getTypeDefinition);
     }
+
+    public static int historyAndStatusFlags(final CopyHistory history,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        return new FlagsBuilder()
+                .setHistory(history)
+                .setStatus(AbstractStatementSupport.findFirstArgument(substatements,
+                    StatusEffectiveStatement.class, Status.CURRENT))
+                .toFlags();
+    }
 }