/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.community.intellij.plugins.communitycase.history.wholeTree;
import com.intellij.util.containers.SLRUMap;
import java.util.*;
/**
* @author irengrig
*/
public class CommitIdsHolder<Item> {
private final MyLruCache<Item, Item> myRequests;
private final Object myLock;
public CommitIdsHolder() {
myRequests = new MyLruCache<Item, Item>(50, 30);
myLock = new Object();
}
public void add(final Collection<Item> s) {
synchronized (myLock) {
for (Item hash : s) {
myRequests.put(hash, hash);
}
}
}
public boolean haveData() {
synchronized (myLock) {
return ! myRequests.isEmpty();
}
}
public Collection<Item> get(final int size) {
final Set<Item> result = new HashSet<Item>();
synchronized (myLock) {
final Iterator<Item> iterator = myRequests.iterator();
int cnt = 0;
for (; iterator.hasNext() && (cnt < size);) {
final Item hash = iterator.next();
iterator.remove();
result.add(hash);
++ cnt;
}
}
return result;
}
private static class MyLruCache<Key, Val> extends SLRUMap<Key, Val> {
private MyLruCache(int protectedQueueSize, int probationalQueueSize) {
super(protectedQueueSize, probationalQueueSize);
}
public boolean isEmpty() {
return myProtectedQueue.keySet().isEmpty() && myProbationalQueue.keySet().isEmpty();
}
public Iterator<Key> iterator() {
final List<Iterator<Key>> iterators = new ArrayList<Iterator<Key>>(2);
iterators.add(myProbationalQueue.keySet().iterator());
iterators.add(myProtectedQueue.keySet().iterator());
return new CompositeIterator<Key>(iterators);
}
private static class CompositeIterator<Key> implements Iterator<Key> {
private int myPreviousIdx;
private int myIdx;
private final List<Iterator<Key>> myIterators;
private CompositeIterator(final List<Iterator<Key>> iterators) {
myIterators = iterators;
myIdx = -1;
myPreviousIdx = -1;
for (int i = 0; i < myIterators.size(); i++) {
final Iterator<Key> iterator = myIterators.get(i);
if (iterator.hasNext()) {
myIdx = i;
break;
}
}
}
@Override
public boolean hasNext() {
return (myIdx >= 0) && myIterators.get(myIdx).hasNext();
}
@Override
public Key next() {
final Key result = myIterators.get(myIdx).next();
recalculateCurrent();
return result;
}
private void recalculateCurrent() {
if (myIdx == -1) return;
if (! myIterators.get(myIdx).hasNext()) {
myPreviousIdx = myIdx;
myIdx = -1;
for (int i = myPreviousIdx; i < myIterators.size(); i++) {
final Iterator<Key> iterator = myIterators.get(i);
if (iterator.hasNext()) {
myIdx = i;
break;
}
}
}
}
@Override
public void remove() {
if ((myPreviousIdx != -1) && (myPreviousIdx != myIdx)) {
// last element
final Iterator<Key> keyIterator = myIterators.get(myPreviousIdx);
keyIterator.remove(); // already on last position
} else {
myIterators.get(myIdx).remove();
}
recalculateCurrent();
}
}
}
}