blob: 599a795b000e34f2d55adc9fef78cac7d9f70bdc [file] [log] [blame]
/**
* <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>&nbsp;&nbsp;</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)));
}
}
}