]> gerrit.simantics Code Review - simantics/platform.git/blob
81029105d203b77c32fc92171fd9d4622918f28c
[simantics/platform.git] /
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12
13 package org.simantics.utils.datastructures.prioritystack;
14
15 import java.lang.reflect.Array;
16 import java.lang.reflect.Method;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.ListIterator;
22 import java.util.Map;
23
24 import org.simantics.utils.strings.EString;
25 import org.simantics.utils.threads.IThreadWorkQueue;
26 import org.simantics.utils.threads.SyncListenerList;
27
28
29 /**
30  * Implementation to IPriorityStack.
31  * 
32  * <p>
33  * Note!
34  * getAllItems() is optimized for result with the penalty of slower add/remove methods. 
35  *
36  * @author Toni Kalajainen
37  * @param <E>
38  */
39 public class PriorityStack<E> implements IPriorityStack<E> {
40         
41         @SuppressWarnings({ "rawtypes" })
42     private SyncListenerList<IPriorityStackListener> listeners =
43                 new SyncListenerList<IPriorityStackListener>(IPriorityStackListener.class);
44         
45         private LinkedList<E> list = 
46                 new LinkedList<E>(); 
47         
48         private E[] snapshotArray;
49         
50         private Map<E, Integer> priorities = 
51                 new HashMap<E, Integer>(); 
52         
53         final Class<E> clazz;
54         
55         public PriorityStack(Class<E> clazz) {
56                 this.clazz = clazz;
57                 snapshotArray = createArray(0);
58         }
59         
60         @Override
61         public void add(E interactor, int priority) {
62                 abu:
63                 synchronized(this) {
64                         if (list.contains(interactor))
65                                 throw new IllegalArgumentException("InteractorStack already contains item "+interactor);
66                 
67                         priorities.put(interactor, priority);
68                 
69                         if (list.size()==0)
70                         {
71                                 list.add(interactor);
72                                 snapshotArray = createSnapshot(list);
73                                 break abu;
74                         }
75                                 
76                         ListIterator<E> li = list.listIterator();
77                         while (li.hasNext()) {
78                                 E i = li.next();
79                                 double w = priorities.get( i );
80                                 if (w > priority) {
81                                         li.previous();
82                                         li.add(interactor);
83                                         snapshotArray = createSnapshot(list);
84                                         break abu;
85                                 }
86                         }
87                         list.addLast(interactor);
88                         snapshotArray = createSnapshot(list);
89                 }
90                 fireInteractorAdded(interactor);                
91         }
92         
93         @Override
94         public boolean remove(E interactor) {
95                 synchronized(this) {
96                         if (!priorities.containsKey(interactor)) 
97                                 return false;
98                         priorities.remove(interactor);
99                         list.remove(interactor);
100                         snapshotArray = createSnapshot(list);
101                 }
102                 fireInteractorRemoved(interactor);
103                 return true;
104         }       
105
106         @Override
107         public synchronized Integer getPriority(E interactor) {
108                 return priorities.get(interactor);
109         }       
110
111         @SuppressWarnings({ "unchecked" })
112         private E[] createArray(int length)
113         {
114                 return (E[]) Array.newInstance(clazz, length);
115         }
116
117         E[] createSnapshot(List<E> list) {
118                 E[] result = createArray(list.size());
119                 int index = 0;
120                 for (E i : list)
121                         result[index++] = i; 
122                 return result;
123         }
124                 
125         public synchronized int indexOf(E item)
126         {
127                 for (int i=0; i<snapshotArray.length; i++)
128                         if (snapshotArray[i]==item)
129                                 return i;
130                 return -1;
131         }       
132         
133         @Override
134         public synchronized E[] toArray() {
135                 return snapshotArray;
136         }
137
138         public synchronized <R extends E> R getSingleItem(Class<R> clazz)
139         {
140                 R array[] = getItemsByClass(clazz);
141                 if (array.length!=1)
142                         throw new RuntimeException("one "+clazz.getName()+" expected in PriorityStack, got "+array.length);
143                 return (R) array[0];
144         }
145         
146         @SuppressWarnings("unchecked")
147     @Override
148         public synchronized <R extends E> R[] getItemsByClass(Class<R> clazz)
149         {
150                 List<E> result = new ArrayList<E>(list.size());
151                 for (E i : list)
152                         if (clazz.isAssignableFrom(i.getClass()))
153                                 result.add(i);
154                 return (R[])result.toArray(createArray(result.size()));
155         }
156
157         private static Method itemAdded = SyncListenerList.getMethod(IPriorityStackListener.class, "itemAdded");
158         private void fireInteractorAdded(E interactor)
159         {
160                 listeners.fireEventSync(itemAdded, this, interactor);
161         }
162         
163         private static Method itemRemoved = SyncListenerList.getMethod(IPriorityStackListener.class, "itemRemoved");
164         private void fireInteractorRemoved(E interactor)
165         {
166                 listeners.fireEventSync(itemRemoved, this, interactor);
167         }
168
169         @Override
170         public synchronized void addStackListener(IPriorityStackListener<E> listener) {
171                 listeners.add(listener);
172         }
173
174         @Override
175         public synchronized void removeStackListener(IPriorityStackListener<E> listener) {
176                 listeners.remove(listener);
177         }
178
179         @Override
180         public synchronized boolean contains(E interactor) {
181                 return list.contains(interactor);
182         }
183
184         @Override
185         public void addStackListener(IThreadWorkQueue thread,
186                         IPriorityStackListener<E> listener) {
187                 listeners.add(thread, listener);
188         }
189
190         @Override
191         public void removeStackListener(IThreadWorkQueue thread,
192                         IPriorityStackListener<E> listener) {
193                 listeners.remove(thread, listener);
194         }
195
196         @Override
197         public String toString() {
198             return EString.implode(snapshotArray, "\n");
199         }
200
201 }