-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.browsing.ui.common.internal;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Deque;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-import org.simantics.browsing.ui.DataSource;\r
-import org.simantics.browsing.ui.NodeContext;\r
-import org.simantics.browsing.ui.NodeContext.CacheKey;\r
-import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey;\r
-import org.simantics.browsing.ui.NodeContext.QueryKey;\r
-import org.simantics.browsing.ui.NodeQueryManager;\r
-import org.simantics.browsing.ui.NodeQueryProcessor;\r
-import org.simantics.browsing.ui.PrimitiveQueryProcessor;\r
-import org.simantics.browsing.ui.PrimitiveQueryUpdater;\r
-import org.simantics.browsing.ui.common.internal.IGECache.IGECacheEntry;\r
-import org.simantics.browsing.ui.exception.NoDataSourceException;\r
-import org.simantics.browsing.ui.exception.NoQueryProcessorException;\r
-\r
-public class GENodeQueryManager implements NodeQueryManager, PrimitiveQueryUpdater {\r
-\r
- private static final boolean DEBUG = false;\r
-\r
- protected IGraphExplorerContext ge;\r
- protected NodeContext parentContext;\r
- protected CacheKey<?> parentKey;\r
- protected UIElementReference treeReference;\r
- protected boolean disposed = false;\r
- List<GENodeQueryManager> children = new ArrayList<GENodeQueryManager>();\r
-\r
- void indent() {\r
- ge.queryIndent(1);\r
- }\r
-\r
- void unindent() {\r
- ge.queryIndent(-1);\r
- }\r
-\r
- void queryDebug(String s) {\r
- for (int i = 0; i < ge.queryIndent(); ++i)\r
- System.err.append(" ");\r
- System.err.println(s);\r
- }\r
-\r
- String toString(UIElementReference ref) {\r
- return ref == null ? "" : ref.toString();\r
- }\r
-\r
- String toString(Set<UIElementReference> refs) {\r
- if (refs == null || refs.isEmpty())\r
- return "{}";\r
- StringBuilder b = new StringBuilder();\r
- for (UIElementReference ref : refs) {\r
- b.append(toString(ref));\r
- }\r
- return b.toString();\r
- }\r
-\r
- String toString(NodeContext ctx, CacheKey<?> key) {\r
- if (ctx == null)\r
- return "null";\r
- Set<UIElementReference> refs = ge.getCache().getTreeReference(ctx, key);\r
- //return String.valueOf(System.identityHashCode(ctx)) + toString(ref);\r
- //return String.valueOf(ctx.hashCode()) + ":" + String.valueOf(System.identityHashCode(ctx)) + toString(ref);\r
- return ctx + toString(refs);\r
- }\r
-\r
-\r
- public GENodeQueryManager(GENodeQueryManager parent, NodeContext parentContext, CacheKey<?> parentKey, UIElementReference treeReference) {\r
- this.ge = parent.ge;\r
- this.parentContext = parentContext;\r
- this.parentKey = parentKey;\r
- this.treeReference = treeReference;\r
- parent.children.add(this);\r
- }\r
- public GENodeQueryManager(IGraphExplorerContext ge, NodeContext parentContext, CacheKey<?> parentKey, UIElementReference treeReference) {\r
- this.ge = ge;\r
- this.parentContext = parentContext;\r
- this.parentKey = parentKey;\r
- this.treeReference = treeReference;\r
- }\r
-\r
- @Override\r
- public Object getExplorerContext() {\r
- return ge;\r
- }\r
- \r
- public void dispose() {\r
- if (disposed)\r
- return;\r
- disposed = true;\r
- if (ge != null && parentContext != null && parentKey != null) {\r
- ge.getCache().remove(parentContext, parentKey);\r
- }\r
- ge = null;\r
- parentContext = null;\r
- parentKey = null;\r
- treeReference = null;\r
- for (GENodeQueryManager m : children)\r
- m.dispose();\r
- children.clear();\r
- children = null;\r
- }\r
-\r
-// @Override\r
-// public String toString() {\r
-// return "GENodeQueryManager[parentKey=" + parentKey + ", parentContext=" + "]";\r
-// }\r
-//\r
-// @Override\r
-// public CacheKey getParentKey() {\r
-// return parentKey;\r
-// }\r
-//\r
-// @Override\r
-// public INodeContext getParentContext() {\r
-// return parentContext;\r
-// }\r
-\r
-// static int koss = 0;\r
- \r
-// @Override\r
- public <T> void replaceResult(NodeContext context, PrimitiveQueryKey<T> key, T newResult, int indent) {\r
-\r
- IGraphExplorerContext ge = this.ge;\r
- if (isDisposed())\r
- return;\r
- \r
- if(DEBUG) {\r
- queryDebug("replaceResult[" + ge.getCache().hashCode() + "] " + key + " -> " + newResult);\r
- indent();\r
- }\r
- \r
-// if((koss++ % 5000) == 0) {\r
-// System.out.println("R" + koss);\r
-// }\r
- \r
- IGECache cache = ge.getCache();\r
- IGECacheEntry oldEntry = cache.getEntry(context, key);\r
- if (oldEntry != null) {\r
- cache.put(context, key, newResult);\r
- propagate(context, key, oldEntry, indent);\r
-\r
- Set<UIElementReference> refs = cache.removeTreeReference(context, key);\r
-\r
- if (refs != null) {\r
- //queryDebug("(replaceResult) found tree references " + toString(refs));\r
- for (UIElementReference ref : refs)\r
- ge.update(ref);\r
- }\r
- } else {\r
- // TODO: explain why this check is here or remove it!\r
-\r
- // Consistency checking, no TreeReference should ever exist in this case!\r
- Set<UIElementReference> ref = cache.getTreeReference(context, key);\r
- assert ref == null;\r
- }\r
- }\r
-\r
-// @Override\r
- public <T> void clearResult(NodeContext context, CacheKey<T> key, int indent) {\r
-// if (key == BuiltinKeys.FINAL_CHILDREN) {\r
-// queryDebug("Clear final children for " + context);\r
-// }\r
- if(DEBUG) queryDebug("clearResult[" + ge.getCache().hashCode() + "] " + key + " " + context);\r
-\r
- IGraphExplorerContext ge = this.ge;\r
- if (isDisposed())\r
- return;\r
-\r
- IGECache cache = ge.getCache();\r
- IGECacheEntry entry = cache.getEntry(context, key);\r
- if (entry != null) {\r
- cache.remove(context, key);\r
- propagate(context, key, entry, indent);\r
- }\r
-\r
- Set<UIElementReference> refs = cache.removeTreeReference(context, key);\r
- if (refs != null) {\r
- //queryDebug("(clearResult) found tree reference " + toString(refs));\r
- for (UIElementReference ref : refs)\r
- ge.update(ref);\r
- }\r
- }\r
-\r
- public <T> void propagate(NodeContext context, CacheKey<T> key, IGECacheEntry entry, int indent) {\r
-\r
- if (isDisposed())\r
- return;\r
-\r
- if(DEBUG) queryDebug("propagate[" + ge.getCache().hashCode() + "] " + key + " - " + context);\r
-\r
- assert entry != null;\r
-\r
- for(IGECacheEntry dependency : entry.getDependencies()) {\r
- clearResult(dependency.getContext(), dependency.getKey(), indent + 3);\r
- }\r
-\r
- entry.reset();\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T query(NodeContext context, QueryKey<T> key) throws NoQueryProcessorException {\r
-\r
- assert(!ge.isDisposed());\r
-\r
- if(DEBUG) {\r
- queryDebug("Query[" + ge.getCache().hashCode() + "] " + key + " " + toString(context, key) + " - " + parentKey + " " + toString(parentContext, parentKey));\r
- indent();\r
- }\r
-\r
- assert(!(context == parentContext && key == parentKey));\r
-\r
- assert(context != null);\r
- assert(key != null);\r
-\r
- T result = null;\r
- IGECache cache = ge.getCache();\r
-\r
- synchronized(ge.getPropagateLock()) {\r
-\r
- IGECacheEntry entry = cache.getEntry(context, key);\r
- //queryDebug(" CACHED RESULT: " + entry);\r
- if(entry == null) {\r
- entry = cache.put(context, key, null);\r
- NodeQueryProcessor<T> processor = ge.getProcessor(key);\r
- if(processor == null) {\r
- throw new NoQueryProcessorException(key);\r
- }\r
-// queryDebug("PERFORMING QUERY...");\r
- T value = processor.query(new GENodeQueryManager(this, context, key, null), context);\r
-// queryDebug("RESULT: " + value);\r
- entry.setValue(value);\r
- }\r
-\r
- if(treeReference != null) {\r
- UIElementReference cachedTreeReference = treeReference;\r
-\r
- Set<UIElementReference> oldRefs = cache.getTreeReference(context, key);\r
- if (oldRefs != null) {\r
- if (cachedTreeReference.isDisposed()) {\r
- oldRefs.remove(cachedTreeReference);\r
- } else {\r
- cache.putTreeReference(context, key, cachedTreeReference);\r
- }\r
- } else {\r
- cache.putTreeReference(context, key, cachedTreeReference);\r
- }\r
- }\r
-\r
- if(parentContext != null) {\r
- assert(parentKey != null);\r
- IGECacheEntry parentEntry = cache.getEntry(parentContext, parentKey);\r
- if(parentEntry != null)\r
- entry.addDependency(parentEntry);\r
- }\r
-\r
- result = (T) entry.getValue();\r
- }\r
-\r
- unindent();\r
- return result;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T query(NodeContext context, PrimitiveQueryKey<T> key) throws NoQueryProcessorException {\r
-\r
- assert(!ge.isDisposed());\r
-\r
- if(DEBUG) {\r
- queryDebug("Primitive Query[" + ge.getCache().hashCode() + "] " + key + " " + toString(context, key) + " - " + parentKey + " " + toString(parentContext, key) + " " + Thread.currentThread().getName());\r
- indent();\r
- }\r
-\r
- assert(!(context == parentContext && key == parentKey));\r
-\r
- // Primitive queries must be leaf queries!\r
- assert(!(parentKey instanceof PrimitiveQueryKey));\r
-\r
- assert(context != null);\r
- assert(key != null);\r
-\r
- T result = null;\r
-\r
- IGECache cache = ge.getCache();\r
-\r
- synchronized(ge.getPropagateLock()) {\r
- IGECacheEntry entry = cache.getEntry(context, key);\r
- if(DEBUG) queryDebug(" CACHED PRIMITIVE RESULT[" + cache.hashCode() + "]: " + ((entry != null) ? (entry.hashCode() + "|" + System.identityHashCode(entry)) : 0));\r
- if(entry == null) {\r
- entry = cache.put(context, key, null);\r
- PrimitiveQueryProcessor<T> processor = ge.getPrimitiveProcessor(key.processorIdenfitier());\r
- if(processor == null) {\r
- throw new NoQueryProcessorException(key);\r
- }\r
-// queryDebug("PERFORMING PRIMITIVE QUERY...");\r
- T value = processor.query(new GENodeQueryManager(this, context, key, null), context, key);\r
-// queryDebug("PRIMITIVE RESULT: " + value);\r
- entry.setValue(value);\r
- }\r
-\r
- if(treeReference != null) {\r
- UIElementReference cachedTreeReference = treeReference;\r
-\r
- Set<UIElementReference> oldRefs = cache.getTreeReference(context, key);\r
- if (oldRefs != null) {\r
- if (cachedTreeReference.isDisposed()) {\r
- oldRefs.remove(cachedTreeReference);\r
- } else {\r
- cache.putTreeReference(context, key, cachedTreeReference);\r
- }\r
- } else {\r
- cache.putTreeReference(context, key, cachedTreeReference);\r
- }\r
- }\r
-\r
- if(parentContext != null) {\r
- assert(parentKey != null);\r
- IGECacheEntry parentEntry = cache.getEntry(parentContext, parentKey);\r
- if(parentEntry != null) {\r
- entry.addDependency(parentEntry);\r
- }\r
- }\r
-\r
- result = (T) entry.getValue();\r
- }\r
-\r
- unindent();\r
- return result;\r
- }\r
-\r
- @Override\r
- public <T> DataSource<T> tryGetDataSource(Class<T> clazz) {\r
- return ge.getDataSource(clazz);\r
- }\r
-\r
- @Override\r
- public <T> DataSource<T> getDataSource(Class<T> clazz) {\r
- DataSource<T> dsp = ge.getDataSource(clazz);\r
- if (dsp == null)\r
- throw new NoDataSourceException(clazz);\r
- return dsp;\r
- }\r
-\r
-// @Override\r
-// public <T> void scheduleClear(final INodeContext context, final PrimitiveQueryKey<T> key) {\r
-// ge.scheduler.execute(new Runnable() {\r
-// @Override\r
-// public void run() {\r
-// synchronized(ge.propagate) {\r
-// clearResult(context, key, 0);\r
-// }\r
-// }\r
-// });\r
-// }\r
-\r
-\r
-// @Override\r
-// public <T> void create(final INodeContext context, final PrimitiveQueryKey<T> key, final T newResult) {\r
-// ge.cache.put(context, key, newResult);\r
-// }\r
-\r
- @Override\r
- public <T> void scheduleReplace(final NodeContext context, final PrimitiveQueryKey<T> key, final T newResult) {\r
-\r
- if(DEBUG) queryDebug("scheduleReplace[" + ge.getCache().hashCode() + "] context=" + context + " key=" + key);\r
-\r
- IGraphExplorerContext ge = this.ge;\r
- if (isDisposed())\r
- return;\r
-\r
- class PropagateRunner implements Runnable {\r
-\r
- @Override\r
- public void run() {\r
- IGraphExplorerContext ge = GENodeQueryManager.this.ge;\r
- if (isDisposed())\r
- return;\r
-\r
- int delay = 0;\r
-\r
- List<Runnable> todo = null;\r
- \r
- synchronized(ge.getPropagateListLock()) {\r
-\r
- ge.setPropagating(true);\r
-\r
- List<Runnable> scheduleList = ge.getScheduleList();\r
- Deque<Integer> activity = ge.getActivity();\r
-\r
- activity.addFirst(scheduleList.size());\r
- activity.pollLast();\r
-\r
- int activityInt = 0;\r
- for(int i : activity) {\r
- activityInt += i;\r
- }\r
- ge.setActivityInt(activityInt);\r
-\r
- if(activityInt < 100) {\r
- delay = 10;\r
- //System.out.println("Scheduling propagate after 10ms.");\r
- } else if (activityInt < 1000) {\r
- delay = 500;\r
- //System.out.println("Scheduling propagate after 500ms.");\r
- } else {\r
- delay = 3000;\r
- //System.out.println("Scheduling propagate after 3000ms.");\r
- }\r
- \r
- todo = ge.getScheduleList();\r
- ge.setScheduleList(new ArrayList<Runnable>());\r
-\r
- }\r
-\r
- try {\r
- if(delay > 0)\r
- Thread.sleep(delay);\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
- if (isDisposed())\r
- return;\r
- \r
- synchronized(ge.getPropagateLock()) {\r
-\r
- for(Runnable r : todo) r.run();\r
-\r
- }\r
- if (isDisposed())\r
- return;\r
- \r
- synchronized(ge.getPropagateListLock()) {\r
-\r
- ge.setPropagating(false);\r
-\r
- if(!ge.getScheduleList().isEmpty())\r
- ge.scheduleQueryUpdate(new PropagateRunner());\r
-\r
- }\r
-\r
- }\r
-\r
- }\r
-\r
- synchronized(ge.getPropagateListLock()) {\r
-// System.out.println("Schedule Replace: " + key + " - " + context);\r
-// new Exception().printStackTrace();\r
- List<Runnable> scheduleList = ge.getScheduleList();\r
- scheduleList.add(new Runnable() {\r
- @Override\r
- public void run() {\r
- replaceResult(context, key, newResult, 0);\r
- }\r
- });\r
-\r
- if(ge.isPropagating()) return;\r
-\r
- ge.scheduleQueryUpdate(new PropagateRunner());\r
- }\r
- }\r
-\r
- @Override\r
- public boolean isDisposed() {\r
- if (disposed)\r
- return true;\r
- if (ge.isDisposed()) {\r
- dispose();\r
- return true;\r
- }\r
- return false;\r
- }\r
- \r
- @Override\r
- public boolean isShown(NodeContext context) {\r
- IGraphExplorerContext ge = this.ge;\r
- if (isDisposed())\r
- return false;\r
- return ge.getCache().isShown(context);\r
- }\r
-\r
- @Override\r
- public void incRef(NodeContext context) {\r
- IGraphExplorerContext ge = this.ge;\r
- if (isDisposed())\r
- return;\r
- ge.getCache().incRef(context);\r
- }\r
- \r
- @Override\r
- public void decRef(NodeContext context) {\r
- IGraphExplorerContext ge = this.ge;\r
- if (isDisposed())\r
- return;\r
- ge.getCache().decRef(context);\r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * 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.browsing.ui.common.internal;
+
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.Set;
+
+import org.simantics.browsing.ui.DataSource;
+import org.simantics.browsing.ui.NodeContext;
+import org.simantics.browsing.ui.NodeContext.CacheKey;
+import org.simantics.browsing.ui.NodeContext.PrimitiveQueryKey;
+import org.simantics.browsing.ui.NodeContext.QueryKey;
+import org.simantics.browsing.ui.NodeQueryManager;
+import org.simantics.browsing.ui.NodeQueryProcessor;
+import org.simantics.browsing.ui.PrimitiveQueryProcessor;
+import org.simantics.browsing.ui.PrimitiveQueryUpdater;
+import org.simantics.browsing.ui.common.internal.IGECache.IGECacheEntry;
+import org.simantics.browsing.ui.exception.NoDataSourceException;
+import org.simantics.browsing.ui.exception.NoQueryProcessorException;
+import org.slf4j.LoggerFactory;
+
+public class GENodeQueryManager implements NodeQueryManager, PrimitiveQueryUpdater {
+
+ private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(GENodeQueryManager.class);
+ private static final boolean DEBUG = false;
+
+ protected IGraphExplorerContext ge;
+ protected NodeContext parentContext;
+ protected CacheKey<?> parentKey;
+ protected UIElementReference treeReference;
+ protected boolean disposed = false;
+ List<GENodeQueryManager> children = new ArrayList<GENodeQueryManager>();
+
+ void indent() {
+ ge.queryIndent(1);
+ }
+
+ void unindent() {
+ ge.queryIndent(-1);
+ }
+
+ void queryDebug(String s) {
+ for (int i = 0; i < ge.queryIndent(); ++i)
+ LOGGER.info(" ");
+ LOGGER.info(s);
+ }
+
+ String toString(UIElementReference ref) {
+ return ref == null ? "" : ref.toString();
+ }
+
+ String toString(Set<UIElementReference> refs) {
+ if (refs == null || refs.isEmpty())
+ return "{}";
+ StringBuilder b = new StringBuilder();
+ for (UIElementReference ref : refs) {
+ b.append(toString(ref));
+ }
+ return b.toString();
+ }
+
+ String toString(NodeContext ctx, CacheKey<?> key) {
+ if (ctx == null)
+ return "null";
+ Set<UIElementReference> refs = ge.getCache().getTreeReference(ctx, key);
+ //return String.valueOf(System.identityHashCode(ctx)) + toString(ref);
+ //return String.valueOf(ctx.hashCode()) + ":" + String.valueOf(System.identityHashCode(ctx)) + toString(ref);
+ return ctx + toString(refs);
+ }
+
+
+ public GENodeQueryManager(GENodeQueryManager parent, NodeContext parentContext, CacheKey<?> parentKey, UIElementReference treeReference) {
+ this.ge = parent.ge;
+ this.parentContext = parentContext;
+ this.parentKey = parentKey;
+ this.treeReference = treeReference;
+ parent.children.add(this);
+ }
+ public GENodeQueryManager(IGraphExplorerContext ge, NodeContext parentContext, CacheKey<?> parentKey, UIElementReference treeReference) {
+ this.ge = ge;
+ this.parentContext = parentContext;
+ this.parentKey = parentKey;
+ this.treeReference = treeReference;
+ }
+
+ @Override
+ public Object getExplorerContext() {
+ return ge;
+ }
+
+ public void dispose() {
+ if (disposed)
+ return;
+ disposed = true;
+ if (ge != null && parentContext != null && parentKey != null) {
+ ge.getCache().remove(parentContext, parentKey);
+ }
+ ge = null;
+ parentContext = null;
+ parentKey = null;
+ treeReference = null;
+ for (GENodeQueryManager m : children)
+ m.dispose();
+ children.clear();
+ children = null;
+ }
+
+// @Override
+// public String toString() {
+// return "GENodeQueryManager[parentKey=" + parentKey + ", parentContext=" + "]";
+// }
+//
+// @Override
+// public CacheKey getParentKey() {
+// return parentKey;
+// }
+//
+// @Override
+// public INodeContext getParentContext() {
+// return parentContext;
+// }
+
+// static int koss = 0;
+
+// @Override
+ public <T> void replaceResult(NodeContext context, PrimitiveQueryKey<T> key, T newResult, int indent) {
+
+ IGraphExplorerContext ge = this.ge;
+ if (isDisposed())
+ return;
+
+ if(DEBUG) {
+ queryDebug("replaceResult[" + ge.getCache().hashCode() + "] " + key + " -> " + newResult);
+ indent();
+ }
+
+// if((koss++ % 5000) == 0) {
+// System.out.println("R" + koss);
+// }
+
+ IGECache cache = ge.getCache();
+ IGECacheEntry oldEntry = cache.getEntry(context, key);
+ if (oldEntry != null) {
+ cache.put(context, key, newResult);
+ propagate(context, key, oldEntry, indent);
+
+ Set<UIElementReference> refs = cache.removeTreeReference(context, key);
+
+ if (refs != null) {
+ //queryDebug("(replaceResult) found tree references " + toString(refs));
+ for (UIElementReference ref : refs)
+ ge.update(ref);
+ }
+ } else {
+ // TODO: explain why this check is here or remove it!
+
+ // Consistency checking, no TreeReference should ever exist in this case!
+ Set<UIElementReference> ref = cache.getTreeReference(context, key);
+ assert ref == null;
+ }
+ }
+
+// @Override
+ public <T> void clearResult(NodeContext context, CacheKey<T> key, int indent) {
+// if (key == BuiltinKeys.FINAL_CHILDREN) {
+// queryDebug("Clear final children for " + context);
+// }
+ if(DEBUG) queryDebug("clearResult[" + ge.getCache().hashCode() + "] " + key + " " + context);
+
+ IGraphExplorerContext ge = this.ge;
+ if (isDisposed())
+ return;
+
+ IGECache cache = ge.getCache();
+ IGECacheEntry entry = cache.getEntry(context, key);
+ if (entry != null) {
+ cache.remove(context, key);
+ propagate(context, key, entry, indent);
+ }
+
+ Set<UIElementReference> refs = cache.removeTreeReference(context, key);
+ if (refs != null) {
+ //queryDebug("(clearResult) found tree reference " + toString(refs));
+ for (UIElementReference ref : refs)
+ ge.update(ref);
+ }
+ }
+
+ public <T> void propagate(NodeContext context, CacheKey<T> key, IGECacheEntry entry, int indent) {
+
+ if (isDisposed())
+ return;
+
+ if(DEBUG) queryDebug("propagate[" + ge.getCache().hashCode() + "] " + key + " - " + context);
+
+ assert entry != null;
+
+ for(IGECacheEntry dependency : entry.getDependencies()) {
+ clearResult(dependency.getContext(), dependency.getKey(), indent + 3);
+ }
+
+ entry.reset();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T query(NodeContext context, QueryKey<T> key) throws NoQueryProcessorException {
+
+ assert(!ge.isDisposed());
+
+ if(DEBUG) {
+ queryDebug("Query[" + ge.getCache().hashCode() + "] " + key + " " + toString(context, key) + " - " + parentKey + " " + toString(parentContext, parentKey));
+ indent();
+ }
+
+ assert(!(context == parentContext && key == parentKey));
+
+ assert(context != null);
+ assert(key != null);
+
+ T result = null;
+ IGECache cache = ge.getCache();
+
+ synchronized(ge.getPropagateLock()) {
+
+ IGECacheEntry entry = cache.getEntry(context, key);
+ //queryDebug(" CACHED RESULT: " + entry);
+ if(entry == null) {
+ entry = cache.put(context, key, null);
+ NodeQueryProcessor<T> processor = ge.getProcessor(key);
+ if(processor == null) {
+ throw new NoQueryProcessorException(key);
+ }
+// queryDebug("PERFORMING QUERY...");
+ T value = processor.query(new GENodeQueryManager(this, context, key, null), context);
+// queryDebug("RESULT: " + value);
+ entry.setValue(value);
+ }
+
+ if(treeReference != null) {
+ UIElementReference cachedTreeReference = treeReference;
+
+ Set<UIElementReference> oldRefs = cache.getTreeReference(context, key);
+ if (oldRefs != null) {
+ if (cachedTreeReference.isDisposed()) {
+ oldRefs.remove(cachedTreeReference);
+ } else {
+ cache.putTreeReference(context, key, cachedTreeReference);
+ }
+ } else {
+ cache.putTreeReference(context, key, cachedTreeReference);
+ }
+ }
+
+ if(parentContext != null) {
+ assert(parentKey != null);
+ IGECacheEntry parentEntry = cache.getEntry(parentContext, parentKey);
+ if(parentEntry != null)
+ entry.addDependency(parentEntry);
+ }
+
+ result = (T) entry.getValue();
+ }
+
+ unindent();
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T query(NodeContext context, PrimitiveQueryKey<T> key) throws NoQueryProcessorException {
+
+ assert(!ge.isDisposed());
+
+ if(DEBUG) {
+ queryDebug("Primitive Query[" + ge.getCache().hashCode() + "] " + key + " " + toString(context, key) + " - " + parentKey + " " + toString(parentContext, key) + " " + Thread.currentThread().getName());
+ indent();
+ }
+
+ assert(!(context == parentContext && key == parentKey));
+
+ // Primitive queries must be leaf queries!
+ assert(!(parentKey instanceof PrimitiveQueryKey));
+
+ assert(context != null);
+ assert(key != null);
+
+ T result = null;
+
+ IGECache cache = ge.getCache();
+
+ synchronized(ge.getPropagateLock()) {
+ IGECacheEntry entry = cache.getEntry(context, key);
+ if(DEBUG) queryDebug(" CACHED PRIMITIVE RESULT[" + cache.hashCode() + "]: " + ((entry != null) ? (entry.hashCode() + "|" + System.identityHashCode(entry)) : 0));
+ if(entry == null) {
+ entry = cache.put(context, key, null);
+ PrimitiveQueryProcessor<T> processor = ge.getPrimitiveProcessor(key.processorIdenfitier());
+ if(processor == null) {
+ throw new NoQueryProcessorException(key);
+ }
+// queryDebug("PERFORMING PRIMITIVE QUERY...");
+ T value = processor.query(new GENodeQueryManager(this, context, key, null), context, key);
+// queryDebug("PRIMITIVE RESULT: " + value);
+ entry.setValue(value);
+ }
+
+ if(treeReference != null) {
+ UIElementReference cachedTreeReference = treeReference;
+
+ Set<UIElementReference> oldRefs = cache.getTreeReference(context, key);
+ if (oldRefs != null) {
+ if (cachedTreeReference.isDisposed()) {
+ oldRefs.remove(cachedTreeReference);
+ } else {
+ cache.putTreeReference(context, key, cachedTreeReference);
+ }
+ } else {
+ cache.putTreeReference(context, key, cachedTreeReference);
+ }
+ }
+
+ if(parentContext != null) {
+ assert(parentKey != null);
+ IGECacheEntry parentEntry = cache.getEntry(parentContext, parentKey);
+ if(parentEntry != null) {
+ entry.addDependency(parentEntry);
+ }
+ }
+
+ result = (T) entry.getValue();
+ }
+
+ unindent();
+ return result;
+ }
+
+ @Override
+ public <T> DataSource<T> tryGetDataSource(Class<T> clazz) {
+ return ge.getDataSource(clazz);
+ }
+
+ @Override
+ public <T> DataSource<T> getDataSource(Class<T> clazz) {
+ DataSource<T> dsp = ge.getDataSource(clazz);
+ if (dsp == null)
+ throw new NoDataSourceException(clazz);
+ return dsp;
+ }
+
+// @Override
+// public <T> void scheduleClear(final INodeContext context, final PrimitiveQueryKey<T> key) {
+// ge.scheduler.execute(new Runnable() {
+// @Override
+// public void run() {
+// synchronized(ge.propagate) {
+// clearResult(context, key, 0);
+// }
+// }
+// });
+// }
+
+
+// @Override
+// public <T> void create(final INodeContext context, final PrimitiveQueryKey<T> key, final T newResult) {
+// ge.cache.put(context, key, newResult);
+// }
+
+ @Override
+ public <T> void scheduleReplace(final NodeContext context, final PrimitiveQueryKey<T> key, final T newResult) {
+
+ if(DEBUG) queryDebug("scheduleReplace[" + ge.getCache().hashCode() + "] context=" + context + " key=" + key);
+
+ IGraphExplorerContext ge = this.ge;
+ if (isDisposed())
+ return;
+
+ class PropagateRunner implements Runnable {
+
+ @Override
+ public void run() {
+ IGraphExplorerContext ge = GENodeQueryManager.this.ge;
+ if (isDisposed())
+ return;
+
+ int delay = 0;
+
+ List<Runnable> todo = null;
+
+ synchronized(ge.getPropagateListLock()) {
+
+ ge.setPropagating(true);
+
+ List<Runnable> scheduleList = ge.getScheduleList();
+ Deque<Integer> activity = ge.getActivity();
+
+ activity.addFirst(scheduleList.size());
+ activity.pollLast();
+
+ int activityInt = 0;
+ for(int i : activity) {
+ activityInt += i;
+ }
+ ge.setActivityInt(activityInt);
+
+ if(activityInt < 100) {
+ delay = 10;
+ //System.out.println("Scheduling propagate after 10ms.");
+ } else if (activityInt < 1000) {
+ delay = 500;
+ //System.out.println("Scheduling propagate after 500ms.");
+ } else {
+ delay = 3000;
+ //System.out.println("Scheduling propagate after 3000ms.");
+ }
+
+ todo = ge.getScheduleList();
+ ge.setScheduleList(new ArrayList<Runnable>());
+
+ }
+
+ try {
+ if(delay > 0)
+ Thread.sleep(delay);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (isDisposed())
+ return;
+
+ synchronized(ge.getPropagateLock()) {
+
+ for(Runnable r : todo) r.run();
+
+ }
+ if (isDisposed())
+ return;
+
+ synchronized(ge.getPropagateListLock()) {
+
+ ge.setPropagating(false);
+
+ if(!ge.getScheduleList().isEmpty())
+ ge.scheduleQueryUpdate(new PropagateRunner());
+
+ }
+
+ }
+
+ }
+
+ synchronized(ge.getPropagateListLock()) {
+// System.out.println("Schedule Replace: " + key + " - " + context);
+// new Exception().printStackTrace();
+ List<Runnable> scheduleList = ge.getScheduleList();
+ scheduleList.add(new Runnable() {
+ @Override
+ public void run() {
+ replaceResult(context, key, newResult, 0);
+ }
+ });
+
+ if(ge.isPropagating()) return;
+
+ ge.scheduleQueryUpdate(new PropagateRunner());
+ }
+ }
+
+ @Override
+ public boolean isDisposed() {
+ if (disposed)
+ return true;
+ if (ge.isDisposed()) {
+ dispose();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isShown(NodeContext context) {
+ IGraphExplorerContext ge = this.ge;
+ if (isDisposed())
+ return false;
+ return ge.getCache().isShown(context);
+ }
+
+ @Override
+ public void incRef(NodeContext context) {
+ IGraphExplorerContext ge = this.ge;
+ if (isDisposed())
+ return;
+ ge.getCache().incRef(context);
+ }
+
+ @Override
+ public void decRef(NodeContext context) {
+ IGraphExplorerContext ge = this.ge;
+ if (isDisposed())
+ return;
+ ge.getCache().decRef(context);
+ }
+
+}