/******************************************************************************
* Copyright © 2013-2016 The Nxt Core Developers. *
* *
* See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* Nxt software, including this file, may be copied, modified, propagated, *
* or distributed except according to the terms contained in the LICENSE.txt *
* file. *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
package nxt;
import nxt.db.DbClause;
import nxt.db.DbIterator;
import nxt.db.DbKey;
import nxt.db.VersionedEntityDbTable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public final class Asset {
private static final DbKey.LongKeyFactory<Asset> assetDbKeyFactory = new DbKey.LongKeyFactory<Asset>("id") {
@Override
public DbKey newKey(Asset asset) {
return asset.dbKey;
}
};
private static final VersionedEntityDbTable<Asset> assetTable = new VersionedEntityDbTable<Asset>("asset", assetDbKeyFactory, "name,description") {
@Override
protected Asset load(Connection con, ResultSet rs) throws SQLException {
return new Asset(rs);
}
@Override
protected void save(Connection con, Asset asset) throws SQLException {
asset.save(con);
}
@Override
public void trim(int height) {
super.trim(Math.max(0, height - Constants.MAX_DIVIDEND_PAYMENT_ROLLBACK));
}
@Override
public void checkAvailable(int height) {
if (height + Constants.MAX_DIVIDEND_PAYMENT_ROLLBACK < Nxt.getBlockchainProcessor().getMinRollbackHeight()) {
throw new IllegalArgumentException("Historical data as of height " + height +" not available.");
}
if (height > Nxt.getBlockchain().getHeight()) {
throw new IllegalArgumentException("Height " + height + " exceeds blockchain height " + Nxt.getBlockchain().getHeight());
}
}
};
public static DbIterator<Asset> getAllAssets(int from, int to) {
return assetTable.getAll(from, to);
}
public static int getCount() {
return assetTable.getCount();
}
public static Asset getAsset(long id) {
return assetTable.get(assetDbKeyFactory.newKey(id));
}
public static Asset getAsset(long id, int height) {
return assetTable.get(assetDbKeyFactory.newKey(id), height);
}
public static DbIterator<Asset> getAssetsIssuedBy(long accountId, int from, int to) {
return assetTable.getManyBy(new DbClause.LongClause("account_id", accountId), from, to);
}
public static DbIterator<Asset> searchAssets(String query, int from, int to) {
return assetTable.search(query, DbClause.EMPTY_CLAUSE, from, to, " ORDER BY ft.score DESC ");
}
static void addAsset(Transaction transaction, Attachment.ColoredCoinsAssetIssuance attachment) {
assetTable.insert(new Asset(transaction, attachment));
}
static void deleteAsset(Transaction transaction, long assetId, long quantityQNT) {
Asset asset = getAsset(assetId);
asset.quantityQNT = Math.max(0, asset.quantityQNT - quantityQNT);
assetTable.insert(asset);
AssetDelete.addAssetDelete(transaction, assetId, quantityQNT);
}
static void init() {}
private final long assetId;
private final DbKey dbKey;
private final long accountId;
private final String name;
private final String description;
private final long initialQuantityQNT;
private long quantityQNT;
private final byte decimals;
private Asset(Transaction transaction, Attachment.ColoredCoinsAssetIssuance attachment) {
this.assetId = transaction.getId();
this.dbKey = assetDbKeyFactory.newKey(this.assetId);
this.accountId = transaction.getSenderId();
this.name = attachment.getName();
this.description = attachment.getDescription();
this.quantityQNT = attachment.getQuantityQNT();
this.initialQuantityQNT = this.quantityQNT;
this.decimals = attachment.getDecimals();
}
private Asset(ResultSet rs) throws SQLException {
this.assetId = rs.getLong("id");
this.dbKey = assetDbKeyFactory.newKey(this.assetId);
this.accountId = rs.getLong("account_id");
this.name = rs.getString("name");
this.description = rs.getString("description");
this.initialQuantityQNT = rs.getLong("initial_quantity");
this.quantityQNT = rs.getLong("quantity");
this.decimals = rs.getByte("decimals");
}
private void save(Connection con) throws SQLException {
try (PreparedStatement pstmt = con.prepareStatement("MERGE INTO asset "
+ "(id, account_id, name, description, initial_quantity, quantity, decimals, height, latest) "
+ "KEY(id, height) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, TRUE)")) {
int i = 0;
pstmt.setLong(++i, this.assetId);
pstmt.setLong(++i, this.accountId);
pstmt.setString(++i, this.name);
pstmt.setString(++i, this.description);
pstmt.setLong(++i, this.initialQuantityQNT);
pstmt.setLong(++i, this.quantityQNT);
pstmt.setByte(++i, this.decimals);
pstmt.setInt(++i, Nxt.getBlockchain().getHeight());
pstmt.executeUpdate();
}
}
public long getId() {
return assetId;
}
public long getAccountId() {
return accountId;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public long getInitialQuantityQNT() {
return initialQuantityQNT;
}
public long getQuantityQNT() {
return quantityQNT;
}
public byte getDecimals() {
return decimals;
}
public DbIterator<Account.AccountAsset> getAccounts(int from, int to) {
return Account.getAssetAccounts(this.assetId, from, to);
}
public DbIterator<Account.AccountAsset> getAccounts(int height, int from, int to) {
return Account.getAssetAccounts(this.assetId, height, from, to);
}
public DbIterator<Trade> getTrades(int from, int to) {
return Trade.getAssetTrades(this.assetId, from, to);
}
public DbIterator<AssetTransfer> getAssetTransfers(int from, int to) {
return AssetTransfer.getAssetTransfers(this.assetId, from, to);
}
}