blob: 08975c1ee42e54dee6a8ce5faa1dc4dff5495d11 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2011 Nicolas Deblock & Manuel Giles.
*
*
* 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:
* Nicolas Deblock nico.deblock@gmail.com - Initial API and implementation
* Manuel Giles giles.manu@live.fr - Initial API and implementation
* Cedric Dumoulin Cedric.dumoulin@lifl.fr - Idea of the java generator project & help for the conception
*
*****************************************************************************/
package org.eclipse.papyrus.designer.languages.java.generator.jdtsynchronizer.impl;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.papyrus.designer.languages.java.generator.jdtsynchronizer.GeneratorPreference;
import org.eclipse.papyrus.designer.languages.java.generator.metamodel.jdt.jdtmm.JDTJavaElement;
import org.eclipse.papyrus.designer.languages.java.generator.metamodel.jdt.jdtmm.JDTMethod;
import org.eclipse.papyrus.designer.languages.java.generator.metamodel.jdt.jdtmm.JDTMethodBody;
import org.eclipse.papyrus.designer.languages.java.generator.metamodel.jdt.jdtmm.JDTParameter;
import org.eclipse.papyrus.designer.languages.java.generator.metamodel.jdt.jdtmm.JDTType;
import org.eclipse.papyrus.designer.languages.java.generator.metamodel.jdt.jdtmm.visitor.JDTVisitorException;
/**
* Allow to generate Method in a IType
*
* @author Deblock Nicolas & Manuel Giles
*
*/
public class SynchJDTMethod extends SynchJDTCommentable {
protected IType itype;
private JDTMethod method;
private GeneratorPreference preference;
/**
* Constructor
*
* @param itype
* the type parent
*/
public SynchJDTMethod(IType itype, GeneratorPreference preference) {
super();
this.itype = itype;
this.preference = preference;
}
@Override
public void visit(JDTJavaElement element) throws JDTVisitorException {
// if element can't be generated, we stop all
if (!element.isGenerated()) {
return;
}
method = (JDTMethod) element;
// IntroduceParameterObjectDescript
IMethod imethod = null;
try {
// See if the method exist
boolean createMethod = true;
for (IMethod m : itype.getMethods()) {
// if it's the same name, and the same parameterTypes, the method exist
if (m.getElementName().equals(method.getElementName()) && m.getSignature().equals(method.getJDTSignature())) {
// stop all
createMethod = false;
imethod = m;
break;
}
}
if (createMethod) {
StringBuffer methodStr = new StringBuffer("\n");
// visibility
if (itype.isInterface()) {
methodStr.append("public ");
} else {
methodStr.append(SynchTools.getVisibility(method).toString());
}
// if method is a constructor, no return Type, and name is class name
if (method.isConstructor()) {
methodStr.append(itype.getElementName() + "(");
}
else {
// return type
if (method.getReturnType() != null) {
// Compute the type, taken into account multivalue
String type = getTypeAsString(method.getReturnType());
// put the import package
SynchTools.createImport(itype, method.getOwner(), method.getReturnType().getType());
methodStr.append(type + " ");
}
else {
methodStr.append("void ");
}
// method name
methodStr.append(method.getElementName() + "(");
}
// parameters
// System.out.println(method.getParam() + " " + method.getParameterTypes());
int nbParam = 0;
for (JDTParameter p : method.getParameters()) {
String typeName = p.getElementName();
String type = "Undefined";
if (p.getType() != null) {
// Compute the type, taken into account multivalue
type = getTypeAsString(p);
// put the import package
SynchTools.createImport(itype, method.getOwner(), p.getType());
}
if (nbParam > 0) {
methodStr.append(", ");
}
methodStr.append(type + " " + typeName);
nbParam++;
}
// close
methodStr.append(")");
// throws
if (method.getExceptions() != null && method.getExceptions().size() > 0) {
methodStr.append(" throws ");
int nbExc = 0;
for (JDTType exception : method.getExceptions()) {
if (nbExc > 0) {
methodStr.append(", ");
}
methodStr.append(exception.getElementName());
if (!SynchTools.isPrimiveType(exception.getQualifiedName()) && exception.getQualifiedName().contains(".")) {
itype.getCompilationUnit().createImport(exception.getQualifiedName(), null, null);
}
nbExc++;
}
}
// Do we need a body ?
if (itype.isInterface() || Flags.isAbstract(method.getFlags())) {
methodStr.append(";");
}
else {
// Generate Body. Open the body
methodStr.append(" {");
// If there is a declared body, use it. Otherwise, use the default body.
if (method.getBodies().size() > 0) {
for (JDTMethodBody body : method.getBodies()) {
methodStr.append("\n\t");
methodStr.append(body.asText());
}
// methodStr.append("\n");
}
else {
// Default body
methodStr.append(" \n\t// TODO Auto-generated method");
if (method.getReturnType() != null) {
methodStr.append("\n\treturn " + SynchTools.defaultReturn(method.getReturnType().getType().getElementName()) + ";");
}
}
// Close the body
methodStr.append("\n }");
}
// create the method
imethod = itype.createMethod(methodStr.toString(), null, true, null);
}
// add javadoc to method
createJavaDocFor(imethod, imethod.getCompilationUnit(), method.getComment(), "");
// Add explicit imports
generateExplicitImports(method, itype);
} catch (JavaModelException e) {
// e.printStackTrace();
// throw new JDTVisitorException(e.getMessage(), e.getCause());
propagateException(e.getMessage(), e);
} catch (Exception e) {
// e.printStackTrace();
// throw new JDTVisitorException(e.getMessage(), e.getCause());
propagateException(e.getMessage(), e);
}
}
/**
* Get the type of the parameter as a String. Take into account the multivalue setting.
*
* @param p
* @return
* @throws JavaModelException
*/
private String getTypeAsString(JDTParameter p) throws JavaModelException {
String type;
if (p.isMultiValued()) {
type = SynchTools.getMultiValued(itype, p.getType().getElementName(), preference);
} else {
type = p.getType().getElementName();
}
return type;
}
/** *************** methods override by SynchJDTCommentable ************** */
@Override
/**
* search the method to insert Javadoc
*
* @see org.eclipse.papyrus.designer.languages.java.generator.jdtsynchronizer.impl.SynchJDTCommentable#searchElementToInsert(org.eclipse.jdt.core.dom.CompilationUnit, org.eclipse.jdt.core.IJavaElement)
*
* @param cu
* @param method
* @return
*/
protected BodyDeclaration searchElementToInsert(CompilationUnit cu, IJavaElement method) {
// search Itype parent
if (method.getParent() instanceof IType) {
IType itype = (IType) method.getParent();
// find the good type
TypeDeclaration type = searchType((TypeDeclaration) cu.types().get(0), itype.getElementName());
// search the method. Fortunately, there are no method getSignature() for the type MethodDeclaration.
// So, we search manually
for (MethodDeclaration m : type.getMethods()) {
if (m.getName().toString().equals(method.getElementName())) {
// verify the signature
if (m.parameters() != null && m.parameters().size() == 0 && this.method.getParameters().size() == 0) {
return m;
}
if (m.parameters().size() == this.method.getParameters().size()) {
int numParam = 0;
boolean goodSignature = true;
for (Object paramObj : m.parameters()) {
if (paramObj instanceof SingleVariableDeclaration) {
SingleVariableDeclaration param = (SingleVariableDeclaration) paramObj;
if (!param.getType().toString().equals(this.method.getParameters().get(numParam).getType().getElementName())) {
goodSignature = false;
}
numParam++;
}
}
if (goodSignature) {
return m;
}
}
}
}
}
return null;
}
@Override
protected List<String> getJavadocTags() {
List<String> lst = new LinkedList<String>();
if (method == null) {
return lst;
}
// parameters
for (JDTParameter param : method.getParameters()) {
String comment = param.getComment();
if (comment == null) {
comment = "";
}
lst.add(TagElement.TAG_PARAM + " " + param.getElementName() + " " + comment);
}
// return
if (method.getReturnType() != null) {
String comment = method.getReturnType().getComment();
if (comment == null) {
comment = "";
}
lst.add(TagElement.TAG_RETURN + " " + comment);
}
// exception
// TODO prendre en compte notion de commentaire
if (method.getExceptions() != null) {
for (JDTType exception : method.getExceptions()) {
// String comment = exception.getComment();
// if(comment == null) comment = "";
lst.add(TagElement.TAG_THROWS + " " + exception.getElementName());
}
}
return lst;
}
/**
* Propagate a {@link JDTVisitorException} if the flag is not set
*
* @param msg
* @param e
* @throws JDTVisitorException
*/
private void propagateException(String msg, Throwable e) throws JDTVisitorException {
if (preference.stopOnFirstError()) {
throw new JDTVisitorException(msg, e.getCause());
}
else {
// Show error
System.err.println(msg);
e.printStackTrace();
}
}
/**
* Generate imports that are explicitly declared in the type
*
* @param srcType
* The src type to be transformed
* @param destType
* The jdt dest type to be generated
* @throws JavaModelException
* @throws JDTVisitorException
*/
private void generateExplicitImports(JDTMethod srcType, IType destType) throws JDTVisitorException {
// Add explicit type
for (JDTType anImport : srcType.getExplicitRequiredImports()) {
try {
destType.getCompilationUnit().createImport(anImport.getQualifiedName(), null, null);
} catch (Exception e) {
propagateException(destType.getFullyQualifiedName() + "Can't add explicit import " + anImport.getQualifiedName(), e);
}
}
// Add explicit plain text types
for (String anImport : srcType.getExplicitPlainTextRequiredImports()) {
try {
destType.getCompilationUnit().createImport(anImport, null, null);
} catch (JavaModelException e) {
propagateException(destType.getFullyQualifiedName() + "Can't add explicit plain text import " + anImport, e);
}
}
}
}