blob: c48ac2ca9566b253e406582f86d5972c73e29404 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.sourcebuilder.method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.Signature;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.sourcebuilder.annotation.AnnotationSourceBuilderFactory;
import org.eclipse.scout.sdk.sourcebuilder.comment.CommentSourceBuilderFactory;
import org.eclipse.scout.sdk.sourcebuilder.field.IFieldSourceBuilder;
import org.eclipse.scout.sdk.sourcebuilder.type.ITypeSourceBuilder;
import org.eclipse.scout.sdk.util.ScoutUtility;
import org.eclipse.scout.sdk.util.internal.sigcache.SignatureCache;
import org.eclipse.scout.sdk.util.signature.IImportValidator;
import org.eclipse.scout.sdk.util.signature.ITypeGenericMapping;
import org.eclipse.scout.sdk.util.signature.SignatureUtility;
import org.eclipse.scout.sdk.util.type.IMethodFilter;
import org.eclipse.scout.sdk.util.type.MethodFilters;
import org.eclipse.scout.sdk.util.type.MethodParameter;
import org.eclipse.scout.sdk.util.type.TypeUtility;
/**
* <h3>{@link MethodSourceBuilderFactory}</h3> ...
*
* @author Andreas Hoegger
* @since 3.10.0 07.03.2013
*/
public final class MethodSourceBuilderFactory {
private MethodSourceBuilderFactory() {
}
public static IMethodSourceBuilder createConstructorSourceBuilder(String typeName) {
return createConstructorSourceBuilder(typeName, Flags.AccPublic, new MethodParameter[0]);
}
public static IMethodSourceBuilder createConstructorSourceBuilder(String typeName, int flags, MethodParameter... parameters) {
MethodSourceBuilder constructorSourceBuilder = new MethodSourceBuilder(typeName);
constructorSourceBuilder.setFlags(flags);
if (parameters != null) {
constructorSourceBuilder.setParameters(parameters);
}
return constructorSourceBuilder;
}
public static IMethodSourceBuilder createOverrideMethodSourceBuilder(String methodName, IType declaringType) throws CoreException {
IMethod method = TypeUtility.findMethodInSuperHierarchy(methodName, declaringType, TypeUtility.getSuperTypeHierarchy(declaringType));
return createOverrideMethodSourceBuilder(method, declaringType);
}
public static IMethodSourceBuilder createOverrideMethodSourceBuilder(IMethod methodToOverride, IType declaringType) throws CoreException {
if (Flags.isInterface(methodToOverride.getDeclaringType().getFlags()) || Flags.isAbstract(methodToOverride.getFlags())) {
return createMethodSourceBuilder(methodToOverride, declaringType, MethodBodySourceBuilderFactory.createAutoGeneratedMethodBody());
}
else {
return createMethodSourceBuilder(methodToOverride, declaringType, MethodBodySourceBuilderFactory.createSuperCallMethodBody(true));
}
}
public static IMethodSourceBuilder createMethodSourceBuilder(IMethod method, IType contextType) throws CoreException {
return createMethodSourceBuilder(method, contextType, MethodBodySourceBuilderFactory.createAutoGeneratedMethodBody());
}
public static IMethodSourceBuilder createMethodSourceBuilder(IMethod method, IType contextType, IMethodBodySourceBuilder bodySourceBuilder) throws CoreException {
MethodSourceBuilder sourceBuilder = new MethodSourceBuilder(method.getElementName());
sourceBuilder.setReturnTypeSignature(SignatureUtility.getReturnTypeSignatureResolved(method, contextType));
String[] unresolvedExceptionSignatures = method.getExceptionTypes();
String[] resolvedExceptionSignatures = new String[unresolvedExceptionSignatures.length];
for (int i = 0; i < unresolvedExceptionSignatures.length; i++) {
resolvedExceptionSignatures[i] = SignatureUtility.getResolvedSignature(unresolvedExceptionSignatures[i], contextType);
}
sourceBuilder.setExceptionSignatures(resolvedExceptionSignatures);
sourceBuilder.setParameters(TypeUtility.getMethodParameters(method, contextType));
int flags = method.getFlags() & (~Flags.AccTransient);
if (!method.getDeclaringType().equals(contextType)) {
if (!Flags.isAbstract(contextType.getFlags())) {
flags = flags & (~Flags.AccAbstract);
}
if (Flags.isInterface(method.getDeclaringType().getFlags()) && Flags.isPackageDefault(flags)) {
flags = flags | Flags.AccPublic;
}
sourceBuilder.addAnnotationSourceBuilder(AnnotationSourceBuilderFactory.createOverrideAnnotationSourceBuilder());
}
sourceBuilder.setFlags(flags);
sourceBuilder.setMethodBodySourceBuilder(bodySourceBuilder);
return sourceBuilder;
}
public static IMethodSourceBuilder createOverrideMethodSourceBuilder(ITypeSourceBuilder typeSourceBuilder, String methodName) throws CoreException {
return createOverrideMethodSourceBuilder(typeSourceBuilder, methodName, null);
}
private static IMethod getMethodToOverride(ITypeSourceBuilder typeSourceBuilder, String methodName, IMethodFilter methodFilter) {
LinkedList<String> superSignatures = new LinkedList<String>(typeSourceBuilder.getInterfaceSignatures());
superSignatures.addFirst(typeSourceBuilder.getSuperTypeSignature());
return getMethodToOverride(superSignatures, methodName, methodFilter);
}
private static IMethod getMethodToOverride(List<String> superSignatures, String methodName, IMethodFilter methodFilter) {
for (String superCandidate : superSignatures) {
if (superCandidate != null) {
IType superType = TypeUtility.getTypeBySignature(superCandidate);
if (TypeUtility.exists(superType)) {
IMethodFilter filter = methodFilter;
if (StringUtility.hasText(methodName)) {
if (methodFilter == null) {
filter = MethodFilters.getNameFilter(methodName);
}
else {
filter = MethodFilters.getMultiMethodFilter(methodFilter, MethodFilters.getNameFilter(methodName));
}
}
IMethod methodToOverride = TypeUtility.findMethodInSuperTypeHierarchy(superType, TypeUtility.getSuperTypeHierarchy(superType), filter);
if (TypeUtility.exists(methodToOverride)) {
return methodToOverride;
}
}
}
}
return null;
}
public static IMethodSourceBuilder createOverrideMethodSourceBuilder(ITypeSourceBuilder typeSourceBuilder, String methodName, IMethodFilter methodFilter) throws CoreException {
IMethod methodToOverride = getMethodToOverride(typeSourceBuilder, methodName, methodFilter);
if (!TypeUtility.exists(methodToOverride)) {
return null;
}
else {
Map<String, ITypeGenericMapping> genericMapping = new HashMap<String, ITypeGenericMapping>();
SignatureUtility.resolveGenericParametersInSuperHierarchy(SignatureCache.createTypeSignature(typeSourceBuilder.getElementName()), new String[0],
typeSourceBuilder.getSuperTypeSignature(), typeSourceBuilder.getInterfaceSignatures().toArray(new String[typeSourceBuilder.getInterfaceSignatures().size()]), genericMapping);
MethodSourceBuilder builder = new MethodSourceBuilder(methodName);
// return type
Map<String, String> localGenericMapping = genericMapping.get(methodToOverride.getDeclaringType().getFullyQualifiedName()).getParameters();
builder.setReturnTypeSignature(SignatureUtility.getResolvedSignature(methodToOverride.getDeclaringType(), localGenericMapping, methodToOverride.getReturnType()));
// exceptions
String[] unresolvedExceptionSignatures = methodToOverride.getExceptionTypes();
String[] resolvedExceptionSignatures = new String[unresolvedExceptionSignatures.length];
for (int i = 0; i < unresolvedExceptionSignatures.length; i++) {
resolvedExceptionSignatures[i] = SignatureUtility.getResolvedSignature(methodToOverride.getDeclaringType(), localGenericMapping, unresolvedExceptionSignatures[i]);
}
builder.setExceptionSignatures(resolvedExceptionSignatures);
// parameters
builder.setParameters(TypeUtility.getMethodParameters(methodToOverride, localGenericMapping));
int flags = methodToOverride.getFlags() & ~(Flags.AccTransient | Flags.AccBridge | Flags.AccAbstract);
if (Flags.isInterface(methodToOverride.getDeclaringType().getFlags()) && Flags.isPackageDefault(flags)) {
flags = flags | Flags.AccPublic;
}
builder.setFlags(flags);
// override annotation
builder.addAnnotationSourceBuilder(AnnotationSourceBuilderFactory.createOverrideAnnotationSourceBuilder());
// add default body
builder.setMethodBodySourceBuilder(MethodBodySourceBuilderFactory.createAutoGeneratedMethodBody());
return builder;
}
}
public static IMethodSourceBuilder createFieldGetterSourceBuilder(final String fieldSignature) {
String fieldSimpleName = Signature.getSignatureSimpleName(fieldSignature);
IMethodSourceBuilder getterBuilder = new MethodSourceBuilder("get" + fieldSimpleName);
getterBuilder.setFlags(Flags.AccPublic);
getterBuilder.setReturnTypeSignature(fieldSignature);
getterBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createPreferencesMethodGetterCommentBuilder());
getterBuilder.setMethodBodySourceBuilder(new IMethodBodySourceBuilder() {
@Override
public void createSource(IMethodSourceBuilder methodBuilder, StringBuilder source, String lineDelimiter, IJavaProject ownerProject, IImportValidator validator) throws CoreException {
source.append("return getFieldByClass(");
source.append(validator.getTypeName(fieldSignature));
source.append(".class);");
}
});
return getterBuilder;
}
public static IMethodSourceBuilder createColumnGetterSourceBuilder(final String columnSignature) {
String columnSimpleName = Signature.getSignatureSimpleName(columnSignature);
IMethodSourceBuilder getterBuilder = new MethodSourceBuilder("get" + columnSimpleName);
getterBuilder.setFlags(Flags.AccPublic);
getterBuilder.setReturnTypeSignature(columnSignature);
getterBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createPreferencesMethodGetterCommentBuilder());
getterBuilder.setMethodBodySourceBuilder(new IMethodBodySourceBuilder() {
@Override
public void createSource(IMethodSourceBuilder methodBuilder, StringBuilder source, String lineDelimiter, IJavaProject ownerProject, IImportValidator validator) throws CoreException {
source.append("return getColumnSet().getColumnByClass(");
source.append(validator.getTypeName(columnSignature));
source.append(".class);");
}
});
return getterBuilder;
}
public static IMethodSourceBuilder createGetter(IFieldSourceBuilder fieldSourceBuilder) {
return createGetter(fieldSourceBuilder.getElementName(), fieldSourceBuilder.getSignature());
}
public static IMethodSourceBuilder createGetter(String fieldName, String signature) {
StringBuilder methodName = new StringBuilder();
if (Signature.SIG_BOOLEAN.equals(signature)) {
methodName.append("is");
}
else {
methodName.append("get");
}
String field = fieldName.replaceFirst("m\\_", "");
if (field.length() > 0) {
methodName.append(Character.toUpperCase(field.charAt(0)));
}
if (field.length() > 1) {
methodName.append(field.substring(1));
}
IMethodSourceBuilder getterBuilder = new MethodSourceBuilder(methodName.toString());
getterBuilder.setReturnTypeSignature(signature);
getterBuilder.setFlags(Flags.AccPublic);
getterBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createPreferencesMethodGetterCommentBuilder());
getterBuilder.setMethodBodySourceBuilder(MethodBodySourceBuilderFactory.createSimpleMethodBody("return " + fieldName + ";"));
return getterBuilder;
}
public static IMethodSourceBuilder createSetter(IFieldSourceBuilder fieldSourceBuilder) {
return createSetter(fieldSourceBuilder.getElementName(), fieldSourceBuilder.getSignature());
}
public static IMethodSourceBuilder createSetter(String fieldName, String signature) {
StringBuilder methodName = new StringBuilder();
methodName.append("set");
String field = fieldName.replaceFirst("m\\_", "");
String paramName = ScoutUtility.ensureValidParameterName(field);
methodName.append(ScoutUtility.ensureStartWithUpperCase(field));
IMethodSourceBuilder setterBuilder = new MethodSourceBuilder(methodName.toString());
setterBuilder.setFlags(Flags.AccPublic);
setterBuilder.setReturnTypeSignature(Signature.SIG_VOID);
setterBuilder.addParameter(new MethodParameter(paramName, signature));
setterBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createPreferencesMethodSetterCommentBuilder());
setterBuilder.setMethodBodySourceBuilder(MethodBodySourceBuilderFactory.createSimpleMethodBody(fieldName + " = " + paramName + ";"));
return setterBuilder;
}
}