blob: 80488d082338b829c624a84da960bb3ce280f380 [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
*******************************************************************************/
package org.eclipse.modisco.infra.discovery.core.internal.catalog;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.gmt.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.modisco.infra.discovery.catalog.CatalogFactory;
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.annotations.Parameter;
import org.eclipse.modisco.infra.discovery.core.annotations.ParameterInitialValue;
import org.eclipse.modisco.infra.discovery.core.internal.Activator;
import org.eclipse.modisco.infra.discovery.core.internal.annotations.DiscoveryAnnotationControls;
import org.eclipse.modisco.infra.discovery.core.internal.annotations.ParameterDeclarationException;
public final class DiscovererParameterUtils {
private static final String VOID_TYPE = "void"; //$NON-NLS-1$
private static DiscovererParameterUtils singleton = new DiscovererParameterUtils();
private DiscovererParameterUtils() {
// empty
}
public static synchronized DiscovererParameterUtils getInstance() {
if (DiscovererParameterUtils.singleton == null) {
DiscovererParameterUtils.singleton = new DiscovererParameterUtils();
}
return DiscovererParameterUtils.singleton;
}
/**
* This method computes the parameters description for one discoverer
* implementation
*
*/
public void computeParameters(final DiscovererDescription discovererDescription) {
// (discoverer parameter ID, (class field or method, Parameter
// annotation))
Map<String, Map<Member, Parameter>> memberToParameterAnnotationMaps = new HashMap<String, Map<Member, Parameter>>();
// (discoverer parameter ID, (class method, ParameterInitialValue
// annotation))
Map<String, Map<Method, ParameterInitialValue>> methodToParameterInitialValueAnnotationMaps = new HashMap<String, Map<Method, ParameterInitialValue>>();
List<Member> members = new ArrayList<Member>();
retrieveMembers(discovererDescription.getImplementationType(), members);
for (Member aMember : members) {
Parameter parameterAnnotation = null;
ParameterInitialValue parameterInitialValueAnnotation = null;
if (aMember instanceof Field) {
parameterAnnotation = ((Field) aMember).getAnnotation(Parameter.class);
}
if (aMember instanceof Method) {
parameterAnnotation = ((Method) aMember).getAnnotation(Parameter.class);
parameterInitialValueAnnotation = ((Method) aMember)
.getAnnotation(ParameterInitialValue.class);
}
if (parameterAnnotation != null) {
try {
DiscoveryAnnotationControls.checkAnnotation(parameterAnnotation, null, aMember);
Map<Member, Parameter> memberToParameterMap = memberToParameterAnnotationMaps
.get(parameterAnnotation.name());
if (memberToParameterMap == null) {
memberToParameterMap = new HashMap<Member, Parameter>();
memberToParameterAnnotationMaps.put(parameterAnnotation.name(),
memberToParameterMap);
}
memberToParameterMap.put(aMember, parameterAnnotation);
} catch (ParameterDeclarationException e) {
MoDiscoLogger.logError(
"Some Discoverer parameter annotation " + parameterAnnotation //$NON-NLS-1$
+ " has problems and will be ignored : " //$NON-NLS-1$
+ e.getMessage(), Activator.getDefault());
}
}
if (parameterInitialValueAnnotation != null) {
try {
DiscoveryAnnotationControls.checkAnnotation(parameterInitialValueAnnotation,
null, (Method) aMember);
Map<Method, ParameterInitialValue> methodToParameterInitialValueMap = methodToParameterInitialValueAnnotationMaps
.get(parameterInitialValueAnnotation.name());
if (methodToParameterInitialValueMap == null) {
methodToParameterInitialValueMap = new HashMap<Method, ParameterInitialValue>();
methodToParameterInitialValueAnnotationMaps.put(
parameterInitialValueAnnotation.name(),
methodToParameterInitialValueMap);
}
methodToParameterInitialValueMap.put((Method) aMember,
parameterInitialValueAnnotation);
} catch (ParameterDeclarationException e) {
MoDiscoLogger
.logError(
"Some Discoverer parameter annotation " + parameterInitialValueAnnotation //$NON-NLS-1$
+ " has problems and will be ignored : " //$NON-NLS-1$
+ e.getMessage(), Activator.getDefault());
}
}
}
// Now that annotations have been collected, we can check them together
// and compute some unified definitions
for (Map.Entry<String, Map<Member, Parameter>> entry : memberToParameterAnnotationMaps
.entrySet()) {
Map<Method, ParameterInitialValue> methodToParameterInitialValueMap = methodToParameterInitialValueAnnotationMaps
.get(entry.getKey());
try {
DiscoveryAnnotationControls.checkAnnotationsForOneParameter(null, entry.getValue(),
null, methodToParameterInitialValueMap);
} catch (ParameterDeclarationException e) {
MoDiscoLogger
.logError(
"Some Discoverer annotations have problems and will be ignored : " + e.getMessage(), //$NON-NLS-1$
Activator.getDefault());
}
Method initializer = null;
// there should be at most one initial value method
if (methodToParameterInitialValueMap != null
&& methodToParameterInitialValueMap.keySet().size() > 0) {
initializer = methodToParameterInitialValueMap.keySet().iterator().next();
}
DiscovererParameter discoveryParameter = CatalogFactory.eINSTANCE
.createDiscovererParameter();
unifyParameterProperties(entry.getValue(), initializer, discoveryParameter);
discovererDescription.getParameterDefinitions().add(discoveryParameter);
}
}
/*
* Iterate on annotations to retrieve and unify the parameter properties.
* Annotations coherence is supposed to be already checked : we compute here
* a very basic initialization, may be with redundant affectations
*/
private static synchronized void unifyParameterProperties(
final Map<Member, Parameter> memberToAnnotationMap, final Method initializer,
final DiscovererParameter discoveryParameter) {
boolean required = false;
Class<?> type = null;
String name = null;
String description = null;
DirectionKind direction = null;
Field field = null;
Method getter = null;
Method setter = null;
List<Parameter> declaringAnnotations = new ArrayList<Parameter>();
for (Map.Entry<Member, Parameter> entry : memberToAnnotationMap.entrySet()) {
if (entry.getValue().name() != null && entry.getValue().name().length() > 0) {
name = entry.getValue().name();
}
if (entry.getValue().description() != null
&& entry.getValue().description().length() > 0) {
description = entry.getValue().description();
}
required = required || entry.getValue().requiresInputValue();
declaringAnnotations.add(entry.getValue());
if (entry.getKey() instanceof Field) {
field = (Field) entry.getKey();
if (Modifier.isPublic(field.getModifiers())) {
direction = DirectionKind.INOUT;
type = field.getType();
}
} else if (entry.getKey() instanceof Method) {
Method method = (Method) entry.getKey();
if (isGetter(method)) {
type = method.getReturnType();
getter = method;
if (direction == null) {
direction = DirectionKind.OUT;
} else {
direction = DirectionKind.INOUT;
}
} else if (isSetter(method)) {
type = method.getParameterTypes()[0];
setter = method;
if (direction == null) {
direction = DirectionKind.IN;
} else {
direction = DirectionKind.INOUT;
}
}
}
}
discoveryParameter.setId(name);
discoveryParameter.setDescription(description);
discoveryParameter.setRequiredInput(required);
discoveryParameter.setType(type);
discoveryParameter.setDirection(direction);
discoveryParameter.setField(field);
discoveryParameter.setGetter(getter);
discoveryParameter.setSetter(setter);
discoveryParameter.setInitializer(initializer);
}
private void retrieveMembers(final Class<?> aClass, final List<Member> members) {
for (Field aField : aClass.getFields()) {
members.add(aField);
}
for (Method aMethod : aClass.getMethods()) {
members.add(aMethod);
}
for (Class<?> anInterface : aClass.getInterfaces()) {
retrieveMembers(anInterface, members);
}
if (aClass.getSuperclass() != null) {
retrieveMembers(aClass.getSuperclass(), members);
}
}
private static boolean isGetter(final Method method) {
// Methods are supposed to be already checked : we do not compute all
// conditions here for a getter
return method.getReturnType() != null
&& !method.getReturnType().getName().equals(DiscovererParameterUtils.VOID_TYPE);
}
private static boolean isSetter(final Method method) {
// Methods are supposed to be already checked : we do not compute all
// conditions here for a setter
return method.getParameterTypes().length > 0;
}
}