Skip to content

Commit 7a07ace

Browse files
Kammerlosatran004
andauthored
369 generate pojos for annoation processor from cip57 plutusblueprints (#376)
* #369 added json models and tests for validation * #369 added parsing of CIP57 Blueprints. Currenlty implemented datatypes: List, Constr, bytes, integer, String, boolean ToDo: Map, tuple, unit * #369 add Mapdatatype * #369 added scriptaddress method and alternatives will be set in converter according to used type * #369 fixed test deployment * #369 had to add resources to sourceSets to enable the filer to find the files used in the tests * #369 still excluding guava * #369 added AnyPlutusData datatype. This field is identified through missing datatype description it can be anything. The correctness will be checked by the smartcontract itself. So it can't be distinguished within the blueprint. * chore: #369 Fixed typo * chore: #369 Remove test classes * Fix: Fix camecase class name, package refactoring and target package folder --------- Co-authored-by: Satya <[email protected]>
1 parent 3bd718a commit 7a07ace

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1780
-30
lines changed

annotation-processor/build.gradle

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
11
dependencies {
22
api project(':plutus')
3-
implementation(libs.google.auto.service) {
3+
api project(':address')
4+
5+
implementation(libs.google.auto.service){
46
exclude group: 'com.google.guava', module: 'guava'
57
}
68
api libs.javapoet
9+
api libs.apache.common.text
710

811
testImplementation libs.google.testing.compile
912
testImplementation libs.lombok
1013

1114
testAnnotationProcessor project(':annotation-processor')
1215
}
1316

17+
sourceSets {
18+
json {
19+
resources {
20+
srcDir('src/test/resources/')
21+
}
22+
}
23+
test {
24+
compileClasspath += sourceSets.json.output
25+
}
26+
}
27+
1428
publishing {
1529
publications {
1630
mavenJava(MavenPublication) {

annotation-processor/src/main/java/com/bloxbean/cardano/client/plutus/annotation/processor/ClassDefinitionGenerator.java

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.bloxbean.cardano.client.plutus.annotation.PlutusIgnore;
66
import com.bloxbean.cardano.client.plutus.annotation.processor.exception.NotSupportedException;
77
import com.bloxbean.cardano.client.plutus.annotation.processor.model.*;
8+
import com.bloxbean.cardano.client.plutus.spec.PlutusData;
89
import com.squareup.javapoet.ClassName;
910
import com.squareup.javapoet.ParameterizedTypeName;
1011
import com.squareup.javapoet.TypeName;
@@ -75,6 +76,7 @@ public ClassDefinition getClassDefinition(TypeElement typeElement) {
7576
VariableElement variableElement = (VariableElement) enclosedElement;
7677
String fieldName = variableElement.getSimpleName().toString();
7778
field.setName(fieldName);
79+
field.setAlternative(getAlternative(fieldName));
7880

7981
ExecutableElement getter = findGetter(typeElement, variableElement);
8082
ExecutableElement setter = findSetter(typeElement, variableElement);
@@ -123,6 +125,16 @@ public ClassDefinition getClassDefinition(TypeElement typeElement) {
123125
return classDefinition;
124126
}
125127

128+
private int getAlternative(String fieldName) {
129+
Optional<TypeElement> first = typeElements.stream().filter(typeElement -> typeElement.getSimpleName().toString().toLowerCase().equals(fieldName.toLowerCase())).findFirst();
130+
if(first.isPresent()) {
131+
TypeElement typeElement = first.get();
132+
return typeElement.getAnnotation(Constr.class).alternative();
133+
} else {
134+
return 0;
135+
}
136+
}
137+
126138
private FieldType detectFieldType(TypeName typeName, TypeMirror typeMirror) throws NotSupportedException {
127139
FieldType fieldType = new FieldType();
128140
fieldType.setFqTypeName(typeName.toString());
@@ -153,6 +165,9 @@ private FieldType detectFieldType(TypeName typeName, TypeMirror typeMirror) thro
153165
} else if (typeName.equals(TypeName.BOOLEAN)) {
154166
fieldType.setType(Type.BOOL);
155167
fieldType.setJavaType(JavaType.BOOLEAN);
168+
} else if (typeName.equals(TypeName.get(PlutusData.class))) {
169+
fieldType.setType(Type.PLUTUSDATA);
170+
fieldType.setJavaType(JavaType.PLUTUSDATA);
156171
} else if (typeName instanceof ParameterizedTypeName &&
157172
(((ParameterizedTypeName) typeName).rawType.equals(ClassName.get(List.class))
158173
|| isAssignableToList(typeMirror))) {

annotation-processor/src/main/java/com/bloxbean/cardano/client/plutus/annotation/processor/ConstrAnnotationProcessor.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
8080
JavaFile javaFile = JavaFile.builder(classDefinition.getPackageName(), typeSpec)
8181
.build();
8282

83+
String fullClassName = classDefinition.getPackageName() + "." + classDefinition.getName();
84+
8385
JavaFileObject builderFile = processingEnv.getFiler()
84-
.createSourceFile(classDefinition.getName());
86+
.createSourceFile(fullClassName);
8587
Writer writer = builderFile.openWriter();
8688
javaFile.writeTo(writer);
8789
writer.close();

annotation-processor/src/main/java/com/bloxbean/cardano/client/plutus/annotation/processor/ConverterCodeGenerator.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ private MethodSpec generateToPlutusDataMethod(ClassDefinition classDef) {
178178
.add("\n")
179179
.build();
180180
break;
181+
case PLUTUSDATA:
182+
codeBlock = CodeBlock.builder()
183+
.add("//Field $L\n", field.getName())
184+
.add(nullCheckStatement(field, fieldOrGetterName(field)))
185+
.addStatement("constr.getData().add(obj.$L)", fieldOrGetterName(field))
186+
.add("\n")
187+
.build();
188+
break;
181189
case OPTIONAL:
182190
/*** Sample Optional Code
183191
if (obj.isEmpty())
@@ -196,9 +204,11 @@ private MethodSpec generateToPlutusDataMethod(ClassDefinition classDef) {
196204
case CONSTRUCTOR:
197205
codeBlock = CodeBlock.builder()
198206
.add("//Field $L\n", field.getName())
199-
.add(nullCheckStatement(field, fieldOrGetterName(field)))
200-
.addStatement("constr.getData().add(new $LConverter().toPlutusData(obj.$L))", field.getFieldType().getJavaType().getName(), fieldOrGetterName(field))
201-
.add("\n")
207+
.beginControlFlow("if(obj.$L != null)", fieldOrGetterName(field))
208+
.addStatement("constr.getData().add(new $LConverter().toPlutusData(obj.$L))", field.getFieldType().getJavaType().getName(), fieldOrGetterName(field))
209+
.addStatement("// Setting the alternative to the childs alternative to use this constructor")
210+
.addStatement("constr = $T.builder().alternative($L).data(constr.getData()).build()", ConstrPlutusData.class, field.getAlternative())
211+
.endControlFlow()
202212
.build();
203213
break;
204214
case BOOL:
@@ -553,6 +563,12 @@ private CodeBlock getDeserializeCodeBlockForField(Field field) {
553563
.add(generateMapDeserializeCode(field.getFieldType(), field.getName(), field.getName() + "Map", "entry"))
554564
.build();
555565
break;
566+
case PLUTUSDATA:
567+
codeBlock = CodeBlock.builder()
568+
.add("//Field $L\n", field.getName())
569+
.add("var $L = data.getPlutusDataList().get($L);\n", field.getName(), field.getIndex())
570+
.build();
571+
break;
556572
case OPTIONAL:
557573
// var optConstr = (ConstrPlutusData)data.getPlutusDataList().get(2);
558574
// if (optConstr.getAlternative() == 1) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package com.bloxbean.cardano.client.plutus.annotation.processor.blueprint;
2+
3+
import com.bloxbean.cardano.client.plutus.annotation.Blueprint;
4+
import com.bloxbean.cardano.client.plutus.blueprint.PlutusBlueprintLoader;
5+
import com.bloxbean.cardano.client.plutus.blueprint.model.*;
6+
import com.google.auto.service.AutoService;
7+
import lombok.extern.slf4j.Slf4j;
8+
9+
import javax.annotation.processing.*;
10+
import javax.lang.model.SourceVersion;
11+
import javax.lang.model.element.Element;
12+
import javax.lang.model.element.TypeElement;
13+
import javax.tools.Diagnostic;
14+
import javax.tools.FileObject;
15+
import javax.tools.StandardLocation;
16+
import java.io.File;
17+
import java.util.*;
18+
19+
@AutoService(Processor.class)
20+
@Slf4j
21+
public class BlueprintAnnotationProcessor extends AbstractProcessor {
22+
23+
private Messager messager;
24+
private List<TypeElement> typeElements = new ArrayList<>();
25+
private ValidatorProcessor validatorProcessor;
26+
27+
@Override
28+
public synchronized void init(ProcessingEnvironment processingEnv) {
29+
super.init(processingEnv);
30+
messager = processingEnv.getMessager();
31+
}
32+
33+
@Override
34+
public Set<String> getSupportedAnnotationTypes() {
35+
Set<String> annotataions = new LinkedHashSet<String>();
36+
annotataions.add(Blueprint.class.getCanonicalName());
37+
return annotataions;
38+
}
39+
40+
@Override
41+
public SourceVersion getSupportedSourceVersion() {
42+
return SourceVersion.latestSupported();
43+
}
44+
45+
@Override
46+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
47+
log.debug("Processing Blueprint annotation");
48+
49+
typeElements = getTypeElementsWithAnnotations(annotations, roundEnv);
50+
51+
for(TypeElement typeElement : typeElements) {
52+
Blueprint annotation = typeElement.getAnnotation(Blueprint.class);
53+
if (annotation == null) {
54+
log.error("Blueprint annotation not found for class {}", typeElement.getSimpleName());
55+
return false;
56+
} else {
57+
validatorProcessor = new ValidatorProcessor(annotation, processingEnv);
58+
}
59+
File blueprintFile = getFileFromAnnotation(annotation);
60+
if (blueprintFile == null || !blueprintFile.exists()) {
61+
log.error("Blueprint file {} not found", annotation.fileInResources());
62+
return false;
63+
}
64+
PlutusContractBlueprint plutusContractBlueprint;
65+
try {
66+
plutusContractBlueprint = PlutusBlueprintLoader.loadBlueprint(blueprintFile);
67+
} catch (Exception e) {
68+
log.error("Error processing blueprint file {}", blueprintFile.getAbsolutePath(), e);
69+
return false;
70+
}
71+
for (Validator validator : plutusContractBlueprint.getValidators()) {
72+
validatorProcessor.processValidator(validator);
73+
}
74+
}
75+
return true;
76+
}
77+
78+
private List<TypeElement> getTypeElementsWithAnnotations(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
79+
List<TypeElement> elementsList = new ArrayList<>();
80+
for (TypeElement annotation : annotations) {
81+
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);
82+
for (Element element : elements) {
83+
if (element instanceof TypeElement) {
84+
TypeElement typeElement = (TypeElement) element;
85+
elementsList.add(typeElement);
86+
87+
}
88+
}
89+
}
90+
return elementsList;
91+
}
92+
93+
private File getFileFromAnnotation(Blueprint annotation) {
94+
File blueprintFile = null;
95+
if(!annotation.file().isEmpty())
96+
blueprintFile = new File(annotation.file());
97+
if(!annotation.fileInResources().isEmpty())
98+
blueprintFile = getFileFromRessourcers(annotation.fileInResources());
99+
if(blueprintFile == null || !blueprintFile.exists()) {
100+
log.error("Blueprint file {} not found", annotation.file());
101+
return null;
102+
}
103+
return blueprintFile;
104+
}
105+
106+
public File getFileFromRessourcers(String s) {
107+
try {
108+
FileObject resource = processingEnv.getFiler().getResource(StandardLocation.CLASS_PATH, "", s);
109+
return new File(resource.toUri());
110+
} catch (Exception e) {
111+
return null;
112+
}
113+
}
114+
115+
116+
private void error(Element e, String msg, Object... args) {
117+
messager.printMessage(
118+
Diagnostic.Kind.ERROR,
119+
String.format(msg, args),
120+
e);
121+
}
122+
}

0 commit comments

Comments
 (0)