]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ServiceLocatorImpl.java
Sync git svn branch with SVN repository r33249.
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / ServiceLocatorImpl.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package fi.vtt.simantics.procore.internal;\r
13 \r
14 import gnu.trove.map.hash.THashMap;\r
15 \r
16 import java.util.Iterator;\r
17 import java.util.Map;\r
18 \r
19 import org.simantics.db.Disposable;\r
20 import org.simantics.db.ServiceLocator;\r
21 import org.simantics.db.exception.ServiceNotFoundException;\r
22 \r
23 /**\r
24  * @author Tuukka Lehtonen\r
25  */\r
26 public class ServiceLocatorImpl implements ServiceLocator {\r
27 \r
28     /**\r
29      * The parent for this service locator. If a service can't be found in this\r
30      * locator, then the parent is asked. This value may be <code>null</code>\r
31      * if there is no parent.\r
32      */\r
33     private final ServiceLocator parent;\r
34 \r
35     /**\r
36      * The map of services maintained by the workbench window. These services\r
37      * are initialized during workbench window during the\r
38      * {@link #configureShell(Shell)}. This value is <code>null</code> until\r
39      * a service is registered.\r
40      */\r
41     private Map<Class<?>, Object> services = null;\r
42 \r
43     /**\r
44      * Constructs a service locator with no parent.\r
45      */\r
46     public ServiceLocatorImpl() {\r
47         this(null);\r
48     }\r
49 \r
50     /**\r
51      * Constructs a service locator with the given parent.\r
52      * \r
53      * @param parent\r
54      *            The parent for this service locator; this value may be\r
55      *            <code>null</code>.\r
56      */\r
57     public ServiceLocatorImpl(final ServiceLocator parent) {\r
58         this.parent = parent;\r
59     }\r
60 \r
61 //    public final void activate() {\r
62 //        if (services != null) {\r
63 //            final Iterator serviceItr = services.values().iterator();\r
64 //            while (serviceItr.hasNext()) {\r
65 //                final Object service = serviceItr.next();\r
66 //                if (service instanceof INestable) {\r
67 //                    final INestable nestableService = (INestable) service;\r
68 //                    nestableService.activate();\r
69 //                }\r
70 //            }\r
71 //        }\r
72 //    }\r
73 //\r
74 //    public final void deactivate() {\r
75 //        if (services != null) {\r
76 //            final Iterator serviceItr = services.values().iterator();\r
77 //            while (serviceItr.hasNext()) {\r
78 //                final Object service = serviceItr.next();\r
79 //                if (service instanceof INestable) {\r
80 //                    final INestable nestableService = (INestable) service;\r
81 //                    nestableService.deactivate();\r
82 //                }\r
83 //            }\r
84 //        }\r
85 //    }\r
86 \r
87     public final void dispose() {\r
88         Map<Class<?>, Object> s = null;\r
89         synchronized (this) {\r
90             s = services;\r
91             services = null;\r
92         }\r
93         if (s != null) {\r
94             final Iterator<Object> serviceItr = s.values().iterator();\r
95             while (serviceItr.hasNext()) {\r
96                 final Object object = serviceItr.next();\r
97                 if (object instanceof Disposable) {\r
98                     final Disposable service = (Disposable) object;\r
99                     service.dispose();\r
100                 }\r
101             }\r
102             s.clear();\r
103         }\r
104     }\r
105 \r
106     @Override\r
107     public final <T> T getService(final Class<T> key) {\r
108         T t = peekService(key);\r
109         if (t == null)\r
110             throw new ServiceNotFoundException(this, key);\r
111         return t;\r
112     }\r
113 \r
114     @SuppressWarnings("unchecked")\r
115     @Override\r
116     public final <T> T peekService(final Class<T> key) {\r
117         final Object service;\r
118         synchronized (this) {\r
119             if (services != null) {\r
120                 service = services.get(key);\r
121             } else {\r
122                 service = null;\r
123             }\r
124         }\r
125         if (service == null)\r
126             if (parent != null)\r
127                 return parent.getService(key);\r
128             else\r
129                 return null;\r
130         T t = null;\r
131         try {\r
132             t = (T)service;\r
133         } catch (ClassCastException e) {\r
134         }\r
135         return t;\r
136     }\r
137 \r
138     @Override\r
139     public final boolean hasService(final Class<?> key) {\r
140         if (services != null) {\r
141             if (services.containsKey(key)) {\r
142                 return true;\r
143             }\r
144         }\r
145 \r
146         return false;\r
147     }\r
148 \r
149     /**\r
150      * Registers a service with this locator. If there is an existing service\r
151      * matching the same <code>api</code> and it implements\r
152      * {@link Disposable}, it will be disposed.\r
153      * \r
154      * @param api\r
155      *            This is the interface that the service implements. Must not be\r
156      *            <code>null</code>.\r
157      * @param service\r
158      *            The service to register. This must be some implementation of\r
159      *            <code>api</code>. This value must not be <code>null</code>.\r
160      */\r
161     public final <T> void registerService(final Class<T> api, final T service) {\r
162         if (api == null) {\r
163             throw new NullPointerException("The service key cannot be null"); //$NON-NLS-1$\r
164         }\r
165 \r
166 //        if (!api.isInstance(service)) {\r
167 //            throw new IllegalArgumentException(\r
168 //                    "The service does not implement the given interface"); //$NON-NLS-1$\r
169 //        }\r
170 \r
171         synchronized (this) {\r
172             if (services == null) {\r
173                 services = new THashMap<Class<?>, Object>();\r
174             }\r
175 \r
176             final Object currentService = services.remove(api);\r
177             if (currentService instanceof Disposable) {\r
178                 final Disposable disposable = (Disposable) currentService;\r
179                 disposable.dispose();\r
180             }\r
181 \r
182             if (service == null) {\r
183                 if (services.isEmpty()) {\r
184                     services = null;\r
185                 }\r
186             } else {\r
187 //              System.out.println("register " + api.toString());\r
188                 services.put(api, service);\r
189             }\r
190         }\r
191     }\r
192 \r
193 \r
194 }\r