--- /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 fi.vtt.simantics.procore.internal;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.Iterator;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.Disposable;\r
+import org.simantics.db.ServiceLocator;\r
+import org.simantics.db.exception.ServiceNotFoundException;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ServiceLocatorImpl implements ServiceLocator {\r
+\r
+ /**\r
+ * The parent for this service locator. If a service can't be found in this\r
+ * locator, then the parent is asked. This value may be <code>null</code>\r
+ * if there is no parent.\r
+ */\r
+ private final ServiceLocator parent;\r
+\r
+ /**\r
+ * The map of services maintained by the workbench window. These services\r
+ * are initialized during workbench window during the\r
+ * {@link #configureShell(Shell)}. This value is <code>null</code> until\r
+ * a service is registered.\r
+ */\r
+ private Map<Class<?>, Object> services = null;\r
+\r
+ /**\r
+ * Constructs a service locator with no parent.\r
+ */\r
+ public ServiceLocatorImpl() {\r
+ this(null);\r
+ }\r
+\r
+ /**\r
+ * Constructs a service locator with the given parent.\r
+ * \r
+ * @param parent\r
+ * The parent for this service locator; this value may be\r
+ * <code>null</code>.\r
+ */\r
+ public ServiceLocatorImpl(final ServiceLocator parent) {\r
+ this.parent = parent;\r
+ }\r
+\r
+// public final void activate() {\r
+// if (services != null) {\r
+// final Iterator serviceItr = services.values().iterator();\r
+// while (serviceItr.hasNext()) {\r
+// final Object service = serviceItr.next();\r
+// if (service instanceof INestable) {\r
+// final INestable nestableService = (INestable) service;\r
+// nestableService.activate();\r
+// }\r
+// }\r
+// }\r
+// }\r
+//\r
+// public final void deactivate() {\r
+// if (services != null) {\r
+// final Iterator serviceItr = services.values().iterator();\r
+// while (serviceItr.hasNext()) {\r
+// final Object service = serviceItr.next();\r
+// if (service instanceof INestable) {\r
+// final INestable nestableService = (INestable) service;\r
+// nestableService.deactivate();\r
+// }\r
+// }\r
+// }\r
+// }\r
+\r
+ public final void dispose() {\r
+ Map<Class<?>, Object> s = null;\r
+ synchronized (this) {\r
+ s = services;\r
+ services = null;\r
+ }\r
+ if (s != null) {\r
+ final Iterator<Object> serviceItr = s.values().iterator();\r
+ while (serviceItr.hasNext()) {\r
+ final Object object = serviceItr.next();\r
+ if (object instanceof Disposable) {\r
+ final Disposable service = (Disposable) object;\r
+ service.dispose();\r
+ }\r
+ }\r
+ s.clear();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public final <T> T getService(final Class<T> key) {\r
+ T t = peekService(key);\r
+ if (t == null)\r
+ throw new ServiceNotFoundException(this, key);\r
+ return t;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public final <T> T peekService(final Class<T> key) {\r
+ final Object service;\r
+ synchronized (this) {\r
+ if (services != null) {\r
+ service = services.get(key);\r
+ } else {\r
+ service = null;\r
+ }\r
+ }\r
+ if (service == null)\r
+ if (parent != null)\r
+ return parent.getService(key);\r
+ else\r
+ return null;\r
+ T t = null;\r
+ try {\r
+ t = (T)service;\r
+ } catch (ClassCastException e) {\r
+ }\r
+ return t;\r
+ }\r
+\r
+ @Override\r
+ public final boolean hasService(final Class<?> key) {\r
+ if (services != null) {\r
+ if (services.containsKey(key)) {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Registers a service with this locator. If there is an existing service\r
+ * matching the same <code>api</code> and it implements\r
+ * {@link Disposable}, it will be disposed.\r
+ * \r
+ * @param api\r
+ * This is the interface that the service implements. Must not be\r
+ * <code>null</code>.\r
+ * @param service\r
+ * The service to register. This must be some implementation of\r
+ * <code>api</code>. This value must not be <code>null</code>.\r
+ */\r
+ public final <T> void registerService(final Class<T> api, final T service) {\r
+ if (api == null) {\r
+ throw new NullPointerException("The service key cannot be null"); //$NON-NLS-1$\r
+ }\r
+\r
+// if (!api.isInstance(service)) {\r
+// throw new IllegalArgumentException(\r
+// "The service does not implement the given interface"); //$NON-NLS-1$\r
+// }\r
+\r
+ synchronized (this) {\r
+ if (services == null) {\r
+ services = new THashMap<Class<?>, Object>();\r
+ }\r
+\r
+ final Object currentService = services.remove(api);\r
+ if (currentService instanceof Disposable) {\r
+ final Disposable disposable = (Disposable) currentService;\r
+ disposable.dispose();\r
+ }\r
+\r
+ if (service == null) {\r
+ if (services.isEmpty()) {\r
+ services = null;\r
+ }\r
+ } else {\r
+// System.out.println("register " + api.toString());\r
+ services.put(api, service);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+}\r