--- /dev/null
+/*******************************************************************************\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 gnu.trove.map.hash.THashMap;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.Collections;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.simantics.browsing.ui.NodeContext;\r
+import org.simantics.browsing.ui.NodeContext.CacheKey;\r
+\r
+public class GECache implements IGECache {\r
+\r
+ final Map<GECacheKey, IGECacheEntry> entries = new THashMap<GECacheKey, IGECacheEntry>();\r
+ final Map<GECacheKey, Set<UIElementReference>> treeReferences = new THashMap<GECacheKey, Set<UIElementReference>>();\r
+\r
+ final private static class GECacheKey {\r
+\r
+ private NodeContext context;\r
+ private CacheKey<?> key;\r
+\r
+ GECacheKey(NodeContext context, CacheKey<?> key) {\r
+ this.context = context;\r
+ this.key = key;\r
+ if (context == null || key == null) \r
+ throw new IllegalArgumentException("Null context or key is not accepted");\r
+ }\r
+\r
+ GECacheKey(GECacheKey other) {\r
+ this.context = other.context;\r
+ this.key = other.key;\r
+ if (context == null || key == null) \r
+ throw new IllegalArgumentException("Null context or key is not accepted");\r
+ }\r
+\r
+ void setValues(NodeContext context, CacheKey<?> key) {\r
+ this.context = context;\r
+ this.key = key;\r
+ if (context == null || key == null) \r
+ throw new IllegalArgumentException("Null context or key is not accepted");\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return context.hashCode() | key.hashCode();\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object object) {\r
+\r
+ if (this == object)\r
+ return true;\r
+ else if (object == null)\r
+ return false;\r
+// else if (getClass() != object.getClass())\r
+// return false;\r
+\r
+ GECacheKey i = (GECacheKey)object;\r
+\r
+ return key.equals(i.key) && context.equals(i.context);\r
+\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * This single instance is used for all get operations from the cache. This\r
+ * should work since the GE cache is meant to be single-threaded within the\r
+ * current UI thread, what ever that thread is. For put operations which\r
+ * store the key, this is not used.\r
+ */\r
+ NodeContext getNC = new NodeContext() {\r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ public Object getAdapter(Class adapter) {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public <T> T getConstant(ConstantKey<T> key) {\r
+ return null;\r
+ }\r
+ \r
+ @Override\r
+ public Set<ConstantKey<?>> getKeys() {\r
+ return Collections.emptySet();\r
+ }\r
+ };\r
+ CacheKey<?> getCK = new CacheKey<Object>() {\r
+ @Override\r
+ public Object processorIdenfitier() {\r
+ return this;\r
+ }\r
+ };\r
+ GECacheKey getKey = new GECacheKey(getNC, getCK);\r
+\r
+ public <T> IGECacheEntry put(NodeContext context, CacheKey<T> key, T value) {\r
+ IGECacheEntry entry = new GECacheEntry(context, key, value);\r
+ entries.put(new GECacheKey(context, key), entry);\r
+ return entry;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public <T> T get(NodeContext context, CacheKey<T> key) {\r
+ getKey.setValues(context, key);\r
+ IGECacheEntry entry = entries.get(getKey);\r
+ if (entry == null)\r
+ return null;\r
+ return (T) entry.getValue();\r
+ }\r
+\r
+ @Override\r
+ public <T> IGECacheEntry getEntry(NodeContext context, CacheKey<T> key) {\r
+ assert(context != null);\r
+ assert(key != null);\r
+ getKey.setValues(context, key);\r
+ return entries.get(getKey);\r
+ }\r
+\r
+ @Override\r
+ public <T> void remove(NodeContext context, CacheKey<T> key) {\r
+ getKey.setValues(context, key);\r
+ entries.remove(getKey);\r
+ }\r
+\r
+ @Override\r
+ public <T> Set<UIElementReference> getTreeReference(NodeContext context, CacheKey<T> key) {\r
+ assert(context != null);\r
+ assert(key != null);\r
+ getKey.setValues(context, key);\r
+ return treeReferences.get(getKey);\r
+ }\r
+\r
+ @Override\r
+ public <T> void putTreeReference(NodeContext context, CacheKey<T> key, UIElementReference reference) {\r
+ assert(context != null);\r
+ assert(key != null);\r
+ getKey.setValues(context, key);\r
+ Set<UIElementReference> refs = treeReferences.get(getKey);\r
+ if (refs != null) {\r
+ refs.add(reference);\r
+ } else {\r
+ refs = new THashSet<UIElementReference>(4);\r
+ refs.add(reference);\r
+ treeReferences.put(new GECacheKey(getKey), refs);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public <T> Set<UIElementReference> removeTreeReference(NodeContext context, CacheKey<T> key) {\r
+ assert(context != null);\r
+ assert(key != null);\r
+ getKey.setValues(context, key);\r
+ return treeReferences.remove(getKey);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isShown(NodeContext context) {\r
+ return references.get(context) > 0;\r
+ }\r
+\r
+ private TObjectIntHashMap<NodeContext> references = new TObjectIntHashMap<NodeContext>();\r
+ \r
+ @Override\r
+ public void incRef(NodeContext context) {\r
+ int exist = references.get(context);\r
+ references.put(context, exist+1);\r
+ }\r
+ \r
+ @Override\r
+ public void decRef(NodeContext context) {\r
+ int exist = references.get(context);\r
+ references.put(context, exist-1);\r
+ if(exist == 1) {\r
+ references.remove(context);\r
+ }\r
+ }\r
+ \r
+ public void dispose() {\r
+ references.clear();\r
+ entries.clear();\r
+ treeReferences.clear();\r
+ }\r
+ \r
+}\r