package qora.naming; import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.json.simple.JSONObject; import com.google.common.primitives.Bytes; import com.google.common.primitives.Ints; import database.DBSet; import qora.account.Account; import qora.crypto.Base58; public class Name { private static final int OWNER_LENGTH = 25; private static final int NAME_SIZE_LENGTH = 4; private static final int VALUE_SIZE_LENGTH = 4; private Account owner; private String name; private String value; public Name(Account owner, String name, String value) { this.owner = owner; this.name = name; this.value = value; } //GETTERS/SETTERS public Account getOwner() { return this.owner; } public String getName() { return this.name; } public String getValue() { return this.value; } public void setOwner(Account owner) { this.owner = owner; } public void setValue(String value) { this.value = value; } public boolean isConfirmed() { return DBSet.getInstance().getNameMap().contains(this); } //PARSE public static Name Parse(byte[] data) throws Exception { int position = 0; //READ OWNER byte[] ownerBytes = Arrays.copyOfRange(data, position, position + OWNER_LENGTH); Account owner = new Account(Base58.encode(ownerBytes)); position += OWNER_LENGTH; //READ NAME byte[] nameLengthBytes = Arrays.copyOfRange(data, position, position + NAME_SIZE_LENGTH); int nameLength = Ints.fromByteArray(nameLengthBytes); position += NAME_SIZE_LENGTH; if(nameLength < 1 || nameLength > 400) { throw new Exception("Invalid name length"); } byte[] nameBytes = Arrays.copyOfRange(data, position, position + nameLength); String name = new String(nameBytes, StandardCharsets.UTF_8); position += nameLength; //READ VALUE byte[] valueLengthBytes = Arrays.copyOfRange(data, position, position + VALUE_SIZE_LENGTH); int valueLength = Ints.fromByteArray(valueLengthBytes); position += VALUE_SIZE_LENGTH; if(valueLength < 1 || valueLength > 4000) { throw new Exception("Invalid value length"); } byte[] valueBytes = Arrays.copyOfRange(data, position, position + valueLength); String value = new String(valueBytes, StandardCharsets.UTF_8); position += valueLength; return new Name(owner, name, value); } @SuppressWarnings("unchecked") public JSONObject toJson() { //GET BASE JSONObject name = new JSONObject(); //ADD NAME/VALUE/OWNER name.put("name", this.getName()); name.put("value", this.getValue()); name.put("owner", this.getOwner().getAddress()); return name; } public byte[] toBytes() { byte[] data = new byte[0]; //WRITE OWNER try { data = Bytes.concat(data , Base58.decode(this.owner.getAddress())); } catch(Exception e) { //DECODE EXCEPTION } //WRITE NAME SIZE byte[] nameBytes = this.name.getBytes(StandardCharsets.UTF_8); int nameLength = nameBytes.length; byte[] nameLengthBytes = Ints.toByteArray(nameLength); data = Bytes.concat(data, nameLengthBytes); //WRITE NAME data = Bytes.concat(data, nameBytes); //WRITE VALUE SIZE byte[] valueBytes = this.value.getBytes(StandardCharsets.UTF_8); int valueLength = valueBytes.length; byte[] valueLengthBytes = Ints.toByteArray(valueLength); data = Bytes.concat(data, valueLengthBytes); //WRITE VALUE data = Bytes.concat(data, valueBytes); return data; } public int getDataLength() { return OWNER_LENGTH + NAME_SIZE_LENGTH + this.name.getBytes(StandardCharsets.UTF_8).length + VALUE_SIZE_LENGTH + this.value.getBytes(StandardCharsets.UTF_8).length; } //REST @Override public String toString() { return this.name; } @Override public boolean equals(Object b) { if(b != null && b instanceof Name) { Name two = (Name) b; return this.getName().endsWith(two.getName()); } return false; } }