blob: c661d1a8868c1f2b4085be550fb3a58243d9dea0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 RBEI and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v. 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Adhith Gopal - Initial API and Implementation
*******************************************************************************/
package org.eclipse.blockchain.core;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.blockchain.core.model.IOABI;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.primitive.Char;
import org.web3j.abi.datatypes.primitive.Int;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
/**
* This class is used to create java data types for each solidity data type. The
* generated java data type must match with web3j's generated solidity type
* because we are dependant on web3j for blockchain interactions
*/
public class SolidityToJavaDataTypeResolver {
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. This method is equivalent to buildTypeName(...) in
* SolidityFunctionWrapper
*
* @param solidityType
* - The solidity data type
* @param ioABI
* - The solidity ABI
* @throws ClassNotFoundException
* - Thrown by TypeReference Class
*/
@SuppressWarnings("rawtypes")
public void assignJavaType(final String solidityType, final IOABI ioABI)
throws ClassNotFoundException {
TypeReference typeReference = TypeReference
.makeTypeReference(solidityType, false, false);
TypeName ty = TypeName.get(typeReference.getType());
if (ty instanceof ParameterizedTypeName) {// This is important
ioABI.setIsArray(true);
} else {
ioABI.setIsArray(false);
}
String javaString = getJavaNativeType(ty, ioABI).toString();
if (ioABI.getIsArray()) {
ioABI.setJavaType(List.class);
} else {
ioABI.setJavaType(ioABI.getCastType());
}
ioABI.setJavaTypeString(javaString);
}
/**
* This is equivalent to getNativeType(TypeName) in SolidityFunctionWrapper
*
* @param type
* @return
*/
private TypeName getJavaNativeType(final TypeName type, final IOABI ioABI) {// NOSONAR
if (type instanceof ParameterizedTypeName) {
ioABI.setDimensionDepth(ioABI.getDimensionDepth() + 1);
return getJavaNativeType((ParameterizedTypeName) type, ioABI);
}
String name = ((ClassName) type).simpleName();
if ((name.equals(Address.class.getSimpleName()))
|| (name.equals(Utf8String.class.getSimpleName()))) {
ioABI.setCastType(String.class);
return TypeName.get(String.class);
} else if (name.startsWith("Uint") || name.startsWith("Int")) {
ioABI.setCastType(BigInteger.class);
return TypeName.get(BigInteger.class);
} else if (name.startsWith("Bytes") || name.equals("DynamicBytes")) {
ioABI.setCastType(byte[].class);
return TypeName.get(byte[].class);
} else if (name.startsWith("Bool")) {
ioABI.setCastType(Boolean.class);
return TypeName.get(java.lang.Boolean.class);
} else if (name.equals(Byte.class.getSimpleName())) {
ioABI.setCastType(Byte.class);
return TypeName.get(java.lang.Byte.class);
} else if (name.equals(Char.class.getSimpleName())) {
ioABI.setCastType(Character.class);
return TypeName.get(Character.class);
} else if (name.equals(Double.class.getSimpleName())) {
ioABI.setCastType(Double.class);
return TypeName.get(java.lang.Double.class);
} else if (name.equals(Float.class.getSimpleName())) {
ioABI.setCastType(Float.class);
return TypeName.get(java.lang.Float.class);
} else if (name.equals(Int.class.getSimpleName())) {
ioABI.setCastType(Integer.class);
return TypeName.get(Integer.class);
} else if (name.equals(Long.class.getSimpleName())) {
ioABI.setCastType(Long.class);
return TypeName.get(java.lang.Long.class);
} else if (name.equals(Short.class.getSimpleName())) {
ioABI.setCastType(Short.class);
return TypeName.get(java.lang.Short.class);
} else {
throw new UnsupportedOperationException("Unsupported type: " + type
+ ", no native type mapping exists.");
}
}
/**
* This is equivalent to getNativeType(ParameterizedTypeName) in
* SolidityFunctionWrapper
*
* @param parameterizedTypeName
* @return
*/
private TypeName getJavaNativeType(
final ParameterizedTypeName parameterizedTypeName,
final IOABI ioABI) {
List<TypeName> typeNames = parameterizedTypeName.typeArguments;
List<TypeName> nativeTypeNames = new ArrayList<>(typeNames.size());
for (TypeName enclosedTypeName : typeNames) {
nativeTypeNames.add(getJavaNativeType(enclosedTypeName, ioABI));
}
return ParameterizedTypeName.get(ClassName.get(List.class),
nativeTypeNames.toArray(new TypeName[nativeTypeNames.size()]));
}
}