/*******************************************************************************
* Copyright (c) 2007, 2010 Association for Decentralized Information Management
* in Industry THTH ry.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.utils.datastructures.prioritystack;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.simantics.utils.strings.EString;
import org.simantics.utils.threads.IThreadWorkQueue;
import org.simantics.utils.threads.SyncListenerList;
/**
* Implementation to IPriorityStack.
*
*
* Note!
* getAllItems() is optimized for result with the penalty of slower add/remove methods.
*
* @author Toni Kalajainen
* @param
*/
public class PriorityStack implements IPriorityStack {
@SuppressWarnings({ "rawtypes" })
private SyncListenerList listeners =
new SyncListenerList(IPriorityStackListener.class);
private LinkedList list =
new LinkedList();
private E[] snapshotArray;
private Map priorities =
new HashMap();
final Class clazz;
public PriorityStack(Class clazz) {
this.clazz = clazz;
snapshotArray = createArray(0);
}
@Override
public void add(E interactor, int priority) {
abu:
synchronized(this) {
if (list.contains(interactor))
throw new IllegalArgumentException("InteractorStack already contains item "+interactor);
priorities.put(interactor, priority);
if (list.size()==0)
{
list.add(interactor);
snapshotArray = createSnapshot(list);
break abu;
}
ListIterator li = list.listIterator();
while (li.hasNext()) {
E i = li.next();
double w = priorities.get( i );
if (w > priority) {
li.previous();
li.add(interactor);
snapshotArray = createSnapshot(list);
break abu;
}
}
list.addLast(interactor);
snapshotArray = createSnapshot(list);
}
fireInteractorAdded(interactor);
}
@Override
public boolean remove(E interactor) {
synchronized(this) {
if (!priorities.containsKey(interactor))
return false;
priorities.remove(interactor);
list.remove(interactor);
snapshotArray = createSnapshot(list);
}
fireInteractorRemoved(interactor);
return true;
}
@Override
public synchronized Integer getPriority(E interactor) {
return priorities.get(interactor);
}
@SuppressWarnings({ "unchecked" })
private E[] createArray(int length)
{
return (E[]) Array.newInstance(clazz, length);
}
E[] createSnapshot(List list) {
E[] result = createArray(list.size());
int index = 0;
for (E i : list)
result[index++] = i;
return result;
}
public synchronized int indexOf(E item)
{
for (int i=0; i R getSingleItem(Class clazz)
{
R array[] = getItemsByClass(clazz);
if (array.length!=1)
throw new RuntimeException("one "+clazz.getName()+" expected in PriorityStack, got "+array.length);
return (R) array[0];
}
@SuppressWarnings("unchecked")
@Override
public synchronized R[] getItemsByClass(Class clazz)
{
List result = new ArrayList(list.size());
for (E i : list)
if (clazz.isAssignableFrom(i.getClass()))
result.add(i);
return (R[])result.toArray(createArray(result.size()));
}
private static Method itemAdded = SyncListenerList.getMethod(IPriorityStackListener.class, "itemAdded");
private void fireInteractorAdded(E interactor)
{
listeners.fireEventSync(itemAdded, this, interactor);
}
private static Method itemRemoved = SyncListenerList.getMethod(IPriorityStackListener.class, "itemRemoved");
private void fireInteractorRemoved(E interactor)
{
listeners.fireEventSync(itemRemoved, this, interactor);
}
@Override
public synchronized void addStackListener(IPriorityStackListener listener) {
listeners.add(listener);
}
@Override
public synchronized void removeStackListener(IPriorityStackListener listener) {
listeners.remove(listener);
}
@Override
public synchronized boolean contains(E interactor) {
return list.contains(interactor);
}
@Override
public void addStackListener(IThreadWorkQueue thread,
IPriorityStackListener listener) {
listeners.add(thread, listener);
}
@Override
public void removeStackListener(IThreadWorkQueue thread,
IPriorityStackListener listener) {
listeners.remove(thread, listener);
}
@Override
public String toString() {
return EString.implode(snapshotArray, "\n");
}
}