Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.fisco.bcos.sdk.abi.wrapper.ABIObject Maven / Gradle / Ivy
package org.fisco.bcos.sdk.abi.wrapper;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.fisco.bcos.sdk.abi.TypeDecoder;
import org.fisco.bcos.sdk.abi.TypeEncoder;
import org.fisco.bcos.sdk.abi.datatypes.Address;
import org.fisco.bcos.sdk.abi.datatypes.Bool;
import org.fisco.bcos.sdk.abi.datatypes.Bytes;
import org.fisco.bcos.sdk.abi.datatypes.DynamicBytes;
import org.fisco.bcos.sdk.abi.datatypes.NumericType;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32;
import org.fisco.bcos.sdk.abi.datatypes.generated.Int256;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ABIObject {
private static final Logger logger = LoggerFactory.getLogger(ABIObject.class);
public enum ObjectType {
VALUE, // uint, int, bool, address, bytes, bytes, string
STRUCT, // tuple
LIST // T[], T[M]
}
public enum ValueType {
BOOL, // bool
UINT, // uint
INT, // int
BYTES, // byteN
ADDRESS, // address
STRING, // string
DBYTES, // bytes
FIXED, // fixedx
UFIXED, // ufixedx
}
public enum ListType {
DYNAMIC, // T[]
FIXED, // T[M]
}
private String name; // field name
private ObjectType type; // for value
private ValueType valueType;
private NumericType numericValue;
private Bytes bytesValue;
private Address addressValue;
private Bool boolValue;
private DynamicBytes dynamicBytesValue;
private Utf8String stringValue;
private ListType listType;
private List listValues; // for list
private int listLength; // for list
private ABIObject listValueType; // for list
private List structFields; // for struct
public ABIObject(ObjectType type) {
this.type = type;
switch (type) {
case VALUE:
{
break;
}
case STRUCT:
{
structFields = new LinkedList();
break;
}
case LIST:
{
listValues = new LinkedList();
break;
}
}
}
public ABIObject(ValueType valueType) {
this.type = ObjectType.VALUE;
this.valueType = valueType;
}
public ABIObject(ListType listType) {
this.type = ObjectType.LIST;
this.listType = listType;
this.listValues = new LinkedList();
}
public ABIObject(Uint256 uintValue) {
this(ValueType.UINT);
this.numericValue = uintValue;
}
public ABIObject(Int256 intValue) {
this(ValueType.INT);
this.numericValue = intValue;
}
public ABIObject(Address addressValue) {
this(ValueType.ADDRESS);
this.addressValue = addressValue;
}
public ABIObject(Bool boolValue) {
this(ValueType.BOOL);
this.boolValue = boolValue;
}
public ABIObject(Utf8String stringValue) {
this(ValueType.STRING);
this.stringValue = stringValue;
}
public ABIObject(DynamicBytes dynamicBytesValue) {
this(ValueType.DBYTES);
this.dynamicBytesValue = dynamicBytesValue;
}
public ABIObject(Bytes bytesValue) {
this(ValueType.BYTES);
this.bytesValue = bytesValue;
}
public ABIObject newObjectWithoutValue() {
ABIObject abiObject = new ABIObject(this.type);
// value
abiObject.setValueType(this.getValueType());
abiObject.setName(this.getName());
// list
abiObject.setListType(this.getListType());
abiObject.setListLength(this.getListLength());
if (this.getListValueType() != null) {
abiObject.setListValueType(this.getListValueType().newObjectWithoutValue());
}
if (this.listValues != null) {
for (ABIObject obj : this.listValues) {
abiObject.listValues.add(obj.newObjectWithoutValue());
}
}
// tuple
if (this.structFields != null) {
for (ABIObject obj : this.structFields) {
abiObject.structFields.add(obj.newObjectWithoutValue());
}
}
return abiObject;
}
// clone itself
public ABIObject newObject() {
ABIObject abiObject = new ABIObject(this.type);
// value
abiObject.setValueType(this.getValueType());
abiObject.setName(this.getName());
if (this.getNumericValue() != null) {
abiObject.setNumericValue(
new NumericType(
this.getNumericValue().getTypeAsString(),
this.getNumericValue().getValue()) {
@Override
public boolean dynamicType() {
return false;
}
@Override
public int offset() {
return 1;
}
});
}
if (this.getBoolValue() != null) {
abiObject.setBoolValue(new Bool(this.getBoolValue().getValue()));
}
if (this.getStringValue() != null) {
abiObject.setStringValue(new Utf8String(this.getStringValue().getValue()));
}
if (this.getDynamicBytesValue() != null) {
abiObject.setDynamicBytesValue(
new DynamicBytes(this.getDynamicBytesValue().getValue()));
}
if (this.getAddressValue() != null) {
abiObject.setAddressValue(new Address(this.getAddressValue().toUint160()));
}
if (this.getBytesValue() != null) {
abiObject.setBytesValue(
new Bytes(
this.getBytesValue().getValue().length,
this.getBytesValue().getValue()));
}
// list
abiObject.setListType(this.getListType());
abiObject.setListLength(this.getListLength());
if (this.getListValueType() != null) {
abiObject.setListValueType(this.getListValueType().newObject());
}
if (this.listValues != null) {
for (ABIObject obj : this.listValues) {
abiObject.listValues.add(obj.newObject());
}
}
// tuple
if (this.structFields != null) {
for (ABIObject obj : this.structFields) {
abiObject.structFields.add(obj.newObject());
}
}
return abiObject;
}
/**
* Checks to see if the current type is dynamic
*
* @return true/false
*/
public boolean isDynamic() {
switch (type) {
case VALUE:
{
switch (valueType) {
case DBYTES: // bytes
case STRING: // string
return true;
default:
return false;
}
// break;
}
case LIST:
{
switch (listType) {
case FIXED: // T[M]
{
return listValueType.isDynamic();
}
case DYNAMIC: // T[]
{
return true;
}
}
break;
}
case STRUCT:
{
for (ABIObject abiObject : structFields) {
if (abiObject.isDynamic()) {
return true;
}
}
return false;
}
}
return false;
}
/**
* dynamic offset of this object
*
* @return the offset of the ABIObject
*/
public int offset() {
if (isDynamic()) { // dynamic
return 1;
}
int offset = 0;
if (type == ObjectType.VALUE) { // basic type
offset = 1;
} else if (type == ObjectType.STRUCT) { // tuple
int l = 0;
for (ABIObject abiObject : structFields) {
l += abiObject.offset();
}
offset = l;
} else { // T[M]
int length = listLength;
int basicOffset = listValueType.offset();
offset = length * basicOffset;
}
return offset;
}
public int offsetAsByteLength() {
return offset() * Type.MAX_BYTE_LENGTH;
}
public int offsetAsHexLength() {
return offset() * (Type.MAX_BYTE_LENGTH << 1);
}
/**
* encode this object
*
* @return the encoded object
*/
public String encode() {
StringBuffer stringBuffer = new StringBuffer();
switch (type) {
case VALUE:
{
switch (valueType) {
case UINT:
case INT:
{
stringBuffer.append(TypeEncoder.encode(numericValue));
break;
}
case BOOL:
{
stringBuffer.append(TypeEncoder.encode(boolValue));
break;
}
case FIXED:
case UFIXED:
{
throw new UnsupportedOperationException(
" Unsupported fixed/unfixed type. ");
// break;
}
case BYTES:
{
stringBuffer.append(TypeEncoder.encode(bytesValue));
break;
}
case ADDRESS:
{
stringBuffer.append(TypeEncoder.encode(addressValue));
break;
}
case DBYTES:
{
stringBuffer.append(TypeEncoder.encode(dynamicBytesValue));
break;
}
case STRING:
{
stringBuffer.append(TypeEncoder.encode(stringValue));
break;
}
default:
{
throw new UnsupportedOperationException(
" Unrecognized valueType: " + valueType);
}
}
break;
}
case STRUCT:
{
long dynamicOffset = 0;
for (ABIObject abiObject : structFields) {
dynamicOffset += abiObject.offsetAsByteLength();
}
StringBuffer fixedBuffer = new StringBuffer();
StringBuffer dynamicBuffer = new StringBuffer();
for (ABIObject abiObject : structFields) {
String encodeValue = abiObject.encode();
if (abiObject.isDynamic()) {
fixedBuffer.append(TypeEncoder.encode(new Uint256(dynamicOffset)));
dynamicBuffer.append(encodeValue);
dynamicOffset += (encodeValue.length() >> 1);
} else {
fixedBuffer.append(encodeValue);
}
}
stringBuffer.append(fixedBuffer).append(dynamicBuffer);
break;
}
case LIST:
{
StringBuffer lengthBuffer = new StringBuffer();
StringBuffer listValueBuffer = new StringBuffer();
StringBuffer offsetBuffer = new StringBuffer();
if (listType == ListType.DYNAMIC) {
lengthBuffer.append(TypeEncoder.encode(new Uint256(listValues.size())));
}
int dynamicOffset = listValues.size() * Type.MAX_BYTE_LENGTH;
for (ABIObject abiObject : listValues) {
String listValueEncode = abiObject.encode();
listValueBuffer.append(abiObject.encode());
if (abiObject.isDynamic()) {
offsetBuffer.append(TypeEncoder.encode(new Uint256(dynamicOffset)));
dynamicOffset += (listValueEncode.length() >> 1);
}
}
stringBuffer.append(lengthBuffer).append(offsetBuffer).append(listValueBuffer);
break;
}
}
if (logger.isTraceEnabled()) {
logger.trace("ABI: {}", stringBuffer.toString());
}
return stringBuffer.toString();
}
/**
* decode this object
*
* @param input the string to be decoded into ABIObject
* @return the decoded ABIObject
*/
public ABIObject decode(String input) {
return decode(input, 0);
}
/**
* decode this object
*
* @return the decoded ABIObject
*/
private ABIObject decode(String input, int offset) {
ABIObject abiObject = newObject();
switch (type) {
case VALUE:
{
switch (valueType) {
case BOOL:
{
abiObject.setBoolValue(
TypeDecoder.decode(input, offset, Bool.class));
break;
}
case UINT:
{
abiObject.setNumericValue(
TypeDecoder.decode(input, offset, Uint256.class));
break;
}
case INT:
{
abiObject.setNumericValue(
TypeDecoder.decode(input, offset, Int256.class));
break;
}
case FIXED:
case UFIXED:
{
throw new UnsupportedOperationException(
" Unsupported fixed/unfixed type. ");
// break;
}
case BYTES:
{
abiObject.setBytesValue(
TypeDecoder.decode(input, offset, Bytes32.class));
break;
}
case ADDRESS:
{
abiObject.setAddressValue(
TypeDecoder.decode(input, offset, Address.class));
break;
}
case DBYTES:
{
abiObject.setDynamicBytesValue(
TypeDecoder.decode(input, offset, DynamicBytes.class));
break;
}
case STRING:
{
abiObject.setStringValue(
TypeDecoder.decode(input, offset, Utf8String.class));
break;
}
}
break;
}
case STRUCT:
{
int structOffset = offset;
int initialOffset = offset;
for (int i = 0; i < structFields.size(); ++i) {
ABIObject structObject = abiObject.structFields.get(i);
ABIObject itemObject = null;
if (structObject.isDynamic()) {
int structValueOffset =
TypeDecoder.decode(input, structOffset, Uint256.class)
.getValue()
.intValue();
itemObject =
structObject.decode(
input, initialOffset + (structValueOffset << 1));
} else {
itemObject = structObject.decode(input, structOffset);
}
abiObject.structFields.set(i, itemObject);
structOffset += structObject.offsetAsHexLength();
}
break;
}
case LIST:
{
int listOffset = offset;
int initialOffset = offset;
int listLength = 0;
if (listType == ListType.DYNAMIC) {
// dynamic list length
listLength =
TypeDecoder.decode(input, listOffset, Uint256.class)
.getValue()
.intValue();
listOffset += (Type.MAX_BYTE_LENGTH << 1);
initialOffset += (Type.MAX_BYTE_LENGTH << 1);
} else {
// fixed list length
listLength = abiObject.getListLength();
}
if (logger.isTraceEnabled()) {
logger.trace(" listType: {}, listLength: {}", listType, listLength);
}
ABIObject listValueObject = abiObject.getListValueType();
for (int i = 0; i < listLength; i++) {
ABIObject itemABIObject = null;
if (listValueObject.isDynamic()) {
int listValueOffset =
TypeDecoder.decode(input, listOffset, Uint256.class)
.getValue()
.intValue();
itemABIObject =
abiObject
.getListValueType()
.decode(input, initialOffset + (listValueOffset << 1));
} else {
itemABIObject = abiObject.getListValueType().decode(input, listOffset);
}
listOffset += listValueObject.offsetAsHexLength();
abiObject.getListValues().add(itemABIObject);
}
break;
}
}
return abiObject;
}
public ObjectType getType() {
return type;
}
public void setType(ObjectType type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ValueType getValueType() {
return valueType;
}
public NumericType getNumericValue() {
return numericValue;
}
public Bool getBoolValue() {
return boolValue;
}
public void setBoolValue(Bool boolValue) {
this.type = ObjectType.VALUE;
this.valueType = ValueType.BOOL;
this.boolValue = boolValue;
}
public void setNumericValue(NumericType numericValue) {
this.type = ObjectType.VALUE;
this.valueType = ValueType.UINT;
this.numericValue = numericValue;
}
public Bytes getBytesValue() {
return bytesValue;
}
public void setBytesValue(Bytes bytesValue) {
this.type = ObjectType.VALUE;
this.valueType = ValueType.BYTES;
this.bytesValue = bytesValue;
}
public Address getAddressValue() {
return addressValue;
}
public void setAddressValue(Address addressValue) {
this.type = ObjectType.VALUE;
this.valueType = ValueType.ADDRESS;
this.addressValue = addressValue;
}
public List getStructFields() {
return structFields;
}
public void setStructFields(List structFields) {
this.type = ObjectType.STRUCT;
this.structFields = structFields;
}
public ListType getListType() {
return listType;
}
public void setListType(ListType listType) {
this.listType = listType;
}
public List getListValues() {
return listValues;
}
public void setListValues(List listValues) {
this.type = ObjectType.LIST;
this.listValues = listValues;
}
public void setValueType(ValueType valueType) {
this.valueType = valueType;
}
public DynamicBytes getDynamicBytesValue() {
return dynamicBytesValue;
}
public void setDynamicBytesValue(DynamicBytes dynamicBytesValue) {
this.dynamicBytesValue = dynamicBytesValue;
}
public Utf8String getStringValue() {
return stringValue;
}
public void setStringValue(Utf8String stringValue) {
this.stringValue = stringValue;
}
public ABIObject getListValueType() {
return listValueType;
}
public void setListValueType(ABIObject listValueType) {
this.listValueType = listValueType;
}
public int getListLength() {
return listLength;
}
public void setListLength(int listLength) {
this.listLength = listLength;
}
@Override
public String toString() {
String str = "ABIObject{" + "name='" + name + '\'' + ", type=" + type;
if (type == ObjectType.VALUE) {
str += ", valueType=" + valueType;
switch (valueType) {
case BOOL:
str += ", booValueType=";
str += Objects.isNull(boolValue) ? "null" : boolValue.getValue();
break;
case UINT:
case INT:
str += ", numericValue=";
str += Objects.isNull(numericValue) ? "null" : numericValue.getValue();
break;
case ADDRESS:
str += ", addressValue=";
str += Objects.isNull(addressValue) ? "null" : addressValue.getValue();
break;
case BYTES:
str += ", bytesValue=";
str += Objects.isNull(bytesValue) ? "null" : bytesValue.getValue();
break;
case DBYTES:
str += ", dynamicBytesValue=";
str +=
Objects.isNull(dynamicBytesValue)
? "null"
: dynamicBytesValue.getValue();
// case STRING:
default:
str += ", stringValue=";
str += Objects.isNull(stringValue) ? "null" : stringValue.getValue();
}
} else if (type == ObjectType.LIST) {
str += ", listType=" + listType;
str += ", listValues=" + listValues + ", listLength=" + listLength;
} else if (type == ObjectType.STRUCT) {
str += ", structFields=" + structFields;
}
str += '}';
return str;
}
}