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