/******************************************************************************* * 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"); } }