package database;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.mapdb.BTreeMap;
import org.mapdb.Bind;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Fun;
import org.mapdb.Fun.Tuple4;
import qora.assets.Order;
import utils.ObserverMessage;
import database.DBSet;
import database.serializer.OrderSerializer;
public class OrderMap extends DBMap<BigInteger, Order>
{
private Map<Integer, Integer> observableData = new HashMap<Integer, Integer>();
@SuppressWarnings("rawtypes")
private BTreeMap haveWantKeyMap;
public OrderMap(DBSet databaseSet, DB database)
{
super(databaseSet, database);
this.observableData.put(DBMap.NOTIFY_ADD, ObserverMessage.ADD_ORDER_TYPE);
this.observableData.put(DBMap.NOTIFY_REMOVE, ObserverMessage.REMOVE_ORDER_TYPE);
//this.observableData.put(DBMap.NOTIFY_LIST, ObserverMessage.LIST_ORDER_TYPE);
}
public OrderMap(OrderMap parent)
{
super(parent);
}
protected void createIndexes(DB database){}
@Override
protected Map<BigInteger, Order> getMap(DB database)
{
//OPEN MAP
return this.openMap(database);
}
@Override
protected Map<BigInteger, Order> getMemoryMap()
{
DB database = DBMaker.newMemoryDB().make();
//OPEN MAP
return this.openMap(database);
}
@SuppressWarnings("unchecked")
private Map<BigInteger, Order> openMap(DB database)
{
//OPEN MAP
BTreeMap<BigInteger, Order> map = database.createTreeMap("orders")
.valueSerializer(new OrderSerializer())
.makeOrGet();
//HAVE/WANT KEY
this.haveWantKeyMap = database.createTreeMap("orders_key_have_want")
.comparator(Fun.COMPARATOR)
.makeOrGet();
//BIND HAVE/WANT KEY
Bind.secondaryKey(map, this.haveWantKeyMap, new Fun.Function2<Tuple4<Long, Long, BigDecimal, BigInteger>, BigInteger, Order>() {
@Override
public Tuple4<Long, Long, BigDecimal, BigInteger> run(BigInteger key, Order value) {
return new Tuple4<Long, Long, BigDecimal, BigInteger>(value.getHave(), value.getWant(), value.getPrice(), key);
}
});
//RETURN
return map;
}
@Override
protected Order getDefaultValue()
{
return null;
}
@Override
protected Map<Integer, Integer> getObservableData()
{
return this.observableData;
}
public void add(Order order) {
this.set(order.getId(), order);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Collection<BigInteger> getKeys(long have, long want) {
//FILTER ALL KEYS
Collection<BigInteger> keys = ((BTreeMap<Tuple4, BigInteger>) this.haveWantKeyMap).subMap(
Fun.t4(have, want, null, null),
Fun.t4(have, want, Fun.HI(), Fun.HI())).values();
//IF THIS IS A FORK
if(this.parent != null)
{
//GET ALL KEYS FOR FORK
Collection<BigInteger> forkKeys = ((OrderMap) this.parent).getKeys(have, want);
//COMBINE LISTS
Set<BigInteger> combinedKeys = new TreeSet<BigInteger>(keys);
combinedKeys.addAll(forkKeys);
//DELETE DELETED
for(BigInteger deleted: this.deleted)
{
combinedKeys.remove(deleted);
}
//CONVERT SET BACK TO COLLECTION
keys = combinedKeys;
}
return keys;
}
public List<Order> getOrders(long have, long want)
{
//FILTER ALL KEYS
Collection<BigInteger> keys = this.getKeys(have, want);
//GET ALL ORDERS FOR KEYS
List<Order> orders = new ArrayList<Order>();
for(BigInteger key: keys)
{
orders.add(this.get(key));
}
//IF THIS IS A FORK
if(this.parent != null)
{
//RESORT ORDERS
Collections.sort(orders);
}
//RETURN
return orders;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public SortableList<BigInteger, Order> getOrdersSortableList(long have, long want)
{
//FILTER ALL KEYS
Collection<BigInteger> keys = ((BTreeMap<Tuple4, BigInteger>) this.haveWantKeyMap).subMap(
Fun.t4(have, want, null, null),
Fun.t4(have, want, Fun.HI(), Fun.HI())).values();
//RETURN
return new SortableList<BigInteger, Order>(this, keys);
}
public void delete(Order order)
{
this.delete(order.getId());
}
}