blob: d89671487d3225da1db22e61e9fd6ef52f3f9b7b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2005 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.j2ee.internal.common.operations;
import java.io.ByteArrayInputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jem.workbench.utility.JemProjectUtilities;
import org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
/**
* NewJavaClassOperation is a data model operation that is used to create a default instance of a new java class
* based on the input and properties set in the NewJavaClassDataModelProvider.
* @see org.eclipse.jst.j2ee.internal.common.operations.NewJavaClassDataModelProvider
*
* It is a subclass of ArtifactEditProviderOperation and clients can invoke this operation as is or it may be subclassed to
* add additional or modify behaviour. The execute() method can be extended to drive this behaviour.
* @see org.eclipse.wst.common.componentcore.internal.operation.ArtifactEditProviderOperation
*
* The new java class is generated through the use of adding a series of static tokens defined within to
* an ongoing string buffer.
*
* The use of this class is EXPERIMENTAL and is subject to substantial changes.
*
* This needs to be removed as it is legacy inherited from another team
*/
public class NewJavaClassOperation extends ArtifactEditProviderOperation {
// Tokens for string buffer creation of default java class
protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
protected static final String TAB = "\t"; //$NON-NLS-1$
protected static final String SPACE = " "; //$NON-NLS-1$
protected static final String DOT = "."; //$NON-NLS-1$
protected static final String COMMA = ","; //$NON-NLS-1$
protected static final String SEMICOLON = ";"; //$NON-NLS-1$
protected static final String POUND = "#"; //$NON-NLS-1$
protected static final String OPEN_PAR = "("; //$NON-NLS-1$
protected static final String CLOSE_PAR = ")"; //$NON-NLS-1$
protected static final String OPEN_BRA = "{"; //$NON-NLS-1$
protected static final String CLOSE_BRA = "}"; //$NON-NLS-1$
protected static final String lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
protected static final String JAVA_LANG_OBJECT = "java.lang.Object"; //$NON-NLS-1$
protected static final String PACKAGE = "package "; //$NON-NLS-1$
protected static final String CLASS = "class "; //$NON-NLS-1$
protected static final String IMPORT = "import "; //$NON-NLS-1$
protected static final String EXTENDS = "extends "; //$NON-NLS-1$
protected static final String IMPLEMENTS = "implements "; //$NON-NLS-1$
protected static final String THROWS = "throws "; //$NON-NLS-1$
protected static final String SUPER = "super"; //$NON-NLS-1$
protected static final String PUBLIC = "public "; //$NON-NLS-1$
protected static final String PROTECTED = "protected "; //$NON-NLS-1$
protected static final String PRIVATE = "private "; //$NON-NLS-1$
protected static final String STATIC = "static "; //$NON-NLS-1$
protected static final String ABSTRACT = "abstract "; //$NON-NLS-1$
protected static final String FINAL = "final "; //$NON-NLS-1$
protected static final String VOID = "void"; //$NON-NLS-1$
protected static final String INT = "int"; //$NON-NLS-1$
protected static final String BOOLEAN = "boolean"; //$NON-NLS-1$
protected static final String MAIN_METHOD = "\tpublic static void main(String[] args) {"; //$NON-NLS-1$
protected static final String TODO_COMMENT = "\t\t// TODO Auto-generated method stub"; //$NON-NLS-1$
protected static final String RETURN_NULL = "\t\treturn null;"; //$NON-NLS-1$
protected static final String RETURN_0 = "\t\treturn 0;"; //$NON-NLS-1$
protected static final String RETURN_FALSE = "\t\treturn false;"; //$NON-NLS-1$
/**
* This is a list of all the calculated import statements that will need to be added
*/
private List importStatements;
/**
* This is a NewJavaClassOperation constructor. Data models passed in should be instances
* of NewJavaClassDataModel. This method does not accept null. It will not return null.
* @see NewJavaClassDataModelProvider
*
* @param dataModel
* @return NewJavaClassOperation
*/
public NewJavaClassOperation(IDataModel dataModel) {
super(dataModel);
importStatements = new ArrayList();
}
/**
* Subclasses may extend this method to add their own actions during execution.
* The implementation of the execute method drives the running of the operation. This
* method will create the source folder, the java package, and then create the java file.
* This method will accept null.
* @see AbstractOperation#execute(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
*
* @param monitor ProgressMonitor
* @throws CoreException
* @throws InterruptedException
* @throws InvocationTargetException
*/
public IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
// Ensure source folder exists
IFolder sourceFolder = createJavaSourceFolder();
// Ensure java package exists
IPackageFragment pack = createJavaPackage();
// Create java class
createJavaFile(sourceFolder, pack);
return OK_STATUS;
}
/**
* This method will return the java source folder as specified in the java class data model.
* It will create the java source folder if it does not exist. This method may return null.
* @see INewJavaClassDataModelProperties#SOURCE_FOLDER
* @see IFolder#create(boolean, boolean, org.eclipse.core.runtime.IProgressMonitor)
*
* @return IFolder the java source folder
*/
protected final IFolder createJavaSourceFolder() {
// Get the source folder name from the data model
String folderFullPath = model.getStringProperty(INewJavaClassDataModelProperties.SOURCE_FOLDER);
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IFolder folder = root.getFolder(new Path(folderFullPath));
// If folder does not exist, create the folder with the specified path
if (!folder.exists()) {
try {
folder.create(true, true, null);
} catch (CoreException e) {
Logger.getLogger().log(e);
}
}
// Return the source folder
return folder;
}
/**
* This method will return the java package as specified by the new java class data model.
* If the package does not exist, it will create the package. This method should not return
* null.
* @see INewJavaClassDataModelProperties#JAVA_PACKAGE
* @see IPackageFragmentRoot#createPackageFragment(java.lang.String, boolean, org.eclipse.core.runtime.IProgressMonitor)
*
* @return IPackageFragment the java package
*/
protected final IPackageFragment createJavaPackage() {
// Retrieve the package name from the java class data model
String packageName = model.getStringProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE);
IPackageFragmentRoot packRoot = (IPackageFragmentRoot) model.getProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE_FRAGMENT_ROOT);
IPackageFragment pack = packRoot.getPackageFragment(packageName);
// Handle default package
if (pack == null) {
pack = packRoot.getPackageFragment(""); //$NON-NLS-1$
}
// Create the package fragment if it does not exist
if (!pack.exists()) {
String packName = pack.getElementName();
try {
pack = packRoot.createPackageFragment(packName, true, null);
} catch (JavaModelException e) {
Logger.getLogger().log(e);
}
}
// Return the package
return pack;
}
/**
* Subclasses may extend this method to provide their own java file creation path.
* This implementation will use the properties specified in the data model to create
* a default java class. The class will be built using pre-defined tokens and will be
* built up using a string buffer. The method getJavaFileContent will handle the building
* of the string buffer while this method will write those contents to the file.
* This method does not accept null parameters.
* @see INewJavaClassDataModelProperties#CLASS_NAME
* @see NewJavaClassOperation#getJavaFileContent(IPackageFragment, String)
*
* @param sourceFolder
* @param pack
*/
protected void createJavaFile(IFolder sourceFolder, IPackageFragment pack) {
// Retrieve properties from the java class data model
String packageName = model.getStringProperty(INewJavaClassDataModelProperties.JAVA_PACKAGE);
String className = model.getStringProperty(INewJavaClassDataModelProperties.CLASS_NAME);
String fileName = className + ".java"; //$NON-NLS-1$
//ICompilationUnit cu = null;
try {
// Get the java file content from the string buffer
String content = getJavaFileContent(pack, className);
// Create the compilation unit
pack.createCompilationUnit(fileName, content, true, null);
byte[] contentBytes = content.getBytes();
IPath packageFullPath = new Path(packageName.replace('.', IPath.SEPARATOR));
IPath javaFileFullPath = packageFullPath.append(fileName);
IFile file = sourceFolder.getFile(javaFileFullPath);
// Set the contents in the file if it already exists
if (file != null && file.exists()) {
file.setContents(new ByteArrayInputStream(contentBytes), false, true, null);
} // If the file does not exist, create it with the contents
else if (file != null) {
file.create(new ByteArrayInputStream(contentBytes), false, null);
}
// editModel.getWorkingCopy(cu, true); //Track CU.
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* This is intended for internal use only. This is where the string buffer for the contents
* of the java file is built up using the properties in the data model and the predefined tokens.
* This method will not accept null parameters. It will not return null.
* @see NewJavaClassDataModelProvider
* @see NewJavaClassOperation#createJavaFile(IFolder, IPackageFragment)
*
* @param pack
* @param className
* @return String java file contents
*/
private String getJavaFileContent(IPackageFragment pack, String className) {
// Create the superclass name
String superclassName = model.getStringProperty(INewJavaClassDataModelProperties.SUPERCLASS);
List interfaces = (List) model.getProperty(INewJavaClassDataModelProperties.INTERFACES);
String packageStatement = getPackageStatement(pack);
// Create the import statements
setupImportStatements(pack, superclassName, interfaces);
// Create the class declaration
String classDeclaration = getClassDeclaration(superclassName, className, interfaces);
// Create the fields
String fields = getFields();
// Create the methods
String methods = getMethodStubs(superclassName, className);
StringBuffer contents = new StringBuffer();
// Add the package statement to the buffer
contents.append(packageStatement);
// Add all the import statements to the buffer
for (int i = 0; i < importStatements.size(); i++) {
contents.append(IMPORT + importStatements.get(i) + SEMICOLON);
contents.append(lineSeparator);
}
contents.append(lineSeparator);
// Add the class declaration to the buffer
contents.append(classDeclaration);
// Add the fields to the buffer
contents.append(fields);
// Add the method bodies to the buffer
contents.append(methods);
contents.append(CLOSE_BRA);
// Return the contents of the buffer
return contents.toString();
}
/**
* This is intended for internal use only. This method will return a package string for
* the class. It will not accept a null parameter. It will not return null.
* @see NewJavaClassOperation#getJavaFileContent(IPackageFragment, String)
*
* @param pack
* @return String package statement
*/
private String getPackageStatement(IPackageFragment pack) {
StringBuffer sb = new StringBuffer();
// If it is not default package, add package statement
if (!pack.isDefaultPackage()) {
sb.append(PACKAGE + pack.getElementName() + SEMICOLON);
sb.append(lineSeparator);
sb.append(lineSeparator);
}
// Return contents of buffer
return sb.toString();
}
/**
* This method is intended for internal use. It checks to see if the qualified class name
* belongs to the specified package. This method will not accept nulls. It will not return null.
* @see NewJavaClassOperation#setupImportStatements(IPackageFragment, String, List)
*
* @param packageFragment
* @param className
* @return boolean is class in this package?
*/
private boolean isSamePackage(IPackageFragment packageFragment, String className) {
if (className != null && className.length() > 0) {
String sPackageName = packageFragment.getElementName();
String classPackageName = Signature.getQualifier(className);
// Does the qualified class's package name match the passed in package's name?
if (classPackageName.equals(sPackageName))
return true;
}
return false;
}
/**
* This method is intended for internal use only. This method will set up the required import
* statements and cache to the importStatements list.
* This method does not accept null parameters.
* @see NewJavaClassOperation#importStatements
* @see NewJavaClassOperation#getJavaFileContent(IPackageFragment, String)
*
* @param pack
* @param superclassName
* @param interfaces
*/
private void setupImportStatements(IPackageFragment pack, String superclassName, List interfaces) {
// If there is a superclass and it is not in the same package, add an import for it
if (superclassName != null && superclassName.length() > 0) {
if (!superclassName.equals(JAVA_LANG_OBJECT) && !isSamePackage(pack, superclassName)) {
importStatements.add(superclassName);
}
}
// Add an import the list of implemented interfaces
if (interfaces != null && interfaces.size() > 0) {
int size = interfaces.size();
for (int i = 0; i < size; i++) {
String interfaceName = (String) interfaces.get(i);
importStatements.add(interfaceName);
}
}
}
/**
* This class is intended for internal use only. This will build up the class declartion
* statement based off the properties set in the java class data model.
* This method does not accept null parameters. It will not return null.
* @see NewJavaClassOperation#getJavaFileContent(IPackageFragment, String)
*
* @param superclassName
* @param className
* @param interfaces
* @return String class declaration string
*/
private String getClassDeclaration(String superclassName, String className, List interfaces) {
StringBuffer sb = new StringBuffer();
// Append appropriate modifiers
if (model.getBooleanProperty(INewJavaClassDataModelProperties.MODIFIER_PUBLIC))
sb.append(PUBLIC);
if (model.getBooleanProperty(INewJavaClassDataModelProperties.MODIFIER_ABSTRACT))
sb.append(ABSTRACT);
if (model.getBooleanProperty(INewJavaClassDataModelProperties.MODIFIER_FINAL))
sb.append(FINAL);
// Add the class token
sb.append(CLASS);
// Add the class name
sb.append(className + SPACE);
// If there is a superclass, add the extends and super class name
if (superclassName != null && superclassName.length() > 0 && !superclassName.equals(JAVA_LANG_OBJECT)) {
int index = superclassName.lastIndexOf(DOT);
if (index != -1)
superclassName = superclassName.substring(index + 1);
sb.append(EXTENDS + superclassName + SPACE);
}
// If there are interfaces, add the implements and then interate over the interface list
if (interfaces != null && interfaces.size() > 0) {
sb.append(IMPLEMENTS);
int size = interfaces.size();
for (int i = 0; i < size; i++) {
String interfaceName = (String) interfaces.get(i);
int index = interfaceName.lastIndexOf(DOT);
if (index != -1)
interfaceName = interfaceName.substring(index + 1);
sb.append(interfaceName);
if (i < size - 1)
sb.append(COMMA);
sb.append(SPACE);
}
}
sb.append(OPEN_BRA);
sb.append(lineSeparator);
// Return the finished class declaration string
return sb.toString();
}
/**
* Subclasses may extend this method to add their own fields. The default implementation
* is not to have any fields. This method will not return null.
* @see NewJavaClassOperation#getJavaFileContent(IPackageFragment, String)
*
* @return String fields string
*/
protected String getFields() {
return EMPTY_STRING;
}
/**
* This method is intended for internal use only. This will build up a string with the
* contents of all the method stubs for the unimplemented methods defined in the interfaces.
* It will also add inherited constructors from the superclass as appropriate.
* This method does not accept null parameters. It will not return null.
* @see NewJavaClassOperation#getJavaFileContent(IPackageFragment, String)
*
* @param superclassName
* @param className
* @return String method stubs string
*/
private String getMethodStubs(String superclassName, String className) {
StringBuffer sb = new StringBuffer();
IJavaProject javaProj = JemProjectUtilities.getJavaProject(getTargetProject());
if (model.getBooleanProperty(INewJavaClassDataModelProperties.MAIN_METHOD)) {
// Add main method
sb.append(MAIN_METHOD);
sb.append(lineSeparator);
sb.append(TODO_COMMENT);
sb.append(lineSeparator);
sb.append(TAB + CLOSE_BRA);
sb.append(lineSeparator);
sb.append(lineSeparator);
}
IType superClassType = null;
if (model.getBooleanProperty(INewJavaClassDataModelProperties.CONSTRUCTOR) || model.getBooleanProperty(INewJavaClassDataModelProperties.ABSTRACT_METHODS)) {
// Find super class type
try {
superClassType = javaProj.findType(superclassName);
} catch (JavaModelException e) {
Logger.getLogger().log(e);
}
}
if (model.getBooleanProperty(INewJavaClassDataModelProperties.CONSTRUCTOR)) {
// Implement constructors from superclass
try {
if (superClassType != null) {
IMethod[] methods = superClassType.getMethods();
for (int j = 0; j < methods.length; j++) {
if (methods[j].isConstructor() && !Flags.isPrivate(methods[j].getFlags())) {
String methodStub = getMethodStub(methods[j], superclassName, className);
sb.append(methodStub);
}
}
}
} catch (JavaModelException e) {
Logger.getLogger().log(e);
}
}
// Add unimplemented methods defined in the interfaces list
if (model.getBooleanProperty(INewJavaClassDataModelProperties.ABSTRACT_METHODS) && superClassType != null) {
String methodStub = getUnimplementedMethodsFromSuperclass(superClassType, className);
if (methodStub != null && methodStub.trim().length() > 0)
sb.append(methodStub);
methodStub = getUnimplementedMethodsFromInterfaces(superClassType, className, javaProj);
if (methodStub != null && methodStub.trim().length() > 0)
sb.append(methodStub);
}
// Add any user defined method stubs
if (superClassType != null) {
String userDefined = getUserDefinedMethodStubs(superClassType);
if (userDefined != null && userDefined.trim().length() > 0)
sb.append(userDefined);
}
// Return the methods string
return sb.toString();
}
/**
* This method is intended for internal use only. This will retrieve method stubs for
* unimplemented methods in the superclass that will need to be created in the new class.
* This method does not accept null parameters. It will not return null.
* @see NewJavaClassOperation#getMethodStubs(String, String)
*
* @param superClassType
* @param className
* @return String unimplemented methods defined in superclass
*/
private String getUnimplementedMethodsFromSuperclass(IType superClassType, String className) {
StringBuffer sb = new StringBuffer();
try {
// Implement abstract methods from superclass
IMethod[] methods = superClassType.getMethods();
for (int j = 0; j < methods.length; j++) {
IMethod method = methods[j];
int flags = method.getFlags();
// Add if the method is abstract, not private or static, and the option is selected in data model
if ((Flags.isAbstract(flags) && !Flags.isStatic(flags) && !Flags.isPrivate(flags)) || implementImplementedMethod(methods[j])) {
String methodStub = getMethodStub(methods[j], superClassType.getFullyQualifiedName(), className);
sb.append(methodStub);
}
}
} catch (JavaModelException e) {
Logger.getLogger().log(e);
}
// Return method stubs string
return sb.toString();
}
/**
* This method is intended for internal use only. This will retrieve method stubs for
* unimplemented methods defined in the interfaces that will need to be created in the new class.
* This method does not accept null parameters. It will not return null.
* @see NewJavaClassOperation#getMethodStubs(String, String)
*
* @param superClassType
* @param className
* @param javaProj
* @return String unimplemented methods defined in interfaces
*/
private String getUnimplementedMethodsFromInterfaces(IType superClassType, String className, IJavaProject javaProj) {
StringBuffer sb = new StringBuffer();
try {
// Implement defined methods from interfaces
List interfaces = (List) model.getProperty(INewJavaClassDataModelProperties.INTERFACES);
if (interfaces != null) {
for (int i = 0; i < interfaces.size(); i++) {
String qualifiedClassName = (String) interfaces.get(i);
IType interfaceType = javaProj.findType(qualifiedClassName);
IMethod[] methodArray = interfaceType.getMethods();
// Make sure the method isn't already defined in the heirarchy
for (int j = 0; j < methodArray.length; j++) {
if (isMethodImplementedInHierarchy(methodArray[j], superClassType))
continue;
String methodStub = getMethodStub(methodArray[j], qualifiedClassName, className);
sb.append(methodStub);
}
}
}
} catch (JavaModelException e) {
Logger.getLogger().log(e);
}
// Return method stubs string
return sb.toString();
}
/**
* This method is intended for internal use only. Checks to see if the passed type name
* is of a primitive type. This method does not accept null. It will not return null.
* @see Signature#getElementType(java.lang.String)
*
* @param typeName
* @return boolean is type Primitive?
*/
private boolean isPrimitiveType(String typeName) {
char first = Signature.getElementType(typeName).charAt(0);
return (first != Signature.C_RESOLVED && first != Signature.C_UNRESOLVED);
}
/**
* This method is intended for internal use only. This will add import statements for the specified
* type if it is determined to be necessary. This does accept null parameters. It will not return null.
* @see NewJavaClassOperation#getMethodStub(IMethod, String, String)
*
* @param refTypeSig
* @param declaringType
* @return String type signature
* @throws JavaModelException
*/
private String resolveAndAdd(String refTypeSig, IType declaringType) throws JavaModelException {
String resolvedTypeName = JavaModelUtil.getResolvedTypeName(refTypeSig, declaringType);
// Could type not be resolved and is import statement missing?
if (resolvedTypeName != null && !importStatements.contains(resolvedTypeName) && !resolvedTypeName.startsWith("java.lang")) { //$NON-NLS-1$
importStatements.add(resolvedTypeName);
}
return Signature.toString(refTypeSig);
}
/**
* This method is intended for internal use only. This will use the predefined tokens to generate the
* actual method stubs. This method does not accept null parameters. It will not return null.
*
* @param method
* @param superClassName
* @param className
* @return String method stub
*/
private String getMethodStub(IMethod method, String superClassName, String className) {
StringBuffer sb = new StringBuffer();
try {
IType parentType = method.getDeclaringType();
String name = method.getElementName();
String[] paramTypes = method.getParameterTypes();
String[] paramNames = method.getParameterNames();
String[] exceptionTypes = method.getExceptionTypes();
// Parameters String
String paramString = EMPTY_STRING;
int nP = paramTypes.length;
for (int i = 0; i < nP; i++) {
String type = paramTypes[i];
// update import statements
if (!isPrimitiveType(type)) {
type = resolveAndAdd(type, parentType);
} else {
type = Signature.toString(type);
}
int index = type.lastIndexOf(DOT);
if (index != -1)
type = type.substring(index + 1);
paramString += type + SPACE + paramNames[i];
if (i < nP - 1)
paramString += COMMA + SPACE;
}
// Java doc
sb.append("\t/* (non-Java-doc)"); //$NON-NLS-1$
sb.append(lineSeparator);
sb.append("\t * @see "); //$NON-NLS-1$
sb.append(superClassName + POUND + name + OPEN_PAR);
sb.append(paramString);
sb.append(CLOSE_PAR);
sb.append(lineSeparator);
sb.append("\t */"); //$NON-NLS-1$
sb.append(lineSeparator);
// access
sb.append(TAB);
if (Flags.isPublic(method.getFlags()))
sb.append(PUBLIC);
else if (Flags.isProtected(method.getFlags()))
sb.append(PROTECTED);
else if (Flags.isPrivate(method.getFlags()))
sb.append(PRIVATE);
String returnType = null;
if (method.isConstructor()) {
sb.append(className);
} else {
// return type
returnType = method.getReturnType();
if (!isPrimitiveType(returnType)) {
returnType = resolveAndAdd(returnType, parentType);
} else {
returnType = Signature.toString(returnType);
}
int idx = returnType.lastIndexOf(DOT);
if (idx == -1)
sb.append(returnType);
else
sb.append(returnType.substring(idx + 1));
sb.append(SPACE);
// name
sb.append(name);
}
// Parameters
sb.append(OPEN_PAR + paramString + CLOSE_PAR);
// exceptions
int nE = exceptionTypes.length;
if (nE > 0) {
sb.append(SPACE + THROWS);
for (int i = 0; i < nE; i++) {
String type = exceptionTypes[i];
if (!isPrimitiveType(type)) {
type = resolveAndAdd(type, parentType);
} else {
type = Signature.toString(type);
}
int index = type.lastIndexOf(DOT);
if (index != -1)
type = type.substring(index + 1);
sb.append(type);
if (i < nE - 1)
sb.append(COMMA + SPACE);
}
}
sb.append(SPACE + OPEN_BRA);
sb.append(lineSeparator);
if (method.isConstructor()) {
sb.append(TAB + TAB + SUPER + OPEN_PAR);
for (int i = 0; i < nP; i++) {
sb.append(paramNames[i]);
if (i < nP - 1)
sb.append(COMMA + SPACE);
}
sb.append(CLOSE_PAR + SEMICOLON);
sb.append(lineSeparator);
} else {
String methodBody = getMethodBody(method, returnType);
sb.append(methodBody);
}
sb.append(TAB + CLOSE_BRA);
sb.append(lineSeparator);
sb.append(lineSeparator);
} catch (JavaModelException e) {
Logger.getLogger().log(e);
}
return sb.toString();
}
/**
* This method is intended for internal use only. It checks to see whether or not the
* method is already implemented in the class heirarchy.
* It does not accept null parameters. It will not return null.
* @see NewJavaClassOperation#getUnimplementedMethodsFromInterfaces(IType, String, IJavaProject)
*
* @param method
* @param superClass
* @return boolean is method already in heirarchy?
*/
private boolean isMethodImplementedInHierarchy(IMethod method, IType superClass) {
boolean ret = false;
IMethod foundMethod = findMethodImplementationInHierarchy(method, superClass);
// if the method exists and the property is set on the data model, then return true
if (foundMethod != null && foundMethod.exists() && !implementImplementedMethod(method))
ret = true;
return ret;
}
/**
* This method is intended for internal use only. This will recursively check the supertype heirarchy for
* the passed in method. This will not accept null parameters. It will return null if the method does
* not already exist in the heirarchy.
* @see NewJavaClassOperation#isMethodImplementedInHierarchy(IMethod, IType)
*
* @param method
* @param superClass
* @return IMethod the method from the heirarchy
*/
private IMethod findMethodImplementationInHierarchy(IMethod method, IType superClass) {
IMethod implementedMethod = null;
try {
if (superClass != null && superClass.exists()) {
ITypeHierarchy tH = superClass.newSupertypeHierarchy(new NullProgressMonitor());
implementedMethod = findMethodImplementationInHierarchy(tH, superClass, method.getElementName(), method.getParameterTypes(), method.isConstructor());
}
} catch (JavaModelException e) {
//Ignore
}
return implementedMethod;
}
/**
* This method is intended for internal use only. This will recursively check the supertype heirarchy for
* the passed in method. This will not accept null parameters. It will return null if the method does
* not already exist in the heirarchy.
* @see NewJavaClassOperation#findMethodImplementationInHierarchy(IMethod, IType)
* @see JavaModelUtil#findMethodImplementationInHierarchy(ITypeHierarchy, IType, String, String[], boolean)
*
* @param tH
* @param thisType
* @param methodName
* @param parameterTypes
* @param isConstructor
* @return IMethod
* @throws JavaModelException
*/
private IMethod findMethodImplementationInHierarchy(ITypeHierarchy tH, IType thisType, String methodName, String parameterTypes[], boolean isConstructor) throws JavaModelException {
IMethod found = JavaModelUtil.findMethod(methodName, parameterTypes, isConstructor, thisType);
// If method exists make sure it is not abstract
if (found != null && !Flags.isAbstract(found.getFlags())) {
return found;
}
// Check recursively
return JavaModelUtil.findMethodImplementationInHierarchy(tH, thisType, methodName, parameterTypes, isConstructor);
}
/**
* Subclasses may extend this method to provide their own specific method body definitions.
* The default implementation is to add a todo, and to return the appropriate type.
* This method does not accept null parameters. It will not return null.
* @see NewJavaClassOperation#getMethodStub(IMethod, String, String)
*
* @param method
* @param returnType
* @return String method body
*/
protected String getMethodBody(IMethod method, String returnType) {
// Add a todo comment
String body = TODO_COMMENT;
body += lineSeparator;
// Add the appropriate default return type
if (returnType == null || returnType.equals(VOID))
return body;
if (returnType.equals(INT))
body += RETURN_0;
else if (returnType.equals(BOOLEAN))
body += RETURN_FALSE;
else
body += RETURN_NULL;
body += lineSeparator;
// Return the method body
return body;
}
/**
* Subclasses may extend this method to provide their own user defined method stubs. The
* default implementation to just return an empty string. This method will not accept
* null parameter. It will not return null.
* @see NewJavaClassOperation#getMethodStubs(String, String)
*
* @param superClassType
* @return String user defined methods
*/
protected String getUserDefinedMethodStubs(IType superClassType) {
return EMPTY_STRING;
}
/**
* Subclasses may extend this method to provide their own specialized return on which nonimplemented
* methods to implement. This does not accept a null parameter. This will not return null.
* The default implementation is to always return false.
*
* @param method
* @return boolean should implement method?
*/
protected boolean implementImplementedMethod(IMethod method) {
return false;
}
}