Repository: netflix/hollow
Issue: Compilation of generated files fails if data model object has `Byte`

If you try and generate an API for object that contains a Byte, the generated files to do not compile. Any generated files that to try reference the type (eg <APIName>HashIndex.java) conflict between my.generated.package.Byte and java.lang.Byte, since we import my.generated.*.

A couple ways to fix this:
* have similar treatment for Byte as we do for String, Integer, etc (include them in com.netflix.hollow.core.type and replace with HByte) #172
* import the generated Byte classes directly, instead of using a star import (WIP)

Changed files:
hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowHashIndexGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowMapJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/HollowConsumerJavaFileGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowUniqueKeyIndexGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowListJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIListJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowObjectJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/api/HollowDataAccessorGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPISetJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/HollowAPIFactoryJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIObjectJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowSetJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowFactoryJavaGenerator.java
hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIMapJavaGenerator.java

diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowAPIFactoryJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowAPIFactoryJavaGenerator.java
index ee0b3a4f7..59739c0bd 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowAPIFactoryJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowAPIFactoryJavaGenerator.java
@@ -44,7 +44,7 @@ public class HollowAPIFactoryJavaGenerator extends HollowConsumerJavaFileGenerat
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname);
 
         builder.append("import ").append(HollowAPIFactory.class.getName()).append(";\\n");
         builder.append("import ").append(HollowAPI.class.getName()).append(";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowConsumerJavaFileGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowConsumerJavaFileGenerator.java
index 5ee932458..1080e6361 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowConsumerJavaFileGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/HollowConsumerJavaFileGenerator.java
@@ -15,6 +15,16 @@
  */
 package com.netflix.hollow.api.codegen;
 
+import com.netflix.hollow.core.schema.HollowListSchema;
+import com.netflix.hollow.core.schema.HollowMapSchema;
+import com.netflix.hollow.core.schema.HollowSchema;
+import com.netflix.hollow.core.schema.HollowSetSchema;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 /**
  * Not intended for external consumption.
  *
@@ -54,7 +64,18 @@ public abstract class HollowConsumerJavaFileGenerator implements HollowJavaFileG
     }
 
     protected void appendPackageAndCommonImports(StringBuilder builder) {
-        String fullPackageName = createFullPackageName(packageName, subPackageName, config.isUsePackageGrouping());
+        appendPackageAndCommonImports(builder, null, new ArrayList<HollowSchema>());
+    }
+
+    protected void appendPackageAndCommonImports(StringBuilder builder,
+            String apiClassname) {
+        appendPackageAndCommonImports(builder, apiClassname, new ArrayList<HollowSchema>());
+    }
+
+    protected void appendPackageAndCommonImports(StringBuilder builder,
+            String apiClassname, List<HollowSchema> schemasToImport) {
+        String fullPackageName =
+            createFullPackageName(packageName, subPackageName, config.isUsePackageGrouping());
         if (!isEmpty(fullPackageName)) {
             builder.append("package ").append(fullPackageName).append(";\\n\\n");
 
@@ -63,9 +84,42 @@ public abstract class HollowConsumerJavaFileGenerator implements HollowJavaFileG
             }
 
             if (config.isUsePackageGrouping()) {
-                builder.append("import ").append(packageName).append(".*;\\n");
-                builder.append("import ").append(packageName).append(".core.*;\\n");
-                if (useCollectionsImport) builder.append("import ").append(packageName).append(".collections.*;\\n\\n");
+                if (apiClassname != null) {
+                    appendImportFromBasePackage(builder, apiClassname);
+                }
+                Set<String> schemaNameSet = new HashSet<>();
+                for (HollowSchema schema : schemasToImport) {
+                    switch (schema.getSchemaType()) {
+                        case OBJECT:
+                            addToSetIfNotPrimitive(schemaNameSet, schema.getName());
+                            break;
+                        case SET:
+                            addToSetIfNotPrimitive(schemaNameSet,
+                                    ((HollowSetSchema) schema).getElementType());
+                            break;
+                        case LIST:
+                            addToSetIfNotPrimitive(schemaNameSet,
+                                    ((HollowListSchema) schema).getElementType());
+                            break;
+                        case MAP:
+                            HollowMapSchema mapSchema = (HollowMapSchema) schema;
+                            addToSetIfNotPrimitive(schemaNameSet, mapSchema.getKeyType(),
+                                    mapSchema.getValueType());
+                            break;
+                        default:
+                            throw new IllegalArgumentException(
+                                    "Unexpected HollowSchema to import: " + schema);
+
+                    }
+                }
+                for (String schemaName : schemaNameSet) {
+                    appendImportFromBasePackage(builder, schemaName);
+                }
+                appendImportFromBasePackage(builder, "core.*");
+                if (useCollectionsImport) {
+                    appendImportFromBasePackage(builder, "collections.*");
+                }
+                builder.append("\\n");
             }
         }
     }
@@ -82,4 +136,22 @@ public abstract class HollowConsumerJavaFileGenerator implements HollowJavaFileG
     private boolean isEmpty(String value) {
         return value == null || value.trim().isEmpty();
     }
+
+    private void appendImportFromBasePackage(StringBuilder builder, String leaf) {
+        builder.append("import ").append(packageName).append(".").append(leaf).append(";\\n");
+    }
+
+    /**
+     * Adds the schema name to the set if the schema name doesn't correspond to a Hollow
+     * primitive type. Factored out to prevent bloat in the switch statement it is called
+     * from.
+     */
+    private void addToSetIfNotPrimitive(Set<String> schemaNameSet,
+            String... schemaNames) {
+        for (String schemaName : schemaNames) {
+            if (!HollowCodeGenerationUtils.isPrimitiveType(schemaName)) {
+                schemaNameSet.add(schemaName);
+            }
+        }
+    }
 }
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/HollowDataAccessorGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/HollowDataAccessorGenerator.java
index e4619c4cf..0d6c1e4b9 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/HollowDataAccessorGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/HollowDataAccessorGenerator.java
@@ -26,6 +26,9 @@ import com.netflix.hollow.api.custom.HollowAPI;
 import com.netflix.hollow.core.index.key.PrimaryKey;
 import com.netflix.hollow.core.read.engine.HollowReadStateEngine;
 import com.netflix.hollow.core.schema.HollowObjectSchema;
+import com.netflix.hollow.core.schema.HollowSchema;
+
+import java.util.Arrays;
 
 /**
  * This class contains template logic for generating a {@link HollowAPI} implementation. Not intended for external consumption.
@@ -54,7 +57,7 @@ public class HollowDataAccessorGenerator extends HollowConsumerJavaFileGenerator
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiclassName, Arrays.<HollowSchema>asList(schema));
 
         builder.append("import " + HollowConsumer.class.getName() + ";\\n");
         builder.append("import " + AbstractHollowDataAccessor.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIListJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIListJavaGenerator.java
index f87262b7b..79e0b8dcb 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIListJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIListJavaGenerator.java
@@ -47,7 +47,7 @@ public class TypeAPIListJavaGenerator extends HollowTypeAPIGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname);
 
         builder.append("import " + HollowListTypeAPI.class.getName() + ";\\n\\n");
         builder.append("import " + HollowListTypeDataAccess.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIMapJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIMapJavaGenerator.java
index edd531d57..be3b6f3b7 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIMapJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIMapJavaGenerator.java
@@ -47,7 +47,7 @@ public class TypeAPIMapJavaGenerator extends HollowTypeAPIGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname);
 
         builder.append("import " + HollowMapTypeAPI.class.getName() + ";\\n\\n");
         builder.append("import " + HollowMapTypeDataAccess.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIObjectJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIObjectJavaGenerator.java
index d7391c6a5..efe84c902 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIObjectJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPIObjectJavaGenerator.java
@@ -116,7 +116,7 @@ public class TypeAPIObjectJavaGenerator extends HollowTypeAPIGenerator {
         classBodyBuilder.append("}");
 
         StringBuilder classBuilder = new StringBuilder();
-        appendPackageAndCommonImports(classBuilder);
+        appendPackageAndCommonImports(classBuilder, apiClassname);
 
         for(Class<?> clazz : importClasses) {
             classBuilder.append("import ").append(clazz.getName()).append(";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPISetJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPISetJavaGenerator.java
index 832697cf2..ca04c9749 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPISetJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/api/TypeAPISetJavaGenerator.java
@@ -47,7 +47,7 @@ public class TypeAPISetJavaGenerator extends HollowTypeAPIGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname);
 
         builder.append("import " + HollowSetTypeAPI.class.getName() + ";\\n\\n");
         builder.append("import " + HollowSetTypeDataAccess.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowHashIndexGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowHashIndexGenerator.java
index fed75797a..04d615a7c 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowHashIndexGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowHashIndexGenerator.java
@@ -21,6 +21,7 @@ import static com.netflix.hollow.api.codegen.HollowCodeGenerationUtils.substitut
 
 import com.netflix.hollow.api.codegen.CodeGeneratorConfig;
 import com.netflix.hollow.api.codegen.HollowAPIGenerator;
+import com.netflix.hollow.api.codegen.HollowCodeGenerationUtils;
 import com.netflix.hollow.api.consumer.HollowConsumer;
 import com.netflix.hollow.api.consumer.data.AbstractHollowOrdinalIterable;
 import com.netflix.hollow.api.consumer.index.AbstractHollowHashIndex;
@@ -29,6 +30,8 @@ import com.netflix.hollow.core.HollowDataset;
 import com.netflix.hollow.core.index.HollowHashIndexResult;
 import com.netflix.hollow.core.schema.HollowSchema;
 import com.netflix.hollow.core.schema.HollowSchemaSorter;
+
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -55,7 +58,7 @@ public class HollowHashIndexGenerator extends HollowIndexGenerator {
         List<HollowSchema> schemaList = HollowSchemaSorter.dependencyOrderedSchemaList(dataset);
 
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname, schemaList);
 
         builder.append("import " + HollowConsumer.class.getName() + ";\\n");
         builder.append("import " + HollowHashIndexResult.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowUniqueKeyIndexGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowUniqueKeyIndexGenerator.java
index 9b7132bf6..c92c0a24c 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowUniqueKeyIndexGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/indexes/HollowUniqueKeyIndexGenerator.java
@@ -23,6 +23,9 @@ import com.netflix.hollow.api.consumer.HollowConsumer;
 import com.netflix.hollow.api.consumer.index.AbstractHollowUniqueKeyIndex;
 import com.netflix.hollow.api.custom.HollowAPI;
 import com.netflix.hollow.core.schema.HollowObjectSchema;
+import com.netflix.hollow.core.schema.HollowSchema;
+
+import java.util.Arrays;
 
 /**
  * This class contains template logic for generating a {@link HollowAPI} implementation.  Not intended for external consumption.
@@ -53,8 +56,7 @@ public class HollowUniqueKeyIndexGenerator extends HollowIndexGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
-
+        appendPackageAndCommonImports(builder, apiClassname, Arrays.<HollowSchema>asList(schema));
         builder.append("import " + HollowConsumer.class.getName() + ";\\n");
         builder.append("import " + AbstractHollowUniqueKeyIndex.class.getName() + ";\\n");
         if (isGenSimpleConstructor)
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowFactoryJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowFactoryJavaGenerator.java
index c5e698b96..5a6c0b1ca 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowFactoryJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowFactoryJavaGenerator.java
@@ -36,6 +36,8 @@ import com.netflix.hollow.core.schema.HollowMapSchema;
 import com.netflix.hollow.core.schema.HollowSchema;
 import com.netflix.hollow.core.schema.HollowSetSchema;
 
+import java.util.Arrays;
+
 /**
  * This class contains template logic for generating a {@link HollowAPI} implementation.  Not intended for external consumption.
  *
@@ -59,7 +61,7 @@ public class HollowFactoryJavaGenerator extends HollowConsumerJavaFileGenerator
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, null, Arrays.asList(schema));
 
         builder.append("import " + HollowFactory.class.getName() + ";\\n");
         builder.append("import " + HollowTypeDataAccess.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowListJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowListJavaGenerator.java
index 4369d1a0e..c677dfd8b 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowListJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowListJavaGenerator.java
@@ -26,6 +26,9 @@ import com.netflix.hollow.api.objects.HollowList;
 import com.netflix.hollow.api.objects.delegate.HollowListDelegate;
 import com.netflix.hollow.api.objects.generic.GenericHollowRecordHelper;
 import com.netflix.hollow.core.schema.HollowListSchema;
+import com.netflix.hollow.core.schema.HollowSchema;
+
+import java.util.Arrays;
 import java.util.Set;
 
 /**
@@ -51,7 +54,7 @@ public class HollowListJavaGenerator extends HollowCollectionsGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname, Arrays.<HollowSchema>asList(schema));
 
         builder.append("import " + HollowList.class.getName() + ";\\n");
         builder.append("import " + HollowListSchema.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowMapJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowMapJavaGenerator.java
index f986235c9..83fba3574 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowMapJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowMapJavaGenerator.java
@@ -30,6 +30,9 @@ import com.netflix.hollow.core.HollowDataset;
 import com.netflix.hollow.core.schema.HollowMapSchema;
 import com.netflix.hollow.core.schema.HollowObjectSchema;
 import com.netflix.hollow.core.schema.HollowObjectSchema.FieldType;
+import com.netflix.hollow.core.schema.HollowSchema;
+
+import java.util.Arrays;
 import java.util.Set;
 
 /**
@@ -63,7 +66,7 @@ public class HollowMapJavaGenerator extends HollowCollectionsGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname, Arrays.<HollowSchema>asList(schema));
 
         builder.append("import " + HollowMap.class.getName() + ";\\n");
         builder.append("import " + HollowMapSchema.class.getName() + ";\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowObjectJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowObjectJavaGenerator.java
index eb224dac8..9bede915e 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowObjectJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowObjectJavaGenerator.java
@@ -80,7 +80,7 @@ public class HollowObjectJavaGenerator extends HollowConsumerJavaFileGenerator {
     @Override
     public String generate() {
         StringBuilder classBuilder = new StringBuilder();
-        appendPackageAndCommonImports(classBuilder);
+        appendPackageAndCommonImports(classBuilder, apiClassname);
 
         classBuilder.append("import " + HollowObject.class.getName() + ";\\n");
         classBuilder.append("import " + HollowObjectSchema.class.getName() + ";\\n\\n");
diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowSetJavaGenerator.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowSetJavaGenerator.java
index 0b56b4a69..b16a363e3 100644
--- a/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowSetJavaGenerator.java
+++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/objects/HollowSetJavaGenerator.java
@@ -25,7 +25,10 @@ import com.netflix.hollow.api.custom.HollowAPI;
 import com.netflix.hollow.api.objects.HollowSet;
 import com.netflix.hollow.api.objects.delegate.HollowSetDelegate;
 import com.netflix.hollow.api.objects.generic.GenericHollowRecordHelper;
+import com.netflix.hollow.core.schema.HollowSchema;
 import com.netflix.hollow.core.schema.HollowSetSchema;
+
+import java.util.Arrays;
 import java.util.Set;
 
 /**
@@ -52,7 +55,7 @@ public class HollowSetJavaGenerator extends HollowCollectionsGenerator {
     @Override
     public String generate() {
         StringBuilder builder = new StringBuilder();
-        appendPackageAndCommonImports(builder);
+        appendPackageAndCommonImports(builder, apiClassname, Arrays.<HollowSchema>asList(schema));
 
         builder.append("import " + HollowSet.class.getName() + ";\\n");
         builder.append("import " + HollowSetSchema.class.getName() + ";\\n");