X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.common%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fcommon%2Finternal%2FGENodeQueryManager.java;h=43b9d3bb253df135ceacc51c67e1ecb81a2d42f0;hp=bcbe40f9e2c2d4be9c3ac7336230d351dc628350;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/internal/GENodeQueryManager.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/internal/GENodeQueryManager.java index bcbe40f9e..43b9d3bb2 100644 --- a/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/internal/GENodeQueryManager.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/internal/GENodeQueryManager.java @@ -1,512 +1,512 @@ -/******************************************************************************* - * 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; - -public class GENodeQueryManager implements NodeQueryManager, PrimitiveQueryUpdater { - - private static final boolean DEBUG = false; - - protected IGraphExplorerContext ge; - protected NodeContext parentContext; - protected CacheKey parentKey; - protected UIElementReference treeReference; - protected boolean disposed = false; - List children = new ArrayList(); - - void indent() { - ge.queryIndent(1); - } - - void unindent() { - ge.queryIndent(-1); - } - - void queryDebug(String s) { - for (int i = 0; i < ge.queryIndent(); ++i) - System.err.append(" "); - System.err.println(s); - } - - String toString(UIElementReference ref) { - return ref == null ? "" : ref.toString(); - } - - String toString(Set 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 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 void replaceResult(NodeContext context, PrimitiveQueryKey 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 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 ref = cache.getTreeReference(context, key); - assert ref == null; - } - } - -// @Override - public void clearResult(NodeContext context, CacheKey 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 refs = cache.removeTreeReference(context, key); - if (refs != null) { - //queryDebug("(clearResult) found tree reference " + toString(refs)); - for (UIElementReference ref : refs) - ge.update(ref); - } - } - - public void propagate(NodeContext context, CacheKey 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 query(NodeContext context, QueryKey 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 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 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 query(NodeContext context, PrimitiveQueryKey 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 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 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 DataSource tryGetDataSource(Class clazz) { - return ge.getDataSource(clazz); - } - - @Override - public DataSource getDataSource(Class clazz) { - DataSource dsp = ge.getDataSource(clazz); - if (dsp == null) - throw new NoDataSourceException(clazz); - return dsp; - } - -// @Override -// public void scheduleClear(final INodeContext context, final PrimitiveQueryKey key) { -// ge.scheduler.execute(new Runnable() { -// @Override -// public void run() { -// synchronized(ge.propagate) { -// clearResult(context, key, 0); -// } -// } -// }); -// } - - -// @Override -// public void create(final INodeContext context, final PrimitiveQueryKey key, final T newResult) { -// ge.cache.put(context, key, newResult); -// } - - @Override - public void scheduleReplace(final NodeContext context, final PrimitiveQueryKey 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 todo = null; - - synchronized(ge.getPropagateListLock()) { - - ge.setPropagating(true); - - List scheduleList = ge.getScheduleList(); - Deque 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()); - - } - - 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 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); - } - -} +/******************************************************************************* + * 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; + +public class GENodeQueryManager implements NodeQueryManager, PrimitiveQueryUpdater { + + private static final boolean DEBUG = false; + + protected IGraphExplorerContext ge; + protected NodeContext parentContext; + protected CacheKey parentKey; + protected UIElementReference treeReference; + protected boolean disposed = false; + List children = new ArrayList(); + + void indent() { + ge.queryIndent(1); + } + + void unindent() { + ge.queryIndent(-1); + } + + void queryDebug(String s) { + for (int i = 0; i < ge.queryIndent(); ++i) + System.err.append(" "); + System.err.println(s); + } + + String toString(UIElementReference ref) { + return ref == null ? "" : ref.toString(); + } + + String toString(Set 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 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 void replaceResult(NodeContext context, PrimitiveQueryKey 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 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 ref = cache.getTreeReference(context, key); + assert ref == null; + } + } + +// @Override + public void clearResult(NodeContext context, CacheKey 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 refs = cache.removeTreeReference(context, key); + if (refs != null) { + //queryDebug("(clearResult) found tree reference " + toString(refs)); + for (UIElementReference ref : refs) + ge.update(ref); + } + } + + public void propagate(NodeContext context, CacheKey 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 query(NodeContext context, QueryKey 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 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 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 query(NodeContext context, PrimitiveQueryKey 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 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 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 DataSource tryGetDataSource(Class clazz) { + return ge.getDataSource(clazz); + } + + @Override + public DataSource getDataSource(Class clazz) { + DataSource dsp = ge.getDataSource(clazz); + if (dsp == null) + throw new NoDataSourceException(clazz); + return dsp; + } + +// @Override +// public void scheduleClear(final INodeContext context, final PrimitiveQueryKey key) { +// ge.scheduler.execute(new Runnable() { +// @Override +// public void run() { +// synchronized(ge.propagate) { +// clearResult(context, key, 0); +// } +// } +// }); +// } + + +// @Override +// public void create(final INodeContext context, final PrimitiveQueryKey key, final T newResult) { +// ge.cache.put(context, key, newResult); +// } + + @Override + public void scheduleReplace(final NodeContext context, final PrimitiveQueryKey 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 todo = null; + + synchronized(ge.getPropagateListLock()) { + + ge.setPropagating(true); + + List scheduleList = ge.getScheduleList(); + Deque 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()); + + } + + 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 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); + } + +}