-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add generator classes to generate platform-specific wrappers (#15)
* Add generator classes to generate platform-specific wrappers * Address PR comments * Rebase to latest master; Address PR comments
- Loading branch information
1 parent
3d3974f
commit 35a3ffc
Showing
32 changed files
with
967 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 0 additions & 60 deletions
60
...fs-annotation-processor/src/main/java/com/linkedin/transport/processor/UDFProperties.java
This file was deleted.
Oops, something went wrong.
8 changes: 4 additions & 4 deletions
8
transportable-udfs-annotation-processor/src/test/resources/outputs/overloadedUDF.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
transportable-udfs-annotation-processor/src/test/resources/outputs/simpleUDF.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...ortable-udfs-annotation-processor/src/test/resources/outputs/udfExtendingAbstractUDF.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...on-processor/src/test/resources/outputs/udfExtendingAbstractUDFImplementingInterface.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
apply plugin: 'java' | ||
|
||
|
||
dependencies { | ||
compile project(':transportable-udfs-api') | ||
compile project(':transportable-udfs-compile-utils') | ||
compile ('com.google.guava:guava:24.1-jre') | ||
compile ('org.apache.commons:commons-io:1.3.2') | ||
compile ('org.apache.commons:commons-text:1.6') | ||
compile ('com.squareup:javapoet:1.11.1') | ||
} | ||
|
||
licenseTest { | ||
exclude 'inputs/**' | ||
exclude 'outputs/**' | ||
} |
76 changes: 76 additions & 0 deletions
76
transportable-udfs-codegen/src/main/java/com/linkedin/transport/codegen/CodegenUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/** | ||
* Copyright 2019 LinkedIn Corporation. All rights reserved. | ||
* Licensed under the BSD-2 Clause license. | ||
* See LICENSE in the project root for license information. | ||
*/ | ||
package com.linkedin.transport.codegen; | ||
|
||
import com.google.common.base.Preconditions; | ||
import java.io.BufferedWriter; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Collection; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
||
|
||
class CodegenUtils { | ||
|
||
private CodegenUtils() { | ||
} | ||
|
||
/** | ||
* Writes a source code file for a class to the provided output directory creating package directories if required | ||
* | ||
* @param outputDir Output directory | ||
* @param packageName Package name of the class (can be {@code null} for the default package) | ||
* @param className Class name | ||
* @param extension Extension of the file (can be {@code null} for no extension) | ||
* @param code Source code of the class | ||
* @throws IOException | ||
*/ | ||
static void writeCodeFile(Path outputDir, String packageName, String className, String extension, | ||
String code) throws IOException { | ||
Preconditions.checkArgument(Files.notExists(outputDir) || Files.isDirectory(outputDir), | ||
"Output directory should not exist or must be a directory", outputDir); | ||
Preconditions.checkArgument(!StringUtils.isBlank(className), "Class name should not be null or an empty string"); | ||
Preconditions.checkNotNull(code, "Code should not be null"); | ||
|
||
final Path packageDir; | ||
if (!StringUtils.isBlank(packageName)) { | ||
packageDir = Paths.get(outputDir.toString(), packageName.split("\\.")); | ||
} else { | ||
packageDir = outputDir; | ||
} | ||
Files.createDirectories(packageDir); | ||
|
||
String fileName = className + (StringUtils.isBlank(extension) ? "" : "." + extension); | ||
Path outputPath = packageDir.resolve(fileName); | ||
Files.write(outputPath, code.getBytes()); | ||
} | ||
|
||
/** | ||
* Writes a list of services to a specified service file | ||
* | ||
* @param outputDir Output directory | ||
* @param serviceFilePath Path of the service file relative to the output directory | ||
* @param services List of services | ||
* @throws IOException | ||
*/ | ||
static void writeServiceFile(Path outputDir, Path serviceFilePath, Collection<String> services) | ||
throws IOException { | ||
Preconditions.checkArgument(Files.notExists(outputDir) || Files.isDirectory(outputDir), | ||
"Output directory should not exist or must be a directory", outputDir); | ||
Preconditions.checkNotNull(serviceFilePath, "Service file path should not be null"); | ||
|
||
Path resolvedServiceFilePath = outputDir.resolve(serviceFilePath); | ||
Files.createDirectories(resolvedServiceFilePath.getParent()); | ||
|
||
try (BufferedWriter writer = Files.newBufferedWriter(resolvedServiceFilePath)) { | ||
for (String service : services) { | ||
writer.write(service + "\n"); | ||
} | ||
} | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
...table-udfs-codegen/src/main/java/com/linkedin/transport/codegen/HiveWrapperGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/** | ||
* Copyright 2019 LinkedIn Corporation. All rights reserved. | ||
* Licensed under the BSD-2 Clause license. | ||
* See LICENSE in the project root for license information. | ||
*/ | ||
package com.linkedin.transport.codegen; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.linkedin.transport.api.udf.StdUDF; | ||
import com.linkedin.transport.api.udf.TopLevelStdUDF; | ||
import com.linkedin.transport.compile.TransportUDFMetadata; | ||
import com.squareup.javapoet.ClassName; | ||
import com.squareup.javapoet.JavaFile; | ||
import com.squareup.javapoet.MethodSpec; | ||
import com.squareup.javapoet.ParameterizedTypeName; | ||
import com.squareup.javapoet.TypeSpec; | ||
import com.squareup.javapoet.WildcardTypeName; | ||
import java.io.File; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import javax.lang.model.element.Modifier; | ||
|
||
|
||
public class HiveWrapperGenerator implements WrapperGenerator { | ||
|
||
private static final String HIVE_PACKAGE_SUFFIX = "hive"; | ||
private static final String GET_TOP_LEVEL_UDF_CLASS_METHOD = "getTopLevelUdfClass"; | ||
private static final String GET_STD_UDF_IMPLEMENTATIONS_METHOD = "getStdUdfImplementations"; | ||
private static final ClassName HIVE_STD_UDF_WRAPPER_CLASS_NAME = | ||
ClassName.bestGuess("com.linkedin.transport.hive.StdUdfWrapper"); | ||
|
||
@Override | ||
public void generateWrappers(WrapperGeneratorContext context) { | ||
TransportUDFMetadata udfMetadata = context.getTransportUdfMetadata(); | ||
for (String topLevelClass : udfMetadata.getTopLevelClasses()) { | ||
generateWrapper(topLevelClass, udfMetadata.getStdUDFImplementations(topLevelClass), | ||
context.getSourcesOutputDir()); | ||
} | ||
} | ||
|
||
private void generateWrapper(String topLevelClass, Collection<String> implementationClasses, File outputDir) { | ||
|
||
ClassName topLevelClassName = ClassName.bestGuess(topLevelClass); | ||
ClassName wrapperClassName = ClassName.get(topLevelClassName.packageName() + "." + HIVE_PACKAGE_SUFFIX, | ||
topLevelClassName.simpleName()); | ||
|
||
/* | ||
Generates -> | ||
@Override | ||
protected Class<? extends TopLevelStdUDF> getTopLevelUdfClass() { | ||
return ${topLevelClass}.class; | ||
} | ||
*/ | ||
MethodSpec getTopLevelUdfClassMethod = MethodSpec.methodBuilder(GET_TOP_LEVEL_UDF_CLASS_METHOD) | ||
.addAnnotation(Override.class) | ||
.returns( | ||
ParameterizedTypeName.get(ClassName.get(Class.class), WildcardTypeName.subtypeOf(TopLevelStdUDF.class))) | ||
.addModifiers(Modifier.PROTECTED) | ||
.addStatement("return $T.class", topLevelClassName) | ||
.build(); | ||
|
||
/* | ||
Generates -> | ||
@Override | ||
protected List<? extends StdUDF> getStdUdfImplementations() { | ||
return ImmutableList.of( | ||
new ${implementationClasses(0)}(), | ||
new ${implementationClasses(1)}(), | ||
. | ||
. | ||
. | ||
); | ||
} | ||
*/ | ||
MethodSpec getStdUdfImplementationsMethod = MethodSpec.methodBuilder(GET_STD_UDF_IMPLEMENTATIONS_METHOD) | ||
.addAnnotation(Override.class) | ||
.returns(ParameterizedTypeName.get(ClassName.get(List.class), WildcardTypeName.subtypeOf(StdUDF.class))) | ||
.addModifiers(Modifier.PROTECTED) | ||
.addStatement("return $T.of($L)", ImmutableList.class, implementationClasses.stream() | ||
.map(clazz -> "new " + clazz + "()") | ||
.collect(Collectors.joining(", "))) | ||
.build(); | ||
|
||
/* | ||
Generates -> | ||
public class ${wrapperClassName} extends StdUdfWrapper { | ||
. | ||
. | ||
. | ||
} | ||
*/ | ||
TypeSpec wrapperClass = TypeSpec.classBuilder(wrapperClassName) | ||
.addModifiers(Modifier.PUBLIC) | ||
.superclass(HIVE_STD_UDF_WRAPPER_CLASS_NAME) | ||
.addMethod(getTopLevelUdfClassMethod) | ||
.addMethod(getStdUdfImplementationsMethod) | ||
.build(); | ||
|
||
JavaFile javaFile = JavaFile.builder(wrapperClassName.packageName(), wrapperClass).build(); | ||
|
||
try { | ||
javaFile.writeTo(outputDir); | ||
} catch (Exception e) { | ||
throw new RuntimeException("Error writing wrapper to file", e); | ||
} | ||
} | ||
} |
Oops, something went wrong.