diff --git a/common/client/pom.xml b/common/client/pom.xml
index c67339949..d8e3bafd3 100644
--- a/common/client/pom.xml
+++ b/common/client/pom.xml
@@ -8,10 +8,38 @@
zingg-common-client
jar
+
+ zingg
+ zingg-common-py
+ ${zingg.version}
+
javax.mail
mail
1.4
+
+
+
+
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.source}
+ ${maven.compiler.source}
+ true
+
+
+
+ zingg.common.py.processors.PythonClassProcessor
+
+
+ zingg.common.py.processors.PythonMethodProcessor
+
+
+
+
+
+
diff --git a/common/client/src/main/java/zingg/common/client/pipe/Pipe.java b/common/client/src/main/java/zingg/common/client/pipe/Pipe.java
index 7a4f8ff88..99e80c9cc 100644
--- a/common/client/src/main/java/zingg/common/client/pipe/Pipe.java
+++ b/common/client/src/main/java/zingg/common/client/pipe/Pipe.java
@@ -11,13 +11,16 @@
import zingg.common.client.ZFrame;
import zingg.common.client.util.StringRedactor;
+import zingg.common.py.annotations.PythonClass;
+import zingg.common.py.annotations.PythonMethod;
+
/**Actual pipe def in the args. One pipe can be used at multiple places with different tables, locations, queries etc
*
* @author sgoyal
*
*/
-
+@PythonClass
@JsonInclude(Include.NON_NULL)
public class Pipe implements Serializable{ // St:StructType, Sv:SaveMode
@@ -57,12 +60,12 @@ public void setSchema(String schema) {
this.schema = schema;
}
-
+ @PythonMethod
public String getName() {
return name;
}
-
+ @PythonMethod
@JsonValue
public void setName(String name) {
this.name = name;
diff --git a/common/pom.xml b/common/pom.xml
index 23dd19064..c50c2b037 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -12,5 +12,6 @@
infra
core
client
+ py
diff --git a/common/py/pom.xml b/common/py/pom.xml
new file mode 100644
index 000000000..bde63932b
--- /dev/null
+++ b/common/py/pom.xml
@@ -0,0 +1,10 @@
+
+ 4.0.0
+
+ zingg
+ zingg-common
+ ${zingg.version}
+
+ zingg-common-py
+
\ No newline at end of file
diff --git a/common/py/src/main/java/zingg/common/py/annotations/PythonClass.java b/common/py/src/main/java/zingg/common/py/annotations/PythonClass.java
new file mode 100644
index 000000000..0d3bf21a5
--- /dev/null
+++ b/common/py/src/main/java/zingg/common/py/annotations/PythonClass.java
@@ -0,0 +1,9 @@
+package zingg.common.py.annotations;
+
+import javax.annotation.processing.*;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target({ElementType.TYPE})
+public @interface PythonClass {}
\ No newline at end of file
diff --git a/common/py/src/main/java/zingg/common/py/annotations/PythonMethod.java b/common/py/src/main/java/zingg/common/py/annotations/PythonMethod.java
new file mode 100644
index 000000000..f59a9c038
--- /dev/null
+++ b/common/py/src/main/java/zingg/common/py/annotations/PythonMethod.java
@@ -0,0 +1,9 @@
+package zingg.common.py.annotations;
+
+import javax.annotation.processing.*;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Target({ElementType.METHOD})
+public @interface PythonMethod {}
\ No newline at end of file
diff --git a/common/py/src/main/java/zingg/common/py/processors/PythonClassProcessor.java b/common/py/src/main/java/zingg/common/py/processors/PythonClassProcessor.java
new file mode 100644
index 000000000..1090628a2
--- /dev/null
+++ b/common/py/src/main/java/zingg/common/py/processors/PythonClassProcessor.java
@@ -0,0 +1,91 @@
+package zingg.common.py.processors;
+
+import java.util.List;
+import javax.annotation.processing.*;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeKind;
+import java.util.Set;
+import javax.lang.model.element.*;
+import javax.lang.model.util.ElementFilter;
+
+import zingg.common.py.annotations.*;
+
+@SupportedAnnotationTypes("zingg.common.py.annotations.PythonClass")
+public class PythonClassProcessor extends AbstractProcessor {
+
+ private boolean importsAndDeclarationsGenerated = false;
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+ // Imports and global declarations
+ if (!importsAndDeclarationsGenerated) {
+ generateImportsAndDeclarations();
+ importsAndDeclarationsGenerated = true;
+ }
+
+
+ // process Services annotation
+ for (Element element : roundEnv.getElementsAnnotatedWith(PythonClass.class)) {
+ if (element.getKind() == ElementKind.CLASS) {
+ TypeElement classElement = (TypeElement) element;
+ PackageElement packageElement =
+ (PackageElement) classElement.getEnclosingElement();
+ System.out.println("class " + element.getSimpleName() + ":");
+
+ // __init__ method
+ System.out.println(" def __init__(self" +
+ generateConstructorParameters(classElement) + "):");
+ if (element.getSimpleName().contentEquals("EPipe")) {
+ generateClassInitializationCode(classElement);
+ }
+ for (VariableElement field : ElementFilter.fieldsIn(classElement.getEnclosedElements())) {
+ if (!field.getSimpleName().contentEquals("serialVersionUID")) {
+ generateFieldInitializationCode(field);
+ }
+ }
+ }
+ System.out.println();
+ // rest of generated class contents
+ }
+
+ return false;
+
+ }
+
+ private void generateImportsAndDeclarations() {
+ System.out.println("import logging");
+ System.out.println("from zingg.client import *");
+ System.out.println("LOG = logging.getLogger(\"zingg.pipes\")");
+ System.out.println();
+ System.out.println("JPipe = getJVM().zingg.spark.client.pipe.SparkPipe");
+ System.out.println("FilePipe = getJVM().zingg.common.client.pipe.FilePipe");
+ System.out.println("JStructType = getJVM().org.apache.spark.sql.types.StructType");
+ System.out.println();
+ }
+
+ private void generateClassInitializationCode(TypeElement classElement) {
+ System.out.println(" self.EPipe = getJVM().zingg.spark.client.pipe.SparkPipe()");
+ }
+
+ // private void generateFieldInitializationCode(VariableElement field, ExecutableElement methodElement, TypeElement classElement) {
+ private void generateFieldInitializationCode(VariableElement field) {
+ System.out.println(" self.EPipe." + field.getSimpleName() + " = " + field.getSimpleName());
+ // String fieldName = field.getSimpleName().toString();
+ // String methodName = methodElement.getSimpleName().toString();
+ // System.out.println(" self." + fieldName + " = " + "getJVM()." +
+ // classElement.getQualifiedName().toString() + "." + methodName + "(" + fieldName + ")");
+ }
+
+ private String generateConstructorParameters(TypeElement classElement) {
+ StringBuilder parameters = new StringBuilder();
+ for (VariableElement field : ElementFilter.fieldsIn(classElement.getEnclosedElements())) {
+ if (!field.getSimpleName().contentEquals("serialVersionUID")) {
+ parameters.append(", ");
+ parameters.append(field.getSimpleName());
+ }
+ }
+ return parameters.toString();
+ }
+
+}
diff --git a/common/py/src/main/java/zingg/common/py/processors/PythonMethodProcessor.java b/common/py/src/main/java/zingg/common/py/processors/PythonMethodProcessor.java
new file mode 100644
index 000000000..fe0b02747
--- /dev/null
+++ b/common/py/src/main/java/zingg/common/py/processors/PythonMethodProcessor.java
@@ -0,0 +1,76 @@
+package zingg.common.py.processors;
+
+import java.util.List;
+import javax.annotation.processing.*;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeKind;
+import java.util.Set;
+import javax.lang.model.element.*;
+import javax.lang.model.util.ElementFilter;
+
+import zingg.common.py.annotations.*;
+
+@SupportedAnnotationTypes("zingg.common.py.annotations.PythonMethod")
+public class PythonMethodProcessor extends AbstractProcessor {
+
+ private boolean importsAndDeclarationsGenerated = false;
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+ // process Services annotation
+ for (Element element : roundEnv.getElementsAnnotatedWith(PythonMethod.class)) {
+
+ if (element.getKind() == ElementKind.METHOD) {
+ ExecutableElement methodElement = (ExecutableElement) element;
+ System.out.println(" def " + methodElement.getSimpleName() + "(self" +
+ generateMethodSignature(methodElement) + "):\n " + generateMethodReturn(methodElement));
+ generateFieldAssignment(methodElement);
+ }
+ System.out.println();
+
+ // rest of generated class contents
+ }
+ return false;
+ }
+
+ private String generateMethodSignature(ExecutableElement methodElement) {
+ StringBuilder signature = new StringBuilder();
+ signature.append(generateMethodParameters(methodElement));
+ return signature.toString();
+ }
+
+ private String generateMethodParameters(ExecutableElement methodElement) {
+ StringBuilder parameters = new StringBuilder();
+ for (VariableElement parameter : methodElement.getParameters()) {
+ parameters.append(", ");
+ parameters.append(parameter.getSimpleName());
+ }
+ return parameters.toString();
+ }
+
+ private String generateMethodReturn(ExecutableElement methodElement) {
+ TypeMirror returnType = methodElement.getReturnType();
+ if (returnType.getKind() == TypeKind.VOID) {
+ return "";
+ } else {
+ String returnTypeString = resolveType(returnType);
+ String variableName = methodElement.getSimpleName().toString();
+ return "return " + variableName;
+ }
+ }
+
+ private String resolveType(TypeMirror typeMirror) {
+ return typeMirror.toString();
+ }
+
+ private void generateFieldAssignment(ExecutableElement methodElement) {
+ List extends VariableElement> parameters = methodElement.getParameters();
+ if (!parameters.isEmpty()) {
+ VariableElement parameter = parameters.get(0);
+ String variableName = parameter.getSimpleName().toString();
+ System.out.println(" self." + variableName + " = " + variableName);
+ }
+}
+
+}