From 29e1356c300266f3e10325c1ac61eb422905b77e Mon Sep 17 00:00:00 2001 From: Eduardo Ramirez Date: Mon, 25 Mar 2024 10:21:47 -0700 Subject: [PATCH] Codegen- option to generate a schema doc --- .../AbstractHollowAPIGeneratorBuilder.java | 15 ++++++- .../api/codegen/CodeGeneratorConfig.java | 31 +++++++++++++ .../codegen/HollowAPIClassJavaGenerator.java | 5 +++ .../api/codegen/HollowAPIGenerator.java | 32 ++++++++++++++ .../AbstractHollowAPIGeneratorTest.java | 19 +++++--- .../api/codegen/HollowAPIGeneratorTest.java | 44 ++++++++++++++++++- .../HollowPerformanceAPIGeneratorTest.java | 7 +-- 7 files changed, 140 insertions(+), 13 deletions(-) diff --git a/hollow/src/main/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorBuilder.java b/hollow/src/main/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorBuilder.java index 069087ee22..6dad1c7835 100644 --- a/hollow/src/main/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorBuilder.java +++ b/hollow/src/main/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorBuilder.java @@ -36,7 +36,6 @@ public abstract class AbstractHollowAPIGeneratorBuilder schemas = HollowSchemaSorter.dependencyOrderedSchemaList(dataset); + Collections.reverse(schemas); + + // line-separated {@code HollowSchema}s for readability + StringBuilder builder = new StringBuilder(); + for(HollowSchema schema : schemas) { + builder.append(schema.toString()).append("\n"); + } + String schemaDoc = builder.toString(); + + FileWriter writer = new FileWriter(new File(metaInfoDir, packageName + "." + apiClassname + SCHEMA_DOC_SUFFIX)); + writer.write(schemaDoc); + writer.close(); + } + protected HollowJavaFileGenerator getStaticAPIGenerator(HollowSchema schema) { if(schema instanceof HollowObjectSchema) { return new TypeAPIObjectJavaGenerator(apiClassname, packageName, (HollowObjectSchema) schema, dataset, config); diff --git a/hollow/src/test/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorTest.java b/hollow/src/test/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorTest.java index c74992ef87..3e4204c3f4 100644 --- a/hollow/src/test/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorTest.java +++ b/hollow/src/test/java/com/netflix/hollow/api/codegen/AbstractHollowAPIGeneratorTest.java @@ -26,13 +26,16 @@ import java.lang.annotation.Annotation; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.function.UnaryOperator; import org.junit.After; public class AbstractHollowAPIGeneratorTest { - private String tmpFolder = System.getProperty("java.io.tmpdir"); + protected String tmpFolder = System.getProperty("java.io.tmpdir"); protected String sourceFolder = String.format("%s/src", tmpFolder); protected String clazzFolder = String.format("%s/classes", tmpFolder); + private Path metaInfoPath = null; void runGenerator(String apiClassName, String packageName, Class clazz, UnaryOperator generatorCustomizer) throws Exception { @@ -49,16 +52,15 @@ void runGenerator(String apiClassName, String packageName, Class clazz, .withDestination(sourceFolder).build(); generator.generateSourceFiles(); + if(generator.config.isUseMetaInfo()) { + metaInfoPath = generator.config.getMetaInfoPath(); + } // Compile to validate generated files HollowCodeGenerationCompileUtil.compileSrcFiles(sourceFolder, clazzFolder); } - protected void assertNonEmptyFileExists(String relativePath) throws IOException { - if (relativePath.startsWith("/")) { - throw new IllegalArgumentException("Relative paths should not start with /"); - } - File f = new File(sourceFolder + "/" + relativePath); - assertTrue("File at " + relativePath + " should exist", f.exists() && f.length() > 0L); + protected void assertNonEmptyFileExists(Path absolutePath) { + assertTrue("File at " + absolutePath + " should exist", absolutePath.toFile().exists() && absolutePath.toFile().length() > 0L); } void assertClassHasHollowTypeName(String clazz, String typeName) throws IOException, ClassNotFoundException { @@ -81,5 +83,8 @@ void assertFileDoesNotExist(String relativePath) { public void cleanup() { HollowCodeGenerationCompileUtil.cleanupFolder(new File(sourceFolder), null); HollowCodeGenerationCompileUtil.cleanupFolder(new File(clazzFolder), null); + if (metaInfoPath != null) { + HollowCodeGenerationCompileUtil.cleanupFolder(metaInfoPath.toFile(), null); + } } } diff --git a/hollow/src/test/java/com/netflix/hollow/api/codegen/HollowAPIGeneratorTest.java b/hollow/src/test/java/com/netflix/hollow/api/codegen/HollowAPIGeneratorTest.java index 54b5ab4dbc..eeb0c34cb5 100644 --- a/hollow/src/test/java/com/netflix/hollow/api/codegen/HollowAPIGeneratorTest.java +++ b/hollow/src/test/java/com/netflix/hollow/api/codegen/HollowAPIGeneratorTest.java @@ -1,9 +1,48 @@ package com.netflix.hollow.api.codegen; +import static org.junit.Assert.assertEquals; + +import com.netflix.hollow.core.schema.HollowSchema; +import com.netflix.hollow.core.schema.HollowSchemaParser; +import com.netflix.hollow.core.schema.SimpleHollowDataset; +import com.netflix.hollow.core.write.objectmapper.HollowPrimaryKey; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; import org.junit.Test; public class HollowAPIGeneratorTest extends AbstractHollowAPIGeneratorTest { + @Test + public void assertMetaInfoAtCustomLocation() throws Exception { + runGenerator("API", "codegen.api", MyClass.class, b -> b.withMetaInfo("meta-info")); + assertNonEmptyFileExists(Paths.get("meta-info")); + } + + @Test + public void testSchemaDocAtCustomLocation() throws Exception { + runGenerator("MyClassTestAPI", "codegen.api", MyClass.class, + builder -> builder.withMetaInfo(tmpFolder + "/" + "resources/META-INF/hollow")); + assertNonEmptyFileExists(Paths.get(tmpFolder, "resources/META-INF/hollow/codegen.api.MyClassTestAPI.schema")); + } + + @Test + public void testSchemaDocContents() throws Exception { + runGenerator("MyClassTestAPI", "codegen.api", MyClass.class, b -> b.withMetaInfo(Paths.get(sourceFolder))); + assertNonEmptyFileExists(Paths.get(sourceFolder, "codegen.api.MyClassTestAPI.schema")); + + List expected = SimpleHollowDataset.fromClassDefinitions(MyClass.class).getSchemas(); + try (InputStream input = new FileInputStream(sourceFolder + "/" + "codegen.api.MyClassTestAPI.schema")) { + List actual = HollowSchemaParser.parseCollectionOfSchemas(new BufferedReader(new InputStreamReader(input))); + assertEquals(expected.size(), actual.size()); + assertEquals(new HashSet(expected), new HashSet(actual)); + } + } + @Test public void generatesFileUsingDestinationPath() throws Exception { runGenerator("API", "com.netflix.hollow.example.api.generated", MyClass.class, b -> b); @@ -13,7 +52,7 @@ public void generatesFileUsingDestinationPath() throws Exception { public void testGenerateWithPostfix() throws Exception { runGenerator("MyClassTestAPI", "codegen.api", MyClass.class, builder -> builder.withClassPostfix("Generated")); - assertNonEmptyFileExists("codegen/api/StringGenerated.java"); + assertNonEmptyFileExists(Paths.get(sourceFolder, "codegen/api/StringGenerated.java")); assertClassHasHollowTypeName("codegen.api.MyClassGenerated", "MyClass"); } @@ -21,7 +60,7 @@ public void testGenerateWithPostfix() throws Exception { public void testGenerateWithPostfixAndPackageGrouping() throws Exception { runGenerator("MyClassTestAPI", "codegen.api", MyClass.class, builder -> builder.withClassPostfix("Generated").withPackageGrouping()); - assertNonEmptyFileExists("codegen/api/core/StringGenerated.java"); + assertNonEmptyFileExists(Paths.get(sourceFolder, "codegen/api/core/StringGenerated.java")); } @Test @@ -43,6 +82,7 @@ public void testGenerateWithPostfixAndAggressiveSubstitutions() throws Exception } @SuppressWarnings("unused") + @HollowPrimaryKey(fields = "id") private static class MyClass { int id; String foo; diff --git a/hollow/src/test/java/com/netflix/hollow/api/codegen/perfapi/HollowPerformanceAPIGeneratorTest.java b/hollow/src/test/java/com/netflix/hollow/api/codegen/perfapi/HollowPerformanceAPIGeneratorTest.java index 7c613c517e..4b8dcc3f78 100644 --- a/hollow/src/test/java/com/netflix/hollow/api/codegen/perfapi/HollowPerformanceAPIGeneratorTest.java +++ b/hollow/src/test/java/com/netflix/hollow/api/codegen/perfapi/HollowPerformanceAPIGeneratorTest.java @@ -4,6 +4,7 @@ import com.netflix.hollow.api.codegen.HollowCodeGenerationCompileUtil; import com.netflix.hollow.core.schema.SimpleHollowDataset; import java.io.File; +import java.nio.file.Paths; import org.junit.Test; public class HollowPerformanceAPIGeneratorTest extends AbstractHollowAPIGeneratorTest { @@ -16,9 +17,9 @@ public void testGeneratePerformanceApi() throws Exception { @Test public void testGeneratedFilesArePlacedInPackageDirectory() throws Exception { runGenerator("API", "codegen.api", MyClass.class); - assertNonEmptyFileExists("codegen/api/MyClassPerfAPI.java"); - assertNonEmptyFileExists("codegen/api/StringPerfAPI.java"); - assertNonEmptyFileExists("codegen/api/API.java"); + assertNonEmptyFileExists(Paths.get(sourceFolder, "codegen/api/MyClassPerfAPI.java")); + assertNonEmptyFileExists(Paths.get(sourceFolder, "codegen/api/StringPerfAPI.java")); + assertNonEmptyFileExists(Paths.get(sourceFolder, "codegen/api/API.java")); } private void runGenerator(String apiClassName, String packageName, Class clazz) throws Exception {