/* | |
* 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()])); | |
} | |
} |