Add BitsTypeObject 40/101840/30
authorIvan Martiniak <ivan.martiniak@pantheon.tech>
Tue, 12 Jul 2022 09:18:39 +0000 (11:18 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 17 Nov 2022 22:49:38 +0000 (23:49 +0100)
The new interface BitsTypeObject, besides grouping bits type objects,
helps clarify which bits are restricted.

Method validValues() returns constant containing valid bits.
The logic of the creation of this constant is contained in the
AbstractTypeObjectGenerator.java.
Method getValue() was included in this interface and its generation
was adjusted for restricted and standard bits types separately.

Related test classes were adjusted as well.

JIRA: MDSAL-743
Change-Id: I74820e7a041e137902c774655517ea8d1e4bccd9
Signed-off-by: Ivan Martiniak <ivan.martiniak@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java
binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/TypedefGenerator.java
binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal406TypeObjectTest.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/ClassTemplate.xtend
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/TypedefCompilationTest.java
binding/mdsal-binding-model-ri/src/main/java/org/opendaylight/mdsal/binding/model/ri/BindingTypes.java
binding/mdsal-binding-model-ri/src/main/java/org/opendaylight/mdsal/binding/model/ri/TypeConstants.java
binding/mdsal-binding-model-ri/src/main/java/org/opendaylight/mdsal/binding/model/ri/Types.java
binding/mdsal-binding-test-model/src/main/yang/opendaylight-of-migration-test-model.yang
binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BitsTypeObject.java [new file with mode: 0644]

index 44b7892cac78e81cb7bc1d3906d34c2f1f25ffef..048cf5a1d84ec7e8b2b9d96e1aaf5f028fde4bc6 100644 (file)
@@ -589,8 +589,8 @@ abstract class AbstractTypeObjectGenerator<S extends EffectiveStatement<?, ?>, R
         final boolean isTypedef = this instanceof TypedefGenerator;
         final QName arg = type.argument();
         if (TypeDefinitions.BITS.equals(arg)) {
-            return createBits(builderFactory, statement(), typeName(), currentModule(), extractTypeDefinition(),
-                    isTypedef);
+            return createBits(builderFactory, statement(), typeName(), currentModule(),
+                (BitsTypeDefinition) extractTypeDefinition(), isTypedef);
         } else if (TypeDefinitions.ENUMERATION.equals(arg)) {
             return createEnumeration(builderFactory, statement(), typeName(), currentModule(),
                 (EnumTypeDefinition) extractTypeDefinition());
@@ -608,14 +608,14 @@ abstract class AbstractTypeObjectGenerator<S extends EffectiveStatement<?, ?>, R
 
     private static @NonNull GeneratedTransferObject createBits(final TypeBuilderFactory builderFactory,
             final EffectiveStatement<?, ?> definingStatement, final JavaTypeName typeName, final ModuleGenerator module,
-            final TypeDefinition<?> typedef, final boolean isTypedef) {
+            final BitsTypeDefinition typedef, final boolean isTypedef) {
         final GeneratedTOBuilder builder = builderFactory.newGeneratedTOBuilder(typeName);
         builder.setTypedef(isTypedef);
-        builder.addImplementsType(BindingTypes.TYPE_OBJECT);
+        builder.addImplementsType(BindingTypes.BITS_TYPE_OBJECT);
         builder.setBaseType(typedef);
         YangSourceDefinition.of(module.statement(), definingStatement).ifPresent(builder::setYangSourceDefinition);
 
-        for (Bit bit : ((BitsTypeDefinition) typedef).getBits()) {
+        for (Bit bit : typedef.getBits()) {
             final String name = bit.getName();
             GeneratedPropertyBuilder genPropertyBuilder = builder.addProperty(BindingMapping.getPropertyName(name));
             genPropertyBuilder.setReadOnly(true);
@@ -625,6 +625,7 @@ abstract class AbstractTypeObjectGenerator<S extends EffectiveStatement<?, ?>, R
             builder.addHashIdentity(genPropertyBuilder);
             builder.addToStringProperty(genPropertyBuilder);
         }
+        builder.addConstant(Types.immutableSetTypeFor(Types.STRING), TypeConstants.VALID_NAMES_NAME, typedef);
 
         // builder.setSchemaPath(typedef.getPath());
         builder.setModuleName(module.statement().argument().getLocalName());
@@ -733,7 +734,7 @@ abstract class AbstractTypeObjectGenerator<S extends EffectiveStatement<?, ?>, R
                 } else if (TypeDefinitions.BITS.equals(subName)) {
                     final GeneratedTransferObject subBits = createBits(builderFactory, definingStatement,
                         typeName.createEnclosed(BindingMapping.getClassName(localName), "$"), module,
-                        subType.getTypeDefinition(), isTypedef);
+                        (BitsTypeDefinition) subType.getTypeDefinition(), isTypedef);
                     builder.addEnclosingTransferObject(subBits);
                     generatedType = subBits;
                 } else if (TypeDefinitions.IDENTITYREF.equals(subName)) {
index d523b60f8dfeacb21565001a99a92a46e8330a61..6b0e06271ac7ab0fa0b40b3649ecdd03a10912ae 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.mdsal.binding.generator.impl.reactor;
 
 import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import java.util.ArrayList;
@@ -19,9 +20,12 @@ import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.mdsal.binding.model.ri.TypeConstants;
+import org.opendaylight.mdsal.binding.model.ri.Types;
 import org.opendaylight.mdsal.binding.runtime.api.TypedefRuntimeType;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 
 /**
@@ -92,10 +96,37 @@ final class TypedefGenerator extends AbstractTypeObjectGenerator<TypedefEffectiv
         addStringRegExAsConstant(builder, resolveRegExpressions(typedef));
         addUnits(builder, typedef);
 
+        if (typedef instanceof BitsTypeDefinition bits) {
+            addValidBits(builder, bits, baseType);
+        }
+
         makeSerializable(builder);
         return builder.build();
     }
 
+    private static void addValidBits(final GeneratedTOBuilder builder, final BitsTypeDefinition typedef,
+            final GeneratedTransferObject baseType) {
+        final var baseDef = verifyNotNull(baseBitsDefinition(baseType), "Could not find definition in %s", baseType);
+        final var myBits = typedef.getBits();
+        if (myBits.size() != baseDef.getBits().size()) {
+            builder.addConstant(Types.immutableSetTypeFor(Types.STRING), TypeConstants.VALID_NAMES_NAME, typedef);
+        }
+    }
+
+    private static BitsTypeDefinition baseBitsDefinition(final GeneratedTransferObject gto) {
+        var wlk = gto;
+        while (wlk != null) {
+            for (var constant : wlk.getConstantDefinitions()) {
+                if (TypeConstants.VALID_NAMES_NAME.equals(constant.getName())) {
+                    return (BitsTypeDefinition) constant.getValue();
+                }
+            }
+
+            wlk = wlk.getSuperType();
+        }
+        return null;
+    }
+
     @Override
     TypedefRuntimeType createExternalRuntimeType(final Type type) {
         verify(type instanceof GeneratedType, "Unexpected type %s", type);
index 15d4e9fc73e06bb4f7e86d3f46c70a96ca37312c..40c3c1e99ef82397973d3fabd61835fc708e6f7d 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.mdsal.binding.generator.impl;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.BITS_TYPE_OBJECT;
 import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.TYPE_OBJECT;
 
 import java.util.List;
@@ -52,7 +53,7 @@ public class Mdsal406TypeObjectTest {
     }
 
     @Test
-    public void typeObjectForBitsTypedefTest() {
+    public void bitsTypeObjectForBitsTypedefTest() {
         final List<GeneratedType> generateTypes = DefaultBindingGenerator.generateFor(CONTEXT);
         assertNotNull(generateTypes);
 
@@ -62,8 +63,8 @@ public class Mdsal406TypeObjectTest {
         assertNotNull(typedefType.getImplements());
         Type objectType = typedefType.getImplements().stream()
                 .filter(type -> type.getFullyQualifiedName()
-                        .equals("org.opendaylight.yangtools.yang.binding.TypeObject")).findAny().get();
-        assertEquals(TYPE_OBJECT, objectType);
+                        .equals("org.opendaylight.yangtools.yang.binding.BitsTypeObject")).findAny().get();
+        assertEquals(BITS_TYPE_OBJECT, objectType);
     }
 
     @Test
index 0afcd92f20c1a1a22d7988f64c694037e3e41e41..d57fab88a597ff29df4f0832345b9d12ebaa9e81 100644 (file)
@@ -86,7 +86,11 @@ abstract class BaseTemplate extends JavaFileTemplate {
     '''
 
     final protected def getterMethodName(GeneratedProperty field) {
-        return '''«BindingMapping.GETTER_PREFIX»«field.name.toFirstUpper»'''
+        return field.name.getterMethodName
+    }
+
+    final protected def getterMethodName(String propName) {
+        return '''«BindingMapping.GETTER_PREFIX»«propName.toFirstUpper»'''
     }
 
     /**
index 8b59b92460d8f80229f00bfd28d22793a54832fb..df7be75af6500637be2a86e50251c07440370c4a 100644 (file)
@@ -23,12 +23,13 @@ import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT32_TYPE
 import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT64_TYPE
 import static org.opendaylight.mdsal.binding.model.ri.BaseYangTypes.UINT8_TYPE
 import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.SCALAR_TYPE_OBJECT
+import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.BITS_TYPE_OBJECT
 import static org.opendaylight.mdsal.binding.model.ri.Types.STRING;
 import static extension org.apache.commons.text.StringEscapeUtils.escapeJava
-import static extension org.opendaylight.mdsal.binding.model.ri.BindingTypes.isBitsType
 
 import com.google.common.base.Preconditions
 import com.google.common.collect.ImmutableList
+import com.google.common.collect.ImmutableSet
 import com.google.common.collect.Lists
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
 import java.util.ArrayList
@@ -51,6 +52,7 @@ import org.opendaylight.mdsal.binding.model.ri.TypeConstants
 import org.opendaylight.mdsal.binding.model.ri.Types
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
 import org.opendaylight.yangtools.yang.common.Empty
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
 
 /**
  * Template for generating JAVA class.
@@ -73,6 +75,11 @@ class ClassTemplate extends BaseTemplate {
      */
     static val BOOLEAN = JavaTypeName.create(Boolean)
 
+    /**
+     * {@code com.google.common.collect.ImmutableSet} as a JavaTypeName.
+     */
+    static val IMMUTABLE_SET = JavaTypeName.create(ImmutableSet)
+
     protected val List<GeneratedProperty> properties
     protected val List<GeneratedProperty> finalProperties
     protected val List<GeneratedProperty> parentProperties
@@ -179,8 +186,8 @@ class ClassTemplate extends BaseTemplate {
 
             «propertyMethods»
 
-            «IF genTO.isBitsType»
-                «generateGetValueForBitsTypeDef»
+            «IF isBitsTypeObject»
+                «validNamesAndValues»
             «ENDIF»
 
             «generateHashCode»
@@ -208,6 +215,19 @@ class ClassTemplate extends BaseTemplate {
         return false
     }
 
+    def private isBitsTypeObject() {
+        var wlk = genTO
+        while (wlk !== null) {
+            for (impl : wlk.implements) {
+                if (BITS_TYPE_OBJECT.identifier.equals(impl.identifier)) {
+                    return true
+                }
+            }
+            wlk = wlk.superType
+        }
+        return false
+    }
+
     def private defaultProperties() '''
         «FOR field : properties SEPARATOR "\n"»
             «field.getterMethod»
@@ -224,20 +244,29 @@ class ClassTemplate extends BaseTemplate {
         }
     '''
 
-    /**
-     * Template method which generates the method <code>getValue()</code> for typedef,
-     * which base type is BitsDefinition.
-     *
-     * @return string with the <code>getValue()</code> method definition in JAVA format
-     */
-    def protected generateGetValueForBitsTypeDef() '''
+    def private validNamesAndValues() {
+        for (c : consts) {
+            if (TypeConstants.VALID_NAMES_NAME.equals(c.name)) {
+                return validNamesAndValues(c.value as BitsTypeDefinition)
+            }
+        }
+        return ""
+    }
 
-        public boolean[] getValue() {
-            return new boolean[]{
-            «FOR property: genTO.properties SEPARATOR ','»
-                 «property.fieldName»
-            «ENDFOR»
-            };
+    def private validNamesAndValues(BitsTypeDefinition typedef) '''
+
+        @«OVERRIDE.importedName»
+        public «IMMUTABLE_SET.importedName»<«STRING.importedName»> validNames() {
+            return «TypeConstants.VALID_NAMES_NAME»;
+        }
+
+        @«OVERRIDE.importedName»
+        public boolean[] values() {
+            return new boolean[] {
+                    «FOR bit : typedef.bits SEPARATOR ','»
+                        «BindingMapping.getPropertyName(bit.name).getterMethodName»()
+                    «ENDFOR»
+                };
         }
     '''
 
@@ -519,6 +548,11 @@ class ClassTemplate extends BaseTemplate {
                         private static final String[] «Constants.MEMBER_REGEX_LIST» = { «
                         FOR v : cValue.values SEPARATOR ", "»"«v.escapeJava»"«ENDFOR» };
                     «ENDIF»
+                «ELSEIF TypeConstants.VALID_NAMES_NAME.equals(c.name)»
+                    «val cValue = c.value as BitsTypeDefinition»
+                    «val immutableSet = IMMUTABLE_SET.importedName»
+                    protected static final «immutableSet»<«STRING.importedName»> «TypeConstants.VALID_NAMES_NAME» = «immutableSet».of(«
+                    FOR bit : cValue.bits SEPARATOR ", "»"«bit.name»"«ENDFOR»);
                 «ELSE»
                     «emitConstant(c)»
                 «ENDIF»
index 4a7f3f198b5e88011aeda5e86567427420f0ed16..96cc85b4ef3eb81668f17afdb85f5991936563c7 100644 (file)
@@ -81,16 +81,16 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         CompilationTestUtils.assertContainsField(bitsExtClass, "_sfmof", boolean.class);
         CompilationTestUtils.assertContainsField(bitsExtClass, "_sfapc", boolean.class);
         CompilationTestUtils.assertContainsFieldWithValue(bitsExtClass, "serialVersionUID", Long.TYPE,
-            -2922917845344851623L, boolean.class, boolean.class, boolean.class, boolean.class, boolean.class,
+            7934653360983102096L, boolean.class, boolean.class, boolean.class, boolean.class, boolean.class,
             boolean.class, boolean.class);
 
-        assertEquals(8, bitsExtClass.getDeclaredFields().length);
+        assertEquals(9, bitsExtClass.getDeclaredFields().length);
         CompilationTestUtils.assertContainsConstructor(bitsExtClass, bitsExtClass);
         assertEquals(2, bitsExtClass.getConstructors().length);
         Method defInst = CompilationTestUtils.assertContainsMethod(bitsExtClass, bitsExtClass, "getDefaultInstance",
             String.class);
         CompilationTestUtils.assertContainsDefaultMethods(bitsExtClass);
-        assertEquals(12, bitsExtClass.getDeclaredMethods().length);
+        assertEquals(13, bitsExtClass.getDeclaredMethods().length);
 
         Constructor<?> expectedConstructor = CompilationTestUtils.assertContainsConstructor(bitsExtClass, boolean.class,
             boolean.class, boolean.class, boolean.class, boolean.class, boolean.class, boolean.class);
index d32bf1c674a181d41a023ba291bd35fa3a4cdf67..7f3607a305e010fff8e5f01c675d81733a9665aa 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BitsTypeObject;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.ChoiceIn;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
@@ -66,6 +67,7 @@ public final class BindingTypes {
     public static final ConcreteType RPC_OUTPUT = typeForClass(RpcOutput.class);
     public static final ConcreteType RPC_SERVICE = typeForClass(RpcService.class);
     public static final ConcreteType SCALAR_TYPE_OBJECT = typeForClass(ScalarTypeObject.class);
+    public static final ConcreteType BITS_TYPE_OBJECT = typeForClass(BitsTypeObject.class);
     public static final ConcreteType INSTANCE_IDENTIFIER = typeForClass(InstanceIdentifier.class);
     public static final ConcreteType KEYED_INSTANCE_IDENTIFIER = typeForClass(KeyedInstanceIdentifier.class);
 
index 20928e6c86dcc0ed22047dc01bf4cf0d6c73315a..0b3ebb364966ec8cf6676fa322be1632f794653a 100644 (file)
@@ -8,19 +8,17 @@
 package org.opendaylight.mdsal.binding.model.ri;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.binding.BitsTypeObject;
 import org.opendaylight.yangtools.yang.binding.ScalarTypeObject;
 
 /**
  * Contains constants used in relations with <code>Type</code>.
  */
 public final class TypeConstants {
-
     /**
-     * Name or prefix (multiple patterns in builder class as composed with '_'
-     * and upper case of the field name) of the class constant which holds the map
-     * of regular expressions that need to be enforced on the string value.
-     * The map is keyed by Pattern-compatible string and values are XSD-compatible
-     * strings.
+     * Name or prefix (multiple patterns in builder class as composed with '_' and upper case of the field name) of the
+     * class constant which holds the map of regular expressions that need to be enforced on the string value. The map
+     * is keyed by Pattern-compatible string and values are XSD-compatible strings.
      */
     public static final @NonNull String PATTERN_CONSTANT_NAME = "PATTERN_CONSTANTS";
 
@@ -30,8 +28,13 @@ public final class TypeConstants {
     public static final @NonNull String VALUE_PROP = "value";
 
     /**
-     * Creation of new instance is prohibited.
+     * Name of the constant holding the names of valid {@code bit}s in a {@link BitsTypeObject}. This constant is
+     * protected and made accessible via {@link BitsTypeObject#validNames()} and its type matches the return type
+     * exactly.
      */
+    public static final @NonNull String VALID_NAMES_NAME = "VALID_NAMES";
+
     private TypeConstants() {
+        // Hidden on purpose
     }
 }
index 1936f9e3fe28f796643eb2ec6bfebc4214b5c707..c106468888d6f260e9fef84a169037bcd97b1d64 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.io.Serializable;
 import java.util.Arrays;
@@ -55,6 +56,7 @@ public final class Types {
     private static final @NonNull ConcreteType PRIMITIVE_VOID = typeForClass(void.class);
     private static final @NonNull ConcreteType SERIALIZABLE = typeForClass(Serializable.class);
     private static final @NonNull ConcreteType SET_TYPE = typeForClass(Set.class);
+    private static final @NonNull ConcreteType IMMUTABLE_SET_TYPE = typeForClass(ImmutableSet.class);
     private static final @NonNull ParameterizedType LIST_TYPE_WILDCARD = parameterizedTypeFor(LIST_TYPE);
     private static final @NonNull ParameterizedType SET_TYPE_WILDCARD = parameterizedTypeFor(SET_TYPE);
 
@@ -181,6 +183,17 @@ public final class Types {
         return parameterizedTypeFor(SET_TYPE, valueType);
     }
 
+    /**
+     * Returns an instance of {@link ParameterizedType} describing the typed {@link ImmutableSet}&lt;V&gt; with concrete
+     * type of value.
+     *
+     * @param valueType Value Type
+     * @return Description of generic type instance of ImmutableSet
+     */
+    public static @NonNull ParameterizedType immutableSetTypeFor(final Type valueType) {
+        return parameterizedTypeFor(IMMUTABLE_SET_TYPE, valueType);
+    }
+
     /**
      * Returns an instance of {@link ParameterizedType} describing the typed {@link Set}&lt;?&gt;.
      *
index 0b74a4461f414f48e13a37977d1887a6fd7a43ac..8d1be665b217569cfdff0368fa0e2c4d062ec953 100644 (file)
@@ -1,5 +1,5 @@
 module opendaylight-of-migration-test-model {
-
+    yang-version 1.1;
     namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:of-migration-test-model";
     prefix of-migration-test;
 
@@ -25,6 +25,18 @@ module opendaylight-of-migration-test-model {
         }
     }
 
+    typedef derived-bit-flags {
+        type bit-flags;
+    }
+
+    typedef restricted-bit-flags {
+        type derived-bit-flags {
+            bit FLAG_ONE;
+            bit FLAG_THREE;
+            bit FLAG_FIVE;
+        }
+    }
+
     typedef custom-enum {
         type enumeration {
             enum type1;
diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BitsTypeObject.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BitsTypeObject.java
new file mode 100644 (file)
index 0000000..7453ece
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022 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.binding;
+
+import com.google.common.collect.ImmutableSet;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * Interface implemented by all {@link TypeObject}s generated for {@code type bits}.
+ */
+public interface BitsTypeObject extends TypeObject {
+    /**
+     * Return the set of strings which are valid {@code bit} names for this type. The iteration order of the returned
+     * set is required to match effective bit {@code position} assignment.
+     *
+     * @return The names of valid bits for this type.
+     */
+    @NonNull ImmutableSet<String> validNames();
+
+    /**
+     * Return the bit values. Returned array contains all bits from {@link #validNames()} in the interation order of
+     * that set. Note that the array is packed, e.g. unassigned positions are skipped over.
+     *
+     * @return Array of values.
+     */
+    boolean @NonNull [] values();
+}