blob: 8eb39eddc78b39d68471bae5cbd28983d388e1c3 [file] [log] [blame]
/*
* Copyright (c) Robert Bosch GmbH. All rights reserved.
*/
package org.eclipse.blockchain.core;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.DynamicBytes;
import org.web3j.abi.datatypes.StaticArray;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.generated.AbiTypes;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
/**
* @author ADG5COB
*/
public class SolidityToJavaDataTypeResolver {
private final Pattern pattern = Pattern.compile("(\\w+)(?:\\[(.*?)\\])(?:\\[(.*?)\\])?");
private static SolidityToJavaDataTypeResolver instance;
private SolidityToJavaDataTypeResolver() {}
/**
* @return - Instance
*/
public static SolidityToJavaDataTypeResolver getInstance() {
if (instance == null) {
instance = new SolidityToJavaDataTypeResolver();
}
return instance;
}
/**
* This method returns the corresponding javatype for the passed solidity type
*
* @param solidityType - The solidity data type
* @param ioABI - The solidity ABI
* @return - The java type string
*/
public String getJavaType(final String solidityType, final IOABI ioABI) {
Matcher matcher = this.pattern.matcher(solidityType);
TypeName ty;
if (matcher.find()) {// Parameterized type
Class<?> baseType = AbiTypes.getType(matcher.group(1));
String dimensionOne = matcher.group(2);
String dimensionTwo = matcher.group(3);
if ("".equals(dimensionOne)) {
ty = ParameterizedTypeName.get(DynamicArray.class, baseType);
}
else {
Class<?> rawType = getRawType(dimensionOne);
ty = ParameterizedTypeName.get(StaticArray.class, rawType);
}
if (dimensionTwo != null) {
if ("".equals(dimensionTwo)) {
ty = ParameterizedTypeName.get(ClassName.get(DynamicArray.class), ty);
}
else {
Class<?> rawType = getRawType(dimensionTwo);
ty = ParameterizedTypeName.get(ClassName.get(rawType), ty);
}
}
ioABI.setIsArray(true);
}
else {// Non-Parameterized type
Class<?> baseType = AbiTypes.getType(solidityType);
ty = ClassName.get(baseType);
ioABI.setIsArray(false);
}
return getJavaNativeType(ty).toString();
}
private Class<?> getRawType(final String type) {
try {
return Class.forName("org.web3j.abi.datatypes.generated.StaticArray" + type);
}
catch (ClassNotFoundException e) {
// Unfortunately we can't encode it's length as a type if it's > 32.
return StaticArray.class;
}
}
private TypeName getJavaNativeType(final TypeName type) {
if (type instanceof ParameterizedTypeName) {
return getJavaNativeType((ParameterizedTypeName) type);
}
String name = ((ClassName) type).simpleName();
if (name.equals(Address.class.getSimpleName())) {
return TypeName.get(String.class);
}
else if (name.startsWith("Uint")) {
return TypeName.get(BigInteger.class);
}
else if (name.startsWith("Int")) {
return TypeName.get(BigInteger.class);
}
else if (name.equals(Utf8String.class.getSimpleName())) {
return TypeName.get(String.class);
}
else if (name.startsWith("Bytes")) {
return TypeName.get(byte[].class);
}
else if (name.equals(DynamicBytes.class.getSimpleName())) {
return TypeName.get(byte[].class);
}
else if (name.equals(Bool.class.getSimpleName())) {
return TypeName.get(Boolean.class);
}
else {
// Throw error for unsupported type
return null;
}
}
private TypeName getJavaNativeType(final ParameterizedTypeName parameterizedTypeName) {
List<TypeName> typeNames = parameterizedTypeName.typeArguments;
List<TypeName> nativeTypeNames = new ArrayList<>(typeNames.size());
for (TypeName enclosedTypeName : typeNames) {
nativeTypeNames.add(getJavaNativeType(enclosedTypeName));
}
return ParameterizedTypeName.get(ClassName.get(List.class),
nativeTypeNames.toArray(new TypeName[nativeTypeNames.size()]));
}
}