/** | |
* <copyright> | |
* | |
* Copyright (c) 2008-2021 See4sys, Siemens and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* See4sys - Initial API and implementation | |
* Siemens - [577073] URI change detector delegate extension | |
* | |
* </copyright> | |
*/ | |
package org.eclipse.sphinx.emf.workspace.referentialintegrity; | |
import java.util.HashSet; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.concurrent.ConcurrentHashMap; | |
import org.eclipse.core.runtime.Assert; | |
import org.eclipse.core.runtime.IConfigurationElement; | |
import org.eclipse.core.runtime.IExtension; | |
import org.eclipse.core.runtime.IExtensionPoint; | |
import org.eclipse.core.runtime.IExtensionRegistry; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.emf.ecore.resource.Resource; | |
import org.eclipse.emf.ecore.resource.impl.ResourceImpl; | |
import org.eclipse.osgi.util.NLS; | |
import org.eclipse.sphinx.emf.metamodel.IMetaModelDescriptor; | |
import org.eclipse.sphinx.emf.workspace.Activator; | |
import org.eclipse.sphinx.emf.workspace.internal.messages.Messages; | |
import org.eclipse.sphinx.platform.util.PlatformLogUtil; | |
/** | |
* Registers all the contributed {@link IURIChangeDetectorDelegate}. | |
*/ | |
public class URIChangeDetectorDelegateRegistry { | |
private static final String EXTP_URI_CHANGE_DETECTOR_DELEGATE = "org.eclipse.sphinx.emf.workspace.uriChangeDetectorDelegates";//$NON-NLS-1$ | |
private static final String NODE_APPLICABLEFOR = "applicableFor";//$NON-NLS-1$ | |
private static final String NODE_DELEGATE = "delegate";//$NON-NLS-1$ | |
private static final String ATTR_ID = "id"; //$NON-NLS-1$ | |
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$ | |
private static final String ATTR_OVERRIDE = "override"; //$NON-NLS-1$ | |
private static final String ATTR_RESOURCE_TYPE = "resourceType";//$NON-NLS-1$ | |
public static final URIChangeDetectorDelegateRegistry INSTANCE = new URIChangeDetectorDelegateRegistry(); | |
private final Map<Class<? extends Resource>, IURIChangeDetectorDelegate> fContributedURIChangeDetectorDelegates = new ConcurrentHashMap<Class<? extends Resource>, IURIChangeDetectorDelegate>(); | |
private URIChangeDetectorDelegateRegistry() { | |
readContributedURIChangeDetectors(); | |
} | |
/** | |
* Returns the contributed {@link IURIChangeDetectorDelegate URIChangeDetectorDelegate} for the provided | |
* {@link Resource resource} if such one exists. | |
* | |
* @param resource | |
* the {@link Resource resource} to retrieve {@link IURIChangeDetectorDelegate URIChangeDetectorDelegate} | |
* for. | |
* @return the {@link IURIChangeDetectorDelegate URIChangeDetectorDelegate} contributed for the provided resource's | |
* {@link Class type}. | |
*/ | |
public IURIChangeDetectorDelegate getDetectorDelegate(Resource resource) { | |
if (resource != null) { | |
// We retrieve delegate contributed for the given resource type | |
Class<? extends Resource> resourceClass = resource.getClass(); | |
return getDetectorDelegate(resourceClass); | |
} | |
return null; | |
} | |
public void removeDelegate(IURIChangeDetectorDelegate delegate) { | |
if (delegate != null) { | |
for (Class<? extends Resource> resourceType : fContributedURIChangeDetectorDelegates.keySet()) { | |
if (fContributedURIChangeDetectorDelegates.get(resourceType).equals(delegate)) { | |
fContributedURIChangeDetectorDelegates.remove(resourceType); | |
} | |
} | |
} | |
} | |
/** | |
* Returns the contributed {@link IURIChangeDetectorDelegate URIChangeDetectorDelegate} for the provided | |
* {@link Class resource Type} if such one exists. | |
* | |
* @param resourceType | |
* the {@link Class resource Type} to retrieve {@link IURIChangeDetectorDelegate | |
* URIChangeDetectorDelegate} for. | |
* @return the {@link IURIChangeDetectorDelegate URIChangeDetectorDelegate} contributed for the provided | |
* {@link Class resource Type}. | |
*/ | |
public IURIChangeDetectorDelegate getDetectorDelegate(Class<? extends Resource> resourceType) { | |
IURIChangeDetectorDelegate uriChangeDetectorDelegate = fContributedURIChangeDetectorDelegates.get(resourceType); | |
// If no such exists we try to match the resource type with one of its super class and return the | |
// contributed delegate | |
if (uriChangeDetectorDelegate == null) { | |
uriChangeDetectorDelegate = getDetectorDelegateOfSuperType(resourceType); | |
if (uriChangeDetectorDelegate != null) { | |
// We register this delegate with the resource type to improve future request on such resource type | |
fContributedURIChangeDetectorDelegates.put(resourceType, uriChangeDetectorDelegate); | |
} | |
} | |
return uriChangeDetectorDelegate; | |
} | |
@SuppressWarnings("unchecked") | |
// TODO refactorize see ReflectUtil , rename method findDetectorDelegate optimize call by including first call | |
private IURIChangeDetectorDelegate getDetectorDelegateOfSuperType(Class<? extends Resource> resourceClass) { | |
Class<? extends Resource> superclass = (Class<? extends Resource>) resourceClass.getSuperclass(); | |
if (Resource.class.equals(superclass) || ResourceImpl.class.equals(superclass)) { | |
return fContributedURIChangeDetectorDelegates.get(ResourceImpl.class); | |
} else { | |
IURIChangeDetectorDelegate uriChangeDetectorDelegate = fContributedURIChangeDetectorDelegates.get(superclass); | |
if (uriChangeDetectorDelegate == null) { | |
return getDetectorDelegateOfSuperType(superclass); | |
} else { | |
return uriChangeDetectorDelegate; | |
} | |
} | |
} | |
private void readContributedURIChangeDetectors() { | |
IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); | |
IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(EXTP_URI_CHANGE_DETECTOR_DELEGATE); | |
IExtension[] extensions = extensionPoint.getExtensions(); | |
Set<String> overriddenIds = new HashSet<String>(); | |
for (IExtension extension : extensions) { | |
IConfigurationElement[] configElements = extension.getConfigurationElements(); | |
overriddenIds.addAll(getOverriddenURIChangeDetectorsIds(configElements)); | |
} | |
for (IExtension extension : extensions) { | |
IConfigurationElement[] configElements = extension.getConfigurationElements(); | |
readContributedURIChangeDetectors(configElements, overriddenIds); | |
} | |
} | |
/** | |
* Reads contributions to <em>Meta-Model Descriptor</em> extension point. | |
* <p> | |
* <table> | |
* <tr valign=top> | |
* <td><b>Note</b> </td> | |
* <td>It is recommended to call this method inside a block <tt><b>synchronized</b></tt> on the encapsulated | |
* <code>fMetaModelDescriptors</code> field in order to avoid inconsistencies in registered meta-model | |
* {@linkplain IMetaModelDescriptor descriptor}s in case of concurrent read/adds.</td> | |
* </tr> | |
* </table> | |
*/ | |
@SuppressWarnings("unchecked") | |
private void readContributedURIChangeDetectors(IConfigurationElement[] configElements, Set<String> overriddenIds) { | |
for (IConfigurationElement configElement : configElements) { | |
try { | |
String id = configElement.getAttribute(ATTR_ID); | |
IURIChangeDetectorDelegate uriChangeDetectorDelegate = null; | |
if (!overriddenIds.contains(id)) { | |
uriChangeDetectorDelegate = (IURIChangeDetectorDelegate) configElement.createExecutableExtension(ATTR_CLASS); | |
IConfigurationElement[] childrenConfigElements = configElement.getChildren(); | |
for (IConfigurationElement childConfigElement : childrenConfigElements) { | |
if (NODE_APPLICABLEFOR.equals(childConfigElement.getName())) { | |
String className = childConfigElement.getAttribute(ATTR_RESOURCE_TYPE); | |
Class<?> clazz = Platform.getBundle(configElement.getContributor().getName()).loadClass(className); | |
if (Resource.class.isAssignableFrom(clazz)) { | |
Class<? extends Resource> resourceType = (Class<? extends Resource>) clazz; | |
addDelegate(resourceType, uriChangeDetectorDelegate); | |
} | |
} | |
} | |
} | |
} catch (Exception ex) { | |
PlatformLogUtil.logAsError(Activator.getDefault(), ex); | |
} | |
} | |
} | |
private Set<String> getOverriddenURIChangeDetectorsIds(IConfigurationElement[] configElements) { | |
Assert.isNotNull(configElements); | |
Set<String> overriddenIds = new HashSet<String>(); | |
for (IConfigurationElement configElement : configElements) { | |
if (NODE_DELEGATE.equals(configElement.getName())) { | |
String overriddenURIChangeDetectorDelegateId = configElement.getAttribute(ATTR_OVERRIDE); | |
if (overriddenURIChangeDetectorDelegateId != null) { | |
if (!overriddenIds.contains(overriddenURIChangeDetectorDelegateId)) { | |
overriddenIds.add(overriddenURIChangeDetectorDelegateId); | |
} else { | |
PlatformLogUtil.logAsWarning(Activator.getPlugin(), new RuntimeException( | |
NLS.bind(Messages.warning_multipleOverridesForSameURIChangeDetectorDelegate, overriddenURIChangeDetectorDelegateId))); | |
} | |
} | |
} | |
} | |
return overriddenIds; | |
} | |
public void addDelegate(Class<? extends Resource> resourceType, IURIChangeDetectorDelegate uriChangeDetectorDelegate) { | |
if (fContributedURIChangeDetectorDelegates.get(resourceType) == null) { | |
fContributedURIChangeDetectorDelegates.put(resourceType, uriChangeDetectorDelegate); | |
} else { | |
PlatformLogUtil.logAsWarning(Activator.getPlugin(), | |
new RuntimeException(NLS.bind(Messages.warning_multipleURIChangeDetectorDelegatesContributedForSameResourceType, resourceType))); | |
} | |
} | |
} |