package org.torrent.internal.data; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class PieceInfoMap<T> { private final Map<BTPart, Collection<T>> map; private final PieceInfos pieceInfos; public PieceInfoMap(PieceInfos infos) { this.pieceInfos = infos; map = new HashMap<BTPart, Collection<T>>(); } public List<BTPart> getUnboundPieceInfos() { List<BTPart> lst = new ArrayList<BTPart>(); for (BTPart pi : pieceInfos) { if (!map.containsKey(pi)) { lst.add(pi); } } assert pieceInfos.getPieceInfoCount() == lst.size() + map.keySet().size() : "Expected " + pieceInfos.getPieceInfoCount() + " but got " + lst.size() + " + " + map.keySet().size() + " = " + (lst.size() + map.keySet().size()); return lst; } public List<BTPart> getBoundPieceInfos(T value) { List<BTPart> lst = new ArrayList<BTPart>(); for (Entry<BTPart, Collection<T>> entry : map.entrySet()) { if (entry.getValue().contains(value)) { lst.add(entry.getKey()); } } return lst; } public boolean unbind(BTPart pieceInfo, T value) { Collection<T> values = map.get(pieceInfo); if (values == null) { return false; } if (values.remove(value)) { if (values.isEmpty()) { map.remove(pieceInfo); } return true; } return false; } public void bind(BTPart pieceInfo, T value) { Collection<T> values = map.get(pieceInfo); if (values == null) { values = new LinkedList<T>(); map.put(pieceInfo, values); } values.add(value); } @Override public String toString() { return "PieceInfoMap: Bound PieceInfos: " + map.keySet().size() + ", " + pieceInfos; } public Iterator<BTPart> unboundPieceInfoIterator() { return new Iterator<BTPart>() { Iterator<BTPart> i = pieceInfos.iterator(); BTPart next; @Override public boolean hasNext() { return peekNext() != null; } private BTPart peekNext() { while (next == null && i.hasNext()) { BTPart pi = i.next(); if (!map.containsKey(pi)) { next = pi; } } return next; } @Override public BTPart next() { BTPart result = peekNext(); next = null; return result; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }