blob: b0025755ff0d766138a88ba29775231e495d10a3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Mia-Software.
* 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:
* Fabien Giquel (Mia-Software) - initial API and implementation
* Nicolas Bros (Mia-Software) - Bug 338702 - [Discovery] specify initial value for Parameters
*******************************************************************************/
package org.eclipse.modisco.infra.discovery.core.internal;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.gmt.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.modisco.infra.discovery.catalog.DirectionKind;
import org.eclipse.modisco.infra.discovery.catalog.DiscovererDescription;
import org.eclipse.modisco.infra.discovery.catalog.DiscovererParameter;
import org.eclipse.modisco.infra.discovery.core.IDiscoverer;
import org.eclipse.modisco.infra.discovery.core.IDiscoveryManager;
import org.eclipse.modisco.infra.discovery.core.exception.DiscoveryException;
import org.eclipse.modisco.infra.discovery.core.internal.catalog.DiscovererRegistry;
/**
* Registry for accessing {@link IDiscoverer} instances.
*
*/
public final class DiscoveryManager implements IDiscoveryManager {
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getDiscoverer(java.lang.String)
*/
public IDiscoverer<?> createDiscovererImpl(final String id) {
DiscovererDescription discovererDescription = getDiscovererDescription(id);
if (discovererDescription != null) {
return createDiscovererImpl(discovererDescription);
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getDiscoverer
* (org.eclipse.modisco.infra.discovery.catalog.DiscovererDescription)
*/
public IDiscoverer<?> createDiscovererImpl(final DiscovererDescription description) {
return DiscovererRegistry.INSTANCE.createDiscoverer(description);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getApplicableDiscoverers(java.lang.Object)
*/
public Collection<DiscovererDescription> getApplicableDiscoverers(final Object source) {
Set<DiscovererDescription> result = new HashSet<DiscovererDescription>();
for (DiscovererDescription aDiscoveryHandler : getDiscoverers()) {
if (isApplicable(aDiscoveryHandler, source)) {
result.add(aDiscoveryHandler);
}
}
return Collections.unmodifiableSet(result);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* isApplicable
* (org.eclipse.modisco.infra.discovery.catalog.DiscovererDescription,
* java.lang.Object)
*/
@SuppressWarnings("unchecked")
public boolean isApplicable(final DiscovererDescription discovererDefinition,
final Object source) {
// We must check the parameterized source type (T) of delegate
// before calling isApplicableTo to avoid ClassCastException (case of
// wildcard declarations)
Class<?> discovererSourceType = discovererDefinition.getSourceType();
// used a cached discoverer to avoid having to create a new instance
// each time this method is called
IDiscoverer<?> cachedDiscoverer = DiscovererRegistry.INSTANCE
.getCachedDiscoverer(discovererDefinition);
return discovererSourceType != null && discovererSourceType.isInstance(source)
&& ((IDiscoverer<Object>) cachedDiscoverer).isApplicableTo(source);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getDiscoverers()
*/
public Collection<DiscovererDescription> getDiscoverers() {
return DiscovererRegistry.INSTANCE.getDiscovererDescriptions();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getDiscovererDescription(java.lang.Class)
*/
public static DiscovererDescription getDiscovererDescription(final Class<?> discovererClass) {
Collection<DiscovererDescription> discovererDescriptions = DiscovererRegistry.INSTANCE
.getDiscovererDescriptions();
for (DiscovererDescription discovererDescription : discovererDescriptions) {
if (discovererClass.equals(discovererDescription.getImplementationType())) {
return discovererDescription;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getDiscovererDescription(java.lang.String)
*/
public DiscovererDescription getDiscovererDescription(final String id) {
for (DiscovererDescription discovererDescription : getDiscoverers()) {
if (id.equals(discovererDescription.getId())) {
return discovererDescription;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* getDiscovererDescription
* (org.eclipse.modisco.infra.discovery.core.IDiscoverer)
*/
public DiscovererDescription getDiscovererDescription(final IDiscoverer<?> discoverer) {
for (DiscovererDescription discovererDescription : getDiscoverers()) {
if (discovererDescription.getImplementationType().equals(discoverer.getClass())) {
return discovererDescription;
}
// IDiscoverer<?> cachedDiscoverer = DiscovererRegistry.INSTANCE
// .getCachedDiscoverer(discovererDescription);
// if (cachedDiscoverer.getClass().equals(discoverer.getClass())) {
// return discovererDescription;
// }
}
return null;
}
/**
* This method computes at runtime the source type argument for one
* discoverer implementation (generic T type)
*/
protected static void computeSourceType(final DiscovererDescription discovererDescription) {
Class<?> sourceType = null;
try {
// At runtime we look for the "isApplicableTo(T)" method to deduce
// the instantiated T type
for (Method aMethod : discovererDescription.getImplementationType().getMethods()) {
if (aMethod.getName().equals("isApplicableTo") //$NON-NLS-1$
&& aMethod.getParameterTypes().length == 1) {
Class<?> parameterClass = aMethod.getParameterTypes()[0];
if (sourceType == null || parameterClass != java.lang.Object.class) {
sourceType = parameterClass;
}
}
}
} catch (IllegalArgumentException e) {
MoDiscoLogger.logWarning(e, Activator.getDefault());
}
discovererDescription.setSourceType(sourceType);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* canRetrieveValue
* (org.eclipse.modisco.infra.discovery.catalog.DiscovererParameter)
*/
public boolean canRetrieveValue(final DiscovererParameter parameter) {
boolean result = parameter.getField() != null
&& Modifier.isPublic(parameter.getField().getModifiers());
result = result
|| (parameter.getGetter() != null && Modifier.isPublic(parameter.getGetter()
.getModifiers()));
return result;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#getValue
* (org.eclipse.modisco.infra.discovery.catalog.DiscovererParameter,
* org.eclipse.modisco.infra.discovery.core.IDiscoverer)
*/
public Object getValue(final DiscovererParameter parameter, final IDiscoverer<?> discoverer)
throws DiscoveryException {
Object parameterValue = null;
try {
if (parameter.getField() != null
&& Modifier.isPublic(parameter.getField().getModifiers())) {
parameterValue = parameter.getField().get(discoverer);
} else if (parameter.getGetter() != null
&& Modifier.isPublic(parameter.getGetter().getModifiers())) {
parameterValue = parameter.getGetter().invoke(discoverer);
} else {
throw new DiscoveryException(discoverer.getClass()
+ " discoverer does not implement public read access to the parameter " //$NON-NLS-1$
+ parameter.getId());
}
} catch (IllegalArgumentException e) {
throw new DiscoveryException("Illegal parameter value for " //$NON-NLS-1$
+ parameter.getId(), e);
} catch (IllegalAccessException e) {
throw new DiscoveryException("Illegal parameter value for " //$NON-NLS-1$
+ parameter.getId(), e);
} catch (InvocationTargetException e) {
throw new DiscoveryException("Illegal parameter value for " //$NON-NLS-1$
+ parameter.getId(), e);
}
return parameterValue;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#setValue
* (org.eclipse.modisco.infra.discovery.catalog.DiscovererParameter,
* org.eclipse.modisco.infra.discovery.core.IDiscoverer, java.lang.Object)
*/
public void setValue(final DiscovererParameter parameter, final IDiscoverer<?> discoverer,
final Object parameterValue) throws DiscoveryException {
try {
if (parameter.getField() != null
&& Modifier.isPublic(parameter.getField().getModifiers())) {
parameter.getField().set(discoverer, parameterValue);
} else if (parameter.getSetter() != null
&& Modifier.isPublic(parameter.getSetter().getModifiers())) {
parameter.getSetter().invoke(discoverer, parameterValue);
} else {
throw new DiscoveryException(discoverer.getClass()
+ " discoverer does not implement public write access to the parameter " //$NON-NLS-1$
+ parameter.getId());
}
} catch (IllegalArgumentException e) {
throw new DiscoveryException("Illegal parameter value for " //$NON-NLS-1$
+ parameter.getId() + " : " + parameterValue, e); //$NON-NLS-1$
} catch (IllegalAccessException e) {
throw new DiscoveryException("Illegal parameter value for " //$NON-NLS-1$
+ parameter.getId() + " : " + parameterValue, e); //$NON-NLS-1$
} catch (InvocationTargetException e) {
throw new DiscoveryException("Illegal parameter value for " //$NON-NLS-1$
+ parameter.getId() + " : " + parameterValue, e); //$NON-NLS-1$
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.modisco.infra.discovery.core.catalog.IDiscoveryManager#
* discoverElement(org.eclipse.modisco.infra.discovery.core.IDiscoverer,
* java.lang.Object, java.util.Map)
*/
@SuppressWarnings("unchecked")
public void discoverElement(final IDiscoverer<?> discoverer, final Object source,
final Map<String, Object> parametersValues, final IProgressMonitor monitor)
throws DiscoveryException {
DiscovererDescription discoDesc = getDiscovererDescription(discoverer);
// affect parameters input values
for (Map.Entry<String, Object> entry : parametersValues.entrySet()) {
DiscovererParameter parameter = discoDesc.getParameterDefinition(entry.getKey());
if (parameter == null) {
throw new DiscoveryException("Illegal parameter name : " + entry.getKey() //$NON-NLS-1$
+ " for discoverer : " + discoDesc.getId()); //$NON-NLS-1$
}
setValue(parameter, discoverer, entry.getValue());
}
final IProgressMonitor progressMonitor;
if (monitor != null) {
progressMonitor = monitor;
} else {
progressMonitor = new NullProgressMonitor();
}
// launch discovery
((IDiscoverer<Object>) discoverer).discoverElement(source, progressMonitor);
// give output values
for (DiscovererParameter parameter : discoDesc.getParameterDefinitions()) {
if (parameter.getDirection().equals(DirectionKind.OUT)
|| parameter.getDirection().equals(DirectionKind.INOUT)) {
parametersValues.put(parameter.getId(), getValue(parameter, discoverer));
}
}
}
public boolean hasInitialValue(final DiscovererParameter parameter,
final DiscovererDescription discoverer) {
return parameter.getInitializer() != null
&& Modifier.isPublic(parameter.getInitializer().getModifiers());
}
public Object getInitialValue(final DiscovererParameter parameter,
final DiscovererDescription discoverer, final Object source) throws DiscoveryException {
Object parameterValue = null;
try {
if (parameter.getInitializer() != null) {
if (Modifier.isPublic(parameter.getInitializer().getModifiers())) {
IDiscoverer<?> cachedDiscoverer = DiscovererRegistry.INSTANCE
.getCachedDiscoverer(discoverer);
parameterValue = parameter.getInitializer().invoke(cachedDiscoverer, source);
} else {
throw new DiscoveryException(
discoverer.getClass()
+ " discoverer does not implement public read access to the parameter initializer " //$NON-NLS-1$
+ parameter.getId());
}
} else {
return null;
}
} catch (IllegalArgumentException e) {
throw new DiscoveryException("Illegal parameter initializer for " //$NON-NLS-1$
+ parameter.getId(), e);
} catch (IllegalAccessException e) {
throw new DiscoveryException("Illegal parameter initializer for " //$NON-NLS-1$
+ parameter.getId(), e);
} catch (InvocationTargetException e) {
throw new DiscoveryException("Illegal parameter initializer for " //$NON-NLS-1$
+ parameter.getId(), e);
}
return parameterValue;
}
}