blob: 3b6be399c4368994db6a4ee1c844ec9dc95b755a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2002 International Business Machines Corp. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.jdt.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
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.SubProgressMonitor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
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.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.internal.compiler.env.IConstants;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.IImportsStructure;
import org.eclipse.jdt.internal.corext.codemanipulation.ImportsStructure;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.template.Template;
import org.eclipse.jdt.internal.corext.template.Templates;
import org.eclipse.jdt.internal.corext.template.java.JavaContext;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.util.SWTUtil;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.dialogs.TypeSelectionDialog;
import org.eclipse.jdt.internal.ui.preferences.CodeGenerationPreferencePage;
import org.eclipse.jdt.internal.ui.preferences.ImportOrganizePreferencePage;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.SuperInterfaceSelectionDialog;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.Separator;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
/**
* The class <code>NewTypeWizardPage</code> contains controls and validation routines
* for a 'New Type WizardPage'. Implementors decide which components to add and to enable.
* Implementors can also customize the validation code. <code>NewTypeWizardPage</code>
* is intended to serve as base class of all wizards that create types like applets, servlets, classes,
* interfaces, etc.
* <p>
* See <code>NewClassWizardPage</code> or <code>NewInterfaceWizardPage</code> for an
* example usage of <code>NewTypeWizardPage</code>.
* </p>
*
* @see org.eclipse.jdt.ui.wizards.NewClassWizardPage
* @see org.eclipse.jdt.ui.wizards.NewInterfaceWizardPage
*
* @since 2.0
*/
public abstract class NewTypeWizardPage extends NewContainerWizardPage {
/**
* Class used in stub creation routines to add needed imports to a
* compilation unit.
*/
public static class ImportsManager {
private IImportsStructure fImportsStructure;
/* package */ ImportsManager(IImportsStructure structure) {
fImportsStructure= structure;
}
/* package */ IImportsStructure getImportsStructure() {
return fImportsStructure;
}
/**
* Adds a new import declaration that is sorted in the existing imports.
* If an import already exists or the import would conflict with another import
* of an other type with the same simple name the import is not added.
*
* @param qualifiedTypeName The fully qualified name of the type to import
* (dot separated)
* @return Retuns the simple type name that can be used in the code or the
* fully qualified type name if an import conflict prevented the import
*/
public String addImport(String qualifiedTypeName) {
return fImportsStructure.addImport(qualifiedTypeName);
}
}
/** Public access flag. See The Java Virtual Machine Specification for more details. */
public int F_PUBLIC = IConstants.AccPublic;
/** Private access flag. See The Java Virtual Machine Specification for more details. */
public int F_PRIVATE = IConstants.AccPrivate;
/** Protected access flag. See The Java Virtual Machine Specification for more details. */
public int F_PROTECTED = IConstants.AccProtected;
/** Static access flag. See The Java Virtual Machine Specification for more details. */
public int F_STATIC = IConstants.AccStatic;
/** Final access flag. See The Java Virtual Machine Specification for more details. */
public int F_FINAL = IConstants.AccFinal;
/** Abstract property flag. See The Java Virtual Machine Specification for more details. */
public int F_ABSTRACT = IConstants.AccAbstract;
private final static String PAGE_NAME= "NewTypeWizardPage"; //$NON-NLS-1$
/** Field ID of the package input field */
protected final static String PACKAGE= PAGE_NAME + ".package"; //$NON-NLS-1$
/** Field ID of the eclosing type input field */
protected final static String ENCLOSING= PAGE_NAME + ".enclosing"; //$NON-NLS-1$
/** Field ID of the enclosing type checkbox */
protected final static String ENCLOSINGSELECTION= ENCLOSING + ".selection"; //$NON-NLS-1$
/** Field ID of the type name input field */
protected final static String TYPENAME= PAGE_NAME + ".typename"; //$NON-NLS-1$
/** Field ID of the super type input field */
protected final static String SUPER= PAGE_NAME + ".superclass"; //$NON-NLS-1$
/** Field ID of the super interfaces input field */
protected final static String INTERFACES= PAGE_NAME + ".interfaces"; //$NON-NLS-1$
/** Field ID of the modifier checkboxes */
protected final static String MODIFIERS= PAGE_NAME + ".modifiers"; //$NON-NLS-1$
/** Field ID of the method stubs checkboxes */
protected final static String METHODS= PAGE_NAME + ".methods"; //$NON-NLS-1$
private class InterfacesListLabelProvider extends LabelProvider {
private Image fInterfaceImage;
public InterfacesListLabelProvider() {
super();
fInterfaceImage= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE);
}
public Image getImage(Object element) {
return fInterfaceImage;
}
}
private StringButtonStatusDialogField fPackageDialogField;
private SelectionButtonDialogField fEnclosingTypeSelection;
private StringButtonDialogField fEnclosingTypeDialogField;
private boolean fCanModifyPackage;
private boolean fCanModifyEnclosingType;
private IPackageFragment fCurrPackage;
private IType fCurrEnclosingType;
private StringDialogField fTypeNameDialogField;
private StringButtonDialogField fSuperClassDialogField;
private ListDialogField fSuperInterfacesDialogField;
private IType fSuperClass;
private SelectionButtonDialogFieldGroup fAccMdfButtons;
private SelectionButtonDialogFieldGroup fOtherMdfButtons;
private IType fCreatedType;
protected IStatus fEnclosingTypeStatus;
protected IStatus fPackageStatus;
protected IStatus fTypeNameStatus;
protected IStatus fSuperClassStatus;
protected IStatus fModifierStatus;
protected IStatus fSuperInterfacesStatus;
private boolean fIsClass;
private int fStaticMdfIndex;
private final int PUBLIC_INDEX= 0, DEFAULT_INDEX= 1, PRIVATE_INDEX= 2, PROTECTED_INDEX= 3;
private final int ABSTRACT_INDEX= 0, FINAL_INDEX= 1;
/**
* Creates a new <code>NewTypeWizardPage</code>
*
* @param isClass <code>true</code> if a new class is to be created; otherwise
* an interface is to be created
* @param pageName the wizard page's name
*/
public NewTypeWizardPage(boolean isClass, String pageName) {
super(pageName);
fCreatedType= null;
fIsClass= isClass;
TypeFieldsAdapter adapter= new TypeFieldsAdapter();
fPackageDialogField= new StringButtonStatusDialogField(adapter);
fPackageDialogField.setDialogFieldListener(adapter);
fPackageDialogField.setLabelText(NewWizardMessages.getString("NewTypeWizardPage.package.label")); //$NON-NLS-1$
fPackageDialogField.setButtonLabel(NewWizardMessages.getString("NewTypeWizardPage.package.button")); //$NON-NLS-1$
fPackageDialogField.setStatusWidthHint(NewWizardMessages.getString("NewTypeWizardPage.default")); //$NON-NLS-1$
fEnclosingTypeSelection= new SelectionButtonDialogField(SWT.CHECK);
fEnclosingTypeSelection.setDialogFieldListener(adapter);
fEnclosingTypeSelection.setLabelText(NewWizardMessages.getString("NewTypeWizardPage.enclosing.selection.label")); //$NON-NLS-1$
fEnclosingTypeDialogField= new StringButtonDialogField(adapter);
fEnclosingTypeDialogField.setDialogFieldListener(adapter);
fEnclosingTypeDialogField.setButtonLabel(NewWizardMessages.getString("NewTypeWizardPage.enclosing.button")); //$NON-NLS-1$
fTypeNameDialogField= new StringDialogField();
fTypeNameDialogField.setDialogFieldListener(adapter);
fTypeNameDialogField.setLabelText(NewWizardMessages.getString("NewTypeWizardPage.typename.label")); //$NON-NLS-1$
fSuperClassDialogField= new StringButtonDialogField(adapter);
fSuperClassDialogField.setDialogFieldListener(adapter);
fSuperClassDialogField.setLabelText(NewWizardMessages.getString("NewTypeWizardPage.superclass.label")); //$NON-NLS-1$
fSuperClassDialogField.setButtonLabel(NewWizardMessages.getString("NewTypeWizardPage.superclass.button")); //$NON-NLS-1$
String[] addButtons= new String[] {
/* 0 */ NewWizardMessages.getString("NewTypeWizardPage.interfaces.add"), //$NON-NLS-1$
/* 1 */ null,
/* 2 */ NewWizardMessages.getString("NewTypeWizardPage.interfaces.remove") //$NON-NLS-1$
};
fSuperInterfacesDialogField= new ListDialogField(adapter, addButtons, new InterfacesListLabelProvider());
fSuperInterfacesDialogField.setDialogFieldListener(adapter);
String interfaceLabel= fIsClass ? NewWizardMessages.getString("NewTypeWizardPage.interfaces.class.label") : NewWizardMessages.getString("NewTypeWizardPage.interfaces.ifc.label"); //$NON-NLS-1$ //$NON-NLS-2$
fSuperInterfacesDialogField.setLabelText(interfaceLabel);
fSuperInterfacesDialogField.setRemoveButtonIndex(2);
String[] buttonNames1= new String[] {
/* 0 == PUBLIC_INDEX */ NewWizardMessages.getString("NewTypeWizardPage.modifiers.public"), //$NON-NLS-1$
/* 1 == DEFAULT_INDEX */ NewWizardMessages.getString("NewTypeWizardPage.modifiers.default"), //$NON-NLS-1$
/* 2 == PRIVATE_INDEX */ NewWizardMessages.getString("NewTypeWizardPage.modifiers.private"), //$NON-NLS-1$
/* 3 == PROTECTED_INDEX*/ NewWizardMessages.getString("NewTypeWizardPage.modifiers.protected") //$NON-NLS-1$
};
fAccMdfButtons= new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames1, 4);
fAccMdfButtons.setDialogFieldListener(adapter);
fAccMdfButtons.setLabelText(NewWizardMessages.getString("NewTypeWizardPage.modifiers.acc.label")); //$NON-NLS-1$
fAccMdfButtons.setSelection(0, true);
String[] buttonNames2;
if (fIsClass) {
buttonNames2= new String[] {
/* 0 == ABSTRACT_INDEX */ NewWizardMessages.getString("NewTypeWizardPage.modifiers.abstract"), //$NON-NLS-1$
/* 1 == FINAL_INDEX */ NewWizardMessages.getString("NewTypeWizardPage.modifiers.final"), //$NON-NLS-1$
/* 2 */ NewWizardMessages.getString("NewTypeWizardPage.modifiers.static") //$NON-NLS-1$
};
fStaticMdfIndex= 2; // index of the static checkbox is 2
} else {
buttonNames2= new String[] {
NewWizardMessages.getString("NewTypeWizardPage.modifiers.static") //$NON-NLS-1$
};
fStaticMdfIndex= 0; // index of the static checkbox is 0
}
fOtherMdfButtons= new SelectionButtonDialogFieldGroup(SWT.CHECK, buttonNames2, 4);
fOtherMdfButtons.setDialogFieldListener(adapter);
fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, false);
fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, false);
fOtherMdfButtons.enableSelectionButton(fStaticMdfIndex, false);
fPackageStatus= new StatusInfo();
fEnclosingTypeStatus= new StatusInfo();
fCanModifyPackage= true;
fCanModifyEnclosingType= true;
updateEnableState();
fTypeNameStatus= new StatusInfo();
fSuperClassStatus= new StatusInfo();
fSuperInterfacesStatus= new StatusInfo();
fModifierStatus= new StatusInfo();
}
/**
* Initializes all fields provided by the page with a given selection.
*
* @param elem the selection used to intialize this page or <code>
* null</code> if no selection was available
*/
protected void initTypePage(IJavaElement elem) {
String initSuperclass= "java.lang.Object"; //$NON-NLS-1$
ArrayList initSuperinterfaces= new ArrayList(5);
IPackageFragment pack= null;
IType enclosingType= null;
if (elem != null) {
// evaluate the enclosing type
pack= (IPackageFragment) elem.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
IType typeInCU= (IType) elem.getAncestor(IJavaElement.TYPE);
if (typeInCU != null) {
if (typeInCU.getCompilationUnit() != null) {
enclosingType= typeInCU;
}
} else {
ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
if (cu != null) {
enclosingType= cu.findPrimaryType();
}
}
try {
IType type= null;
if (elem.getElementType() == IJavaElement.TYPE) {
type= (IType)elem;
if (type.exists()) {
String superName= JavaModelUtil.getFullyQualifiedName(type);
if (type.isInterface()) {
initSuperinterfaces.add(superName);
} else {
initSuperclass= superName;
}
}
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
// ignore this exception now
}
}
setPackageFragment(pack, true);
setEnclosingType(enclosingType, true);
setEnclosingTypeSelection(false, true);
setTypeName("", true); //$NON-NLS-1$
setSuperClass(initSuperclass, true);
setSuperInterfaces(initSuperinterfaces, true);
}
// -------- UI Creation ---------
/**
* Creates a separator line. Expects a <code>GridLayout</code> with at least 1 column.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createSeparator(Composite composite, int nColumns) {
(new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1));
}
/**
* Creates the controls for the package name field. Expects a <code>GridLayout</code> with at
* least 4 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createPackageControls(Composite composite, int nColumns) {
fPackageDialogField.doFillIntoGrid(composite, nColumns);
LayoutUtil.setWidthHint(fPackageDialogField.getTextControl(null), getMaxFieldWidth());
LayoutUtil.setHorizontalGrabbing(fPackageDialogField.getTextControl(null));
}
/**
* Creates the controls for the enclosing type name field. Expects a <code>GridLayout</code> with at
* least 4 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createEnclosingTypeControls(Composite composite, int nColumns) {
// #6891
Composite tabGroup= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginWidth= 0;
layout.marginHeight= 0;
tabGroup.setLayout(layout);
fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1);
Control c= fEnclosingTypeDialogField.getTextControl(composite);
GridData gd= new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint= getMaxFieldWidth();
gd.horizontalSpan= 2;
c.setLayoutData(gd);
Button button= fEnclosingTypeDialogField.getChangeControl(composite);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.heightHint = SWTUtil.getButtonHeigthHint(button);
gd.widthHint = SWTUtil.getButtonWidthHint(button);
button.setLayoutData(gd);
}
/**
* Creates the controls for the type name field. Expects a <code>GridLayout</code> with at
* least 2 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createTypeNameControls(Composite composite, int nColumns) {
fTypeNameDialogField.doFillIntoGrid(composite, nColumns - 1);
DialogField.createEmptySpace(composite);
LayoutUtil.setWidthHint(fTypeNameDialogField.getTextControl(null), getMaxFieldWidth());
}
/**
* Creates the controls for the modifiers radio/ceckbox buttons. Expects a
* <code>GridLayout</code> with at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createModifierControls(Composite composite, int nColumns) {
LayoutUtil.setHorizontalSpan(fAccMdfButtons.getLabelControl(composite), 1);
Control control= fAccMdfButtons.getSelectionButtonsGroup(composite);
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= nColumns - 2;
control.setLayoutData(gd);
DialogField.createEmptySpace(composite);
DialogField.createEmptySpace(composite);
control= fOtherMdfButtons.getSelectionButtonsGroup(composite);
gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan= nColumns - 2;
control.setLayoutData(gd);
DialogField.createEmptySpace(composite);
}
/**
* Creates the controls for the superclass name field. Expects a <code>GridLayout</code>
* with at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createSuperClassControls(Composite composite, int nColumns) {
fSuperClassDialogField.doFillIntoGrid(composite, nColumns);
LayoutUtil.setWidthHint(fSuperClassDialogField.getTextControl(null), getMaxFieldWidth());
}
/**
* Creates the controls for the superclass name field. Expects a <code>GridLayout</code> with
* at least 3 columns.
*
* @param composite the parent composite
* @param nColumns number of columns to span
*/
protected void createSuperInterfacesControls(Composite composite, int nColumns) {
fSuperInterfacesDialogField.doFillIntoGrid(composite, nColumns);
GridData gd= (GridData)fSuperInterfacesDialogField.getListControl(null).getLayoutData();
if (fIsClass) {
gd.heightHint= convertHeightInCharsToPixels(3);
} else {
gd.heightHint= convertHeightInCharsToPixels(6);
}
gd.grabExcessVerticalSpace= false;
gd.widthHint= getMaxFieldWidth();
}
/**
* Sets the focus on the type name input field.
*/
protected void setFocus() {
fTypeNameDialogField.setFocus();
}
// -------- TypeFieldsAdapter --------
private class TypeFieldsAdapter implements IStringButtonAdapter, IDialogFieldListener, IListAdapter {
// -------- IStringButtonAdapter
public void changeControlPressed(DialogField field) {
typePageChangeControlPressed(field);
}
// -------- IListAdapter
public void customButtonPressed(DialogField field, int index) {
typePageCustomButtonPressed(field, index);
}
public void selectionChanged(DialogField field) {}
// -------- IDialogFieldListener
public void dialogFieldChanged(DialogField field) {
typePageDialogFieldChanged(field);
}
}
private void typePageChangeControlPressed(DialogField field) {
if (field == fPackageDialogField) {
IPackageFragment pack= choosePackage();
if (pack != null) {
fPackageDialogField.setText(pack.getElementName());
}
} else if (field == fEnclosingTypeDialogField) {
IType type= chooseEnclosingType();
if (type != null) {
fEnclosingTypeDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
}
} else if (field == fSuperClassDialogField) {
IType type= chooseSuperType();
if (type != null) {
fSuperClassDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
}
}
}
private void typePageCustomButtonPressed(DialogField field, int index) {
if (field == fSuperInterfacesDialogField) {
chooseSuperInterfaces();
}
}
/*
* A field on the type has changed. The fields' status and all dependend
* status are updated.
*/
private void typePageDialogFieldChanged(DialogField field) {
String fieldName= null;
if (field == fPackageDialogField) {
fPackageStatus= packageChanged();
updatePackageStatusLabel();
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fieldName= PACKAGE;
} else if (field == fEnclosingTypeDialogField) {
fEnclosingTypeStatus= enclosingTypeChanged();
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fieldName= ENCLOSING;
} else if (field == fEnclosingTypeSelection) {
updateEnableState();
boolean isEnclosedType= isEnclosingTypeSelected();
if (!isEnclosedType) {
if (fAccMdfButtons.isSelected(PRIVATE_INDEX) || fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
fAccMdfButtons.setSelection(PRIVATE_INDEX, false);
fAccMdfButtons.setSelection(PROTECTED_INDEX, false);
fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
}
if (fOtherMdfButtons.isSelected(fStaticMdfIndex)) {
fOtherMdfButtons.setSelection(fStaticMdfIndex, false);
}
}
fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, isEnclosedType && fIsClass);
fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, isEnclosedType && fIsClass);
fOtherMdfButtons.enableSelectionButton(fStaticMdfIndex, isEnclosedType);
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fieldName= ENCLOSINGSELECTION;
} else if (field == fTypeNameDialogField) {
fTypeNameStatus= typeNameChanged();
fieldName= TYPENAME;
} else if (field == fSuperClassDialogField) {
fSuperClassStatus= superClassChanged();
fieldName= SUPER;
} else if (field == fSuperInterfacesDialogField) {
fSuperInterfacesStatus= superInterfacesChanged();
fieldName= INTERFACES;
} else if (field == fOtherMdfButtons) {
fModifierStatus= modifiersChanged();
fieldName= MODIFIERS;
} else {
fieldName= METHODS;
}
// tell all others
handleFieldChanged(fieldName);
}
// -------- update message ----------------
/*
* @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
*/
protected void handleFieldChanged(String fieldName) {
super.handleFieldChanged(fieldName);
if (fieldName == CONTAINER) {
fPackageStatus= packageChanged();
fEnclosingTypeStatus= enclosingTypeChanged();
fTypeNameStatus= typeNameChanged();
fSuperClassStatus= superClassChanged();
fSuperInterfacesStatus= superInterfacesChanged();
}
}
// ---- set / get ----------------
/**
* Returns the text of the package input field.
*
* @return the text of the package input field
*/
public String getPackageText() {
return fPackageDialogField.getText();
}
/**
* Returns the text of the enclosing type input field.
*
* @return the text of the enclosing type input field
*/
public String getEnclosingTypeText() {
return fEnclosingTypeDialogField.getText();
}
/**
* Returns the package fragment corresponding to the current input.
*
* @return a package fragement or <code>null</code> if the input
* could not be resolved.
*/
public IPackageFragment getPackageFragment() {
if (!isEnclosingTypeSelected()) {
return fCurrPackage;
} else {
if (fCurrEnclosingType != null) {
return fCurrEnclosingType.getPackageFragment();
}
}
return null;
}
/**
* Sets the package fragment to the given value. The method updates the model
* and the text of the control.
*
* @param pack the package fragement to be set
* @param canBeModified if <code>true</code> the package fragment is
* editable; otherwise it is read-only.
*/
public void setPackageFragment(IPackageFragment pack, boolean canBeModified) {
fCurrPackage= pack;
fCanModifyPackage= canBeModified;
String str= (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$
fPackageDialogField.setText(str);
updateEnableState();
}
/**
* Returns the enclosing type corresponding to the current input.
*
* @return the enclosing type or <code>null</code> if the enclosing type is
* not selected or the input could not be resolved
*/
public IType getEnclosingType() {
if (isEnclosingTypeSelected()) {
return fCurrEnclosingType;
}
return null;
}
/**
* Sets the enclosing type. The method updates the underlying model
* and the text of the control.
*
* @param type the enclosing type
* @param canBeModified if <code>true</code> the enclosing type field is
* editable; otherwise it is read-only.
*/
public void setEnclosingType(IType type, boolean canBeModified) {
fCurrEnclosingType= type;
fCanModifyEnclosingType= canBeModified;
String str= (type == null) ? "" : JavaModelUtil.getFullyQualifiedName(type); //$NON-NLS-1$
fEnclosingTypeDialogField.setText(str);
updateEnableState();
}
/**
* Returns the selection state of the enclosing type checkbox.
*
* @return the seleciton state of the enclosing type checkbox
*/
public boolean isEnclosingTypeSelected() {
return fEnclosingTypeSelection.isSelected();
}
/**
* Sets the enclosing type checkbox's selection state.
*
* @param isSelected the checkbox's selection state
* @param canBeModified if <code>true</code> the enclosing type checkbox is
* modifiable; otherwise it is read-only.
*/
public void setEnclosingTypeSelection(boolean isSelected, boolean canBeModified) {
fEnclosingTypeSelection.setSelection(isSelected);
fEnclosingTypeSelection.setEnabled(canBeModified);
updateEnableState();
}
/**
* Returns the type name entered into the type input field.
*
* @return the type name
*/
public String getTypeName() {
return fTypeNameDialogField.getText();
}
/**
* Sets the type name input field's text to the given value. Method doesn't update
* the model.
*
* @param name the new type name
* @param canBeModified if <code>true</code> the enclosing type name field is
* editable; otherwise it is read-only.
*/
public void setTypeName(String name, boolean canBeModified) {
fTypeNameDialogField.setText(name);
fTypeNameDialogField.setEnabled(canBeModified);
}
/**
* Returns the selected modifiers.
*
* @return the selected modifiers
* @see Flags
*/
public int getModifiers() {
int mdf= 0;
if (fAccMdfButtons.isSelected(PUBLIC_INDEX)) {
mdf+= F_PUBLIC;
} else if (fAccMdfButtons.isSelected(PRIVATE_INDEX)) {
mdf+= F_PRIVATE;
} else if (fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
mdf+= F_PROTECTED;
}
if (fOtherMdfButtons.isSelected(ABSTRACT_INDEX) && (fStaticMdfIndex != 0)) {
mdf+= F_ABSTRACT;
}
if (fOtherMdfButtons.isSelected(FINAL_INDEX)) {
mdf+= F_FINAL;
}
if (fOtherMdfButtons.isSelected(fStaticMdfIndex)) {
mdf+= F_STATIC;
}
return mdf;
}
/**
* Sets the modifiers.
*
* @param modifiers <code>F_PUBLIC</code>, <code>F_PRIVATE</code>,
* <code>F_PROTECTED</code>, <code>F_ABSTRACT, F_FINAL</code>
* or <code>F_STATIC</code> or, a valid combination.
* @param canBeModified if <code>true</code> the modifier fields are
* editable; otherwise they are read-only
* @see Flags
*/
public void setModifiers(int modifiers, boolean canBeModified) {
if (Flags.isPublic(modifiers)) {
fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
} else if (Flags.isPrivate(modifiers)) {
fAccMdfButtons.setSelection(PRIVATE_INDEX, true);
} else if (Flags.isProtected(modifiers)) {
fAccMdfButtons.setSelection(PROTECTED_INDEX, true);
} else {
fAccMdfButtons.setSelection(DEFAULT_INDEX, true);
}
if (Flags.isAbstract(modifiers)) {
fOtherMdfButtons.setSelection(ABSTRACT_INDEX, true);
}
if (Flags.isFinal(modifiers)) {
fOtherMdfButtons.setSelection(FINAL_INDEX, true);
}
if (Flags.isStatic(modifiers)) {
fOtherMdfButtons.setSelection(fStaticMdfIndex, true);
}
fAccMdfButtons.setEnabled(canBeModified);
fOtherMdfButtons.setEnabled(canBeModified);
}
/**
* Returns the content of the superclass input field.
*
* @return the superclass name
*/
public String getSuperClass() {
return fSuperClassDialogField.getText();
}
/**
* Sets the super class name.
*
* @param name the new superclass name
* @param canBeModified if <code>true</code> the superclass name field is
* editable; otherwise it is read-only.
*/
public void setSuperClass(String name, boolean canBeModified) {
fSuperClassDialogField.setText(name);
fSuperClassDialogField.setEnabled(canBeModified);
}
/**
* Returns the chosen super interfaces.
*
* @return a list of chosen super interfaces. The list's elements
* are of type <code>String</code>
*/
public List getSuperInterfaces() {
return fSuperInterfacesDialogField.getElements();
}
/**
* Sets the super interfaces.
*
* @param interfacesNames a list of super interface. The method requires that
* the list's elements are of type <code>String</code>
* @param canBeModified if <code>true</code> the super interface field is
* editable; otherwise it is read-only.
*/
public void setSuperInterfaces(List interfacesNames, boolean canBeModified) {
fSuperInterfacesDialogField.setElements(interfacesNames);
fSuperInterfacesDialogField.setEnabled(canBeModified);
}
// ----------- validation ----------
/**
* A hook method that gets called when the package field has changed. The method
* validates the package name and returns the status of the validation. The validation
* also updates the package fragment model.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus packageChanged() {
StatusInfo status= new StatusInfo();
fPackageDialogField.enableButton(getPackageFragmentRoot() != null);
String packName= getPackageText();
if (packName.length() > 0) {
IStatus val= JavaConventions.validatePackageName(packName);
if (val.getSeverity() == IStatus.ERROR) {
status.setError(NewWizardMessages.getFormattedString("NewTypeWizardPage.error.InvalidPackageName", val.getMessage())); //$NON-NLS-1$
return status;
} else if (val.getSeverity() == IStatus.WARNING) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.DiscouragedPackageName", val.getMessage())); //$NON-NLS-1$
// continue
}
}
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root != null) {
if (root.getJavaProject().exists() && packName.length() > 0) {
try {
IPath rootPath= root.getPath();
IPath outputPath= root.getJavaProject().getOutputLocation();
if (rootPath.isPrefixOf(outputPath) && !rootPath.equals(outputPath)) {
// if the bin folder is inside of our root, dont allow to name a package
// like the bin folder
IPath packagePath= rootPath.append(packName.replace('.', '/'));
if (outputPath.isPrefixOf(packagePath)) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.ClashOutputLocation")); //$NON-NLS-1$
return status;
}
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
// let pass
}
}
fCurrPackage= root.getPackageFragment(packName);
} else {
status.setError(""); //$NON-NLS-1$
}
return status;
}
/*
* Updates the 'default' label next to the package field.
*/
private void updatePackageStatusLabel() {
String packName= getPackageText();
if (packName.length() == 0) {
fPackageDialogField.setStatus(NewWizardMessages.getString("NewTypeWizardPage.default")); //$NON-NLS-1$
} else {
fPackageDialogField.setStatus(""); //$NON-NLS-1$
}
}
/*
* Updates the enable state of buttons related to the enclosing type selection checkbox.
*/
private void updateEnableState() {
boolean enclosing= isEnclosingTypeSelected();
fPackageDialogField.setEnabled(fCanModifyPackage && !enclosing);
fEnclosingTypeDialogField.setEnabled(fCanModifyEnclosingType && enclosing);
}
/**
* Hook method that gets called when the enclosing type name has changed. The method
* validates the enclosing type and returns the status of the validation. It also updates the
* enclosing type model.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus enclosingTypeChanged() {
StatusInfo status= new StatusInfo();
fCurrEnclosingType= null;
IPackageFragmentRoot root= getPackageFragmentRoot();
fEnclosingTypeDialogField.enableButton(root != null);
if (root == null) {
status.setError(""); //$NON-NLS-1$
return status;
}
String enclName= getEnclosingTypeText();
if (enclName.length() == 0) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingTypeEnterName")); //$NON-NLS-1$
return status;
}
try {
IType type= root.getJavaProject().findType(enclName);
if (type == null) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingTypeNotExists")); //$NON-NLS-1$
return status;
}
if (type.getCompilationUnit() == null) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingNotInCU")); //$NON-NLS-1$
return status;
}
if (!JavaModelUtil.isEditable(type.getCompilationUnit())) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingNotEditable")); //$NON-NLS-1$
return status;
}
fCurrEnclosingType= type;
IPackageFragmentRoot enclosingRoot= JavaModelUtil.getPackageFragmentRoot(type);
if (!enclosingRoot.equals(root)) {
status.setWarning(NewWizardMessages.getString("NewTypeWizardPage.warning.EnclosingNotInSourceFolder")); //$NON-NLS-1$
}
return status;
} catch (JavaModelException e) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnclosingTypeNotExists")); //$NON-NLS-1$
JavaPlugin.log(e);
return status;
}
}
/**
* Hook method that gets called when the type name has changed. The method validates the
* type name and returns the status of the validation.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus typeNameChanged() {
StatusInfo status= new StatusInfo();
String typeName= getTypeName();
// must not be empty
if (typeName.length() == 0) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.EnterTypeName")); //$NON-NLS-1$
return status;
}
if (typeName.indexOf('.') != -1) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.QualifiedName")); //$NON-NLS-1$
return status;
}
IStatus val= JavaConventions.validateJavaTypeName(typeName);
if (val.getSeverity() == IStatus.ERROR) {
status.setError(NewWizardMessages.getFormattedString("NewTypeWizardPage.error.InvalidTypeName", val.getMessage())); //$NON-NLS-1$
return status;
} else if (val.getSeverity() == IStatus.WARNING) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.TypeNameDiscouraged", val.getMessage())); //$NON-NLS-1$
// continue checking
}
// must not exist
if (!isEnclosingTypeSelected()) {
IPackageFragment pack= getPackageFragment();
if (pack != null) {
ICompilationUnit cu= pack.getCompilationUnit(typeName + ".java"); //$NON-NLS-1$
if (cu.exists()) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.TypeNameExists")); //$NON-NLS-1$
return status;
}
}
} else {
IType type= getEnclosingType();
if (type != null) {
IType member= type.getType(typeName);
if (member.exists()) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.TypeNameExists")); //$NON-NLS-1$
return status;
}
}
}
return status;
}
/**
* Hook method that gets called when the superclass name has changed. The method
* validates the superclass name and returns the status of the validation.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus superClassChanged() {
StatusInfo status= new StatusInfo();
IPackageFragmentRoot root= getPackageFragmentRoot();
fSuperClassDialogField.enableButton(root != null);
fSuperClass= null;
String sclassName= getSuperClass();
if (sclassName.length() == 0) {
// accept the empty field (stands for java.lang.Object)
return status;
}
IStatus val= JavaConventions.validateJavaTypeName(sclassName);
if (val.getSeverity() == IStatus.ERROR) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.InvalidSuperClassName")); //$NON-NLS-1$
return status;
}
if (root != null) {
try {
IType type= resolveSuperTypeName(root.getJavaProject(), sclassName);
if (type == null) {
status.setWarning(NewWizardMessages.getString("NewTypeWizardPage.warning.SuperClassNotExists")); //$NON-NLS-1$
return status;
} else {
if (type.isInterface()) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.SuperClassIsNotClass", sclassName)); //$NON-NLS-1$
return status;
}
int flags= type.getFlags();
if (Flags.isFinal(flags)) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.SuperClassIsFinal", sclassName)); //$NON-NLS-1$
return status;
} else if (!JavaModelUtil.isVisible(type, getPackageFragment())) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.SuperClassIsNotVisible", sclassName)); //$NON-NLS-1$
return status;
}
}
fSuperClass= type;
} catch (JavaModelException e) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.InvalidSuperClassName")); //$NON-NLS-1$
JavaPlugin.log(e);
}
} else {
status.setError(""); //$NON-NLS-1$
}
return status;
}
private IType resolveSuperTypeName(IJavaProject jproject, String sclassName) throws JavaModelException {
IType type= null;
if (isEnclosingTypeSelected()) {
// search in the context of the enclosing type
IType enclosingType= getEnclosingType();
if (enclosingType != null) {
String[][] res= enclosingType.resolveType(sclassName);
if (res != null && res.length > 0) {
type= jproject.findType(res[0][0], res[0][1]);
}
}
} else {
IPackageFragment currPack= getPackageFragment();
if (type == null && currPack != null) {
String packName= currPack.getElementName();
// search in own package
if (!currPack.isDefaultPackage()) {
type= jproject.findType(packName, sclassName);
}
// search in java.lang
if (type == null && !"java.lang".equals(packName)) { //$NON-NLS-1$
type= jproject.findType("java.lang", sclassName); //$NON-NLS-1$
}
}
// search fully qualified
if (type == null) {
type= jproject.findType(sclassName);
}
}
return type;
}
/**
* Hook method that gets called when the list of super interface has changed. The method
* validates the superinterfaces and returns the status of the validation.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus superInterfacesChanged() {
StatusInfo status= new StatusInfo();
IPackageFragmentRoot root= getPackageFragmentRoot();
fSuperInterfacesDialogField.enableButton(0, root != null);
if (root != null) {
List elements= fSuperInterfacesDialogField.getElements();
int nElements= elements.size();
for (int i= 0; i < nElements; i++) {
String intfname= (String)elements.get(i);
try {
IType type= root.getJavaProject().findType(intfname);
if (type == null) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.InterfaceNotExists", intfname)); //$NON-NLS-1$
return status;
} else {
if (type.isClass()) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.InterfaceIsNotInterface", intfname)); //$NON-NLS-1$
return status;
}
if (!JavaModelUtil.isVisible(type, getPackageFragment())) {
status.setWarning(NewWizardMessages.getFormattedString("NewTypeWizardPage.warning.InterfaceIsNotVisible", intfname)); //$NON-NLS-1$
return status;
}
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
// let pass, checking is an extra
}
}
}
return status;
}
/**
* Hook method that gets called when the modifiers have changed. The method validates
* the modifiers and returns the status of the validation.
* <p>
* Subclasses may extend this method to perform their own validation.
* </p>
*
* @return the status of the validation
*/
protected IStatus modifiersChanged() {
StatusInfo status= new StatusInfo();
int modifiers= getModifiers();
if (Flags.isFinal(modifiers) && Flags.isAbstract(modifiers)) {
status.setError(NewWizardMessages.getString("NewTypeWizardPage.error.ModifiersFinalAndAbstract")); //$NON-NLS-1$
}
return status;
}
// selection dialogs
private IPackageFragment choosePackage() {
IPackageFragmentRoot froot= getPackageFragmentRoot();
IJavaElement[] packages= null;
try {
if (froot != null) {
packages= froot.getChildren();
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
}
if (packages == null) {
packages= new IJavaElement[0];
}
ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT));
dialog.setIgnoreCase(false);
dialog.setTitle(NewWizardMessages.getString("NewTypeWizardPage.ChoosePackageDialog.title")); //$NON-NLS-1$
dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.ChoosePackageDialog.description")); //$NON-NLS-1$
dialog.setEmptyListMessage(NewWizardMessages.getString("NewTypeWizardPage.ChoosePackageDialog.empty")); //$NON-NLS-1$
dialog.setElements(packages);
if (fCurrPackage != null) {
dialog.setInitialSelections(new Object[] { fCurrPackage });
}
if (dialog.open() == dialog.OK) {
return (IPackageFragment) dialog.getFirstResult();
}
return null;
}
private IType chooseEnclosingType() {
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null) {
return null;
}
IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[] { root });
TypeSelectionDialog dialog= new TypeSelectionDialog(getShell(), getWizard().getContainer(), IJavaSearchConstants.TYPE, scope);
dialog.setTitle(NewWizardMessages.getString("NewTypeWizardPage.ChooseEnclosingTypeDialog.title")); //$NON-NLS-1$
dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.ChooseEnclosingTypeDialog.description")); //$NON-NLS-1$
if (fCurrEnclosingType != null) {
dialog.setInitialSelections(new Object[] { fCurrEnclosingType });
dialog.setFilter(fCurrEnclosingType.getElementName().substring(0, 1));
}
if (dialog.open() == dialog.OK) {
return (IType) dialog.getFirstResult();
}
return null;
}
private IType chooseSuperType() {
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null) {
return null;
}
IJavaElement[] elements= new IJavaElement[] { root.getJavaProject() };
IJavaSearchScope scope= SearchEngine.createJavaSearchScope(elements);
TypeSelectionDialog dialog= new TypeSelectionDialog(getShell(), getWizard().getContainer(), IJavaSearchConstants.CLASS, scope);
dialog.setTitle(NewWizardMessages.getString("NewTypeWizardPage.SuperClassDialog.title")); //$NON-NLS-1$
dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.SuperClassDialog.message")); //$NON-NLS-1$
if (fSuperClass != null) {
dialog.setFilter(fSuperClass.getElementName());
}
if (dialog.open() == dialog.OK) {
return (IType) dialog.getFirstResult();
}
return null;
}
private void chooseSuperInterfaces() {
IPackageFragmentRoot root= getPackageFragmentRoot();
if (root == null) {
return;
}
IJavaProject project= root.getJavaProject();
SuperInterfaceSelectionDialog dialog= new SuperInterfaceSelectionDialog(getShell(), getWizard().getContainer(), fSuperInterfacesDialogField, project);
dialog.setTitle(fIsClass ? NewWizardMessages.getString("NewTypeWizardPage.InterfacesDialog.class.title") : NewWizardMessages.getString("NewTypeWizardPage.InterfacesDialog.interface.title")); //$NON-NLS-1$ //$NON-NLS-2$
dialog.setMessage(NewWizardMessages.getString("NewTypeWizardPage.InterfacesDialog.message")); //$NON-NLS-1$
dialog.open();
return;
}
// ---- creation ----------------
/**
* Creates the new type using the entered field values.
*
* @param monitor a progress monitor to report progress. The progress
* monitor must not be <code>null</code>
*/
public void createType(IProgressMonitor monitor) throws CoreException, InterruptedException {
monitor.beginTask(NewWizardMessages.getString("NewTypeWizardPage.operationdesc"), 10); //$NON-NLS-1$
IPackageFragmentRoot root= getPackageFragmentRoot();
IPackageFragment pack= getPackageFragment();
if (pack == null) {
pack= root.getPackageFragment(""); //$NON-NLS-1$
}
if (!pack.exists()) {
String packName= pack.getElementName();
pack= root.createPackageFragment(packName, true, null);
}
monitor.worked(1);
String clName= getTypeName();
boolean isInnerClass= isEnclosingTypeSelected();
IType createdType;
ImportsStructure imports;
int indent= 0;
String[] prefOrder= ImportOrganizePreferencePage.getImportOrderPreference();
int threshold= ImportOrganizePreferencePage.getImportNumberThreshold();
String lineDelimiter= null;
if (!isInnerClass) {
lineDelimiter= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
String packStatement= pack.isDefaultPackage() ? "" : "package " + pack.getElementName() + ";" + lineDelimiter + lineDelimiter; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
ICompilationUnit parentCU= pack.createCompilationUnit(clName + ".java", packStatement, false, new SubProgressMonitor(monitor, 2)); //$NON-NLS-1$
imports= new ImportsStructure(parentCU, prefOrder, threshold, false);
// add an import that will be removed again. Having this import solves 14661
imports.addImport(pack.getElementName(), getTypeName());
String content= constructTypeStub(new ImportsManager(imports), lineDelimiter, parentCU);
createdType= parentCU.createType(content, null, false, new SubProgressMonitor(monitor, 3));
} else {
IType enclosingType= getEnclosingType();
// if we are working on a enclosed type that is open in an editor,
// then replace the enclosing type with its working copy
IType workingCopy= (IType) EditorUtility.getWorkingCopy(enclosingType);
if (workingCopy != null) {
enclosingType= workingCopy;
}
ICompilationUnit parentCU= enclosingType.getCompilationUnit();
imports= new ImportsStructure(parentCU, prefOrder, threshold, true);
// add imports that will be removed again. Having the imports solves 14661
IType[] topLevelTypes= parentCU.getTypes();
for (int i= 0; i < topLevelTypes.length; i++) {
imports.addImport(topLevelTypes[i].getFullyQualifiedName('.'));
}
lineDelimiter= StubUtility.getLineDelimiterUsed(enclosingType);
String content= constructTypeStub(new ImportsManager(imports), lineDelimiter, parentCU);
IJavaElement[] elems= enclosingType.getChildren();
IJavaElement sibling= elems.length > 0 ? elems[0] : null;
createdType= enclosingType.createType(content, sibling, false, new SubProgressMonitor(monitor, 1));
indent= StubUtility.getIndentUsed(enclosingType) + 1;
}
// add imports for superclass/interfaces, so types can be resolved correctly
imports.create(!isInnerClass, new SubProgressMonitor(monitor, 1));
createTypeMembers(createdType, new ImportsManager(imports), new SubProgressMonitor(monitor, 1));
// add imports
imports.create(!isInnerClass, new SubProgressMonitor(monitor, 1));
ICompilationUnit cu= createdType.getCompilationUnit();
ISourceRange range;
if (isInnerClass) {
synchronized(cu) {
cu.reconcile();
}
range= createdType.getSourceRange();
} else {
range= cu.getSourceRange();
}
IBuffer buf= cu.getBuffer();
String originalContent= buf.getText(range.getOffset(), range.getLength());
String formattedContent= StubUtility.codeFormat(originalContent, indent, lineDelimiter);
buf.replace(range.getOffset(), range.getLength(), formattedContent);
if (!isInnerClass) {
String fileComment= getFileComment(cu);
if (fileComment != null && fileComment.length() > 0) {
buf.replace(0, 0, fileComment + lineDelimiter);
}
buf.save(new SubProgressMonitor(monitor, 1), false);
} else {
monitor.worked(1);
}
fCreatedType= createdType;
monitor.done();
}
/**
* Returns the created type. The method only returns a valid type
* after <code>createType</code> has been called.
*
* @return the created type
* @see #createType(IProgressMonitor)
*/
public IType getCreatedType() {
return fCreatedType;
}
// ---- construct cu body----------------
private void writeSuperClass(StringBuffer buf, ImportsManager imports) {
String typename= getSuperClass();
if (fIsClass && typename.length() > 0 && !"java.lang.Object".equals(typename)) { //$NON-NLS-1$
buf.append(" extends "); //$NON-NLS-1$
String qualifiedName= fSuperClass != null ? JavaModelUtil.getFullyQualifiedName(fSuperClass) : typename;
buf.append(imports.addImport(qualifiedName));
}
}
private void writeSuperInterfaces(StringBuffer buf, ImportsManager imports) {
List interfaces= getSuperInterfaces();
int last= interfaces.size() - 1;
if (last >= 0) {
if (fIsClass) {
buf.append(" implements "); //$NON-NLS-1$
} else {
buf.append(" extends "); //$NON-NLS-1$
}
for (int i= 0; i <= last; i++) {
String typename= (String) interfaces.get(i);
buf.append(imports.addImport(typename));
if (i < last) {
buf.append(',');
}
}
}
}
/*
* Called from createType to construct the source for this type
*/
private String constructTypeStub(ImportsManager imports, String lineDelimiter, ICompilationUnit parentCU) {
StringBuffer buf= new StringBuffer();
String typeComment= getTypeComment(parentCU);
if (typeComment != null && typeComment.length() > 0) {
buf.append(typeComment);
buf.append(lineDelimiter);
}
int modifiers= getModifiers();
buf.append(Flags.toString(modifiers));
if (modifiers != 0) {
buf.append(' ');
}
buf.append(fIsClass ? "class " : "interface "); //$NON-NLS-2$ //$NON-NLS-1$
buf.append(getTypeName());
writeSuperClass(buf, imports);
writeSuperInterfaces(buf, imports);
buf.append('{');
buf.append(lineDelimiter);
buf.append(lineDelimiter);
buf.append('}');
buf.append(lineDelimiter);
return buf.toString();
}
/**
* @deprecated Overwrite createTypeMembers(IType, IImportsManager, IProgressMonitor) instead
*/
protected void createTypeMembers(IType newType, IImportsStructure imports, IProgressMonitor monitor) throws CoreException {
//deprecated
}
/**
* Hook method that gets called from <code>createType</code> to support adding of
* unanticipated methods, fields, and inner types to the created type.
* <p>
* Implementers can use any methods defined on <code>IType</code> to manipulate the
* new type.
* </p>
* <p>
* The source code of the new type will be formtted using the platform's formatter. Needed
* imports are added by the wizard at the end of the type creation process using the given
* import manager.
* </p>
*
* @param newType the new type created via <code>createType</code>
* @param imports an import manager which can be used to add new imports
* @param monitor a progress monitor to report progress. Must not be <code>null</code>
*
* @see #createType(IProgressMonitor)
*/
protected void createTypeMembers(IType newType, ImportsManager imports, IProgressMonitor monitor) throws CoreException {
// call for compatibility
createTypeMembers(newType, ((ImportsManager)imports).getImportsStructure(), monitor);
// default implementation does nothing
// example would be
// String mainMathod= "public void foo(Vector vec) {}"
// createdType.createMethod(main, null, false, null);
// imports.addImport("java.lang.Vector");
}
/**
* Hook mathod that gets called from <code>createType</code> to retrieve
* a file comment. This default implementation returns the content of the
* 'filecomment' template.
*
* @return the file comment or <code>null</code> if a file comment
* is not desired
*/
protected String getFileComment(ICompilationUnit parentCU) {
if (CodeGenerationPreferencePage.doFileComments()) {
return getTemplate("filecomment", parentCU, 0); //$NON-NLS-1$
}
return null;
}
/**
* Hook method that gets called from <code>createType</code> to retrieve
* a type comment. This default implementation returns the content of the
* 'typecomment' template.
*
* @return the type comment or <code>null</code> if a type comment
* is not desired
*/
protected String getTypeComment(ICompilationUnit parentCU) {
if (CodeGenerationPreferencePage.doCreateComments()) {
return getTemplate("typecomment", parentCU, 0); //$NON-NLS-1$
}
return null;
}
/**
* @deprecated Use getTemplate(String,ICompilationUnit,int)
*/
protected String getTemplate(String name, ICompilationUnit parentCU) {
return getTemplate(name, parentCU, 0);
}
/**
* Returns the string resulting from evaluation the given template in
* the context of the given compilation unit.
*
* @param name the template to be evaluated
* @param parentCU the templates evaluation context
* @param pos a source offset into the parent compilation unit. The
* template is evalutated at the given source offset
*/
protected String getTemplate(String name, ICompilationUnit parentCU, int pos) {
try {
Template[] templates= Templates.getInstance().getTemplates(name);
if (templates.length > 0) {
return JavaContext.evaluateTemplate(templates[0], parentCU, pos);
}
} catch (CoreException e) {
JavaPlugin.log(e);
}
return null;
}
/**
* @deprecated Use createInheritedMethods(IType,boolean,boolean,IImportsManager,IProgressMonitor)
*/
protected IMethod[] createInheritedMethods(IType type, boolean doConstructors, boolean doUnimplementedMethods, IImportsStructure imports, IProgressMonitor monitor) throws CoreException {
return createInheritedMethods(type, doConstructors, doUnimplementedMethods, new ImportsManager(imports), monitor);
}
/**
* Creates the bodies of all unimplemented methods and constructors and adds them to the type.
* Method is typically called by implementers of <code>NewTypeWizardPage</code> to add
* needed method and constructors.
*
* @param type the type for which the new methods and constructor are to be created
* @param doConstructors if <code>true</code> unimplemented constructors are created
* @param doUnimplementedMethods if <code>true</code> unimplemented methods are created
* @param imports an import manager to add all neded import statements
* @param monitor a progress monitor to report progress
*/
protected IMethod[] createInheritedMethods(IType type, boolean doConstructors, boolean doUnimplementedMethods, ImportsManager imports, IProgressMonitor monitor) throws CoreException {
ArrayList newMethods= new ArrayList();
ITypeHierarchy hierarchy= type.newSupertypeHierarchy(monitor);
CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings();
if (doConstructors) {
IType superclass= hierarchy.getSuperclass(type);
if (superclass != null) {
String[] constructors= StubUtility.evalConstructors(type, superclass, settings, imports.getImportsStructure());
if (constructors != null) {
for (int i= 0; i < constructors.length; i++) {
newMethods.add(constructors[i]);
}
}
}
}
if (doUnimplementedMethods) {
String[] unimplemented= StubUtility.evalUnimplementedMethods(type, hierarchy, false, settings, null, imports.getImportsStructure());
if (unimplemented != null) {
for (int i= 0; i < unimplemented.length; i++) {
newMethods.add(unimplemented[i]);
}
}
}
IMethod[] createdMethods= new IMethod[newMethods.size()];
for (int i= 0; i < newMethods.size(); i++) {
String content= (String) newMethods.get(i) + '\n'; // content will be formatted, ok to use \n
createdMethods[i]= type.createMethod(content, null, false, null);
}
return createdMethods;
}
// ---- creation ----------------
/**
* Returns the runnable that creates the type using the current settings.
* The returned runnable must be executed in the UI thread.
*
* @return the runnable to create the new type
*/
public IRunnableWithProgress getRunnable() {
return new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
createType(monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
}
}