0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: * John Kaplan, johnkaplantech@gmail.com - 108071 [code templates] template for body of newly created class
0011: *******************************************************************************/package org.eclipse.jdt.ui.wizards;
0012:
0013: import java.lang.reflect.InvocationTargetException;
0014: import java.net.URI;
0015: import java.util.ArrayList;
0016: import java.util.HashSet;
0017: import java.util.Iterator;
0018: import java.util.List;
0019: import java.util.Set;
0020:
0021: import org.eclipse.text.edits.TextEdit;
0022:
0023: import org.eclipse.core.filesystem.EFS;
0024: import org.eclipse.core.filesystem.IFileStore;
0025:
0026: import org.eclipse.core.runtime.CoreException;
0027: import org.eclipse.core.runtime.IPath;
0028: import org.eclipse.core.runtime.IProgressMonitor;
0029: import org.eclipse.core.runtime.IStatus;
0030: import org.eclipse.core.runtime.NullProgressMonitor;
0031: import org.eclipse.core.runtime.SubProgressMonitor;
0032:
0033: import org.eclipse.core.resources.IResource;
0034:
0035: import org.eclipse.swt.SWT;
0036: import org.eclipse.swt.accessibility.AccessibleAdapter;
0037: import org.eclipse.swt.accessibility.AccessibleEvent;
0038: import org.eclipse.swt.events.KeyAdapter;
0039: import org.eclipse.swt.events.KeyEvent;
0040: import org.eclipse.swt.events.SelectionEvent;
0041: import org.eclipse.swt.events.SelectionListener;
0042: import org.eclipse.swt.graphics.Image;
0043: import org.eclipse.swt.layout.GridData;
0044: import org.eclipse.swt.layout.GridLayout;
0045: import org.eclipse.swt.widgets.Button;
0046: import org.eclipse.swt.widgets.Composite;
0047: import org.eclipse.swt.widgets.Control;
0048: import org.eclipse.swt.widgets.Item;
0049: import org.eclipse.swt.widgets.Link;
0050: import org.eclipse.swt.widgets.Text;
0051:
0052: import org.eclipse.jface.contentassist.SubjectControlContentAssistant;
0053: import org.eclipse.jface.dialogs.MessageDialog;
0054: import org.eclipse.jface.operation.IRunnableWithProgress;
0055: import org.eclipse.jface.preference.PreferenceDialog;
0056: import org.eclipse.jface.viewers.CellEditor;
0057: import org.eclipse.jface.viewers.ICellModifier;
0058: import org.eclipse.jface.viewers.ISelection;
0059: import org.eclipse.jface.viewers.IStructuredSelection;
0060: import org.eclipse.jface.viewers.LabelProvider;
0061: import org.eclipse.jface.viewers.TableViewer;
0062: import org.eclipse.jface.window.Window;
0063:
0064: import org.eclipse.jface.text.BadLocationException;
0065: import org.eclipse.jface.text.ITextSelection;
0066: import org.eclipse.jface.text.templates.Template;
0067: import org.eclipse.jface.text.templates.TemplateException;
0068:
0069: import org.eclipse.ui.contentassist.ContentAssistHandler;
0070: import org.eclipse.ui.dialogs.ElementListSelectionDialog;
0071: import org.eclipse.ui.dialogs.PreferencesUtil;
0072:
0073: import org.eclipse.jdt.core.Flags;
0074: import org.eclipse.jdt.core.IBuffer;
0075: import org.eclipse.jdt.core.ICompilationUnit;
0076: import org.eclipse.jdt.core.IField;
0077: import org.eclipse.jdt.core.IJavaElement;
0078: import org.eclipse.jdt.core.IJavaProject;
0079: import org.eclipse.jdt.core.IMethod;
0080: import org.eclipse.jdt.core.IPackageFragment;
0081: import org.eclipse.jdt.core.IPackageFragmentRoot;
0082: import org.eclipse.jdt.core.ISourceRange;
0083: import org.eclipse.jdt.core.IType;
0084: import org.eclipse.jdt.core.JavaConventions;
0085: import org.eclipse.jdt.core.JavaCore;
0086: import org.eclipse.jdt.core.JavaModelException;
0087: import org.eclipse.jdt.core.Signature;
0088: import org.eclipse.jdt.core.ToolFactory;
0089: import org.eclipse.jdt.core.compiler.IProblem;
0090: import org.eclipse.jdt.core.compiler.IScanner;
0091: import org.eclipse.jdt.core.compiler.ITerminalSymbols;
0092: import org.eclipse.jdt.core.compiler.InvalidInputException;
0093: import org.eclipse.jdt.core.dom.AST;
0094: import org.eclipse.jdt.core.dom.ASTNode;
0095: import org.eclipse.jdt.core.dom.ASTParser;
0096: import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
0097: import org.eclipse.jdt.core.dom.CompilationUnit;
0098: import org.eclipse.jdt.core.dom.ITypeBinding;
0099: import org.eclipse.jdt.core.dom.ImportDeclaration;
0100: import org.eclipse.jdt.core.dom.ParameterizedType;
0101: import org.eclipse.jdt.core.dom.Type;
0102: import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
0103: import org.eclipse.jdt.core.formatter.CodeFormatter;
0104: import org.eclipse.jdt.core.search.IJavaSearchConstants;
0105: import org.eclipse.jdt.core.search.IJavaSearchScope;
0106: import org.eclipse.jdt.core.search.SearchEngine;
0107:
0108: import org.eclipse.jdt.internal.corext.codemanipulation.AddUnimplementedConstructorsOperation;
0109: import org.eclipse.jdt.internal.corext.codemanipulation.AddUnimplementedMethodsOperation;
0110: import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
0111: import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
0112: import org.eclipse.jdt.internal.corext.dom.ASTNodes;
0113: import org.eclipse.jdt.internal.corext.dom.TokenScanner;
0114: import org.eclipse.jdt.internal.corext.refactoring.StubTypeContext;
0115: import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker;
0116: import org.eclipse.jdt.internal.corext.template.java.JavaContext;
0117: import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
0118: import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
0119: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0120: import org.eclipse.jdt.internal.corext.util.Messages;
0121: import org.eclipse.jdt.internal.corext.util.Resources;
0122: import org.eclipse.jdt.internal.corext.util.Strings;
0123:
0124: import org.eclipse.jdt.ui.CodeGeneration;
0125: import org.eclipse.jdt.ui.CodeStyleConfiguration;
0126: import org.eclipse.jdt.ui.JavaElementLabelProvider;
0127:
0128: import org.eclipse.jdt.internal.ui.JavaPlugin;
0129: import org.eclipse.jdt.internal.ui.JavaPluginImages;
0130: import org.eclipse.jdt.internal.ui.dialogs.FilteredTypesSelectionDialog;
0131: import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
0132: import org.eclipse.jdt.internal.ui.dialogs.TableTextCellEditor;
0133: import org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler;
0134: import org.eclipse.jdt.internal.ui.preferences.CodeTemplatePreferencePage;
0135: import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
0136: import org.eclipse.jdt.internal.ui.refactoring.contentassist.CompletionContextRequestor;
0137: import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
0138: import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaPackageCompletionProcessor;
0139: import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;
0140: import org.eclipse.jdt.internal.ui.util.SWTUtil;
0141: import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
0142: import org.eclipse.jdt.internal.ui.wizards.SuperInterfaceSelectionDialog;
0143: import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
0144: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
0145: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
0146: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
0147: import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
0148: import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
0149: import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
0150: import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
0151: import org.eclipse.jdt.internal.ui.wizards.dialogfields.Separator;
0152: import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
0153: import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
0154: import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
0155:
0156: /**
0157: * The class <code>NewTypeWizardPage</code> contains controls and validation routines
0158: * for a 'New Type WizardPage'. Implementors decide which components to add and to enable.
0159: * Implementors can also customize the validation code. <code>NewTypeWizardPage</code>
0160: * is intended to serve as base class of all wizards that create types like applets, servlets, classes,
0161: * interfaces, etc.
0162: * <p>
0163: * See {@link NewClassWizardPage} or {@link NewInterfaceWizardPage} for an
0164: * example usage of the <code>NewTypeWizardPage</code>.
0165: * </p>
0166: *
0167: * @see org.eclipse.jdt.ui.wizards.NewClassWizardPage
0168: * @see org.eclipse.jdt.ui.wizards.NewInterfaceWizardPage
0169: * @see org.eclipse.jdt.ui.wizards.NewEnumWizardPage
0170: * @see org.eclipse.jdt.ui.wizards.NewAnnotationWizardPage
0171: *
0172: * @since 2.0
0173: */
0174: public abstract class NewTypeWizardPage extends NewContainerWizardPage {
0175:
0176: /**
0177: * Class used in stub creation routines to add needed imports to a
0178: * compilation unit.
0179: */
0180: public static class ImportsManager {
0181:
0182: private ImportRewrite fImportsRewrite;
0183:
0184: /* package */ImportsManager(CompilationUnit astRoot)
0185: throws CoreException {
0186: fImportsRewrite = CodeStyleConfiguration
0187: .createImportRewrite(astRoot, true);
0188: }
0189:
0190: /* package */ICompilationUnit getCompilationUnit() {
0191: return fImportsRewrite.getCompilationUnit();
0192: }
0193:
0194: /**
0195: * Adds a new import declaration that is sorted in the existing imports.
0196: * If an import already exists or the import would conflict with an import
0197: * of an other type with the same simple name, the import is not added.
0198: *
0199: * @param qualifiedTypeName The fully qualified name of the type to import
0200: * (dot separated).
0201: * @return Returns the simple type name that can be used in the code or the
0202: * fully qualified type name if an import conflict prevented the import.
0203: */
0204: public String addImport(String qualifiedTypeName) {
0205: return fImportsRewrite.addImport(qualifiedTypeName);
0206: }
0207:
0208: /**
0209: * Adds a new import declaration that is sorted in the existing imports.
0210: * If an import already exists or the import would conflict with an import
0211: * of an other type with the same simple name, the import is not added.
0212: *
0213: * @param typeBinding the binding of the type to import
0214: *
0215: * @return Returns the simple type name that can be used in the code or the
0216: * fully qualified type name if an import conflict prevented the import.
0217: */
0218: public String addImport(ITypeBinding typeBinding) {
0219: return fImportsRewrite.addImport(typeBinding);
0220: }
0221:
0222: /**
0223: * Adds a new import declaration for a static type that is sorted in the existing imports.
0224: * If an import already exists or the import would conflict with an import
0225: * of an other static import with the same simple name, the import is not added.
0226: *
0227: * @param declaringTypeName The qualified name of the static's member declaring type
0228: * @param simpleName the simple name of the member; either a field or a method name.
0229: * @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
0230: * method.
0231: * @return returns either the simple member name if the import was successful or else the qualified name if
0232: * an import conflict prevented the import.
0233: *
0234: * @since 3.2
0235: */
0236: public String addStaticImport(String declaringTypeName,
0237: String simpleName, boolean isField) {
0238: return fImportsRewrite.addStaticImport(declaringTypeName,
0239: simpleName, isField);
0240: }
0241:
0242: /* package */void create(boolean needsSave,
0243: IProgressMonitor monitor) throws CoreException {
0244: TextEdit edit = fImportsRewrite.rewriteImports(monitor);
0245: JavaModelUtil.applyEdit(fImportsRewrite
0246: .getCompilationUnit(), edit, needsSave, null);
0247: }
0248:
0249: /* package */void removeImport(String qualifiedName) {
0250: fImportsRewrite.removeImport(qualifiedName);
0251: }
0252:
0253: /* package */void removeStaticImport(String qualifiedName) {
0254: fImportsRewrite.removeStaticImport(qualifiedName);
0255: }
0256: }
0257:
0258: /** Public access flag. See The Java Virtual Machine Specification for more details. */
0259: public int F_PUBLIC = Flags.AccPublic;
0260: /** Private access flag. See The Java Virtual Machine Specification for more details. */
0261: public int F_PRIVATE = Flags.AccPrivate;
0262: /** Protected access flag. See The Java Virtual Machine Specification for more details. */
0263: public int F_PROTECTED = Flags.AccProtected;
0264: /** Static access flag. See The Java Virtual Machine Specification for more details. */
0265: public int F_STATIC = Flags.AccStatic;
0266: /** Final access flag. See The Java Virtual Machine Specification for more details. */
0267: public int F_FINAL = Flags.AccFinal;
0268: /** Abstract property flag. See The Java Virtual Machine Specification for more details. */
0269: public int F_ABSTRACT = Flags.AccAbstract;
0270:
0271: private final static String PAGE_NAME = "NewTypeWizardPage"; //$NON-NLS-1$
0272:
0273: /** Field ID of the package input field. */
0274: protected final static String PACKAGE = PAGE_NAME + ".package"; //$NON-NLS-1$
0275: /** Field ID of the enclosing type input field. */
0276: protected final static String ENCLOSING = PAGE_NAME + ".enclosing"; //$NON-NLS-1$
0277: /** Field ID of the enclosing type checkbox. */
0278: protected final static String ENCLOSINGSELECTION = ENCLOSING
0279: + ".selection"; //$NON-NLS-1$
0280: /** Field ID of the type name input field. */
0281: protected final static String TYPENAME = PAGE_NAME + ".typename"; //$NON-NLS-1$
0282: /** Field ID of the super type input field. */
0283: protected final static String SUPER = PAGE_NAME + ".superclass"; //$NON-NLS-1$
0284: /** Field ID of the super interfaces input field. */
0285: protected final static String INTERFACES = PAGE_NAME
0286: + ".interfaces"; //$NON-NLS-1$
0287: /** Field ID of the modifier check boxes. */
0288: protected final static String MODIFIERS = PAGE_NAME + ".modifiers"; //$NON-NLS-1$
0289: /** Field ID of the method stubs check boxes. */
0290: protected final static String METHODS = PAGE_NAME + ".methods"; //$NON-NLS-1$
0291:
0292: private static class InterfaceWrapper {
0293: public String interfaceName;
0294:
0295: public InterfaceWrapper(String interfaceName) {
0296: this .interfaceName = interfaceName;
0297: }
0298:
0299: public int hashCode() {
0300: return interfaceName.hashCode();
0301: }
0302:
0303: public boolean equals(Object obj) {
0304: return obj != null
0305: && getClass().equals(obj.getClass())
0306: && ((InterfaceWrapper) obj).interfaceName
0307: .equals(interfaceName);
0308: }
0309: }
0310:
0311: private static class InterfacesListLabelProvider extends
0312: LabelProvider {
0313: private Image fInterfaceImage;
0314:
0315: public InterfacesListLabelProvider() {
0316: fInterfaceImage = JavaPluginImages
0317: .get(JavaPluginImages.IMG_OBJS_INTERFACE);
0318: }
0319:
0320: public String getText(Object element) {
0321: return ((InterfaceWrapper) element).interfaceName;
0322: }
0323:
0324: public Image getImage(Object element) {
0325: return fInterfaceImage;
0326: }
0327: }
0328:
0329: private StringButtonStatusDialogField fPackageDialogField;
0330:
0331: private SelectionButtonDialogField fEnclosingTypeSelection;
0332: private StringButtonDialogField fEnclosingTypeDialogField;
0333:
0334: private boolean fCanModifyPackage;
0335: private boolean fCanModifyEnclosingType;
0336:
0337: private IPackageFragment fCurrPackage;
0338:
0339: private IType fCurrEnclosingType;
0340: /**
0341: * a handle to the type to be created (does usually not exist, can be null)
0342: */
0343: private IType fCurrType;
0344: private StringDialogField fTypeNameDialogField;
0345:
0346: private StringButtonDialogField fSuperClassDialogField;
0347: private ListDialogField fSuperInterfacesDialogField;
0348:
0349: private SelectionButtonDialogFieldGroup fAccMdfButtons;
0350: private SelectionButtonDialogFieldGroup fOtherMdfButtons;
0351:
0352: private SelectionButtonDialogField fAddCommentButton;
0353: private boolean fUseAddCommentButtonValue; // used for compatibility: Wizards that don't show the comment button control
0354: // will use the preferences settings
0355:
0356: private IType fCreatedType;
0357:
0358: private JavaPackageCompletionProcessor fCurrPackageCompletionProcessor;
0359: private JavaTypeCompletionProcessor fEnclosingTypeCompletionProcessor;
0360: private StubTypeContext fSuperClassStubTypeContext;
0361: private StubTypeContext fSuperInterfaceStubTypeContext;
0362:
0363: protected IStatus fEnclosingTypeStatus;
0364: protected IStatus fPackageStatus;
0365: protected IStatus fTypeNameStatus;
0366: protected IStatus fSuperClassStatus;
0367: protected IStatus fModifierStatus;
0368: protected IStatus fSuperInterfacesStatus;
0369:
0370: private final int PUBLIC_INDEX = 0, DEFAULT_INDEX = 1,
0371: PRIVATE_INDEX = 2, PROTECTED_INDEX = 3;
0372: private final int ABSTRACT_INDEX = 0, FINAL_INDEX = 1,
0373: STATIC_INDEX = 2, ENUM_ANNOT_STATIC_INDEX = 1;
0374:
0375: private int fTypeKind;
0376:
0377: /**
0378: * Constant to signal that the created type is a class.
0379: * @since 3.1
0380: */
0381: public static final int CLASS_TYPE = 1;
0382:
0383: /**
0384: * Constant to signal that the created type is a interface.
0385: * @since 3.1
0386: */
0387: public static final int INTERFACE_TYPE = 2;
0388:
0389: /**
0390: * Constant to signal that the created type is an enum.
0391: * @since 3.1
0392: */
0393: public static final int ENUM_TYPE = 3;
0394:
0395: /**
0396: * Constant to signal that the created type is an annotation.
0397: * @since 3.1
0398: */
0399: public static final int ANNOTATION_TYPE = 4;
0400:
0401: /**
0402: * Creates a new <code>NewTypeWizardPage</code>.
0403: *
0404: * @param isClass <code>true</code> if a new class is to be created; otherwise
0405: * an interface is to be created
0406: * @param pageName the wizard page's name
0407: */
0408: public NewTypeWizardPage(boolean isClass, String pageName) {
0409: this (isClass ? CLASS_TYPE : INTERFACE_TYPE, pageName);
0410: }
0411:
0412: /**
0413: * Creates a new <code>NewTypeWizardPage</code>.
0414: *
0415: * @param typeKind Signals the kind of the type to be created. Valid kinds are
0416: * {@link #CLASS_TYPE}, {@link #INTERFACE_TYPE}, {@link #ENUM_TYPE} and {@link #ANNOTATION_TYPE}
0417: * @param pageName the wizard page's name
0418: * @since 3.1
0419: */
0420: public NewTypeWizardPage(int typeKind, String pageName) {
0421: super (pageName);
0422: fTypeKind = typeKind;
0423:
0424: fCreatedType = null;
0425:
0426: TypeFieldsAdapter adapter = new TypeFieldsAdapter();
0427:
0428: fPackageDialogField = new StringButtonStatusDialogField(adapter);
0429: fPackageDialogField.setDialogFieldListener(adapter);
0430: fPackageDialogField.setLabelText(getPackageLabel());
0431: fPackageDialogField
0432: .setButtonLabel(NewWizardMessages.NewTypeWizardPage_package_button);
0433: fPackageDialogField
0434: .setStatusWidthHint(NewWizardMessages.NewTypeWizardPage_default);
0435:
0436: fEnclosingTypeSelection = new SelectionButtonDialogField(
0437: SWT.CHECK);
0438: fEnclosingTypeSelection.setDialogFieldListener(adapter);
0439: fEnclosingTypeSelection.setLabelText(getEnclosingTypeLabel());
0440:
0441: fEnclosingTypeDialogField = new StringButtonDialogField(adapter);
0442: fEnclosingTypeDialogField.setDialogFieldListener(adapter);
0443: fEnclosingTypeDialogField
0444: .setButtonLabel(NewWizardMessages.NewTypeWizardPage_enclosing_button);
0445:
0446: fTypeNameDialogField = new StringDialogField();
0447: fTypeNameDialogField.setDialogFieldListener(adapter);
0448: fTypeNameDialogField.setLabelText(getTypeNameLabel());
0449:
0450: fSuperClassDialogField = new StringButtonDialogField(adapter);
0451: fSuperClassDialogField.setDialogFieldListener(adapter);
0452: fSuperClassDialogField.setLabelText(getSuperClassLabel());
0453: fSuperClassDialogField
0454: .setButtonLabel(NewWizardMessages.NewTypeWizardPage_super class_button);
0455:
0456: String[] addButtons = new String[] {
0457: NewWizardMessages.NewTypeWizardPage_interfaces_add,
0458: /* 1 */null,
0459: NewWizardMessages.NewTypeWizardPage_interfaces_remove };
0460: fSuperInterfacesDialogField = new ListDialogField(adapter,
0461: addButtons, new InterfacesListLabelProvider());
0462: fSuperInterfacesDialogField.setDialogFieldListener(adapter);
0463: fSuperInterfacesDialogField
0464: .setTableColumns(new ListDialogField.ColumnsDescription(
0465: 1, false));
0466: fSuperInterfacesDialogField
0467: .setLabelText(getSuperInterfacesLabel());
0468: fSuperInterfacesDialogField.setRemoveButtonIndex(2);
0469:
0470: String[] buttonNames1 = new String[] {
0471: NewWizardMessages.NewTypeWizardPage_modifiers_public,
0472: NewWizardMessages.NewTypeWizardPage_modifiers_default,
0473: NewWizardMessages.NewTypeWizardPage_modifiers_private,
0474: NewWizardMessages.NewTypeWizardPage_modifiers_protected };
0475: fAccMdfButtons = new SelectionButtonDialogFieldGroup(SWT.RADIO,
0476: buttonNames1, 4);
0477: fAccMdfButtons.setDialogFieldListener(adapter);
0478: fAccMdfButtons.setLabelText(getModifiersLabel());
0479: fAccMdfButtons.setSelection(0, true);
0480:
0481: String[] buttonNames2;
0482: if (fTypeKind == CLASS_TYPE) {
0483: buttonNames2 = new String[] {
0484: NewWizardMessages.NewTypeWizardPage_modifiers_abstract,
0485: NewWizardMessages.NewTypeWizardPage_modifiers_final,
0486: NewWizardMessages.NewTypeWizardPage_modifiers_static };
0487: } else {
0488: if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
0489: buttonNames2 = new String[] {
0490: NewWizardMessages.NewTypeWizardPage_modifiers_abstract,
0491: NewWizardMessages.NewTypeWizardPage_modifiers_static };
0492: } else
0493: buttonNames2 = new String[] {};
0494: }
0495:
0496: fOtherMdfButtons = new SelectionButtonDialogFieldGroup(
0497: SWT.CHECK, buttonNames2, 4);
0498: fOtherMdfButtons.setDialogFieldListener(adapter);
0499:
0500: fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, false);
0501: fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, false);
0502: fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, false);
0503:
0504: if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
0505: fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX,
0506: false);
0507: fOtherMdfButtons.enableSelectionButton(
0508: ENUM_ANNOT_STATIC_INDEX, false);
0509: }
0510:
0511: fAddCommentButton = new SelectionButtonDialogField(SWT.CHECK);
0512: fAddCommentButton
0513: .setLabelText(NewWizardMessages.NewTypeWizardPage_addcomment_label);
0514:
0515: fUseAddCommentButtonValue = false; // only used when enabled
0516:
0517: fCurrPackageCompletionProcessor = new JavaPackageCompletionProcessor();
0518: fEnclosingTypeCompletionProcessor = new JavaTypeCompletionProcessor(
0519: false, false, true);
0520:
0521: fPackageStatus = new StatusInfo();
0522: fEnclosingTypeStatus = new StatusInfo();
0523:
0524: fCanModifyPackage = true;
0525: fCanModifyEnclosingType = true;
0526: updateEnableState();
0527:
0528: fTypeNameStatus = new StatusInfo();
0529: fSuperClassStatus = new StatusInfo();
0530: fSuperInterfacesStatus = new StatusInfo();
0531: fModifierStatus = new StatusInfo();
0532: }
0533:
0534: /**
0535: * Initializes all fields provided by the page with a given selection.
0536: *
0537: * @param elem the selection used to initialize this page or <code>
0538: * null</code> if no selection was available
0539: */
0540: protected void initTypePage(IJavaElement elem) {
0541: String initSuperclass = "java.lang.Object"; //$NON-NLS-1$
0542: ArrayList initSuperinterfaces = new ArrayList(5);
0543:
0544: IJavaProject project = null;
0545: IPackageFragment pack = null;
0546: IType enclosingType = null;
0547:
0548: if (elem != null) {
0549: // evaluate the enclosing type
0550: project = elem.getJavaProject();
0551: pack = (IPackageFragment) elem
0552: .getAncestor(IJavaElement.PACKAGE_FRAGMENT);
0553: IType typeInCU = (IType) elem
0554: .getAncestor(IJavaElement.TYPE);
0555: if (typeInCU != null) {
0556: if (typeInCU.getCompilationUnit() != null) {
0557: enclosingType = typeInCU;
0558: }
0559: } else {
0560: ICompilationUnit cu = (ICompilationUnit) elem
0561: .getAncestor(IJavaElement.COMPILATION_UNIT);
0562: if (cu != null) {
0563: enclosingType = cu.findPrimaryType();
0564: }
0565: }
0566:
0567: try {
0568: IType type = null;
0569: if (elem.getElementType() == IJavaElement.TYPE) {
0570: type = (IType) elem;
0571: if (type.exists()) {
0572: String super Name = JavaModelUtil
0573: .getFullyQualifiedName(type);
0574: if (type.isInterface()) {
0575: initSuperinterfaces.add(super Name);
0576: } else {
0577: initSuperclass = super Name;
0578: }
0579: }
0580: }
0581: } catch (JavaModelException e) {
0582: JavaPlugin.log(e);
0583: // ignore this exception now
0584: }
0585: }
0586:
0587: String typeName = ""; //$NON-NLS-1$
0588:
0589: ITextSelection selection = getCurrentTextSelection();
0590: if (selection != null) {
0591: String text = selection.getText();
0592: if (text != null
0593: && validateJavaTypeName(text, project).isOK()) {
0594: typeName = text;
0595: }
0596: }
0597:
0598: setPackageFragment(pack, true);
0599: setEnclosingType(enclosingType, true);
0600: setEnclosingTypeSelection(false, true);
0601:
0602: setTypeName(typeName, true);
0603: setSuperClass(initSuperclass, true);
0604: setSuperInterfaces(initSuperinterfaces, true);
0605:
0606: setAddComments(StubUtility.doAddComments(project), true); // from project or workspace
0607: }
0608:
0609: private static IStatus validateJavaTypeName(String text,
0610: IJavaProject project) {
0611: if (project == null || !project.exists()) {
0612: return JavaConventions.validateJavaTypeName(text,
0613: JavaCore.VERSION_1_3, JavaCore.VERSION_1_3);
0614: }
0615: return JavaConventionsUtil.validateJavaTypeName(text, project);
0616: }
0617:
0618: private static IStatus validatePackageName(String text,
0619: IJavaProject project) {
0620: if (project == null || !project.exists()) {
0621: return JavaConventions.validatePackageName(text,
0622: JavaCore.VERSION_1_3, JavaCore.VERSION_1_3);
0623: }
0624: return JavaConventionsUtil.validatePackageName(text, project);
0625: }
0626:
0627: // -------- UI Creation ---------
0628:
0629: /**
0630: * Returns the label that is used for the package input field.
0631: *
0632: * @return the label that is used for the package input field.
0633: * @since 3.2
0634: */
0635: protected String getPackageLabel() {
0636: return NewWizardMessages.NewTypeWizardPage_package_label;
0637: }
0638:
0639: /**
0640: * Returns the label that is used for the enclosing type input field.
0641: *
0642: * @return the label that is used for the enclosing type input field.
0643: * @since 3.2
0644: */
0645: protected String getEnclosingTypeLabel() {
0646: return NewWizardMessages.NewTypeWizardPage_enclosing_selection_label;
0647: }
0648:
0649: /**
0650: * Returns the label that is used for the type name input field.
0651: *
0652: * @return the label that is used for the type name input field.
0653: * @since 3.2
0654: */
0655: protected String getTypeNameLabel() {
0656: return NewWizardMessages.NewTypeWizardPage_typename_label;
0657: }
0658:
0659: /**
0660: * Returns the label that is used for the modifiers input field.
0661: *
0662: * @return the label that is used for the modifiers input field
0663: * @since 3.2
0664: */
0665: protected String getModifiersLabel() {
0666: return NewWizardMessages.NewTypeWizardPage_modifiers_acc_label;
0667: }
0668:
0669: /**
0670: * Returns the label that is used for the super class input field.
0671: *
0672: * @return the label that is used for the super class input field.
0673: * @since 3.2
0674: */
0675: protected String getSuperClassLabel() {
0676: return NewWizardMessages.NewTypeWizardPage_super class_label;
0677: }
0678:
0679: /**
0680: * Returns the label that is used for the super interfaces input field.
0681: *
0682: * @return the label that is used for the super interfaces input field.
0683: * @since 3.2
0684: */
0685: protected String getSuperInterfacesLabel() {
0686: if (fTypeKind != INTERFACE_TYPE)
0687: return NewWizardMessages.NewTypeWizardPage_interfaces_class_label;
0688: return NewWizardMessages.NewTypeWizardPage_interfaces_ifc_label;
0689: }
0690:
0691: /**
0692: * Creates a separator line. Expects a <code>GridLayout</code> with at least 1 column.
0693: *
0694: * @param composite the parent composite
0695: * @param nColumns number of columns to span
0696: */
0697: protected void createSeparator(Composite composite, int nColumns) {
0698: (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(
0699: composite, nColumns, convertHeightInCharsToPixels(1));
0700: }
0701:
0702: /**
0703: * Creates the controls for the package name field. Expects a <code>GridLayout</code> with at
0704: * least 4 columns.
0705: *
0706: * @param composite the parent composite
0707: * @param nColumns number of columns to span
0708: */
0709: protected void createPackageControls(Composite composite,
0710: int nColumns) {
0711: fPackageDialogField.doFillIntoGrid(composite, nColumns);
0712: Text text = fPackageDialogField.getTextControl(null);
0713: LayoutUtil.setWidthHint(text, getMaxFieldWidth());
0714: LayoutUtil.setHorizontalGrabbing(text);
0715: ControlContentAssistHelper.createTextContentAssistant(text,
0716: fCurrPackageCompletionProcessor);
0717: TextFieldNavigationHandler.install(text);
0718: }
0719:
0720: /**
0721: * Creates the controls for the enclosing type name field. Expects a <code>GridLayout</code> with at
0722: * least 4 columns.
0723: *
0724: * @param composite the parent composite
0725: * @param nColumns number of columns to span
0726: */
0727: protected void createEnclosingTypeControls(Composite composite,
0728: int nColumns) {
0729: // #6891
0730: Composite tabGroup = new Composite(composite, SWT.NONE);
0731: GridLayout layout = new GridLayout();
0732: layout.marginWidth = 0;
0733: layout.marginHeight = 0;
0734: tabGroup.setLayout(layout);
0735:
0736: fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1);
0737:
0738: Text text = fEnclosingTypeDialogField.getTextControl(composite);
0739: text.getAccessible().addAccessibleListener(
0740: new AccessibleAdapter() {
0741: public void getName(AccessibleEvent e) {
0742: e.result = NewWizardMessages.NewTypeWizardPage_enclosing_field_description;
0743: }
0744: });
0745: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
0746: gd.widthHint = getMaxFieldWidth();
0747: gd.horizontalSpan = 2;
0748: text.setLayoutData(gd);
0749:
0750: Button button = fEnclosingTypeDialogField
0751: .getChangeControl(composite);
0752: gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
0753: gd.widthHint = SWTUtil.getButtonWidthHint(button);
0754: button.setLayoutData(gd);
0755: ControlContentAssistHelper.createTextContentAssistant(text,
0756: fEnclosingTypeCompletionProcessor);
0757: TextFieldNavigationHandler.install(text);
0758: }
0759:
0760: /**
0761: * Creates the controls for the type name field. Expects a <code>GridLayout</code> with at
0762: * least 2 columns.
0763: *
0764: * @param composite the parent composite
0765: * @param nColumns number of columns to span
0766: */
0767: protected void createTypeNameControls(Composite composite,
0768: int nColumns) {
0769: fTypeNameDialogField.doFillIntoGrid(composite, nColumns - 1);
0770: DialogField.createEmptySpace(composite);
0771:
0772: Text text = fTypeNameDialogField.getTextControl(null);
0773: LayoutUtil.setWidthHint(text, getMaxFieldWidth());
0774: TextFieldNavigationHandler.install(text);
0775: }
0776:
0777: /**
0778: * Creates the controls for the modifiers radio/checkbox buttons. Expects a
0779: * <code>GridLayout</code> with at least 3 columns.
0780: *
0781: * @param composite the parent composite
0782: * @param nColumns number of columns to span
0783: */
0784: protected void createModifierControls(Composite composite,
0785: int nColumns) {
0786: LayoutUtil.setHorizontalSpan(fAccMdfButtons
0787: .getLabelControl(composite), 1);
0788:
0789: Control control = fAccMdfButtons
0790: .getSelectionButtonsGroup(composite);
0791: GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
0792: gd.horizontalSpan = nColumns - 2;
0793: control.setLayoutData(gd);
0794:
0795: DialogField.createEmptySpace(composite);
0796:
0797: if (fTypeKind == CLASS_TYPE) {
0798: DialogField.createEmptySpace(composite);
0799:
0800: control = fOtherMdfButtons
0801: .getSelectionButtonsGroup(composite);
0802: gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
0803: gd.horizontalSpan = nColumns - 2;
0804: control.setLayoutData(gd);
0805:
0806: DialogField.createEmptySpace(composite);
0807: }
0808: }
0809:
0810: /**
0811: * Creates the controls for the superclass name field. Expects a <code>GridLayout</code>
0812: * with at least 3 columns.
0813: *
0814: * @param composite the parent composite
0815: * @param nColumns number of columns to span
0816: */
0817: protected void createSuperClassControls(Composite composite,
0818: int nColumns) {
0819: fSuperClassDialogField.doFillIntoGrid(composite, nColumns);
0820: Text text = fSuperClassDialogField.getTextControl(null);
0821: LayoutUtil.setWidthHint(text, getMaxFieldWidth());
0822:
0823: JavaTypeCompletionProcessor super ClassCompletionProcessor = new JavaTypeCompletionProcessor(
0824: false, false, true);
0825: super ClassCompletionProcessor
0826: .setCompletionContextRequestor(new CompletionContextRequestor() {
0827: public StubTypeContext getStubTypeContext() {
0828: return getSuperClassStubTypeContext();
0829: }
0830: });
0831:
0832: ControlContentAssistHelper.createTextContentAssistant(text,
0833: super ClassCompletionProcessor);
0834: TextFieldNavigationHandler.install(text);
0835: }
0836:
0837: /**
0838: * Creates the controls for the superclass name field. Expects a <code>GridLayout</code> with
0839: * at least 3 columns.
0840: *
0841: * @param composite the parent composite
0842: * @param nColumns number of columns to span
0843: */
0844: protected void createSuperInterfacesControls(Composite composite,
0845: int nColumns) {
0846: final String INTERFACE = "interface"; //$NON-NLS-1$
0847: fSuperInterfacesDialogField.doFillIntoGrid(composite, nColumns);
0848: final TableViewer tableViewer = fSuperInterfacesDialogField
0849: .getTableViewer();
0850: tableViewer.setColumnProperties(new String[] { INTERFACE });
0851:
0852: TableTextCellEditor cellEditor = new TableTextCellEditor(
0853: tableViewer, 0) {
0854: protected void doSetFocus() {
0855: if (text != null) {
0856: text.setFocus();
0857: text.setSelection(text.getText().length());
0858: checkSelection();
0859: checkDeleteable();
0860: checkSelectable();
0861: }
0862: }
0863: };
0864: JavaTypeCompletionProcessor super InterfaceCompletionProcessor = new JavaTypeCompletionProcessor(
0865: false, false, true);
0866: super InterfaceCompletionProcessor
0867: .setCompletionContextRequestor(new CompletionContextRequestor() {
0868: public StubTypeContext getStubTypeContext() {
0869: return getSuperInterfacesStubTypeContext();
0870: }
0871: });
0872: SubjectControlContentAssistant contentAssistant = ControlContentAssistHelper
0873: .createJavaContentAssistant(super InterfaceCompletionProcessor);
0874: Text cellEditorText = cellEditor.getText();
0875: ContentAssistHandler.createHandlerForText(cellEditorText,
0876: contentAssistant);
0877: TextFieldNavigationHandler.install(cellEditorText);
0878: cellEditor.setContentAssistant(contentAssistant);
0879:
0880: tableViewer.setCellEditors(new CellEditor[] { cellEditor });
0881: tableViewer.setCellModifier(new ICellModifier() {
0882: public void modify(Object element, String property,
0883: Object value) {
0884: if (element instanceof Item)
0885: element = ((Item) element).getData();
0886:
0887: ((InterfaceWrapper) element).interfaceName = (String) value;
0888: fSuperInterfacesDialogField.elementChanged(element);
0889: }
0890:
0891: public Object getValue(Object element, String property) {
0892: return ((InterfaceWrapper) element).interfaceName;
0893: }
0894:
0895: public boolean canModify(Object element, String property) {
0896: return true;
0897: }
0898: });
0899: tableViewer.getTable().addKeyListener(new KeyAdapter() {
0900: public void keyPressed(KeyEvent event) {
0901: if (event.keyCode == SWT.F2 && event.stateMask == 0) {
0902: ISelection selection = tableViewer.getSelection();
0903: if (!(selection instanceof IStructuredSelection))
0904: return;
0905: IStructuredSelection structuredSelection = (IStructuredSelection) selection;
0906: tableViewer.editElement(structuredSelection
0907: .getFirstElement(), 0);
0908: }
0909: }
0910: });
0911: GridData gd = (GridData) fSuperInterfacesDialogField
0912: .getListControl(null).getLayoutData();
0913: if (fTypeKind == CLASS_TYPE) {
0914: gd.heightHint = convertHeightInCharsToPixels(3);
0915: } else {
0916: gd.heightHint = convertHeightInCharsToPixels(6);
0917: }
0918: gd.grabExcessVerticalSpace = false;
0919: gd.widthHint = getMaxFieldWidth();
0920: }
0921:
0922: /**
0923: * Creates the controls for the preference page links. Expects a <code>GridLayout</code> with
0924: * at least 3 columns.
0925: *
0926: * @param composite the parent composite
0927: * @param nColumns number of columns to span
0928: *
0929: * @since 3.1
0930: */
0931: protected void createCommentControls(Composite composite,
0932: int nColumns) {
0933: Link link = new Link(composite, SWT.NONE);
0934: link
0935: .setText(NewWizardMessages.NewTypeWizardPage_addcomment_description);
0936: link.addSelectionListener(new TypeFieldsAdapter());
0937: link.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
0938: false, false, nColumns, 1));
0939: DialogField.createEmptySpace(composite);
0940: fAddCommentButton.doFillIntoGrid(composite, nColumns - 1);
0941: }
0942:
0943: /**
0944: * Sets the focus on the type name input field.
0945: */
0946: protected void setFocus() {
0947: if (fTypeNameDialogField.isEnabled()) {
0948: fTypeNameDialogField.setFocus();
0949: } else {
0950: setFocusOnContainer();
0951: }
0952: }
0953:
0954: // -------- TypeFieldsAdapter --------
0955:
0956: private class TypeFieldsAdapter implements IStringButtonAdapter,
0957: IDialogFieldListener, IListAdapter, SelectionListener {
0958:
0959: // -------- IStringButtonAdapter
0960: public void changeControlPressed(DialogField field) {
0961: typePageChangeControlPressed(field);
0962: }
0963:
0964: // -------- IListAdapter
0965: public void customButtonPressed(ListDialogField field, int index) {
0966: typePageCustomButtonPressed(field, index);
0967: }
0968:
0969: public void selectionChanged(ListDialogField field) {
0970: }
0971:
0972: // -------- IDialogFieldListener
0973: public void dialogFieldChanged(DialogField field) {
0974: typePageDialogFieldChanged(field);
0975: }
0976:
0977: public void doubleClicked(ListDialogField field) {
0978: }
0979:
0980: public void widgetSelected(SelectionEvent e) {
0981: typePageLinkActivated(e);
0982: }
0983:
0984: public void widgetDefaultSelected(SelectionEvent e) {
0985: typePageLinkActivated(e);
0986: }
0987: }
0988:
0989: private void typePageLinkActivated(SelectionEvent e) {
0990: IJavaProject project = getJavaProject();
0991: if (project != null) {
0992: PreferenceDialog dialog = PreferencesUtil
0993: .createPropertyDialogOn(getShell(), project
0994: .getProject(),
0995: CodeTemplatePreferencePage.PROP_ID, null,
0996: null);
0997: dialog.open();
0998: } else {
0999: String title = NewWizardMessages.NewTypeWizardPage_configure_templates_title;
1000: String message = NewWizardMessages.NewTypeWizardPage_configure_templates_message;
1001: MessageDialog.openInformation(getShell(), title, message);
1002: }
1003: }
1004:
1005: private void typePageChangeControlPressed(DialogField field) {
1006: if (field == fPackageDialogField) {
1007: IPackageFragment pack = choosePackage();
1008: if (pack != null) {
1009: fPackageDialogField.setText(pack.getElementName());
1010: }
1011: } else if (field == fEnclosingTypeDialogField) {
1012: IType type = chooseEnclosingType();
1013: if (type != null) {
1014: fEnclosingTypeDialogField.setText(JavaModelUtil
1015: .getFullyQualifiedName(type));
1016: }
1017: } else if (field == fSuperClassDialogField) {
1018: IType type = chooseSuperClass();
1019: if (type != null) {
1020: fSuperClassDialogField.setText(JavaModelUtil
1021: .getFullyQualifiedName(type));
1022: }
1023: }
1024: }
1025:
1026: private void typePageCustomButtonPressed(DialogField field,
1027: int index) {
1028: if (field == fSuperInterfacesDialogField) {
1029: chooseSuperInterfaces();
1030: List interfaces = fSuperInterfacesDialogField.getElements();
1031: if (!interfaces.isEmpty()) {
1032: Object element = interfaces.get(interfaces.size() - 1);
1033: fSuperInterfacesDialogField.editElement(element);
1034: }
1035: }
1036: }
1037:
1038: /*
1039: * A field on the type has changed. The fields' status and all dependent
1040: * status are updated.
1041: */
1042: private void typePageDialogFieldChanged(DialogField field) {
1043: String fieldName = null;
1044: if (field == fPackageDialogField) {
1045: fPackageStatus = packageChanged();
1046: updatePackageStatusLabel();
1047: fTypeNameStatus = typeNameChanged();
1048: fSuperClassStatus = super ClassChanged();
1049: fieldName = PACKAGE;
1050: } else if (field == fEnclosingTypeDialogField) {
1051: fEnclosingTypeStatus = enclosingTypeChanged();
1052: fTypeNameStatus = typeNameChanged();
1053: fSuperClassStatus = super ClassChanged();
1054: fieldName = ENCLOSING;
1055: } else if (field == fEnclosingTypeSelection) {
1056: updateEnableState();
1057: boolean isEnclosedType = isEnclosingTypeSelected();
1058: if (!isEnclosedType) {
1059: if (fAccMdfButtons.isSelected(PRIVATE_INDEX)
1060: || fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
1061: fAccMdfButtons.setSelection(PRIVATE_INDEX, false);
1062: fAccMdfButtons.setSelection(PROTECTED_INDEX, false);
1063: fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
1064: }
1065: if (fOtherMdfButtons.isSelected(STATIC_INDEX)) {
1066: fOtherMdfButtons.setSelection(STATIC_INDEX, false);
1067: }
1068: }
1069: fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX,
1070: isEnclosedType);
1071: fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX,
1072: isEnclosedType);
1073: fOtherMdfButtons.enableSelectionButton(STATIC_INDEX,
1074: isEnclosedType);
1075: fTypeNameStatus = typeNameChanged();
1076: fSuperClassStatus = super ClassChanged();
1077: fieldName = ENCLOSINGSELECTION;
1078: } else if (field == fTypeNameDialogField) {
1079: fTypeNameStatus = typeNameChanged();
1080: fieldName = TYPENAME;
1081: } else if (field == fSuperClassDialogField) {
1082: fSuperClassStatus = super ClassChanged();
1083: fieldName = SUPER;
1084: } else if (field == fSuperInterfacesDialogField) {
1085: fSuperInterfacesStatus = super InterfacesChanged();
1086: fieldName = INTERFACES;
1087: } else if (field == fOtherMdfButtons || field == fAccMdfButtons) {
1088: fModifierStatus = modifiersChanged();
1089: fieldName = MODIFIERS;
1090: } else {
1091: fieldName = METHODS;
1092: }
1093: // tell all others
1094: handleFieldChanged(fieldName);
1095: }
1096:
1097: // -------- update message ----------------
1098:
1099: /*
1100: * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
1101: */
1102: protected void handleFieldChanged(String fieldName) {
1103: super .handleFieldChanged(fieldName);
1104: if (fieldName == CONTAINER) {
1105: fPackageStatus = packageChanged();
1106: fEnclosingTypeStatus = enclosingTypeChanged();
1107: fTypeNameStatus = typeNameChanged();
1108: fSuperClassStatus = super ClassChanged();
1109: fSuperInterfacesStatus = super InterfacesChanged();
1110: }
1111: }
1112:
1113: // ---- set / get ----------------
1114:
1115: /**
1116: * Returns the text of the package input field.
1117: *
1118: * @return the text of the package input field
1119: */
1120: public String getPackageText() {
1121: return fPackageDialogField.getText();
1122: }
1123:
1124: /**
1125: * Returns the text of the enclosing type input field.
1126: *
1127: * @return the text of the enclosing type input field
1128: */
1129: public String getEnclosingTypeText() {
1130: return fEnclosingTypeDialogField.getText();
1131: }
1132:
1133: /**
1134: * Returns the package fragment corresponding to the current input.
1135: *
1136: * @return a package fragment or <code>null</code> if the input
1137: * could not be resolved.
1138: */
1139: public IPackageFragment getPackageFragment() {
1140: if (!isEnclosingTypeSelected()) {
1141: return fCurrPackage;
1142: } else {
1143: if (fCurrEnclosingType != null) {
1144: return fCurrEnclosingType.getPackageFragment();
1145: }
1146: }
1147: return null;
1148: }
1149:
1150: /**
1151: * Sets the package fragment to the given value. The method updates the model
1152: * and the text of the control.
1153: *
1154: * @param pack the package fragment to be set
1155: * @param canBeModified if <code>true</code> the package fragment is
1156: * editable; otherwise it is read-only.
1157: */
1158: public void setPackageFragment(IPackageFragment pack,
1159: boolean canBeModified) {
1160: fCurrPackage = pack;
1161: fCanModifyPackage = canBeModified;
1162: String str = (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$
1163: fPackageDialogField.setText(str);
1164: updateEnableState();
1165: }
1166:
1167: /**
1168: * Returns the enclosing type corresponding to the current input.
1169: *
1170: * @return the enclosing type or <code>null</code> if the enclosing type is
1171: * not selected or the input could not be resolved
1172: */
1173: public IType getEnclosingType() {
1174: if (isEnclosingTypeSelected()) {
1175: return fCurrEnclosingType;
1176: }
1177: return null;
1178: }
1179:
1180: /**
1181: * Sets the enclosing type. The method updates the underlying model
1182: * and the text of the control.
1183: *
1184: * @param type the enclosing type
1185: * @param canBeModified if <code>true</code> the enclosing type field is
1186: * editable; otherwise it is read-only.
1187: */
1188: public void setEnclosingType(IType type, boolean canBeModified) {
1189: fCurrEnclosingType = type;
1190: fCanModifyEnclosingType = canBeModified;
1191: String str = (type == null) ? "" : JavaModelUtil.getFullyQualifiedName(type); //$NON-NLS-1$
1192: fEnclosingTypeDialogField.setText(str);
1193: updateEnableState();
1194: }
1195:
1196: /**
1197: * Returns the selection state of the enclosing type checkbox.
1198: *
1199: * @return the selection state of the enclosing type checkbox
1200: */
1201: public boolean isEnclosingTypeSelected() {
1202: return fEnclosingTypeSelection.isSelected();
1203: }
1204:
1205: /**
1206: * Sets the enclosing type checkbox's selection state.
1207: *
1208: * @param isSelected the checkbox's selection state
1209: * @param canBeModified if <code>true</code> the enclosing type checkbox is
1210: * modifiable; otherwise it is read-only.
1211: */
1212: public void setEnclosingTypeSelection(boolean isSelected,
1213: boolean canBeModified) {
1214: fEnclosingTypeSelection.setSelection(isSelected);
1215: fEnclosingTypeSelection.setEnabled(canBeModified);
1216: updateEnableState();
1217: }
1218:
1219: /**
1220: * Returns the type name entered into the type input field.
1221: *
1222: * @return the type name
1223: */
1224: public String getTypeName() {
1225: return fTypeNameDialogField.getText();
1226: }
1227:
1228: /**
1229: * Sets the type name input field's text to the given value. Method doesn't update
1230: * the model.
1231: *
1232: * @param name the new type name
1233: * @param canBeModified if <code>true</code> the type name field is
1234: * editable; otherwise it is read-only.
1235: */
1236: public void setTypeName(String name, boolean canBeModified) {
1237: fTypeNameDialogField.setText(name);
1238: fTypeNameDialogField.setEnabled(canBeModified);
1239: }
1240:
1241: /**
1242: * Returns the selected modifiers.
1243: *
1244: * @return the selected modifiers
1245: * @see Flags
1246: */
1247: public int getModifiers() {
1248: int mdf = 0;
1249: if (fAccMdfButtons.isSelected(PUBLIC_INDEX)) {
1250: mdf += F_PUBLIC;
1251: } else if (fAccMdfButtons.isSelected(PRIVATE_INDEX)) {
1252: mdf += F_PRIVATE;
1253: } else if (fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
1254: mdf += F_PROTECTED;
1255: }
1256: if (fOtherMdfButtons.isSelected(ABSTRACT_INDEX)) {
1257: mdf += F_ABSTRACT;
1258: }
1259: if (fOtherMdfButtons.isSelected(FINAL_INDEX)) {
1260: mdf += F_FINAL;
1261: }
1262: if (fOtherMdfButtons.isSelected(STATIC_INDEX)) {
1263: mdf += F_STATIC;
1264: }
1265: return mdf;
1266: }
1267:
1268: /**
1269: * Sets the modifiers.
1270: *
1271: * @param modifiers <code>F_PUBLIC</code>, <code>F_PRIVATE</code>,
1272: * <code>F_PROTECTED</code>, <code>F_ABSTRACT</code>, <code>F_FINAL</code>
1273: * or <code>F_STATIC</code> or a valid combination.
1274: * @param canBeModified if <code>true</code> the modifier fields are
1275: * editable; otherwise they are read-only
1276: * @see Flags
1277: */
1278: public void setModifiers(int modifiers, boolean canBeModified) {
1279: if (Flags.isPublic(modifiers)) {
1280: fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
1281: } else if (Flags.isPrivate(modifiers)) {
1282: fAccMdfButtons.setSelection(PRIVATE_INDEX, true);
1283: } else if (Flags.isProtected(modifiers)) {
1284: fAccMdfButtons.setSelection(PROTECTED_INDEX, true);
1285: } else {
1286: fAccMdfButtons.setSelection(DEFAULT_INDEX, true);
1287: }
1288: if (Flags.isAbstract(modifiers)) {
1289: fOtherMdfButtons.setSelection(ABSTRACT_INDEX, true);
1290: }
1291: if (Flags.isFinal(modifiers)) {
1292: fOtherMdfButtons.setSelection(FINAL_INDEX, true);
1293: }
1294: if (Flags.isStatic(modifiers)) {
1295: fOtherMdfButtons.setSelection(STATIC_INDEX, true);
1296: }
1297:
1298: fAccMdfButtons.setEnabled(canBeModified);
1299: fOtherMdfButtons.setEnabled(canBeModified);
1300: }
1301:
1302: /**
1303: * Returns the content of the superclass input field.
1304: *
1305: * @return the superclass name
1306: */
1307: public String getSuperClass() {
1308: return fSuperClassDialogField.getText();
1309: }
1310:
1311: /**
1312: * Sets the super class name.
1313: *
1314: * @param name the new superclass name
1315: * @param canBeModified if <code>true</code> the superclass name field is
1316: * editable; otherwise it is read-only.
1317: */
1318: public void setSuperClass(String name, boolean canBeModified) {
1319: fSuperClassDialogField.setText(name);
1320: fSuperClassDialogField.setEnabled(canBeModified);
1321: }
1322:
1323: /**
1324: * Returns the chosen super interfaces.
1325: *
1326: * @return a list of chosen super interfaces. The list's elements
1327: * are of type <code>String</code>
1328: */
1329: public List getSuperInterfaces() {
1330: List interfaces = fSuperInterfacesDialogField.getElements();
1331: ArrayList result = new ArrayList(interfaces.size());
1332: for (Iterator iter = interfaces.iterator(); iter.hasNext();) {
1333: InterfaceWrapper wrapper = (InterfaceWrapper) iter.next();
1334: result.add(wrapper.interfaceName);
1335: }
1336: return result;
1337: }
1338:
1339: /**
1340: * Sets the super interfaces.
1341: *
1342: * @param interfacesNames a list of super interface. The method requires that
1343: * the list's elements are of type <code>String</code>
1344: * @param canBeModified if <code>true</code> the super interface field is
1345: * editable; otherwise it is read-only.
1346: */
1347: public void setSuperInterfaces(List interfacesNames,
1348: boolean canBeModified) {
1349: ArrayList interfaces = new ArrayList(interfacesNames.size());
1350: for (Iterator iter = interfacesNames.iterator(); iter.hasNext();) {
1351: interfaces.add(new InterfaceWrapper((String) iter.next()));
1352: }
1353: fSuperInterfacesDialogField.setElements(interfaces);
1354: fSuperInterfacesDialogField.setEnabled(canBeModified);
1355: }
1356:
1357: /**
1358: * Adds a super interface to the end of the list and selects it if it is not in the list yet.
1359: *
1360: * @param superInterface the fully qualified type name of the interface.
1361: * @return returns <code>true</code>if the interfaces has been added, <code>false</code>
1362: * if the interface already is in the list.
1363: * @since 3.2
1364: */
1365: public boolean addSuperInterface(String super Interface) {
1366: return fSuperInterfacesDialogField
1367: .addElement(new InterfaceWrapper(super Interface));
1368: }
1369:
1370: /**
1371: * Sets 'Add comment' checkbox. The value set will only be used when creating source when
1372: * the comment control is enabled (see {@link #enableCommentControl(boolean)}
1373: *
1374: * @param doAddComments if <code>true</code>, comments are added.
1375: * @param canBeModified if <code>true</code> check box is
1376: * editable; otherwise it is read-only.
1377: * @since 3.1
1378: */
1379: public void setAddComments(boolean doAddComments,
1380: boolean canBeModified) {
1381: fAddCommentButton.setSelection(doAddComments);
1382: fAddCommentButton.setEnabled(canBeModified);
1383: }
1384:
1385: /**
1386: * Sets to use the 'Add comment' checkbox value. Clients that use the 'Add comment' checkbox
1387: * additionally have to enable the control. This has been added for backwards compatibility.
1388: *
1389: * @param useAddCommentValue if <code>true</code>,
1390: * @since 3.1
1391: */
1392: public void enableCommentControl(boolean useAddCommentValue) {
1393: fUseAddCommentButtonValue = useAddCommentValue;
1394: }
1395:
1396: /**
1397: * Returns if comments are added. This method can be overridden by clients.
1398: * The selection of the comment control is taken if enabled (see {@link #enableCommentControl(boolean)}, otherwise
1399: * the settings as specified in the preferences is used.
1400: *
1401: * @return Returns <code>true</code> if comments can be added
1402: * @since 3.1
1403: */
1404: public boolean isAddComments() {
1405: if (fUseAddCommentButtonValue) {
1406: return fAddCommentButton.isSelected();
1407: }
1408: return StubUtility.doAddComments(getJavaProject());
1409: }
1410:
1411: /**
1412: * Returns the resource handle that corresponds to the compilation unit to was or
1413: * will be created or modified.
1414: * @return A resource or null if the page contains illegal values.
1415: * @since 3.0
1416: */
1417: public IResource getModifiedResource() {
1418: IType enclosing = getEnclosingType();
1419: if (enclosing != null) {
1420: return enclosing.getResource();
1421: }
1422: IPackageFragment pack = getPackageFragment();
1423: if (pack != null) {
1424: String cuName = getCompilationUnitName(getTypeNameWithoutParameters());
1425: return pack.getCompilationUnit(cuName).getResource();
1426: }
1427: return null;
1428: }
1429:
1430: // ----------- validation ----------
1431:
1432: /*
1433: * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#containerChanged()
1434: */
1435: protected IStatus containerChanged() {
1436: IStatus status = super .containerChanged();
1437: IPackageFragmentRoot root = getPackageFragmentRoot();
1438: if ((fTypeKind == ANNOTATION_TYPE || fTypeKind == ENUM_TYPE)
1439: && !status.matches(IStatus.ERROR)) {
1440: if (root != null
1441: && !JavaModelUtil.is50OrHigher(root
1442: .getJavaProject())) {
1443: // error as createType will fail otherwise (bug 96928)
1444: return new StatusInfo(
1445: IStatus.ERROR,
1446: Messages
1447: .format(
1448: NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant,
1449: root.getJavaProject()
1450: .getElementName()));
1451: }
1452: if (fTypeKind == ENUM_TYPE) {
1453: try {
1454: // if findType(...) == null then Enum is unavailable
1455: if (findType(root.getJavaProject(),
1456: "java.lang.Enum") == null) //$NON-NLS-1$
1457: return new StatusInfo(
1458: IStatus.WARNING,
1459: NewWizardMessages.NewTypeWizardPage_warning_EnumClassNotFound);
1460: } catch (JavaModelException e) {
1461: JavaPlugin.log(e);
1462: }
1463: }
1464: }
1465:
1466: fCurrPackageCompletionProcessor.setPackageFragmentRoot(root);
1467: if (root != null) {
1468: fEnclosingTypeCompletionProcessor.setPackageFragment(root
1469: .getPackageFragment("")); //$NON-NLS-1$
1470: }
1471: return status;
1472: }
1473:
1474: /**
1475: * A hook method that gets called when the package field has changed. The method
1476: * validates the package name and returns the status of the validation. The validation
1477: * also updates the package fragment model.
1478: * <p>
1479: * Subclasses may extend this method to perform their own validation.
1480: * </p>
1481: *
1482: * @return the status of the validation
1483: */
1484: protected IStatus packageChanged() {
1485: StatusInfo status = new StatusInfo();
1486: IPackageFragmentRoot root = getPackageFragmentRoot();
1487: fPackageDialogField.enableButton(root != null);
1488:
1489: IJavaProject project = root != null ? root.getJavaProject()
1490: : null;
1491:
1492: String packName = getPackageText();
1493: if (packName.length() > 0) {
1494: IStatus val = validatePackageName(packName, project);
1495: if (val.getSeverity() == IStatus.ERROR) {
1496: status
1497: .setError(Messages
1498: .format(
1499: NewWizardMessages.NewTypeWizardPage_error_InvalidPackageName,
1500: val.getMessage()));
1501: return status;
1502: } else if (val.getSeverity() == IStatus.WARNING) {
1503: status
1504: .setWarning(Messages
1505: .format(
1506: NewWizardMessages.NewTypeWizardPage_warning_DiscouragedPackageName,
1507: val.getMessage()));
1508: // continue
1509: }
1510: } else {
1511: status
1512: .setWarning(NewWizardMessages.NewTypeWizardPage_warning_DefaultPackageDiscouraged);
1513: }
1514:
1515: if (project != null) {
1516: if (project.exists() && packName.length() > 0) {
1517: try {
1518: IPath rootPath = root.getPath();
1519: IPath outputPath = project.getOutputLocation();
1520: if (rootPath.isPrefixOf(outputPath)
1521: && !rootPath.equals(outputPath)) {
1522: // if the bin folder is inside of our root, don't allow to name a package
1523: // like the bin folder
1524: IPath packagePath = rootPath.append(packName
1525: .replace('.', '/'));
1526: if (outputPath.isPrefixOf(packagePath)) {
1527: status
1528: .setError(NewWizardMessages.NewTypeWizardPage_error_ClashOutputLocation);
1529: return status;
1530: }
1531: }
1532: } catch (JavaModelException e) {
1533: JavaPlugin.log(e);
1534: // let pass
1535: }
1536: }
1537:
1538: fCurrPackage = root.getPackageFragment(packName);
1539: } else {
1540: status.setError(""); //$NON-NLS-1$
1541: }
1542: return status;
1543: }
1544:
1545: /*
1546: * Updates the 'default' label next to the package field.
1547: */
1548: private void updatePackageStatusLabel() {
1549: String packName = getPackageText();
1550:
1551: if (packName.length() == 0) {
1552: fPackageDialogField
1553: .setStatus(NewWizardMessages.NewTypeWizardPage_default);
1554: } else {
1555: fPackageDialogField.setStatus(""); //$NON-NLS-1$
1556: }
1557: }
1558:
1559: /*
1560: * Updates the enable state of buttons related to the enclosing type selection checkbox.
1561: */
1562: private void updateEnableState() {
1563: boolean enclosing = isEnclosingTypeSelected();
1564: fPackageDialogField.setEnabled(fCanModifyPackage && !enclosing);
1565: fEnclosingTypeDialogField.setEnabled(fCanModifyEnclosingType
1566: && enclosing);
1567: if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
1568: fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX,
1569: enclosing);
1570: fOtherMdfButtons.enableSelectionButton(
1571: ENUM_ANNOT_STATIC_INDEX, enclosing);
1572: }
1573: }
1574:
1575: /**
1576: * Hook method that gets called when the enclosing type name has changed. The method
1577: * validates the enclosing type and returns the status of the validation. It also updates the
1578: * enclosing type model.
1579: * <p>
1580: * Subclasses may extend this method to perform their own validation.
1581: * </p>
1582: *
1583: * @return the status of the validation
1584: */
1585: protected IStatus enclosingTypeChanged() {
1586: StatusInfo status = new StatusInfo();
1587: fCurrEnclosingType = null;
1588:
1589: IPackageFragmentRoot root = getPackageFragmentRoot();
1590:
1591: fEnclosingTypeDialogField.enableButton(root != null);
1592: if (root == null) {
1593: status.setError(""); //$NON-NLS-1$
1594: return status;
1595: }
1596:
1597: String enclName = getEnclosingTypeText();
1598: if (enclName.length() == 0) {
1599: status
1600: .setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeEnterName);
1601: return status;
1602: }
1603: try {
1604: IType type = findType(root.getJavaProject(), enclName);
1605: if (type == null) {
1606: status
1607: .setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists);
1608: return status;
1609: }
1610:
1611: if (type.getCompilationUnit() == null) {
1612: status
1613: .setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotInCU);
1614: return status;
1615: }
1616: if (!JavaModelUtil.isEditable(type.getCompilationUnit())) {
1617: status
1618: .setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotEditable);
1619: return status;
1620: }
1621:
1622: fCurrEnclosingType = type;
1623: IPackageFragmentRoot enclosingRoot = JavaModelUtil
1624: .getPackageFragmentRoot(type);
1625: if (!enclosingRoot.equals(root)) {
1626: status
1627: .setWarning(NewWizardMessages.NewTypeWizardPage_warning_EnclosingNotInSourceFolder);
1628: }
1629: return status;
1630: } catch (JavaModelException e) {
1631: status
1632: .setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists);
1633: JavaPlugin.log(e);
1634: return status;
1635: }
1636: }
1637:
1638: private IType findType(IJavaProject project, String typeName)
1639: throws JavaModelException {
1640: if (project.exists()) {
1641: return project.findType(typeName);
1642: }
1643: return null;
1644: }
1645:
1646: private String getTypeNameWithoutParameters() {
1647: String typeNameWithParameters = getTypeName();
1648: int angleBracketOffset = typeNameWithParameters.indexOf('<');
1649: if (angleBracketOffset == -1) {
1650: return typeNameWithParameters;
1651: } else {
1652: return typeNameWithParameters.substring(0,
1653: angleBracketOffset);
1654: }
1655: }
1656:
1657: /**
1658: * Hook method that is called when evaluating the name of the compilation unit to create. By default, a file extension
1659: * <code>java</code> is added to the given type name, but implementors can override this behavior.
1660: *
1661: * @param typeName the name of the type to create the compilation unit for.
1662: * @return the name of the compilation unit to be created for the given name
1663: *
1664: * @since 3.2
1665: */
1666: protected String getCompilationUnitName(String typeName) {
1667: return typeName + JavaModelUtil.DEFAULT_CU_SUFFIX;
1668: }
1669:
1670: /**
1671: * Hook method that gets called when the type name has changed. The method validates the
1672: * type name and returns the status of the validation.
1673: * <p>
1674: * Subclasses may extend this method to perform their own validation.
1675: * </p>
1676: *
1677: * @return the status of the validation
1678: */
1679: protected IStatus typeNameChanged() {
1680: StatusInfo status = new StatusInfo();
1681: fCurrType = null;
1682: String typeNameWithParameters = getTypeName();
1683: // must not be empty
1684: if (typeNameWithParameters.length() == 0) {
1685: status
1686: .setError(NewWizardMessages.NewTypeWizardPage_error_EnterTypeName);
1687: return status;
1688: }
1689:
1690: String typeName = getTypeNameWithoutParameters();
1691: if (typeName.indexOf('.') != -1) {
1692: status
1693: .setError(NewWizardMessages.NewTypeWizardPage_error_QualifiedName);
1694: return status;
1695: }
1696:
1697: IJavaProject project = getJavaProject();
1698: IStatus val = validateJavaTypeName(typeName, project);
1699: if (val.getSeverity() == IStatus.ERROR) {
1700: status
1701: .setError(Messages
1702: .format(
1703: NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName,
1704: val.getMessage()));
1705: return status;
1706: } else if (val.getSeverity() == IStatus.WARNING) {
1707: status
1708: .setWarning(Messages
1709: .format(
1710: NewWizardMessages.NewTypeWizardPage_warning_TypeNameDiscouraged,
1711: val.getMessage()));
1712: // continue checking
1713: }
1714:
1715: // must not exist
1716: if (!isEnclosingTypeSelected()) {
1717: IPackageFragment pack = getPackageFragment();
1718: if (pack != null) {
1719: ICompilationUnit cu = pack
1720: .getCompilationUnit(getCompilationUnitName(typeName));
1721: fCurrType = cu.getType(typeName);
1722: IResource resource = cu.getResource();
1723:
1724: if (resource.exists()) {
1725: status
1726: .setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists);
1727: return status;
1728: }
1729: URI location = resource.getLocationURI();
1730: if (location != null) {
1731: try {
1732: IFileStore store = EFS.getStore(location);
1733: if (store.fetchInfo().exists()) {
1734: status
1735: .setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExistsDifferentCase);
1736: return status;
1737: }
1738: } catch (CoreException e) {
1739: status
1740: .setError(Messages
1741: .format(
1742: NewWizardMessages.NewTypeWizardPage_error_uri_location_unkown,
1743: Resources
1744: .getLocationString(resource)));
1745: }
1746: }
1747: }
1748: } else {
1749: IType type = getEnclosingType();
1750: if (type != null) {
1751: fCurrType = type.getType(typeName);
1752: if (fCurrType.exists()) {
1753: status
1754: .setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists);
1755: return status;
1756: }
1757: }
1758: }
1759:
1760: if (!typeNameWithParameters.equals(typeName) && project != null) {
1761: if (!JavaModelUtil.is50OrHigher(project)) {
1762: status
1763: .setError(NewWizardMessages.NewTypeWizardPage_error_TypeParameters);
1764: return status;
1765: }
1766: String typeDeclaration = "class " + typeNameWithParameters + " {}"; //$NON-NLS-1$//$NON-NLS-2$
1767: ASTParser parser = ASTParser.newParser(AST.JLS3);
1768: parser.setSource(typeDeclaration.toCharArray());
1769: parser.setProject(project);
1770: CompilationUnit compilationUnit = (CompilationUnit) parser
1771: .createAST(null);
1772: IProblem[] problems = compilationUnit.getProblems();
1773: if (problems.length > 0) {
1774: status
1775: .setError(Messages
1776: .format(
1777: NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName,
1778: problems[0].getMessage()));
1779: return status;
1780: }
1781: }
1782: return status;
1783: }
1784:
1785: /**
1786: * Hook method that gets called when the superclass name has changed. The method
1787: * validates the superclass name and returns the status of the validation.
1788: * <p>
1789: * Subclasses may extend this method to perform their own validation.
1790: * </p>
1791: *
1792: * @return the status of the validation
1793: */
1794: protected IStatus super ClassChanged() {
1795: StatusInfo status = new StatusInfo();
1796: IPackageFragmentRoot root = getPackageFragmentRoot();
1797: fSuperClassDialogField.enableButton(root != null);
1798:
1799: fSuperClassStubTypeContext = null;
1800:
1801: String sclassName = getSuperClass();
1802: if (sclassName.length() == 0) {
1803: // accept the empty field (stands for java.lang.Object)
1804: return status;
1805: }
1806:
1807: if (root != null) {
1808: Type type = TypeContextChecker.parseSuperClass(sclassName);
1809: if (type == null) {
1810: status
1811: .setError(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassName);
1812: return status;
1813: }
1814: if (type instanceof ParameterizedType
1815: && !JavaModelUtil.is50OrHigher(root
1816: .getJavaProject())) {
1817: status
1818: .setError(NewWizardMessages.NewTypeWizardPage_error_SuperClassNotParameterized);
1819: return status;
1820: }
1821: } else {
1822: status.setError(""); //$NON-NLS-1$
1823: }
1824: return status;
1825: }
1826:
1827: private StubTypeContext getSuperClassStubTypeContext() {
1828: if (fSuperClassStubTypeContext == null) {
1829: String typeName;
1830: if (fCurrType != null) {
1831: typeName = getTypeName();
1832: } else {
1833: typeName = JavaTypeCompletionProcessor.DUMMY_CLASS_NAME;
1834: }
1835: fSuperClassStubTypeContext = TypeContextChecker
1836: .createSuperClassStubTypeContext(typeName,
1837: getEnclosingType(), getPackageFragment());
1838: }
1839: return fSuperClassStubTypeContext;
1840: }
1841:
1842: /**
1843: * Hook method that gets called when the list of super interface has changed. The method
1844: * validates the super interfaces and returns the status of the validation.
1845: * <p>
1846: * Subclasses may extend this method to perform their own validation.
1847: * </p>
1848: *
1849: * @return the status of the validation
1850: */
1851: protected IStatus super InterfacesChanged() {
1852: StatusInfo status = new StatusInfo();
1853:
1854: IPackageFragmentRoot root = getPackageFragmentRoot();
1855: fSuperInterfacesDialogField.enableButton(0, root != null);
1856:
1857: if (root != null) {
1858: List elements = fSuperInterfacesDialogField.getElements();
1859: int nElements = elements.size();
1860: for (int i = 0; i < nElements; i++) {
1861: String intfname = ((InterfaceWrapper) elements.get(i)).interfaceName;
1862: Type type = TypeContextChecker
1863: .parseSuperInterface(intfname);
1864: if (type == null) {
1865: status
1866: .setError(Messages
1867: .format(
1868: NewWizardMessages.NewTypeWizardPage_error_InvalidSuperInterfaceName,
1869: intfname));
1870: return status;
1871: }
1872: if (type instanceof ParameterizedType
1873: && !JavaModelUtil.is50OrHigher(root
1874: .getJavaProject())) {
1875: status
1876: .setError(Messages
1877: .format(
1878: NewWizardMessages.NewTypeWizardPage_error_SuperInterfaceNotParameterized,
1879: intfname));
1880: return status;
1881: }
1882: }
1883: }
1884: return status;
1885: }
1886:
1887: private StubTypeContext getSuperInterfacesStubTypeContext() {
1888: if (fSuperInterfaceStubTypeContext == null) {
1889: String typeName;
1890: if (fCurrType != null) {
1891: typeName = getTypeName();
1892: } else {
1893: typeName = JavaTypeCompletionProcessor.DUMMY_CLASS_NAME;
1894: }
1895: fSuperInterfaceStubTypeContext = TypeContextChecker
1896: .createSuperInterfaceStubTypeContext(typeName,
1897: getEnclosingType(), getPackageFragment());
1898: }
1899: return fSuperInterfaceStubTypeContext;
1900: }
1901:
1902: /**
1903: * Hook method that gets called when the modifiers have changed. The method validates
1904: * the modifiers and returns the status of the validation.
1905: * <p>
1906: * Subclasses may extend this method to perform their own validation.
1907: * </p>
1908: *
1909: * @return the status of the validation
1910: */
1911: protected IStatus modifiersChanged() {
1912: StatusInfo status = new StatusInfo();
1913: int modifiers = getModifiers();
1914: if (Flags.isFinal(modifiers) && Flags.isAbstract(modifiers)) {
1915: status
1916: .setError(NewWizardMessages.NewTypeWizardPage_error_ModifiersFinalAndAbstract);
1917: }
1918: return status;
1919: }
1920:
1921: // selection dialogs
1922:
1923: /**
1924: * Opens a selection dialog that allows to select a package.
1925: *
1926: * @return returns the selected package or <code>null</code> if the dialog has been canceled.
1927: * The caller typically sets the result to the package input field.
1928: * <p>
1929: * Clients can override this method if they want to offer a different dialog.
1930: * </p>
1931: *
1932: * @since 3.2
1933: */
1934: protected IPackageFragment choosePackage() {
1935: IPackageFragmentRoot froot = getPackageFragmentRoot();
1936: IJavaElement[] packages = null;
1937: try {
1938: if (froot != null && froot.exists()) {
1939: packages = froot.getChildren();
1940: }
1941: } catch (JavaModelException e) {
1942: JavaPlugin.log(e);
1943: }
1944: if (packages == null) {
1945: packages = new IJavaElement[0];
1946: }
1947:
1948: ElementListSelectionDialog dialog = new ElementListSelectionDialog(
1949: getShell(), new JavaElementLabelProvider(
1950: JavaElementLabelProvider.SHOW_DEFAULT));
1951: dialog.setIgnoreCase(false);
1952: dialog
1953: .setTitle(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_title);
1954: dialog
1955: .setMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_description);
1956: dialog
1957: .setEmptyListMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_empty);
1958: dialog.setElements(packages);
1959: dialog.setHelpAvailable(false);
1960:
1961: IPackageFragment pack = getPackageFragment();
1962: if (pack != null) {
1963: dialog.setInitialSelections(new Object[] { pack });
1964: }
1965:
1966: if (dialog.open() == Window.OK) {
1967: return (IPackageFragment) dialog.getFirstResult();
1968: }
1969: return null;
1970: }
1971:
1972: /**
1973: * Opens a selection dialog that allows to select an enclosing type.
1974: *
1975: * @return returns the selected type or <code>null</code> if the dialog has been canceled.
1976: * The caller typically sets the result to the enclosing type input field.
1977: * <p>
1978: * Clients can override this method if they want to offer a different dialog.
1979: * </p>
1980: *
1981: * @since 3.2
1982: */
1983: protected IType chooseEnclosingType() {
1984: IPackageFragmentRoot root = getPackageFragmentRoot();
1985: if (root == null) {
1986: return null;
1987: }
1988:
1989: IJavaSearchScope scope = SearchEngine
1990: .createJavaSearchScope(new IJavaElement[] { root });
1991:
1992: FilteredTypesSelectionDialog dialog = new FilteredTypesSelectionDialog(
1993: getShell(), false, getWizard().getContainer(), scope,
1994: IJavaSearchConstants.TYPE);
1995: dialog
1996: .setTitle(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_title);
1997: dialog
1998: .setMessage(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_description);
1999: dialog.setInitialPattern(Signature
2000: .getSimpleName(getEnclosingTypeText()));
2001:
2002: if (dialog.open() == Window.OK) {
2003: return (IType) dialog.getFirstResult();
2004: }
2005: return null;
2006: }
2007:
2008: /**
2009: * Opens a selection dialog that allows to select a super class.
2010: *
2011: * @return returns the selected type or <code>null</code> if the dialog has been canceled.
2012: * The caller typically sets the result to the super class input field.
2013: * <p>
2014: * Clients can override this method if they want to offer a different dialog.
2015: * </p>
2016: *
2017: * @since 3.2
2018: */
2019: protected IType chooseSuperClass() {
2020: IJavaProject project = getJavaProject();
2021: if (project == null) {
2022: return null;
2023: }
2024:
2025: IJavaElement[] elements = new IJavaElement[] { project };
2026: IJavaSearchScope scope = SearchEngine
2027: .createJavaSearchScope(elements);
2028:
2029: FilteredTypesSelectionDialog dialog = new FilteredTypesSelectionDialog(
2030: getShell(), false, getWizard().getContainer(), scope,
2031: IJavaSearchConstants.CLASS);
2032: dialog
2033: .setTitle(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_title);
2034: dialog
2035: .setMessage(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_message);
2036: dialog.setInitialPattern(getSuperClass());
2037:
2038: if (dialog.open() == Window.OK) {
2039: return (IType) dialog.getFirstResult();
2040: }
2041: return null;
2042: }
2043:
2044: /**
2045: * Opens a selection dialog that allows to select the super interfaces. The selected interfaces are
2046: * directly added to the wizard page using {@link #addSuperInterface(String)}.
2047: *
2048: * <p>
2049: * Clients can override this method if they want to offer a different dialog.
2050: * </p>
2051: *
2052: * @since 3.2
2053: */
2054: protected void chooseSuperInterfaces() {
2055: IJavaProject project = getJavaProject();
2056: if (project == null) {
2057: return;
2058: }
2059:
2060: SuperInterfaceSelectionDialog dialog = new SuperInterfaceSelectionDialog(
2061: getShell(), getWizard().getContainer(), this , project);
2062: dialog.setTitle(getInterfaceDialogTitle());
2063: dialog
2064: .setMessage(NewWizardMessages.NewTypeWizardPage_InterfacesDialog_message);
2065: dialog.open();
2066: }
2067:
2068: private String getInterfaceDialogTitle() {
2069: if (fTypeKind == INTERFACE_TYPE)
2070: return NewWizardMessages.NewTypeWizardPage_InterfacesDialog_interface_title;
2071: return NewWizardMessages.NewTypeWizardPage_InterfacesDialog_class_title;
2072: }
2073:
2074: // ---- creation ----------------
2075:
2076: /**
2077: * Creates the new type using the entered field values.
2078: *
2079: * @param monitor a progress monitor to report progress.
2080: * @throws CoreException Thrown when the creation failed.
2081: * @throws InterruptedException Thrown when the operation was canceled.
2082: */
2083: public void createType(IProgressMonitor monitor)
2084: throws CoreException, InterruptedException {
2085: if (monitor == null) {
2086: monitor = new NullProgressMonitor();
2087: }
2088:
2089: monitor.beginTask(
2090: NewWizardMessages.NewTypeWizardPage_operationdesc, 8);
2091:
2092: IPackageFragmentRoot root = getPackageFragmentRoot();
2093: IPackageFragment pack = getPackageFragment();
2094: if (pack == null) {
2095: pack = root.getPackageFragment(""); //$NON-NLS-1$
2096: }
2097:
2098: if (!pack.exists()) {
2099: String packName = pack.getElementName();
2100: pack = root.createPackageFragment(packName, true,
2101: new SubProgressMonitor(monitor, 1));
2102: } else {
2103: monitor.worked(1);
2104: }
2105:
2106: boolean needsSave;
2107: ICompilationUnit connectedCU = null;
2108:
2109: try {
2110: String typeName = getTypeNameWithoutParameters();
2111:
2112: boolean isInnerClass = isEnclosingTypeSelected();
2113:
2114: IType createdType;
2115: ImportsManager imports;
2116: int indent = 0;
2117:
2118: Set /* String (import names) */existingImports;
2119:
2120: String lineDelimiter = null;
2121: if (!isInnerClass) {
2122: lineDelimiter = StubUtility.getLineDelimiterUsed(pack
2123: .getJavaProject());
2124:
2125: String cuName = getCompilationUnitName(typeName);
2126: ICompilationUnit parentCU = pack.createCompilationUnit(
2127: cuName,
2128: "", false, new SubProgressMonitor(monitor, 2)); //$NON-NLS-1$
2129: // create a working copy with a new owner
2130:
2131: needsSave = true;
2132: parentCU.becomeWorkingCopy(new SubProgressMonitor(
2133: monitor, 1)); // cu is now a (primary) working copy
2134: connectedCU = parentCU;
2135:
2136: IBuffer buffer = parentCU.getBuffer();
2137:
2138: String simpleTypeStub = constructSimpleTypeStub();
2139: String cuContent = constructCUContent(parentCU,
2140: simpleTypeStub, lineDelimiter);
2141: buffer.setContents(cuContent);
2142:
2143: CompilationUnit astRoot = createASTForImports(parentCU);
2144: existingImports = getExistingImports(astRoot);
2145:
2146: imports = new ImportsManager(astRoot);
2147: // add an import that will be removed again. Having this import solves 14661
2148: imports.addImport(JavaModelUtil.concatenateName(pack
2149: .getElementName(), typeName));
2150:
2151: String typeContent = constructTypeStub(parentCU,
2152: imports, lineDelimiter);
2153:
2154: int index = cuContent.lastIndexOf(simpleTypeStub);
2155: if (index == -1) {
2156: AbstractTypeDeclaration typeNode = (AbstractTypeDeclaration) astRoot
2157: .types().get(0);
2158: int start = ((ASTNode) typeNode.modifiers().get(0))
2159: .getStartPosition();
2160: int end = typeNode.getStartPosition()
2161: + typeNode.getLength();
2162: buffer.replace(start, end - start, typeContent);
2163: } else {
2164: buffer.replace(index, simpleTypeStub.length(),
2165: typeContent);
2166: }
2167:
2168: createdType = parentCU.getType(typeName);
2169: } else {
2170: IType enclosingType = getEnclosingType();
2171:
2172: ICompilationUnit parentCU = enclosingType
2173: .getCompilationUnit();
2174:
2175: needsSave = !parentCU.isWorkingCopy();
2176: parentCU.becomeWorkingCopy(new SubProgressMonitor(
2177: monitor, 1)); // cu is now for sure (primary) a working copy
2178: connectedCU = parentCU;
2179:
2180: CompilationUnit astRoot = createASTForImports(parentCU);
2181: imports = new ImportsManager(astRoot);
2182: existingImports = getExistingImports(astRoot);
2183:
2184: // add imports that will be removed again. Having the imports solves 14661
2185: IType[] topLevelTypes = parentCU.getTypes();
2186: for (int i = 0; i < topLevelTypes.length; i++) {
2187: imports.addImport(topLevelTypes[i]
2188: .getFullyQualifiedName('.'));
2189: }
2190:
2191: lineDelimiter = StubUtility
2192: .getLineDelimiterUsed(enclosingType);
2193: StringBuffer content = new StringBuffer();
2194:
2195: String comment = getTypeComment(parentCU, lineDelimiter);
2196: if (comment != null) {
2197: content.append(comment);
2198: content.append(lineDelimiter);
2199: }
2200:
2201: content.append(constructTypeStub(parentCU, imports,
2202: lineDelimiter));
2203: IJavaElement sibling = null;
2204: if (enclosingType.isEnum()) {
2205: IField[] fields = enclosingType.getFields();
2206: if (fields.length > 0) {
2207: for (int i = 0, max = fields.length; i < max; i++) {
2208: if (!fields[i].isEnumConstant()) {
2209: sibling = fields[i];
2210: break;
2211: }
2212: }
2213: }
2214: } else {
2215: IJavaElement[] elems = enclosingType.getChildren();
2216: sibling = elems.length > 0 ? elems[0] : null;
2217: }
2218:
2219: createdType = enclosingType.createType(content
2220: .toString(), sibling, false,
2221: new SubProgressMonitor(monitor, 2));
2222:
2223: indent = StubUtility.getIndentUsed(enclosingType) + 1;
2224: }
2225: if (monitor.isCanceled()) {
2226: throw new InterruptedException();
2227: }
2228:
2229: // add imports for superclass/interfaces, so types can be resolved correctly
2230:
2231: ICompilationUnit cu = createdType.getCompilationUnit();
2232:
2233: imports.create(false, new SubProgressMonitor(monitor, 1));
2234:
2235: JavaModelUtil.reconcile(cu);
2236:
2237: if (monitor.isCanceled()) {
2238: throw new InterruptedException();
2239: }
2240:
2241: // set up again
2242: CompilationUnit astRoot = createASTForImports(imports
2243: .getCompilationUnit());
2244: imports = new ImportsManager(astRoot);
2245:
2246: createTypeMembers(createdType, imports,
2247: new SubProgressMonitor(monitor, 1));
2248:
2249: // add imports
2250: imports.create(false, new SubProgressMonitor(monitor, 1));
2251:
2252: removeUnusedImports(cu, existingImports, false);
2253:
2254: JavaModelUtil.reconcile(cu);
2255:
2256: ISourceRange range = createdType.getSourceRange();
2257:
2258: IBuffer buf = cu.getBuffer();
2259: String originalContent = buf.getText(range.getOffset(),
2260: range.getLength());
2261:
2262: String formattedContent = CodeFormatterUtil.format(
2263: CodeFormatter.K_CLASS_BODY_DECLARATIONS,
2264: originalContent, indent, lineDelimiter, pack
2265: .getJavaProject());
2266: formattedContent = Strings
2267: .trimLeadingTabsAndSpaces(formattedContent);
2268: buf.replace(range.getOffset(), range.getLength(),
2269: formattedContent);
2270: if (!isInnerClass) {
2271: String fileComment = getFileComment(cu);
2272: if (fileComment != null && fileComment.length() > 0) {
2273: buf.replace(0, 0, fileComment + lineDelimiter);
2274: }
2275: }
2276: fCreatedType = createdType;
2277:
2278: if (needsSave) {
2279: cu.commitWorkingCopy(true, new SubProgressMonitor(
2280: monitor, 1));
2281: } else {
2282: monitor.worked(1);
2283: }
2284:
2285: } finally {
2286: if (connectedCU != null) {
2287: connectedCU.discardWorkingCopy();
2288: }
2289: monitor.done();
2290: }
2291: }
2292:
2293: private CompilationUnit createASTForImports(ICompilationUnit cu) {
2294: ASTParser parser = ASTParser.newParser(AST.JLS3);
2295: parser.setSource(cu);
2296: parser.setResolveBindings(false);
2297: parser.setFocalPosition(0);
2298: return (CompilationUnit) parser.createAST(null);
2299: }
2300:
2301: private Set /* String */getExistingImports(CompilationUnit root) {
2302: List imports = root.imports();
2303: Set res = new HashSet(imports.size());
2304: for (int i = 0; i < imports.size(); i++) {
2305: res.add(ASTNodes.asString((ImportDeclaration) imports
2306: .get(i)));
2307: }
2308: return res;
2309: }
2310:
2311: private void removeUnusedImports(ICompilationUnit cu,
2312: Set existingImports, boolean needsSave)
2313: throws CoreException {
2314: ASTParser parser = ASTParser.newParser(AST.JLS3);
2315: parser.setSource(cu);
2316: parser.setResolveBindings(true);
2317:
2318: CompilationUnit root = (CompilationUnit) parser.createAST(null);
2319: if (root.getProblems().length == 0) {
2320: return;
2321: }
2322:
2323: List importsDecls = root.imports();
2324: if (importsDecls.isEmpty()) {
2325: return;
2326: }
2327: ImportsManager imports = new ImportsManager(root);
2328:
2329: int importsEnd = ASTNodes
2330: .getExclusiveEnd((ASTNode) importsDecls
2331: .get(importsDecls.size() - 1));
2332: IProblem[] problems = root.getProblems();
2333: for (int i = 0; i < problems.length; i++) {
2334: IProblem curr = problems[i];
2335: if (curr.getSourceEnd() < importsEnd) {
2336: int id = curr.getID();
2337: if (id == IProblem.UnusedImport
2338: || id == IProblem.NotVisibleType) { // not visible problems hide unused -> remove both
2339: int pos = curr.getSourceStart();
2340: for (int k = 0; k < importsDecls.size(); k++) {
2341: ImportDeclaration decl = (ImportDeclaration) importsDecls
2342: .get(k);
2343: if (decl.getStartPosition() <= pos
2344: && pos < decl.getStartPosition()
2345: + decl.getLength()) {
2346: if (existingImports.isEmpty()
2347: || !existingImports
2348: .contains(ASTNodes
2349: .asString(decl))) {
2350: String name = decl.getName()
2351: .getFullyQualifiedName();
2352: if (decl.isOnDemand()) {
2353: name += ".*"; //$NON-NLS-1$
2354: }
2355: if (decl.isStatic()) {
2356: imports.removeStaticImport(name);
2357: } else {
2358: imports.removeImport(name);
2359: }
2360: }
2361: break;
2362: }
2363: }
2364: }
2365: }
2366: }
2367: imports.create(needsSave, null);
2368: }
2369:
2370: /**
2371: * Uses the New Java file template from the code template page to generate a
2372: * compilation unit with the given type content.
2373: * @param cu The new created compilation unit
2374: * @param typeContent The content of the type, including signature and type
2375: * body.
2376: * @param lineDelimiter The line delimiter to be used.
2377: * @return String Returns the result of evaluating the new file template
2378: * with the given type content.
2379: * @throws CoreException
2380: * @since 2.1
2381: */
2382: protected String constructCUContent(ICompilationUnit cu,
2383: String typeContent, String lineDelimiter)
2384: throws CoreException {
2385: String fileComment = getFileComment(cu, lineDelimiter);
2386: String typeComment = getTypeComment(cu, lineDelimiter);
2387: IPackageFragment pack = (IPackageFragment) cu.getParent();
2388: String content = CodeGeneration.getCompilationUnitContent(cu,
2389: fileComment, typeComment, typeContent, lineDelimiter);
2390: if (content != null) {
2391: ASTParser parser = ASTParser.newParser(AST.JLS3);
2392: parser.setProject(cu.getJavaProject());
2393: parser.setSource(content.toCharArray());
2394: CompilationUnit unit = (CompilationUnit) parser
2395: .createAST(null);
2396: if ((pack.isDefaultPackage() || unit.getPackage() != null)
2397: && !unit.types().isEmpty()) {
2398: return content;
2399: }
2400: }
2401: StringBuffer buf = new StringBuffer();
2402: if (!pack.isDefaultPackage()) {
2403: buf
2404: .append("package ").append(pack.getElementName()).append(';'); //$NON-NLS-1$
2405: }
2406: buf.append(lineDelimiter).append(lineDelimiter);
2407: if (typeComment != null) {
2408: buf.append(typeComment).append(lineDelimiter);
2409: }
2410: buf.append(typeContent);
2411: return buf.toString();
2412: }
2413:
2414: /**
2415: * Returns the created type or <code>null</code> is the type has not been created yet. The method
2416: * only returns a valid type after <code>createType</code> has been called.
2417: *
2418: * @return the created type
2419: * @see #createType(IProgressMonitor)
2420: */
2421: public IType getCreatedType() {
2422: return fCreatedType;
2423: }
2424:
2425: // ---- construct CU body----------------
2426:
2427: private void writeSuperClass(StringBuffer buf,
2428: ImportsManager imports) {
2429: String super class = getSuperClass();
2430: if (fTypeKind == CLASS_TYPE && super class.length() > 0
2431: && !"java.lang.Object".equals(super class)) { //$NON-NLS-1$
2432: buf.append(" extends "); //$NON-NLS-1$
2433:
2434: ITypeBinding binding = null;
2435: if (fCurrType != null) {
2436: binding = TypeContextChecker.resolveSuperClass(
2437: super class, fCurrType,
2438: getSuperClassStubTypeContext());
2439: }
2440: if (binding != null) {
2441: buf.append(imports.addImport(binding));
2442: } else {
2443: buf.append(imports.addImport(super class));
2444: }
2445: }
2446: }
2447:
2448: private void writeSuperInterfaces(StringBuffer buf,
2449: ImportsManager imports) {
2450: List interfaces = getSuperInterfaces();
2451: int last = interfaces.size() - 1;
2452: if (last >= 0) {
2453: if (fTypeKind != INTERFACE_TYPE) {
2454: buf.append(" implements "); //$NON-NLS-1$
2455: } else {
2456: buf.append(" extends "); //$NON-NLS-1$
2457: }
2458: String[] intfs = (String[]) interfaces
2459: .toArray(new String[interfaces.size()]);
2460: ITypeBinding[] bindings;
2461: if (fCurrType != null) {
2462: bindings = TypeContextChecker.resolveSuperInterfaces(
2463: intfs, fCurrType,
2464: getSuperInterfacesStubTypeContext());
2465: } else {
2466: bindings = new ITypeBinding[intfs.length];
2467: }
2468: for (int i = 0; i <= last; i++) {
2469: ITypeBinding binding = bindings[i];
2470: if (binding != null) {
2471: buf.append(imports.addImport(binding));
2472: } else {
2473: buf.append(imports.addImport(intfs[i]));
2474: }
2475: if (i < last) {
2476: buf.append(',');
2477: }
2478: }
2479: }
2480: }
2481:
2482: private String constructSimpleTypeStub() {
2483: StringBuffer buf = new StringBuffer("public class "); //$NON-NLS-1$
2484: buf.append(getTypeName());
2485: buf.append("{ }"); //$NON-NLS-1$
2486: return buf.toString();
2487: }
2488:
2489: /*
2490: * Called from createType to construct the source for this type
2491: */
2492: private String constructTypeStub(ICompilationUnit parentCU,
2493: ImportsManager imports, String lineDelimiter)
2494: throws CoreException {
2495: StringBuffer buf = new StringBuffer();
2496:
2497: int modifiers = getModifiers();
2498: buf.append(Flags.toString(modifiers));
2499: if (modifiers != 0) {
2500: buf.append(' ');
2501: }
2502: String type = ""; //$NON-NLS-1$
2503: String templateID = ""; //$NON-NLS-1$
2504: switch (fTypeKind) {
2505: case CLASS_TYPE:
2506: type = "class "; //$NON-NLS-1$
2507: templateID = CodeGeneration.CLASS_BODY_TEMPLATE_ID;
2508: break;
2509: case INTERFACE_TYPE:
2510: type = "interface "; //$NON-NLS-1$
2511: templateID = CodeGeneration.INTERFACE_BODY_TEMPLATE_ID;
2512: break;
2513: case ENUM_TYPE:
2514: type = "enum "; //$NON-NLS-1$
2515: templateID = CodeGeneration.ENUM_BODY_TEMPLATE_ID;
2516: break;
2517: case ANNOTATION_TYPE:
2518: type = "@interface "; //$NON-NLS-1$
2519: templateID = CodeGeneration.ANNOTATION_BODY_TEMPLATE_ID;
2520: break;
2521: }
2522: buf.append(type);
2523: buf.append(getTypeName());
2524: writeSuperClass(buf, imports);
2525: writeSuperInterfaces(buf, imports);
2526:
2527: buf.append(" {").append(lineDelimiter); //$NON-NLS-1$
2528: String typeBody = CodeGeneration.getTypeBody(templateID,
2529: parentCU, getTypeName(), lineDelimiter);
2530: if (typeBody != null) {
2531: buf.append(typeBody);
2532: } else {
2533: buf.append(lineDelimiter);
2534: }
2535: buf.append('}').append(lineDelimiter);
2536: return buf.toString();
2537: }
2538:
2539: /**
2540: * Hook method that gets called from <code>createType</code> to support adding of
2541: * unanticipated methods, fields, and inner types to the created type.
2542: * <p>
2543: * Implementers can use any methods defined on <code>IType</code> to manipulate the
2544: * new type.
2545: * </p>
2546: * <p>
2547: * The source code of the new type will be formatted using the platform's formatter. Needed
2548: * imports are added by the wizard at the end of the type creation process using the given
2549: * import manager.
2550: * </p>
2551: *
2552: * @param newType the new type created via <code>createType</code>
2553: * @param imports an import manager which can be used to add new imports
2554: * @param monitor a progress monitor to report progress. Must not be <code>null</code>
2555: * @throws CoreException thrown when creation of the type members failed
2556: *
2557: * @see #createType(IProgressMonitor)
2558: */
2559: protected void createTypeMembers(IType newType,
2560: final ImportsManager imports, IProgressMonitor monitor)
2561: throws CoreException {
2562: // default implementation does nothing
2563: // example would be
2564: // String mainMathod= "public void foo(Vector vec) {}"
2565: // createdType.createMethod(main, null, false, null);
2566: // imports.addImport("java.lang.Vector");
2567: }
2568:
2569: /**
2570: * @param parentCU the current compilation unit
2571: * @return returns the file template or <code>null</code>
2572: * @deprecated Instead of file templates, the new type code template
2573: * specifies the stub for a compilation unit.
2574: */
2575: protected String getFileComment(ICompilationUnit parentCU) {
2576: return null;
2577: }
2578:
2579: /**
2580: * Hook method that gets called from <code>createType</code> to retrieve
2581: * a file comment. This default implementation returns the content of the
2582: * 'file comment' template or <code>null</code> if no comment should be created.
2583: *
2584: * @param parentCU the parent compilation unit
2585: * @param lineDelimiter the line delimiter to use
2586: * @return the file comment or <code>null</code> if a file comment
2587: * is not desired
2588: * @throws CoreException
2589: *
2590: * @since 3.1
2591: */
2592: protected String getFileComment(ICompilationUnit parentCU,
2593: String lineDelimiter) throws CoreException {
2594: if (isAddComments()) {
2595: return CodeGeneration.getFileComment(parentCU,
2596: lineDelimiter);
2597: }
2598: return null;
2599:
2600: }
2601:
2602: private boolean isValidComment(String template) {
2603: IScanner scanner = ToolFactory.createScanner(true, false,
2604: false, false);
2605: scanner.setSource(template.toCharArray());
2606: try {
2607: int next = scanner.getNextToken();
2608: while (TokenScanner.isComment(next)) {
2609: next = scanner.getNextToken();
2610: }
2611: return next == ITerminalSymbols.TokenNameEOF;
2612: } catch (InvalidInputException e) {
2613: }
2614: return false;
2615: }
2616:
2617: /**
2618: * Hook method that gets called from <code>createType</code> to retrieve
2619: * a type comment. This default implementation returns the content of the
2620: * 'type comment' template.
2621: *
2622: * @param parentCU the parent compilation unit
2623: * @param lineDelimiter the line delimiter to use
2624: * @return the type comment or <code>null</code> if a type comment
2625: * is not desired
2626: *
2627: * @since 3.0
2628: */
2629: protected String getTypeComment(ICompilationUnit parentCU,
2630: String lineDelimiter) {
2631: if (isAddComments()) {
2632: try {
2633: StringBuffer typeName = new StringBuffer();
2634: if (isEnclosingTypeSelected()) {
2635: typeName
2636: .append(
2637: JavaModelUtil
2638: .getTypeQualifiedName(getEnclosingType()))
2639: .append('.');
2640: }
2641: typeName.append(getTypeNameWithoutParameters());
2642: String[] typeParamNames = new String[0];
2643: String comment = CodeGeneration.getTypeComment(
2644: parentCU, typeName.toString(), typeParamNames,
2645: lineDelimiter);
2646: if (comment != null && isValidComment(comment)) {
2647: return comment;
2648: }
2649: } catch (CoreException e) {
2650: JavaPlugin.log(e);
2651: }
2652: }
2653: return null;
2654: }
2655:
2656: /**
2657: * @param parentCU the current compilation unit
2658: * @return returns the template or <code>null</code>
2659: * @deprecated Use getTypeComment(ICompilationUnit, String)
2660: */
2661: protected String getTypeComment(ICompilationUnit parentCU) {
2662: if (StubUtility.doAddComments(parentCU.getJavaProject()))
2663: return getTypeComment(parentCU, StubUtility
2664: .getLineDelimiterUsed(parentCU));
2665: return null;
2666: }
2667:
2668: /**
2669: * @param name the name of the template
2670: * @param parentCU the current compilation unit
2671: * @return returns the template or <code>null</code>
2672: * @deprecated Use getTemplate(String,ICompilationUnit,int)
2673: */
2674: protected String getTemplate(String name, ICompilationUnit parentCU) {
2675: return getTemplate(name, parentCU, 0);
2676: }
2677:
2678: /**
2679: * Returns the string resulting from evaluation the given template in
2680: * the context of the given compilation unit. This accesses the normal
2681: * template page, not the code templates. To use code templates use
2682: * <code>constructCUContent</code> to construct a compilation unit stub or
2683: * getTypeComment for the comment of the type.
2684: *
2685: * @param name the template to be evaluated
2686: * @param parentCU the templates evaluation context
2687: * @param pos a source offset into the parent compilation unit. The
2688: * template is evaluated at the given source offset
2689: * @return return the template with the given name or <code>null</code> if the template could not be found.
2690: */
2691: protected String getTemplate(String name,
2692: ICompilationUnit parentCU, int pos) {
2693: try {
2694: Template template = JavaPlugin.getDefault()
2695: .getTemplateStore().findTemplate(name);
2696: if (template != null) {
2697: return JavaContext.evaluateTemplate(template, parentCU,
2698: pos);
2699: }
2700: } catch (CoreException e) {
2701: JavaPlugin.log(e);
2702: } catch (BadLocationException e) {
2703: JavaPlugin.log(e);
2704: } catch (TemplateException e) {
2705: JavaPlugin.log(e);
2706: }
2707: return null;
2708: }
2709:
2710: /**
2711: * Creates the bodies of all unimplemented methods and constructors and adds them to the type.
2712: * Method is typically called by implementers of <code>NewTypeWizardPage</code> to add
2713: * needed method and constructors.
2714: *
2715: * @param type the type for which the new methods and constructor are to be created
2716: * @param doConstructors if <code>true</code> unimplemented constructors are created
2717: * @param doUnimplementedMethods if <code>true</code> unimplemented methods are created
2718: * @param imports an import manager to add all needed import statements
2719: * @param monitor a progress monitor to report progress
2720: * @return the created methods.
2721: * @throws CoreException thrown when the creation fails.
2722: */
2723: protected IMethod[] createInheritedMethods(IType type,
2724: boolean doConstructors, boolean doUnimplementedMethods,
2725: ImportsManager imports, IProgressMonitor monitor)
2726: throws CoreException {
2727: final ICompilationUnit cu = type.getCompilationUnit();
2728: JavaModelUtil.reconcile(cu);
2729: IMethod[] typeMethods = type.getMethods();
2730: Set handleIds = new HashSet(typeMethods.length);
2731: for (int index = 0; index < typeMethods.length; index++)
2732: handleIds.add(typeMethods[index].getHandleIdentifier());
2733: ArrayList newMethods = new ArrayList();
2734: CodeGenerationSettings settings = JavaPreferencesSettings
2735: .getCodeGenerationSettings(type.getJavaProject());
2736: settings.createComments = isAddComments();
2737: ASTParser parser = ASTParser.newParser(AST.JLS3);
2738: parser.setResolveBindings(true);
2739: parser.setSource(cu);
2740: CompilationUnit unit = (CompilationUnit) parser
2741: .createAST(new SubProgressMonitor(monitor, 1));
2742: final ITypeBinding binding = ASTNodes
2743: .getTypeBinding(unit, type);
2744: if (binding != null) {
2745: if (doUnimplementedMethods) {
2746: AddUnimplementedMethodsOperation operation = new AddUnimplementedMethodsOperation(
2747: unit, binding, null, -1, false, true, false);
2748: operation.setCreateComments(isAddComments());
2749: operation.run(monitor);
2750: createImports(imports, operation.getCreatedImports());
2751: }
2752: if (doConstructors) {
2753: AddUnimplementedConstructorsOperation operation = new AddUnimplementedConstructorsOperation(
2754: unit, binding, null, -1, false, true, false);
2755: operation.setOmitSuper(true);
2756: operation.setCreateComments(isAddComments());
2757: operation.run(monitor);
2758: createImports(imports, operation.getCreatedImports());
2759: }
2760: }
2761: JavaModelUtil.reconcile(cu);
2762: typeMethods = type.getMethods();
2763: for (int index = 0; index < typeMethods.length; index++)
2764: if (!handleIds.contains(typeMethods[index]
2765: .getHandleIdentifier()))
2766: newMethods.add(typeMethods[index]);
2767: IMethod[] methods = new IMethod[newMethods.size()];
2768: newMethods.toArray(methods);
2769: return methods;
2770: }
2771:
2772: private void createImports(ImportsManager imports,
2773: String[] createdImports) {
2774: for (int index = 0; index < createdImports.length; index++)
2775: imports.addImport(createdImports[index]);
2776: }
2777:
2778: // ---- creation ----------------
2779:
2780: /**
2781: * Returns the runnable that creates the type using the current settings.
2782: * The returned runnable must be executed in the UI thread.
2783: *
2784: * @return the runnable to create the new type
2785: */
2786: public IRunnableWithProgress getRunnable() {
2787: return new IRunnableWithProgress() {
2788: public void run(IProgressMonitor monitor)
2789: throws InvocationTargetException,
2790: InterruptedException {
2791: try {
2792: if (monitor == null) {
2793: monitor = new NullProgressMonitor();
2794: }
2795: createType(monitor);
2796: } catch (CoreException e) {
2797: throw new InvocationTargetException(e);
2798: }
2799: }
2800: };
2801: }
2802: }
|