Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

369 generate pojos for annoation processor from cip57 plutusblueprints #376

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion annotation-processor/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
dependencies {
api project(':plutus')
implementation(libs.google.auto.service) {
api project(':address')

implementation(libs.google.auto.service){
exclude group: 'com.google.guava', module: 'guava'
}
api libs.javapoet
api libs.apache.common.text

testImplementation libs.google.testing.compile
testImplementation libs.lombok

testAnnotationProcessor project(':annotation-processor')
}

sourceSets {
json {
resources {
srcDir('src/test/resources/')
}
}
test {
compileClasspath += sourceSets.json.output
}
}

publishing {
publications {
mavenJava(MavenPublication) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.bloxbean.cardano.client.plutus.annotation.PlutusIgnore;
import com.bloxbean.cardano.client.plutus.annotation.processor.exception.NotSupportedException;
import com.bloxbean.cardano.client.plutus.annotation.processor.model.*;
import com.bloxbean.cardano.client.plutus.spec.PlutusData;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
Expand Down Expand Up @@ -75,6 +76,7 @@ public ClassDefinition getClassDefinition(TypeElement typeElement) {
VariableElement variableElement = (VariableElement) enclosedElement;
String fieldName = variableElement.getSimpleName().toString();
field.setName(fieldName);
field.setAlternative(getAlternative(fieldName));

ExecutableElement getter = findGetter(typeElement, variableElement);
ExecutableElement setter = findSetter(typeElement, variableElement);
Expand Down Expand Up @@ -123,6 +125,16 @@ public ClassDefinition getClassDefinition(TypeElement typeElement) {
return classDefinition;
}

private int getAlternative(String fieldName) {
Optional<TypeElement> first = typeElements.stream().filter(typeElement -> typeElement.getSimpleName().toString().toLowerCase().equals(fieldName.toLowerCase())).findFirst();
if(first.isPresent()) {
TypeElement typeElement = first.get();
return typeElement.getAnnotation(Constr.class).alternative();
} else {
return 0;
}
}

private FieldType detectFieldType(TypeName typeName, TypeMirror typeMirror) throws NotSupportedException {
FieldType fieldType = new FieldType();
fieldType.setFqTypeName(typeName.toString());
Expand Down Expand Up @@ -153,6 +165,9 @@ private FieldType detectFieldType(TypeName typeName, TypeMirror typeMirror) thro
} else if (typeName.equals(TypeName.BOOLEAN)) {
fieldType.setType(Type.BOOL);
fieldType.setJavaType(JavaType.BOOLEAN);
} else if (typeName.equals(TypeName.get(PlutusData.class))) {
fieldType.setType(Type.PLUTUSDATA);
fieldType.setJavaType(JavaType.PLUTUSDATA);
} else if (typeName instanceof ParameterizedTypeName &&
(((ParameterizedTypeName) typeName).rawType.equals(ClassName.get(List.class))
|| isAssignableToList(typeMirror))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
JavaFile javaFile = JavaFile.builder(classDefinition.getPackageName(), typeSpec)
.build();

String fullClassName = classDefinition.getPackageName() + "." + classDefinition.getName();

JavaFileObject builderFile = processingEnv.getFiler()
.createSourceFile(classDefinition.getName());
.createSourceFile(fullClassName);
Writer writer = builderFile.openWriter();
javaFile.writeTo(writer);
writer.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ private MethodSpec generateToPlutusDataMethod(ClassDefinition classDef) {
.add("\n")
.build();
break;
case PLUTUSDATA:
codeBlock = CodeBlock.builder()
.add("//Field $L\n", field.getName())
.add(nullCheckStatement(field, fieldOrGetterName(field)))
.addStatement("constr.getData().add(obj.$L)", fieldOrGetterName(field))
.add("\n")
.build();
break;
case OPTIONAL:
/*** Sample Optional Code
if (obj.isEmpty())
Expand All @@ -196,9 +204,11 @@ private MethodSpec generateToPlutusDataMethod(ClassDefinition classDef) {
case CONSTRUCTOR:
codeBlock = CodeBlock.builder()
.add("//Field $L\n", field.getName())
.add(nullCheckStatement(field, fieldOrGetterName(field)))
.addStatement("constr.getData().add(new $LConverter().toPlutusData(obj.$L))", field.getFieldType().getJavaType().getName(), fieldOrGetterName(field))
.add("\n")
.beginControlFlow("if(obj.$L != null)", fieldOrGetterName(field))
.addStatement("constr.getData().add(new $LConverter().toPlutusData(obj.$L))", field.getFieldType().getJavaType().getName(), fieldOrGetterName(field))
.addStatement("// Setting the alternative to the childs alternative to use this constructor")
.addStatement("constr = $T.builder().alternative($L).data(constr.getData()).build()", ConstrPlutusData.class, field.getAlternative())
.endControlFlow()
.build();
break;
case BOOL:
Expand Down Expand Up @@ -553,6 +563,12 @@ private CodeBlock getDeserializeCodeBlockForField(Field field) {
.add(generateMapDeserializeCode(field.getFieldType(), field.getName(), field.getName() + "Map", "entry"))
.build();
break;
case PLUTUSDATA:
codeBlock = CodeBlock.builder()
.add("//Field $L\n", field.getName())
.add("var $L = data.getPlutusDataList().get($L);\n", field.getName(), field.getIndex())
.build();
break;
case OPTIONAL:
// var optConstr = (ConstrPlutusData)data.getPlutusDataList().get(2);
// if (optConstr.getAlternative() == 1) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.bloxbean.cardano.client.plutus.annotation.processor.blueprint;

import com.bloxbean.cardano.client.plutus.annotation.Blueprint;
import com.bloxbean.cardano.client.plutus.blueprint.PlutusBlueprintLoader;
import com.bloxbean.cardano.client.plutus.blueprint.model.*;
import com.google.auto.service.AutoService;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.File;
import java.util.*;

@AutoService(Processor.class)
@Slf4j
public class BlueprintAnnotationProcessor extends AbstractProcessor {

private Messager messager;
private List<TypeElement> typeElements = new ArrayList<>();
private ValidatorProcessor validatorProcessor;

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
messager = processingEnv.getMessager();
}

@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> annotataions = new LinkedHashSet<String>();
annotataions.add(Blueprint.class.getCanonicalName());
return annotataions;
}

@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
log.debug("Processing Blueprint annotation");

typeElements = getTypeElementsWithAnnotations(annotations, roundEnv);

for(TypeElement typeElement : typeElements) {
Blueprint annotation = typeElement.getAnnotation(Blueprint.class);
if (annotation == null) {
log.error("Blueprint annotation not found for class {}", typeElement.getSimpleName());
return false;
} else {
validatorProcessor = new ValidatorProcessor(annotation, processingEnv);
}
File blueprintFile = getFileFromAnnotation(annotation);
if (blueprintFile == null || !blueprintFile.exists()) {
log.error("Blueprint file {} not found", annotation.fileInResources());
return false;
}
PlutusContractBlueprint plutusContractBlueprint;
try {
plutusContractBlueprint = PlutusBlueprintLoader.loadBlueprint(blueprintFile);
} catch (Exception e) {
log.error("Error processing blueprint file {}", blueprintFile.getAbsolutePath(), e);
return false;
}
for (Validator validator : plutusContractBlueprint.getValidators()) {
validatorProcessor.processValidator(validator);
}
}
return true;
}

private List<TypeElement> getTypeElementsWithAnnotations(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
List<TypeElement> elementsList = new ArrayList<>();
for (TypeElement annotation : annotations) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);
for (Element element : elements) {
if (element instanceof TypeElement) {
TypeElement typeElement = (TypeElement) element;
elementsList.add(typeElement);

}
}
}
return elementsList;
}

private File getFileFromAnnotation(Blueprint annotation) {
File blueprintFile = null;
if(!annotation.file().isEmpty())
blueprintFile = new File(annotation.file());
if(!annotation.fileInResources().isEmpty())
blueprintFile = getFileFromRessourcers(annotation.fileInResources());
if(blueprintFile == null || !blueprintFile.exists()) {
log.error("Blueprint file {} not found", annotation.file());
return null;
}
return blueprintFile;
}

public File getFileFromRessourcers(String s) {
try {
FileObject resource = processingEnv.getFiler().getResource(StandardLocation.CLASS_PATH, "", s);
return new File(resource.toUri());
} catch (Exception e) {
return null;
}
}


private void error(Element e, String msg, Object... args) {
messager.printMessage(
Diagnostic.Kind.ERROR,
String.format(msg, args),
e);
}
}
Loading
Loading