/****************************************************************************** * 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.DbUtils; import nxt.db.EntityDbTable; import nxt.util.Listener; import nxt.util.Listeners; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public final class CurrencyTransfer { public enum Event { TRANSFER } private static final Listeners<CurrencyTransfer,Event> listeners = new Listeners<>(); private static final DbKey.LongKeyFactory<CurrencyTransfer> currencyTransferDbKeyFactory = new DbKey.LongKeyFactory<CurrencyTransfer>("id") { @Override public DbKey newKey(CurrencyTransfer transfer) { return transfer.dbKey; } }; private static final EntityDbTable<CurrencyTransfer> currencyTransferTable = new EntityDbTable<CurrencyTransfer>("currency_transfer", currencyTransferDbKeyFactory) { @Override protected CurrencyTransfer load(Connection con, ResultSet rs) throws SQLException { return new CurrencyTransfer(rs); } @Override protected void save(Connection con, CurrencyTransfer transfer) throws SQLException { transfer.save(con); } }; public static DbIterator<CurrencyTransfer> getAllTransfers(int from, int to) { return currencyTransferTable.getAll(from, to); } public static int getCount() { return currencyTransferTable.getCount(); } public static boolean addListener(Listener<CurrencyTransfer> listener, Event eventType) { return listeners.addListener(listener, eventType); } public static boolean removeListener(Listener<CurrencyTransfer> listener, Event eventType) { return listeners.removeListener(listener, eventType); } public static DbIterator<CurrencyTransfer> getCurrencyTransfers(long currencyId, int from, int to) { return currencyTransferTable.getManyBy(new DbClause.LongClause("currency_id", currencyId), from, to); } public static DbIterator<CurrencyTransfer> getAccountCurrencyTransfers(long accountId, int from, int to) { Connection con = null; try { con = Db.db.getConnection(); PreparedStatement pstmt = con.prepareStatement("SELECT * FROM currency_transfer WHERE sender_id = ?" + " UNION ALL SELECT * FROM currency_transfer WHERE recipient_id = ? AND sender_id <> ? ORDER BY height DESC, db_id DESC" + DbUtils.limitsClause(from, to)); int i = 0; pstmt.setLong(++i, accountId); pstmt.setLong(++i, accountId); pstmt.setLong(++i, accountId); DbUtils.setLimits(++i, pstmt, from, to); return currencyTransferTable.getManyBy(con, pstmt, false); } catch (SQLException e) { DbUtils.close(con); throw new RuntimeException(e.toString(), e); } } public static DbIterator<CurrencyTransfer> getAccountCurrencyTransfers(long accountId, long currencyId, int from, int to) { Connection con = null; try { con = Db.db.getConnection(); PreparedStatement pstmt = con.prepareStatement("SELECT * FROM currency_transfer WHERE sender_id = ? AND currency_id = ?" + " UNION ALL SELECT * FROM currency_transfer WHERE recipient_id = ? AND sender_id <> ? AND currency_id = ? ORDER BY height DESC, db_id DESC" + DbUtils.limitsClause(from, to)); int i = 0; pstmt.setLong(++i, accountId); pstmt.setLong(++i, currencyId); pstmt.setLong(++i, accountId); pstmt.setLong(++i, accountId); pstmt.setLong(++i, currencyId); DbUtils.setLimits(++i, pstmt, from, to); return currencyTransferTable.getManyBy(con, pstmt, false); } catch (SQLException e) { DbUtils.close(con); throw new RuntimeException(e.toString(), e); } } public static int getTransferCount(long currencyId) { return currencyTransferTable.getCount(new DbClause.LongClause("currency_id", currencyId)); } static CurrencyTransfer addTransfer(Transaction transaction, Attachment.MonetarySystemCurrencyTransfer attachment) { CurrencyTransfer transfer = new CurrencyTransfer(transaction, attachment); currencyTransferTable.insert(transfer); listeners.notify(transfer, Event.TRANSFER); return transfer; } static void init() {} private final long id; private final DbKey dbKey; private final long currencyId; private final int height; private final long senderId; private final long recipientId; private final long units; private final int timestamp; private CurrencyTransfer(Transaction transaction, Attachment.MonetarySystemCurrencyTransfer attachment) { this.id = transaction.getId(); this.dbKey = currencyTransferDbKeyFactory.newKey(this.id); this.height = Nxt.getBlockchain().getHeight(); this.currencyId = attachment.getCurrencyId(); this.senderId = transaction.getSenderId(); this.recipientId = transaction.getRecipientId(); this.units = attachment.getUnits(); this.timestamp = Nxt.getBlockchain().getLastBlockTimestamp(); } private CurrencyTransfer(ResultSet rs) throws SQLException { this.id = rs.getLong("id"); this.dbKey = currencyTransferDbKeyFactory.newKey(this.id); this.currencyId = rs.getLong("currency_id"); this.senderId = rs.getLong("sender_id"); this.recipientId = rs.getLong("recipient_id"); this.units = rs.getLong("units"); this.timestamp = rs.getInt("timestamp"); this.height = rs.getInt("height"); } private void save(Connection con) throws SQLException { try (PreparedStatement pstmt = con.prepareStatement("INSERT INTO currency_transfer (id, currency_id, " + "sender_id, recipient_id, units, timestamp, height) " + "VALUES (?, ?, ?, ?, ?, ?, ?)")) { int i = 0; pstmt.setLong(++i, this.id); pstmt.setLong(++i, this.currencyId); pstmt.setLong(++i, this.senderId); pstmt.setLong(++i, this.recipientId); pstmt.setLong(++i, this.units); pstmt.setInt(++i, this.timestamp); pstmt.setInt(++i, this.height); pstmt.executeUpdate(); } } public long getId() { return id; } public long getCurrencyId() { return currencyId; } public long getSenderId() { return senderId; } public long getRecipientId() { return recipientId; } public long getUnits() { return units; } public int getTimestamp() { return timestamp; } public int getHeight() { return height; } }