1 19 package org.netbeans.modules.java.ui.nodes.elements; 20 21 import org.openide.nodes.Node; 22 import org.openide.nodes.Children; 23 import org.openide.util.RequestProcessor; 24 import org.openide.util.Mutex; 25 import org.openide.ErrorManager; 26 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 27 import org.netbeans.modules.javacore.JMManager; 28 import org.netbeans.jmi.javamodel.Element; 29 30 import javax.jmi.reflect.JmiException; 31 import javax.jmi.reflect.InvalidObjectException; 32 import java.util.*; 33 34 38 final class ChildrenProvider implements Runnable { 39 40 43 interface KeyHandler { 44 48 List collectKeys(); 49 50 57 Node[] prepareNodes(Object key); 58 59 65 void presentKeys(List keys, List nodes); 66 } 67 68 72 static final RequestProcessor RP = new RequestProcessor("Java Children Provider"); 74 private RequestProcessor.Task currentTask; 75 76 private Map nodes = initNodeMap(); 77 78 79 private List elements; 80 81 private final KeyHandler keyHandler; 82 83 public ChildrenProvider(KeyHandler keyHandler) { 84 this.keyHandler = keyHandler; 85 } 86 87 public void run() { 88 JMManager.getTransactionMutex().addPriorityThread(); 89 List keys; 90 Map nodesNew; 91 try { 92 keys = keyHandler.collectKeys(); 93 nodesNew = createNodeMap(nodes, keys); 94 } catch (InvalidObjectException e) { 95 keys = Collections.EMPTY_LIST; 97 nodesNew = Collections.EMPTY_MAP; 98 } catch (JmiException e) { 99 keys = Collections.EMPTY_LIST; 100 nodesNew = Collections.EMPTY_MAP; 101 ErrorManager.getDefault().notify(ErrorManager.WARNING, e); 102 } 103 104 synchronized(this) { 105 elements = keys; 106 nodes = nodesNew; 107 } 108 presentKeys(keys, nodesNew); 109 } 110 111 private void presentKeys(final List keys, final Map nodesNew) { 112 List nodes = new ArrayList(keys.size()); 113 for (Iterator it = keys.iterator(); it.hasNext();) { 114 Object key = it.next(); 115 Node[] ns = (Node[]) nodesNew.get(key); 116 nodes.add(ns); 117 118 } 119 keyHandler.presentKeys(keys, nodes); 120 } 121 122 private Map initNodeMap() { 123 Map nodesNew = new WeakHashMap(); 124 return nodesNew; 125 } 126 127 130 public synchronized void recomputeChildren() { 131 if (currentTask == null) { 132 currentTask = RP.post(this); 133 } else { 134 currentTask.schedule(0); 135 } 136 } 137 138 143 public Node getNode(Object element) { 144 Node[] ns = null; 145 synchronized (this) { 146 ns = (Node[]) nodes.get(element); 147 } 148 return ns == null? null: ns[0]; 149 } 150 151 155 public Collection getKeys() { 156 computeChildren(); 157 synchronized (this) { 158 return elements; 159 } 160 } 161 162 165 public void waitFinished() { 166 computeChildren(); 167 } 168 169 172 public void clear() { 173 RP.post(new CleanTask()); 174 } 175 176 private void clearImpl() { 177 synchronized (this) { 178 elements = Collections.EMPTY_LIST; 179 nodes = Collections.EMPTY_MAP; 180 } 181 presentKeys(elements, nodes); 182 } 183 184 private void computeChildren() { 185 synchronized (this) { 186 if (currentTask == null) { 187 recomputeChildren(); 188 } 189 } 190 currentTask.waitFinished(); 191 } 192 193 private Map createNodeMap( 194 final Map nodes, final List keys) throws JmiException { 195 final Map nodesNew = initNodeMap(); 196 if (keys.isEmpty()) { 197 return nodesNew; 198 } 199 200 JmiException ex = (JmiException) Children.MUTEX.readAccess(new Mutex.Action() { 201 public Object run() { 202 try { 203 JMManager.getTransactionMutex().addPriorityThread(); 204 JavaMetamodel.getDefaultRepository().beginTrans(false); 205 try { 206 for (Iterator it = keys.iterator(); it.hasNext();) { 207 Object key = it.next(); 208 if (key instanceof Element && !((Element) key).isValid()) { 209 nodesNew.clear(); 212 keys.clear(); 213 return null; 214 } else { 215 Node[] ns = (Node[]) nodes.get(key); 216 if (ns == null) { 217 ns = keyHandler.prepareNodes(key); 218 } 219 nodesNew.put(key, ns); 220 } 221 } 222 } finally { 223 JavaMetamodel.getDefaultRepository().endTrans(); 224 } 225 } catch (JmiException ex) { 226 return ex; 227 } 228 return null; 229 } 230 231 }); 232 233 if (ex != null) { 234 throw ex; 235 } 236 return nodesNew; 237 } 238 239 private final class CleanTask implements Runnable { 240 241 public void run() { 242 clearImpl(); 243 } 244 245 } 246 247 } 248 | Popular Tags |