Skip to content

Commit

Permalink
Merge pull request #682 from Netflix/custom-generated-annotation
Browse files Browse the repository at this point in the history
codegen: option to add @com.netflix.hollow.Generated annotation
  • Loading branch information
rpalcolea authored Jun 6, 2024
2 parents 43d8541 + 3f9ac80 commit f4da104
Show file tree
Hide file tree
Showing 31 changed files with 155 additions and 15 deletions.
35 changes: 35 additions & 0 deletions hollow/src/main/java/com/netflix/hollow/HollowGenerated.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2016-2024 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.hollow;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;

/**
* This represents code that is generated by HollowAPIGenerator
* This is helpful for tools that instrument code, such as JaCoCo.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {CONSTRUCTOR, METHOD, TYPE})
@Documented
public @interface HollowGenerated {}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,15 @@ public B withMetaInfo(Path metaInfoPath) {
return getBuilder();
}

/**
* Enable @Generated annotation in the generated API
* @return
*/
public B withGeneratedAnnotation() {
config.setUseGeneratedAnnotation(true);
return getBuilder();
}

public G build() {
if (apiClassname == null)
throw new IllegalStateException("Please specify an API classname (.withAPIClassname()) before calling .build()");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class CodeGeneratorConfig {
private boolean useHollowPrimitiveTypes = false;
private boolean restrictApiToFieldType = false;
private boolean useVerboseToString = false;
private boolean useGeneratedAnnotation = false;

private boolean useMetaInfo = false;
private Path metaInfoPath;
Expand Down Expand Up @@ -139,6 +140,15 @@ public void setUseVerboseToString(boolean useVerboseToString) {
this.useVerboseToString = useVerboseToString;
}

public boolean isUseGeneratedAnnotation() {
return useGeneratedAnnotation;
}

public void setUseGeneratedAnnotation(boolean useGeneratedAnnotation) {
this.useGeneratedAnnotation = useGeneratedAnnotation;
}


@Override
public int hashCode() {
final int prime = 31;
Expand All @@ -149,6 +159,7 @@ public int hashCode() {
result = prime * result + (restrictApiToFieldType ? 1231 : 1237);
result = prime * result + (useAggressiveSubstitutions ? 1231 : 1237);
result = prime * result + (useBooleanFieldErgonomics ? 1231 : 1237);
result = prime * result + (useGeneratedAnnotation ? 1231 : 1237);
result = prime * result + (useHollowPrimitiveTypes ? 1231 : 1237);
result = prime * result + (usePackageGrouping ? 1231 : 1237);
result = prime * result + (useVerboseToString ? 1231 : 1237);
Expand Down Expand Up @@ -184,6 +195,8 @@ public boolean equals(Object obj) {
return false;
if (useBooleanFieldErgonomics != other.useBooleanFieldErgonomics)
return false;
if (useGeneratedAnnotation != other.useGeneratedAnnotation)
return false;
if (useHollowPrimitiveTypes != other.useHollowPrimitiveTypes)
return false;
if (usePackageGrouping != other.usePackageGrouping)
Expand All @@ -207,6 +220,8 @@ public String toString() {
builder.append(classPostfix);
builder.append(", getterPrefix=");
builder.append(getterPrefix);
builder.append(", useGeneratedAnnotation=");
builder.append(useGeneratedAnnotation);
builder.append(", usePackageGrouping=");
builder.append(usePackageGrouping);
builder.append(", useAggressiveSubstitutions=");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ public String generate() {
builder.append("import ").append(SampleResult.class.getName()).append(";\n");
builder.append("import ").append(AllHollowRecordCollection.class.getName()).append(";\n");

appendGeneratedAnnotation(builder);

builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" extends HollowAPI ");
Set<String> primitiveTypes = HollowCodeGenerationUtils.getPrimitiveTypes(schemaList); // Implement Primitive Type Retriever(s)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public String generate() {
builder.append("import ").append(Collections.class.getName()).append(";\n");
builder.append("import ").append(Set.class.getName()).append(";\n");

appendGeneratedAnnotation(builder);

builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" implements HollowAPIFactory {\n\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.netflix.hollow.api.codegen;

import com.netflix.hollow.HollowGenerated;
import com.netflix.hollow.api.codegen.objects.HollowCollectionsGenerator;
import com.netflix.hollow.core.HollowDataset;
import com.netflix.hollow.core.schema.HollowListSchema;
Expand Down Expand Up @@ -129,6 +130,16 @@ protected void appendPackageAndCommonImports(StringBuilder builder,
}
}

/**
* Add @com.netflix.hollow.Generated annotation to the generated class
*/
protected void appendGeneratedAnnotation(StringBuilder builder) {
if(config.isUseGeneratedAnnotation()) {
builder.append("import ").append(HollowGenerated.class.getName()).append(";\n");
builder.append("\n@HollowGenerated");
}
}

private String createFullPackageName(String packageName, String subPackageName, boolean usePackageGrouping) {
if (usePackageGrouping && !isEmpty(packageName) && !isEmpty(subPackageName)) {
return packageName + "." + subPackageName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public String generate() {
builder.append("import " + HollowReadStateEngine.class.getName() + ";\n");

builder.append("\n");
builder.append("@SuppressWarnings(\"all\")\n");
appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class " + className + " extends " + AbstractHollowDataAccessor.class.getSimpleName() + "<" + type +"> {\n\n");

builder.append(" public static final String TYPE = \"" + schema.getName() + "\";\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public String generate() {
builder.append("import " + HollowListTypeDataAccess.class.getName() + ";\n");
builder.append("import " + HollowListLookupDelegate.class.getName() + ";\n");

appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" extends HollowListTypeAPI {\n\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public String generate() {
builder.append("import " + HollowMapTypeDataAccess.class.getName() + ";\n");
builder.append("import " + HollowMapLookupDelegate.class.getName() + ";\n");

appendGeneratedAnnotation(builder);

builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" extends HollowMapTypeAPI {\n\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ public TypeAPIObjectJavaGenerator(String apiClassname, String packageName, Hollo
public String generate() {
StringBuilder classBodyBuilder = new StringBuilder();

classBodyBuilder.append("@SuppressWarnings(\"all\")\n");
appendGeneratedAnnotation(classBodyBuilder);
classBodyBuilder.append("\n@SuppressWarnings(\"all\")\n");
classBodyBuilder.append("public class " + className + " extends HollowObjectTypeAPI {\n\n");

classBodyBuilder.append(" private final ").append(delegateLookupClassname(objectSchema)).append(" delegateLookupImpl;\n\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public String generate() {
builder.append("import " + HollowSetTypeDataAccess.class.getName() + ";\n");
builder.append("import " + HollowSetLookupDelegate.class.getName() + ";\n");

appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" extends HollowSetTypeAPI {\n\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public String generate() {
builder.append("import ").append(HollowTypeAPI.class.getName()).append(";\n");
builder.append("import ").append(HollowCachedDelegate.class.getName()).append(";\n");

appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" extends HollowObjectAbstractDelegate implements HollowCachedDelegate, ").append(delegateInterfaceName(schema.getName())).append(" {\n\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public String generate() {
builder.append("import ").append(HollowObjectTypeDataAccess.class.getName()).append(";\n");
builder.append("import ").append(HollowObjectSchema.class.getName()).append(";\n");

appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class ").append(className).append(" extends HollowObjectAbstractDelegate implements ").append(delegateInterfaceName(schema.getName())).append(" {\n\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ public String generate() {
builder.append("import " + AbstractHollowHashIndex.class.getName() + ";\n");
builder.append("import " + AbstractHollowOrdinalIterable.class.getName() + ";\n\n");

appendGeneratedAnnotation(builder);

builder.append("\n");
builder.append("/**\n");
genDeprecatedJavaDoc(schemaList, builder);
builder.append(" */\n");
builder.append("@Deprecated\n");
builder.append("@SuppressWarnings(\"all\")\n");
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class " + className + " extends " + AbstractHollowHashIndex.class.getSimpleName() + "<" + apiClassname + "> {\n\n");

builder.append(" public " + className + "(HollowConsumer consumer, String queryType, String selectFieldPath, String... matchFieldPaths) {\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ public String generate() {
if (isGenSimpleConstructor)
builder.append("import " + HollowObjectSchema.class.getName() + ";\n");

appendGeneratedAnnotation(builder);
builder.append("\n/**\n");
genDeprecatedJavaDoc(builder);
builder.append(" */\n");
builder.append("@Deprecated\n");
builder.append("@SuppressWarnings(\"all\")\n");
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class " + className + " extends " + AbstractHollowUniqueKeyIndex.class.getSimpleName() + "<" + apiClassname + ", " + hollowImplClassname(type) + "> ");
if (isImplementsUniqueKeyIndex) {
builder.append("implements " + HollowUniqueKeyIndex.class.getSimpleName() + "<" + hollowImplClassname(type) + "> ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public String generate() {
if(schema instanceof HollowMapSchema)
builder.append("import " + HollowMapCachedDelegate.class.getName() + ";\n");

appendGeneratedAnnotation(builder);

builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class " + className + "<T extends " + objectClassName + "> extends HollowFactory<T> {\n\n");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ public String generate() {
builder.append("import " + HollowListDelegate.class.getName() + ";\n");
builder.append("import " + GenericHollowRecordHelper.class.getName() + ";\n\n");

builder.append("@SuppressWarnings(\"all\")\n");
appendGeneratedAnnotation(builder);

builder.append("\n@SuppressWarnings(\"all\")\n");
if(parameterize)
builder.append("public class " + className + "<T> extends HollowList<T> {\n\n");
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ public String generate() {
builder.append("import " + HollowMapDelegate.class.getName() + ";\n");
builder.append("import " + GenericHollowRecordHelper.class.getName() + ";\n\n");

builder.append("@SuppressWarnings(\"all\")\n");
appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");

String keyGeneric = parameterizeKey ? "K" : keyClassName;
String valueGeneric = parameterizeValue ? "V" : valueClassName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ public String generate() {
}
classBuilder.append("\n");

classBuilder.append("@SuppressWarnings(\"all\")\n");
appendGeneratedAnnotation(classBuilder);
classBuilder.append("\n@SuppressWarnings(\"all\")\n");
if (requiresHollowTypeName) {
classBuilder.append("@" + HollowTypeName.class.getSimpleName() + "(name=\"" + schema.getName() + "\")\n");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public String generate() {
builder.append("import " + HollowSetDelegate.class.getName() + ";\n");
builder.append("import " + GenericHollowRecordHelper.class.getName() + ";\n\n");

builder.append("@SuppressWarnings(\"all\")\n");
appendGeneratedAnnotation(builder);
builder.append("\n@SuppressWarnings(\"all\")\n");
if(parameterize)
builder.append("public class " + className + "<T> extends HollowSet<T> {\n\n");
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public String generate() {
"import com.netflix.hollow.api.perfapi.Ref;\n" +
"import com.netflix.hollow.core.read.dataaccess.HollowDataAccess;\n\n");

builder.append("@SuppressWarnings(\"all\")\n");
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class " + schema.getName() + "PerfAPI extends HollowObjectTypePerfAPI {\n\n");

builder.append(" public static final String fieldNames[] = { ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public String generate() {
"import java.util.Set;\n" +
"\n");

builder.append("@SuppressWarnings(\"all\")\n");
builder.append("\n@SuppressWarnings(\"all\")\n");
builder.append("public class " + apiClassName + " extends HollowPerformanceAPI {\n\n");

List<HollowSchema> schemas = new ArrayList<>(dataset.getSchemas());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.netflix.hollow.HollowGenerated;
import com.netflix.hollow.core.write.objectmapper.HollowTypeName;
import java.io.File;
import java.io.IOException;
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;

Expand All @@ -37,7 +37,7 @@ public class AbstractHollowAPIGeneratorTest {
protected String clazzFolder = String.format("%s/classes", tmpFolder);
private Path metaInfoPath = null;

void runGenerator(String apiClassName, String packageName, Class<?> clazz,
protected void runGenerator(String apiClassName, String packageName, Class<?> clazz,
UnaryOperator<HollowAPIGenerator.Builder> generatorCustomizer) throws Exception {
System.out.println(String.format("Folders (%s) : \n\tsource=%s \n\tclasses=%s",
getClass().getSimpleName(), sourceFolder, clazzFolder));
Expand Down Expand Up @@ -71,6 +71,13 @@ void assertClassHasHollowTypeName(String clazz, String typeName) throws IOExcept
assertEquals(typeName, ((HollowTypeName) annotation).name());
}

protected void assertClassHasGeneratedAnnotation(String clazz) throws IOException, ClassNotFoundException {
ClassLoader cl = new URLClassLoader(new URL[]{new File(clazzFolder).toURI().toURL()});
Class cls = cl.loadClass(clazz);
Annotation annotation = cls.getAnnotation(HollowGenerated.class);
assertNotNull(annotation);
}

void assertFileDoesNotExist(String relativePath) {
if (relativePath.startsWith("/")) {
throw new IllegalArgumentException("Relative paths should not start with /");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ public void testGenerateWithPostfixAndAggressiveSubstitutions() throws Exception
assertFileDoesNotExist("codegen/api/StringGenerated.java");
}

@Test
public void testGenerateWithGeneratedAnnotation() throws Exception {
runGenerator("MyClassTestAPI", "codegen.api", MyClass.class,
builder -> builder.withClassPostfix("Generated").withGeneratedAnnotation());
assertClassHasGeneratedAnnotation("codegen.api.MyClassTestAPI");
}


@SuppressWarnings("unused")
@HollowPrimaryKey(fields = "id")
private static class MyClass {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public void test() throws Exception {
String apiClassName = "BooleanErgoTestAPI";
String packageName = "codegen.booleanfield.ergo";
runGenerator(apiClassName, packageName, Movie.class,
builder -> builder.withBooleanFieldErgonomics(true));
builder -> builder.withBooleanFieldErgonomics(true).withGeneratedAnnotation());
assertClassHasGeneratedAnnotation(packageName + "." + apiClassName);
}

static class Movie {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ public void testGenerateWithPostfix() throws Exception {
builder -> builder.withClassPostfix("Generated").withPackageGrouping());
}

@Test
public void testGenerateWithGeneratedAnnotation() throws Exception {
runGenerator(API_CLASS_NAME, PACKAGE_NAME, Movie.class,
builder -> builder.withClassPostfix("Generated").withGeneratedAnnotation());
assertClassHasGeneratedAnnotation(PACKAGE_NAME + "." + API_CLASS_NAME);
assertClassHasGeneratedAnnotation(PACKAGE_NAME + ".StringGenerated");
}

@HollowPrimaryKey(fields="id")
static class Movie {
int id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,11 @@ public void test_withPackageGrouping() throws Exception {
public void test_withoutPackageGrouping() throws Exception {
runGenerator(API_CLASS_NAME, PACKAGE_NAME, Gru.class, b -> b);
}

@Test
public void test_withGeneratedAnnotation() throws Exception {
runGenerator(API_CLASS_NAME, PACKAGE_NAME, Gru.class,
HollowAPIGenerator.Builder::withGeneratedAnnotation);
assertClassHasGeneratedAnnotation(PACKAGE_NAME + "." + API_CLASS_NAME);
}
}
Loading

0 comments on commit f4da104

Please sign in to comment.