package advancedsystemsmanager.flow.execution.buffers; import advancedsystemsmanager.api.execution.IBuffer; import advancedsystemsmanager.api.execution.IBufferElement; import advancedsystemsmanager.api.execution.Key; import com.google.common.collect.LinkedListMultimap; import java.util.Iterator; import java.util.List; import java.util.Map; public class Buffer<Type> implements IBuffer<Type> { private LinkedListMultimap<Key<Type>, IBufferElement<Type>> multiMap = LinkedListMultimap.create(); @Override public boolean contains(Type type) { return multiMap.containsKey(getKey(type)); } @Override public List<IBufferElement<Type>> get(Type type) { return multiMap.get(getKey(type)); } @Override public int getAccessibleCount(Type type) { int amount = 0; for (IBufferElement<Type> subElement : multiMap.get(getKey(type))) amount += subElement.getSizeLeft(); return amount; } @Override public void remove(Type type, int amount, boolean fair) { Key<Type> key = getKey(type); if (multiMap.containsKey(key)) remove(multiMap.get(key), amount, fair); } @Override public boolean add(IBufferElement<Type> subElement) { return multiMap.put(subElement.getKey(), subElement); } @Override public Iterator<Map.Entry<Key<Type>, IBufferElement<Type>>> getOrderedIterator() { return multiMap.entries().iterator(); } @Override public Iterator<Key<Type>> getKeyIterator() { return multiMap.keySet().iterator(); } @Override public boolean shouldSplit() { return true; } @Override public IBuffer split(int amount, int i, boolean fair) { Buffer<Type> buffer = getNewBuffer(); if (amount == 1) { buffer.multiMap.putAll(multiMap); return buffer; } else { for (Map.Entry<Key<Type>, IBufferElement<Type>> entry : multiMap.entries()) { buffer.multiMap.put(entry.getKey(), entry.getValue().getSplitElement(amount, i, fair)); } } return buffer; } public Buffer<Type> getNewBuffer() { return new Buffer<Type>(); } public Key<Type> getKey(Type key) { return new Key<Type>(key); } public void remove(List<IBufferElement<Type>> subElements, int amount, boolean fair) { int amountToRemove = fair ? Math.min(amount / subElements.size(), 1) : amount; Iterator<IBufferElement<Type>> iterator = subElements.iterator(); while (amount > 0 && iterator.hasNext()) { int removed = iterator.next().reduceBufferAmount(amountToRemove); if (removed < amountToRemove) { iterator.remove(); } amount -= removed; } if (amount > 0 && subElements.size() > 0) remove(subElements, amount, fair); } }