Skip to content

Package: Registry

Registry

nameinstructionbranchcomplexitylinemethod
Registry()
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
addObserver(ECPObserver)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
changeElements(Set, Set)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
disposed(ECPDisposable)
M: 23 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
doChangeElements(Set, Set)
M: 0 C: 127
100%
M: 4 C: 16
80%
M: 4 C: 7
64%
M: 0 C: 32
100%
M: 0 C: 1
100%
elementsChanged(Collection, Collection)
M: 0 C: 1
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getElement(String)
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getElementCount()
M: 12 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
getElementNames()
M: 0 C: 16
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getElements()
M: 0 C: 16
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
hasElement(String)
M: 13 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
hasElements()
M: 2 C: 14
88%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 3
100%
M: 0 C: 1
100%
isDisposingElement()
M: 5 C: 8
62%
M: 3 C: 1
25%
M: 2 C: 1
33%
M: 0 C: 2
100%
M: 0 C: 1
100%
isRemoveDisposedElements()
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
removeObserver(ECPObserver)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011 Eike Stepper (Berlin, Germany) and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * Eike Stepper - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emf.ecp.internal.core.util;
15:
16: import java.util.ArrayList;
17: import java.util.Collection;
18: import java.util.Collections;
19: import java.util.HashMap;
20: import java.util.HashSet;
21: import java.util.Map;
22: import java.util.Set;
23:
24: import org.eclipse.emf.ecp.core.util.ECPUtil;
25: import org.eclipse.emf.ecp.core.util.observer.ECPObserver;
26: import org.eclipse.emf.ecp.internal.core.Activator;
27: import org.eclipse.emf.ecp.spi.core.util.ECPDisposable;
28: import org.eclipse.emf.ecp.spi.core.util.ECPDisposable.DisposeListener;
29: import org.eclipse.net4j.util.lifecycle.Lifecycle;
30:
31: /**
32: * @author Eike Stepper
33: * @param <ELEMENT>
34: * @param <OBSERVER>
35: */
36: public abstract class Registry<ELEMENT, OBSERVER extends ECPObserver> extends Lifecycle implements DisposeListener {
37:         private static final ThreadLocal<Boolean> DISPOSING_ELEMENT = new InheritableThreadLocal<Boolean>();
38:
39:         private final Map<String, ELEMENT> elements = new HashMap<String, ELEMENT>();
40:
41:         /**
42:          * Default constructor.
43:          */
44:         public Registry() {
45:         }
46:
47:         /**
48:          * Retrieves an element with a certain name from the registry.
49:          *
50:          * @param key the name of the element to retrieve
51:          * @return the element or null if not contained in the registry
52:          */
53:         public final ELEMENT getElement(String key) {
54:                 checkActive();
55:                 synchronized (this) {
56:                         return elements.get(key);
57:                 }
58:         }
59:
60:         /**
61:          * Returns the names of the elements managed by the registry.
62:          *
63:          * @return a set of strings representing the names of elements
64:          */
65:         public final Set<String> getElementNames() {
66:                 checkActive();
67:                 synchronized (this) {
68:                         // return elements.keySet().toArray(new String[elements.size()]);
69:                         return Collections.unmodifiableSet(new HashSet<String>(elements.keySet()));
70:                 }
71:         }
72:
73:         /**
74:          * Returns the number of elements managed by the registry.
75:          *
76:          * @return an integer
77:          */
78:         public final int getElementCount() {
79:                 checkActive();
80:                 synchronized (this) {
81:                         return elements.size();
82:                 }
83:         }
84:
85:         /**
86:          * Returns the list of elements managed by the registry.
87:          *
88:          * @return a collection of elements
89:          */
90:         public final Collection<ELEMENT> getElements() {
91:                 checkActive();
92:                 synchronized (this) {
93:                         return Collections.unmodifiableCollection(new ArrayList<ELEMENT>(elements.values()));
94:                         // ELEMENT[] result = createElementArray(elements.size());
95:                         // return elements.values().toArray(result);
96:                 }
97:         }
98:
99:         /**
100:          * Returns if the registry has elements.
101:          *
102:          * @return true if the registry has elements
103:          */
104:         public final boolean hasElements() {
105:                 checkActive();
106:                 synchronized (this) {
107:•                        return !elements.isEmpty();
108:                 }
109:         }
110:
111:         /**
112:          * Checks if an element with a certain name is managed by the registry.
113:          *
114:          * @param name the name of the element to check
115:          * @return true if the element is managed by the registry
116:          */
117:         public final boolean hasElement(String name) {
118:                 checkActive();
119:                 synchronized (this) {
120:                         return elements.containsKey(name);
121:                 }
122:         }
123:
124:         /**
125:          * Adds or remove elements contained in the registry.
126:          *
127:          * @param remove a set of elements to be removed
128:          * @param add a set of elements to be added
129:          */
130:         public final void changeElements(Set<String> remove, Set<ELEMENT> add) {
131:                 checkActive();
132:                 doChangeElements(remove, add);
133:         }
134:
135:         /** {@inheritDoc} */
136:         @Override
137:         @SuppressWarnings("unchecked")
138:         public final void disposed(ECPDisposable disposable) {
139:•                if (isRemoveDisposedElements()) {
140:                         final String name = getElementName((ELEMENT) disposable);
141:•                        if (name != null) {
142:                                 try {
143:                                         DISPOSING_ELEMENT.set(true);
144:                                         doChangeElements(Collections.singleton(name), null);
145:                                 } finally {
146:                                         DISPOSING_ELEMENT.remove();
147:                                 }
148:                         }
149:                 }
150:         }
151:
152:         /**
153:          *
154:          * @return Whether elements should be removed from the registry if they are disposed.
155:          */
156:         protected boolean isRemoveDisposedElements() {
157:                 return true;
158:         }
159:
160:         /**
161:          * Executes adding or removing elements contained in the registry.
162:          * As a caller, use changeElements().
163:          *
164:          * @param remove a set of elements to be removed
165:          * @param add a set of elements to be added
166:          * @return a set of elements, which have been removed
167:          */
168:         protected final Set<ELEMENT> doChangeElements(Set<String> remove, Set<ELEMENT> add) {
169:                 Set<ELEMENT> result = null;
170:                 final Set<ELEMENT> oldElements = new HashSet<ELEMENT>();
171:                 Set<ELEMENT> newElements = null;
172:
173:                 synchronized (this) {
174:                         oldElements.addAll(elements.values());
175:
176:•                        if (remove != null) {
177:•                                for (final String name : remove) {
178:                                         final ELEMENT element = elements.remove(name);
179:•                                        if (element != null) {
180:•                                                if (element instanceof ECPDisposable) {
181:                                                         final ECPDisposable disposable = (ECPDisposable) element;
182:                                                         disposable.removeDisposeListener(this);
183:                                                 }
184:
185:•                                                if (result == null) {
186:                                                         result = new HashSet<ELEMENT>();
187:                                                 }
188:
189:                                                 result.add(element);
190:                                         }
191:                                 }
192:                         }
193:
194:•                        if (add != null) {
195:•                                for (final ELEMENT element : add) {
196:                                         final String name = getElementName(element);
197:                                         elements.put(name, element);
198:
199:•                                        if (element instanceof ECPDisposable) {
200:                                                 final ECPDisposable disposable = (ECPDisposable) element;
201:                                                 disposable.addDisposeListener(this);
202:                                         }
203:                                 }
204:                         }
205:
206:•                        if (!oldElements.equals(elements)) {
207:                                 newElements = new HashSet<ELEMENT>(elements.values());
208:                         }
209:                 }
210:
211:•                if (newElements != null) {
212:                         // ELEMENT[] oldArray = oldElements.toArray(createElementArray(oldElements.size()));
213:                         // ELEMENT[] newArray = newElements.toArray(createElementArray(newElements.size()));
214:                         final Collection<ELEMENT> unmodifiableOld = Collections.unmodifiableCollection(oldElements);
215:                         final Collection<ELEMENT> unmodifiableNew = Collections.unmodifiableCollection(newElements);
216:                         elementsChanged(unmodifiableOld, unmodifiableNew);
217:
218:                         try {
219:                                 notifyObservers(unmodifiableOld, unmodifiableNew);
220:                         } catch (final Exception ex) {
221:                                 Activator.log(ex);
222:                         }
223:                 }
224:
225:                 return result;
226:         }
227:
228:         /**
229:          * Adds an {@link ECPObserver} to the {@link org.eclipse.emf.ecp.core.util.observer.ECPObserverBus}.
230:          *
231:          * @param observer the observer to be added
232:          */
233:         public void addObserver(OBSERVER observer) {
234:                 ECPUtil.getECPObserverBus().register(observer);
235:         }
236:
237:         /**
238:          * Removes an {@link ECPObserver} to the {@link org.eclipse.emf.ecp.core.util.observer.ECPObserverBus}.
239:          *
240:          * @param observer the observer to be removed
241:          */
242:         public void removeObserver(OBSERVER observer) {
243:                 ECPUtil.getECPObserverBus().unregister(observer);
244:         }
245:
246:         /**
247:          * Notifies observers that the elements in the registry have changed.
248:          *
249:          * @param oldArray The old collection of elements
250:          * @param newArray The new collection of elements
251:          * @throws Exception
252:          */
253:         protected abstract void notifyObservers(Collection<ELEMENT> oldArray, Collection<ELEMENT> newArray)
254:                 throws Exception;
255:
256:         protected void elementsChanged(Collection<ELEMENT> oldElements, Collection<ELEMENT> newElements) {
257:                 // Can be overridden in subclasses
258:         }
259:
260:         /**
261:          * @param element the element to retrieve a name for.
262:          * @return the name of an element
263:          */
264:         protected abstract String getElementName(ELEMENT element);
265:
266:         protected static boolean isDisposingElement() {
267:                 final Boolean disposingElement = DISPOSING_ELEMENT.get();
268:•                return disposingElement != null && disposingElement;
269:         }
270: }