Skip to content

Package: DefaultProvider$1

DefaultProvider$1

nameinstructionbranchcomplexitylinemethod
doDispose()
M: 17 C: 41
71%
M: 4 C: 4
50%
M: 3 C: 2
40%
M: 2 C: 7
78%
M: 0 C: 1
100%
{...}
M: 0 C: 7
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.spi.core;
15:
16: import java.util.ArrayList;
17: import java.util.Collection;
18: import java.util.Collections;
19: import java.util.Iterator;
20: import java.util.LinkedHashSet;
21: import java.util.Set;
22: import java.util.concurrent.CopyOnWriteArraySet;
23:
24: import org.eclipse.core.runtime.Platform;
25: import org.eclipse.emf.common.command.BasicCommandStack;
26: import org.eclipse.emf.common.command.CommandStack;
27: import org.eclipse.emf.common.notify.Notification;
28: import org.eclipse.emf.common.notify.Notifier;
29: import org.eclipse.emf.ecore.EClass;
30: import org.eclipse.emf.ecore.EClassifier;
31: import org.eclipse.emf.ecore.EObject;
32: import org.eclipse.emf.ecore.EPackage;
33: import org.eclipse.emf.ecore.EReference;
34: import org.eclipse.emf.ecore.resource.Resource;
35: import org.eclipse.emf.ecore.resource.ResourceSet;
36: import org.eclipse.emf.ecore.util.EcoreUtil;
37: import org.eclipse.emf.ecp.core.ECPProject;
38: import org.eclipse.emf.ecp.core.ECPRepository;
39: import org.eclipse.emf.ecp.core.util.ECPContainer;
40: import org.eclipse.emf.ecp.core.util.ECPModelContextAdapter;
41: import org.eclipse.emf.ecp.core.util.ECPModelContextProvider;
42: import org.eclipse.emf.ecp.core.util.ECPUtil;
43: import org.eclipse.emf.ecp.internal.core.Activator;
44: import org.eclipse.emf.ecp.internal.core.util.Disposable;
45: import org.eclipse.emf.ecp.internal.core.util.Element;
46: import org.eclipse.emf.ecp.spi.core.util.AdapterProvider;
47: import org.eclipse.emf.ecp.spi.core.util.InternalChildrenList;
48: import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
49: import org.eclipse.emf.edit.domain.EditingDomain;
50: import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
51: import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
52:
53: /**
54: * @author Eike Stepper
55: * @since 1.1
56: */
57: public abstract class DefaultProvider extends Element implements InternalProvider {
58:         private final Disposable disposable = new Disposable(this) {
59:                 @Override
60:                 protected void doDispose() {
61:                         uiProvider = null;
62:
63:•                        for (final ECPRepository repository : ECPUtil.getECPRepositoryManager().getRepositories()) {
64:•                                if (repository.getProvider().getName().equals(getName())) {
65:                                         handleLifecycle(repository, LifecycleEvent.DISPOSE);
66:                                 }
67:                         }
68:
69:•                        for (final ECPProject project : ECPUtil.getECPProjectManager().getProjects()) {
70:•                                if (project.getProvider().getName().equals(getName())) {
71:                                         handleLifecycle(project, LifecycleEvent.DISPOSE);
72:                                 }
73:                         }
74:
75:                         DefaultProvider.this.doDispose();
76:                 }
77:         };
78:
79:         private String label;
80:
81:         private String description;
82:
83:         private AdapterProvider uiProvider;
84:
85:         /**
86:          * Convenient constructor for an {@link org.eclipse.emf.ecp.core.ECPProvider ECPProvider}.
87:          *
88:          * @param name the name of the implementing provider
89:          */
90:         protected DefaultProvider(String name) {
91:                 super(name);
92:                 label = name;
93:                 description = ""; //$NON-NLS-1$
94:         }
95:
96:         /** {@inheritDoc} */
97:         @Override
98:         public final String getType() {
99:                 return TYPE;
100:         }
101:
102:         /** {@inheritDoc} */
103:         @Override
104:         public final InternalProvider getProvider() {
105:                 return this;
106:         }
107:
108:         /** {@inheritDoc} */
109:         @Override
110:         public final String getLabel() {
111:                 return label;
112:         }
113:
114:         /** {@inheritDoc} */
115:         @Override
116:         public final void setLabel(String label) {
117:                 this.label = label;
118:         }
119:
120:         /** {@inheritDoc} */
121:         @Override
122:         public final String getDescription() {
123:                 return description;
124:         }
125:
126:         /** {@inheritDoc} */
127:         @Override
128:         public final void setDescription(String description) {
129:                 this.description = description;
130:         }
131:
132:         /** {@inheritDoc} */
133:         @Override
134:         public final AdapterProvider getUIProvider() {
135:                 return uiProvider;
136:         }
137:
138:         /** {@inheritDoc} */
139:         @Override
140:         public final void setUIProvider(AdapterProvider uiProvider) {
141:                 this.uiProvider = uiProvider;
142:         }
143:
144:         /** {@inheritDoc} */
145:         @Override
146:         public final Set<InternalProject> getOpenProjects() {
147:                 final Set<InternalProject> result = new LinkedHashSet<InternalProject>();
148:                 for (final ECPProject project : ECPUtil.getECPProjectManager().getProjects()) {
149:                         if (project.isOpen()) {
150:                                 if (project.getProvider().equals(this)) {
151:                                         result.add((InternalProject) project);
152:                                 }
153:
154:                         }
155:                 }
156:
157:                 // TODO Consider to cache the result
158:                 return result;
159:         }
160:
161:         /** {@inheritDoc} */
162:         @Override
163:         public final boolean isDisposed() {
164:                 return disposable.isDisposed();
165:         }
166:
167:         /** {@inheritDoc} */
168:         @Override
169:         public final void dispose() {
170:                 disposable.dispose();
171:         }
172:
173:         /** {@inheritDoc} */
174:         @Override
175:         public final void addDisposeListener(DisposeListener listener) {
176:                 disposable.addDisposeListener(listener);
177:         }
178:
179:         /** {@inheritDoc} */
180:         @Override
181:         public final void removeDisposeListener(DisposeListener listener) {
182:                 disposable.removeDisposeListener(listener);
183:         }
184:
185:         /**
186:          * This method is called when a provider is disposed. Subclasses which need to dispose should overwrite this.
187:          */
188:         protected void doDispose() {
189:         }
190:
191:         /** {@inheritDoc} */
192:         @Override
193:         public <T> T getAdapter(Object adaptable, Class<T> adapterType) {
194:                 if (uiProvider != null) {
195:                         return uiProvider.getAdapter(adaptable, adapterType);
196:                 }
197:
198:                 return null;
199:         }
200:
201:         /**
202:          * Returns an object which is an instance of the given class associated with this object. Returns <code>null</code>
203:          * if
204:          * no such object can be found.
205:          * <p>
206:          * This implementation of the method declared by <code>IAdaptable</code> passes the request along to the platform's
207:          * adapter manager; roughly <code>Platform.getAdapterManager().getAdapter(this, adapter)</code>. Subclasses may
208:          * override this method (however, if they do so, they should invoke the method on their superclass to ensure that
209:          * the Platform's adapter manager is consulted).
210:          * </p>
211:          *
212:          * @param adapterType
213:          * the class to adapt to
214:          * @return the adapted object or <code>null</code>
215:          * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
216:          */
217:         @Override
218:         public Object getAdapter(@SuppressWarnings("rawtypes") Class adapterType) {
219:                 return Platform.getAdapterManager().getAdapter(this, adapterType);
220:         }
221:
222:         /** {@inheritDoc} */
223:         @Override
224:         public EditingDomain createEditingDomain(InternalProject project) {
225:                 final CommandStack commandStack = createCommandStack(project);
226:                 final EditingDomain editingDomain = new AdapterFactoryEditingDomain(InternalProvider.EMF_ADAPTER_FACTORY,
227:                         commandStack);
228:                 editingDomain.getResourceSet().eAdapters().add(new ECPModelContextAdapter(project));
229:                 return editingDomain;
230:         }
231:
232:         /**
233:          * This is used during the creation of the {@link EditingDomain}. This implementation creates an
234:          * {@link BasicCommandStack}.
235:          *
236:          * @param project the project to create the {@link CommandStack} for
237:          * @return the created {@link CommandStack}
238:          */
239:         protected CommandStack createCommandStack(InternalProject project) {
240:                 return new BasicCommandStack();
241:         }
242:
243:         /** {@inheritDoc} */
244:         @Override
245:         public boolean hasCreateRepositorySupport() {
246:                 return true;
247:         }
248:
249:         /** {@inheritDoc} */
250:         @Override
251:         public boolean isSlow(Object parent) {
252:                 return false;
253:         }
254:
255:         /** {@inheritDoc} */
256:         @Override
257:         public ECPContainer getModelContext(Object element) {
258:                 if (element instanceof ECPContainer) {
259:                         return (ECPContainer) element;
260:                 }
261:
262:                 if (element instanceof ECPModelContextProvider) {
263:                         return ((ECPModelContextProvider) element).getModelContext(element);
264:                 }
265:
266:                 if (element instanceof EObject) {
267:                         final EObject eObject = (EObject) element;
268:                         final ECPContainer context = getModelContextFromAdapter(eObject);
269:                         if (context != null) {
270:                                 return context;
271:                         }
272:
273:                         element = eObject.eResource();
274:                 }
275:
276:                 if (element instanceof Resource) {
277:                         final Resource resource = (Resource) element;
278:                         final ECPContainer context = getModelContextFromAdapter(resource);
279:                         if (context != null) {
280:                                 return context;
281:                         }
282:
283:                         element = resource.getResourceSet();
284:                 }
285:
286:                 if (element instanceof ResourceSet) {
287:                         final ResourceSet resourceSet = (ResourceSet) element;
288:                         final ECPContainer context = getModelContextFromAdapter(resourceSet);
289:                         if (context != null) {
290:                                 return context;
291:                         }
292:                 }
293:
294:                 return null;
295:         }
296:
297:         /**
298:          * This allows to get the {@link ECPContainer} from a {@link Notifier} using the EcoreUtil.
299:          * This first gets the {@link ECPModelContextAdapter} and from it it gets the {@link ECPContainer}.
300:          *
301:          * @param notifier the {@link Notifier} to get the {@link ECPContainer} from
302:          * @return the {@link ECPContainer} registered as an Adapter on this {@link Notifier} or null
303:          */
304:         protected final ECPContainer getModelContextFromAdapter(Notifier notifier) {
305:                 final ECPModelContextAdapter adapter = (ECPModelContextAdapter) EcoreUtil.getAdapter(notifier.eAdapters(),
306:                         ECPModelContextAdapter.class);
307:                 if (adapter != null) {
308:                         return adapter.getContext();
309:                 }
310:
311:                 return null;
312:         }
313:
314:         /** {@inheritDoc} */
315:         @Override
316:         public void fillChildren(ECPContainer context, Object parent, InternalChildrenList childrenList) {
317:                 if (parent == ECPUtil.getECPProjectManager()) {
318:                         childrenList.addChildren(ECPUtil.getECPProjectManager().getProjects());
319:                 } else if (parent == ECPUtil.getECPRepositoryManager()) {
320:                         childrenList.addChildren(ECPUtil.getECPRepositoryManager().getRepositories());
321:                 } else {
322:                         // Get the adapter from the factory.
323:                         final ITreeItemContentProvider treeItemContentProvider = (ITreeItemContentProvider) EMF_ADAPTER_FACTORY
324:                                 .adapt(
325:                                         parent, ITreeItemContentProvider.class);
326:
327:                         // Either delegate the call or return nothing.
328:                         if (treeItemContentProvider != null) {
329:                                 final Collection<?> children = treeItemContentProvider.getChildren(parent);
330:                                 childrenList.addChildren(children);
331:                         }
332:                 }
333:         }
334:
335:         /** {@inheritDoc} */
336:         @Override
337:         public void handleLifecycle(ECPContainer context, LifecycleEvent event) {
338:                 final String providerClass = getClass().getSimpleName();
339:                 final String contextClass = context.getClass().getSimpleName();
340:                 Activator.log(providerClass + " received " + event + " for " + contextClass + " " + context); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
341:         }
342:
343:         /**
344:          * Convenient implementation of the {@link #getUnsupportedEPackages(Collection,InternalRepository)} method to return
345:          * an empty list. The
346:          * provider has to {@link Override} this method if not all {@link EPackage}s are supported.
347:          *
348:          * @param packages available packages
349:          * @param repository the repository to check
350:          *
351:          * @return the {@link Collection} of {@link EPackage EPackages} unsupported by this provider for the specified
352:          * repository
353:          */
354:         @Override
355:         public Set<EPackage> getUnsupportedEPackages(Collection<EPackage> packages, InternalRepository repository) {
356:                 return Collections.emptySet();
357:         }
358:
359:         /**
360:          * Convenient implementation of the {@link #getLinkElements(InternalProject, EObject, EReference)} method to use the
361:          * {@link ItemPropertyDescriptor} to get all object of an object.
362:          *
363:          * @param project
364:          * the project the call is from
365:          * @param modelElement
366:          * {@link EObject} to add the {@link EReference} to
367:          * @param eReference
368:          * the {@link EReference} to add
369:          * @return {@link Iterator} of {@link EObject} that can be linked
370:          */
371:         @Override
372:         public Iterator<EObject> getLinkElements(InternalProject project, EObject modelElement, EReference eReference) {
373:                 final EClass elementClass = modelElement.eClass();
374:                 EClassifier type = EcoreUtil.getReifiedType(elementClass, eReference.getEGenericType()).getEClassifier();
375:                 if (type == null) {
376:                         type = eReference.getEType();
377:                 }
378:                 return ItemPropertyDescriptor.getReachableObjectsOfType(modelElement, type).iterator();
379:         }
380:
381:         /**
382:          * Convenient implementation where nothing happens.
383:          *
384:          * @param project
385:          * the project to save
386:          */
387:         @Override
388:         public void doSave(InternalProject project) {
389:                 // do nothing
390:         }
391:
392:         /**
393:          * Convenient implementation where the provider saves changes of the project automatically, so a project never gets
394:          * dirty. Thus this returns false.
395:          *
396:          * @param project
397:          * the project to check
398:          * @return false
399:          */
400:         @Override
401:         public boolean isDirty(InternalProject project) {
402:                 return false;
403:         }
404:
405:         /**
406:          * Convenient implementation that return true during this check.
407:          *
408:          * @param project the project to check
409:          * @return true
410:          */
411:         @Override
412:         public boolean modelExists(InternalProject project) {
413:                 return true;
414:         }
415:
416:         /**
417:          * Convenient implementation that return false.
418:          *
419:          * @return false
420:          */
421:         @Override
422:         public boolean hasCreateProjectWithoutRepositorySupport() {
423:                 return false;
424:         }
425:
426:         /** {@inheritDoc} */
427:         // FIXME implement only in provider
428:         @Override
429:         public boolean contains(InternalProject project, Object object) {
430:                 return false;
431:         }
432:
433:         /**
434:          * List of registered {@link ProviderChangeListener}.
435:          *
436:          * @since 1.7
437:          */
438:         private final Set<ProviderChangeListener> changeListeners = new CopyOnWriteArraySet<ProviderChangeListener>();
439:
440:         /**
441:          * Registers a new {@link ProviderChangeListener}.
442:          *
443:          * @param listener the listener
444:          * @since 1.7
445:          */
446:         @Override
447:         public void registerChangeListener(ProviderChangeListener listener) {
448:                 changeListeners.add(listener);
449:         }
450:
451:         /**
452:          * Unregisters a new {@link ProviderChangeListener}.
453:          *
454:          * @param listener the listener
455:          * @since 1.7
456:          */
457:         @Override
458:         public void unregisterChangeListener(ProviderChangeListener listener) {
459:                 changeListeners.remove(listener);
460:         }
461:
462:         /**
463:          * @param notification a {@link Notification}
464:          * @since 1.7
465:          */
466:         protected void notifyProviderChangeListeners(Notification notification) {
467:                 for (final ProviderChangeListener listener : changeListeners) {
468:                         listener.notify(notification);
469:                 }
470:
471:         }
472:
473:         /**
474:          * {@inheritDoc}
475:          *
476:          * @see org.eclipse.emf.ecp.spi.core.InternalProvider#delete(org.eclipse.emf.ecp.spi.core.InternalProject,
477:          * java.util.Collection)
478:          * @since 1.7
479:          */
480:         @Override
481:         public void delete(InternalProject project, Collection<Object> objects) {
482:                 final ArrayList<Object> toBeDeleted = new ArrayList<Object>();
483:                 for (final Object object : objects) {
484:                         if (object instanceof EObject) {
485:                                 final EObject eObject = (EObject) object;
486:                                 final boolean canDelete = notifyCanDelete(eObject);
487:                                 if (!canDelete) {
488:                                         continue;
489:                                 }
490:                                 notifyPredelete(eObject);
491:
492:                         }
493:                         toBeDeleted.add(object);
494:                 }
495:
496:                 doDelete(project, toBeDeleted);
497:                 for (final Object object : toBeDeleted) {
498:                         if (object instanceof EObject) {
499:                                 final EObject eObject = (EObject) object;
500:                                 notifyPostDelete(eObject);
501:                         }
502:                 }
503:
504:         }
505:
506:         private void notifyPostDelete(EObject toBeDeleted) {
507:                 for (final ProviderChangeListener listener : changeListeners) {
508:                         listener.postDelete(toBeDeleted);
509:                 }
510:
511:         }
512:
513:         private void notifyPredelete(EObject toBeDeleted) {
514:                 for (final ProviderChangeListener listener : changeListeners) {
515:                         listener.preDelete(toBeDeleted);
516:                 }
517:
518:         }
519:
520:         private boolean notifyCanDelete(EObject toBeDeleted) {
521:                 boolean canDelete = true;
522:                 for (final ProviderChangeListener listener : changeListeners) {
523:                         canDelete = listener.canDelete(toBeDeleted);
524:                         if (!canDelete) {
525:                                 break;
526:                         }
527:                 }
528:                 return canDelete;
529:         }
530:
531:         /**
532:          * Executes the delete opertation. Is supposed to be implemented by providers.
533:          *
534:          * @param project the project from where to delete
535:          * @param objects the {@link Collection} if {@link Object Objects} to delete
536:          * @since 1.7
537:          */
538:         public abstract void doDelete(InternalProject project, Collection<Object> objects);
539: }