diff options
Diffstat (limited to 'src/plugins/android.codeutils/src/com/motorola/studio/android/wizards/buildingblocks/NewBuildingBlocksWizardPage.java')
-rw-r--r-- | src/plugins/android.codeutils/src/com/motorola/studio/android/wizards/buildingblocks/NewBuildingBlocksWizardPage.java | 1078 |
1 files changed, 1078 insertions, 0 deletions
diff --git a/src/plugins/android.codeutils/src/com/motorola/studio/android/wizards/buildingblocks/NewBuildingBlocksWizardPage.java b/src/plugins/android.codeutils/src/com/motorola/studio/android/wizards/buildingblocks/NewBuildingBlocksWizardPage.java new file mode 100644 index 0000000..c10e668 --- /dev/null +++ b/src/plugins/android.codeutils/src/com/motorola/studio/android/wizards/buildingblocks/NewBuildingBlocksWizardPage.java @@ -0,0 +1,1078 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.motorola.studio.android.wizards.buildingblocks; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.ui.JavaElementComparator; +import org.eclipse.jdt.ui.JavaElementLabelProvider; +import org.eclipse.jdt.ui.StandardJavaElementContentProvider; +import org.eclipse.jdt.ui.wizards.NewTypeWizardPage; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.events.ShellListener; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; +import org.eclipse.ui.dialogs.ISelectionStatusValidator; + +import com.motorola.studio.android.codeutils.CodeUtilsActivator; +import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS; +import com.motorola.studio.android.common.IAndroidConstants; +import com.motorola.studio.android.common.exception.AndroidException; +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.common.utilities.AndroidUtils; +import com.motorola.studio.android.common.utilities.EclipseUtils; +import com.motorola.studio.android.manifest.AndroidProjectManifestFile; +import com.motorola.studio.android.model.BuildingBlockModel; +import com.motorola.studio.android.model.manifest.AndroidManifestFile; +import com.motorola.studio.android.wizards.elements.AddRemoveButtons; + +/** + * Abstract class used to create the building block wizard main pages. + */ +public abstract class NewBuildingBlocksWizardPage extends NewTypeWizardPage +{ + private static final String JAVA_EXTENSION = ".java"; //$NON-NLS-1$ + + private static final int MAX_PATH_SIZE = 255; + + protected static String LABEL = TYPENAME + ".LABEL"; //$NON-NLS-1$ + + protected IWorkspaceRoot fWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + + private BuildingBlockModel buildBlock; + + private Text labelText; + + private Button defaultLabelButton; + + private AddRemoveButtons addRemovePermissionsButtons; + + private List activityPermissions; + + private final Set<String> intentFilterPermissions = new HashSet<String>(); + + private MethodCreationControl methodCreationControl; + + /** + * Listener to check if the wizard can be opened. + */ + private class WizardShellListener implements ShellListener + { + private boolean wasChecked = false; + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt + * .events.ShellEvent) + */ + @Override + public void shellActivated(ShellEvent e) + { + if (!wasChecked) + { + wasChecked = true; + + if (!canOpen()) + { + ((Shell) e.widget).close(); + } + } + + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.ShellListener#shellClosed(org.eclipse.swt. + * events.ShellEvent) + */ + @Override + public void shellClosed(ShellEvent e) + { + // Do nothing + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.ShellListener#shellDeactivated(org.eclipse + * .swt.events.ShellEvent) + */ + @Override + public void shellDeactivated(ShellEvent e) + { + // Do nothing + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.ShellListener#shellDeiconified(org.eclipse + * .swt.events.ShellEvent) + */ + @Override + public void shellDeiconified(ShellEvent e) + { + // Do nothing + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.ShellListener#shellIconified(org.eclipse.swt + * .events.ShellEvent) + */ + @Override + public void shellIconified(ShellEvent e) + { + // Do nothing + } + + } + + /* Each building block is represent by a class (e.g., an Activity or Service). + * Each of these classes contain some methods that must be overridden by subclasses + * in order to be called by android framework (e.g., onCreate(...) methods). + * This class is responsible to create check boxes that let users choose which of these methods + * should be automatically created by the wizard. + * */ + private class MethodCreationControl + { + private Label stubMessage; + + private Button[] stubButtonArray; + + MethodCreationControl(Composite parent, Method[] methods) + { + if (methods != null) + { + if (methods.length > 0) + { + stubMessage = new Label(parent, SWT.NONE); + stubMessage.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, + false, 4, 1)); + stubMessage + .setText(CodeUtilsNLS.UI_NewBuildingBlocksWizardPage_QuestionWhichMethodCreate); + } + + createStubsComponent(parent, methods); + } + } + + /* + * Creates a single method declaration to the wizard page + * + * @param parent + * The wizard page composite + * @param method + * The method to add + */ + private void createStubsComponent(Composite parent, Method[] methods) + { + stubButtonArray = new Button[methods.length]; + int i = 0; + for (final Method method : methods) + { + new Label(parent, SWT.NONE); + final Button stubsButton = new Button(parent, SWT.CHECK); + stubsButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, + 3, 1)); + stubsButton.setText(method.getMessage()); + stubsButton.addListener(SWT.Selection, new Listener() + { + @Override + public void handleEvent(Event event) + { + method.handle(stubsButton.getSelection()); + } + }); + stubButtonArray[i++] = stubsButton; + } + } + + public void setMethodCreationControlEnabled(boolean enabled) + { + stubMessage.setEnabled(enabled); + for (Button stubButton : stubButtonArray) + { + stubButton.setEnabled(enabled); + } + } + } + + /** + * Default constructor. + * + * @param buildBlock + * The building block model that the wizard will create. + * @param pageName + * The page name. + */ + protected NewBuildingBlocksWizardPage(BuildingBlockModel buildBlock, String pageName) + { + super(true, pageName); + this.buildBlock = buildBlock; + setTitle(getWizardTitle()); + setDescription(getDefaultMessage()); + setPageComplete(false); + } + + /** + * Gets the help ID to be used for attaching context sensitive help. + * + * Classes that extends this class and want to set their own help should + * override this method. + */ + protected abstract String getHelpId(); + + /** + * Returns the wizard title. + * + * @return the wizard title. + */ + public abstract String getWizardTitle(); + + /** + * Returns the wizard default status message. + * + * @return the wizard default status message. + */ + public abstract String getDefaultMessage(); + + /** + * Returns all methods that the building block can override. + * + * @return all methods that the building block can override. + */ + protected abstract Method[] getMethods(); + + /** + * @param enabled If true, all available methods in the building block will be checked + * for automatic creation. + * */ + public void setMethodCreationControlEnabled(boolean enabled) + { + methodCreationControl.setMethodCreationControlEnabled(enabled); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets + * .Composite) + */ + @Override + public void createControl(Composite parent) + { + initializeDialogUnits(parent); + + // main control + Composite mainComposite = new Composite(parent, SWT.FILL); + mainComposite.setLayout(new FillLayout(SWT.FILL)); + final ScrolledComposite scroll = + new ScrolledComposite(mainComposite, SWT.H_SCROLL | SWT.V_SCROLL); + + final Composite composite = new Composite(scroll, SWT.NONE); + composite.setFont(parent.getFont()); + + int nColumns = 4; + + createSampleControls(composite, nColumns); + + GridLayout layout = new GridLayout(nColumns, false); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); + + if (hasHeader()) + { + setPackageFragmentRoot(getBuildBlock().getPackageFragmentRoot(), true); + createContainerControls(composite, nColumns); + setPackageFragment(getBuildBlock().getPackageFragment(), true); + createPackageControls(composite, nColumns); + + createSeparator(composite, nColumns); + + createTypeNameControls(composite, nColumns); + + createLabelControls(composite); + + setSuperClass(getBuildBlock().getSuperClass(), getBuildBlock().useExtendedClass()); + createSuperClassControls(composite, nColumns); + + createPermissionControls(composite); + + createIntermediateControls(composite); + + createMethodCreationControl(composite, getMethods()); + } + createExtendedControls(composite); + + // set up scroll + scroll.setContent(composite); + + scroll.setExpandHorizontal(true); + scroll.setExpandVertical(true); + + scroll.addControlListener(new ControlAdapter() + { + @Override + public void controlResized(ControlEvent e) + { + scroll.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + } + }); + + setControl(mainComposite); + Dialog.applyDialogFont(mainComposite); + + mainComposite.getShell().addShellListener(new WizardShellListener()); + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, getHelpId()); + PlatformUI.getWorkbench().getHelpSystem().setHelp(mainComposite, getHelpId()); + } + + /** + * Override this class to create the label controls. + * + * @param parent + * The wizard page composite + */ + protected void createLabelControls(Composite parent) + { + Label label = new Label(parent, SWT.NONE); + label.setText(CodeUtilsNLS.UI_NewBuildingBlocksWizardPage_TextLabel); + + labelText = new Text(parent, SWT.BORDER); + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); + gridData.horizontalSpan = 2; + labelText.setLayoutData(gridData); + labelText.setEnabled(false); + + defaultLabelButton = new Button(parent, SWT.CHECK); + defaultLabelButton.setText(CodeUtilsNLS.UI_NewBuildingBlocksWizardPage_ButtonNameDefault); + defaultLabelButton.setSelection(true); + + Listener listener = new Listener() + { + @Override + public void handleEvent(Event event) + { + if (!defaultLabelButton.getSelection() || !event.widget.equals(labelText)) + { + handleFieldChanged(LABEL); + } + if (event.widget.equals(defaultLabelButton) && !defaultLabelButton.getSelection() + && labelText.isEnabled()) + { + labelText.forceFocus(); + labelText.selectAll(); + } + } + }; + + labelText.addListener(SWT.Modify, listener); + defaultLabelButton.addListener(SWT.Selection, listener); + } + + /** + * Override this class to add samples control. + * + * @param composite + * The wizard page composite + */ + protected void createSampleControls(Composite composite, int nColumns) + { + //default implementation does nothing + } + + /** + * Override this class to add components after superclass control. + * + * @param composite + * The wizard page composite + */ + protected void createIntermediateControls(Composite composite) + { + //default implementation does nothing + } + + /** + * Return all Filter Permissions as an Array. + * + * @return + */ + public String[] getIntentFilterPermissionsAsArray() + { + return intentFilterPermissions.toArray(new String[intentFilterPermissions.size()]); + } + + /** + * Creates the "Permissions" section on the wizard. + * + * @param composite + * the wizard composite + */ + protected void createPermissionControls(Composite composite) + { + GridData gridData; + Label activityPermissionsLabel = new Label(composite, SWT.NONE); + activityPermissionsLabel.setText(CodeUtilsNLS.NewBuildingBlocksWizardPage_PermissionLabel); + gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false); + gridData.verticalAlignment = GridData.BEGINNING; + activityPermissionsLabel.setLayoutData(gridData); + + activityPermissions = new List(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + activityPermissions.setItems(getBuildBlock().getIntentFilterPermissionsAsArray()); + gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); + gridData.heightHint = convertHeightInCharsToPixels(3); + activityPermissions.setLayoutData(gridData); + + addRemovePermissionsButtons = new AddRemoveButtons(composite); + setButtonLayoutData(addRemovePermissionsButtons.getAddButton()); + setButtonLayoutData(addRemovePermissionsButtons.getRemoveButton()); + addRemovePermissionsButtons.getAddButton().addListener(SWT.Selection, new Listener() + { + @Override + public void handleEvent(Event arg0) + { + Set<String> permissionSet = + new HashSet<String>(Arrays.asList(AndroidUtils + .getIntentFilterPermissions(getBuildBlock().getProject()))); + + permissionSet.removeAll(getBuildBlock().getIntentFilterPermissions()); + + FilteredActionsSelectionDialog dialog = + new FilteredActionsSelectionDialog(getShell(), permissionSet); + dialog.setInitialPattern("**"); //$NON-NLS-1$ + dialog.setTitle("Select an action permission"); //$NON-NLS-1$ + dialog.setMessage(CodeUtilsNLS.UI_NewLauncherWizardPage_CategorySelectionDialogMessage); + + if (Dialog.OK == dialog.open()) + { + for (Object result : dialog.getResult()) + { + getBuildBlock().addIntentFilterPermissions((String) result); + } + activityPermissions.setItems(getBuildBlock() + .getIntentFilterPermissionsAsArray()); + addRemovePermissionsButtons.getRemoveButton().setEnabled( + activityPermissions.getSelectionCount() > 0); + updateStatus(getBuildBlock().getStatus()); + } + } + }); + addRemovePermissionsButtons.getRemoveButton().addListener(SWT.Selection, new Listener() + { + @Override + public void handleEvent(Event arg0) + { + for (int selection : activityPermissions.getSelectionIndices()) + { + getBuildBlock().removeIntentFilterPermissions( + activityPermissions.getItem(selection)); + } + activityPermissions.setItems(getBuildBlock().getIntentFilterPermissionsAsArray()); + addRemovePermissionsButtons.getRemoveButton().setEnabled( + activityPermissions.getSelectionCount() > 0); + updateStatus(getBuildBlock().getStatus()); + } + }); + addRemovePermissionsButtons.getRemoveButton().setEnabled( + activityPermissions.getSelectionCount() > 0); + activityPermissions.addListener(SWT.Selection, new Listener() + { + @Override + public void handleEvent(Event arg0) + { + addRemovePermissionsButtons.getRemoveButton().setEnabled( + activityPermissions.getSelectionCount() > 0); + } + }); + } + + /** + * Override this class to add components at the end of the Page. + * + * @param parent + * The wizard page composite + */ + protected void createExtendedControls(Composite parent) + { + //default implementation does nothing + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.ui.wizards.NewElementWizardPage#setVisible(boolean) + */ + @Override + public void setVisible(boolean visible) + { + super.setVisible(visible); + if (visible) + { + setFocus(); + } + } + + /** + * Returns true if page has header false otherwise. + * + * @return true if page has header false otherwise. + */ + public boolean hasHeader() + { + return true; + } + + /** + * Adds the methods that a building block can override to the wizard page. + * + * @param parent + * The wizard page composite. + * @param methods + * The methods to add to the wizard. + */ + protected void createMethodCreationControl(Composite parent, Method[] methods) + { + methodCreationControl = new MethodCreationControl(parent, methods); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#chooseContainer() + */ + @Override + protected IPackageFragmentRoot chooseContainer() + { + IJavaElement initElement = getPackageFragmentRoot(); + + ISelectionStatusValidator validator = new ElementTreeValidator(); + ViewerFilter filter = new ElementTreeViewFilter(); + StandardJavaElementContentProvider provider = new ElementTreeContentProvider(); + + ILabelProvider labelProvider = + new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT); + ElementTreeSelectionDialog dialog = + new ElementTreeSelectionDialog(getShell(), labelProvider, provider); + dialog.setComparator(new JavaElementComparator()); + dialog.setValidator(validator); + dialog.setTitle(CodeUtilsNLS.UI_NewBuildingBlocksWizardPage_WizardTitle); + dialog.setMessage(CodeUtilsNLS.UI_NewBuildingBlocksWizardPage_MessageChooseFolder); + dialog.setInput(JavaCore.create(fWorkspaceRoot)); + dialog.setInitialSelection(initElement); + dialog.addFilter(filter); + dialog.setHelpAvailable(false); + + IPackageFragmentRoot rootSelection = null; + if (dialog.open() == Window.OK) + { + Object element = dialog.getFirstResult(); + if (element instanceof IJavaProject) + { + IJavaProject jproject = (IJavaProject) element; + rootSelection = jproject.getPackageFragmentRoot(jproject.getProject()); + } + else if (element instanceof IPackageFragmentRoot) + { + rootSelection = (IPackageFragmentRoot) element; + } + } + return rootSelection; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jdt.ui.wizards.NewTypeWizardPage#handleFieldChanged(java. + * lang.String) + */ + @Override + protected void handleFieldChanged(String fieldName) + { + if (NewTypeWizardPage.TYPENAME.equals(fieldName)) + { + getBuildBlock().setName(getTypeName()); + getBuildBlock().setNameStatus(typeNameChanged()); + getBuildBlock().setPackageStatus(packageChanged()); + } + else if (NewTypeWizardPage.CONTAINER.equals(fieldName)) + { + // source folder + getBuildBlock().setPackageFragmentRoot(getPackageFragmentRoot()); + getBuildBlock().setPackageFragmentRootStatus(containerChanged()); + getBuildBlock().setPackageStatus(packageChanged()); + getBuildBlock().setNameStatus(typeNameChanged()); + + updatePackage(getPackageFragmentRoot()); + } + else if (NewTypeWizardPage.PACKAGE.equals(fieldName)) + { + if (getPackageFragmentRoot() != null) + { + getBuildBlock().setPackageFragment( + getPackageFragmentRoot().getPackageFragment(getPackageText())); + } + getBuildBlock().setPackageStatus(packageChanged()); + getBuildBlock().setNameStatus(typeNameChanged()); + } + else if (LABEL.equals(fieldName)) + { + getBuildBlock().setLabelStatus(labelChanged()); + } + updateStatus(getBuildBlock().getStatus()); + } + + private void updatePackage(IPackageFragmentRoot packageFragmentRoot) + { + if (packageFragmentRoot != null) + { + IJavaProject project = null; + IPackageFragment pack = null; + + project = packageFragmentRoot.getJavaProject(); + try + { + pack = EclipseUtils.getDefaultPackageFragment(project); + getBuildBlock().setPackageFragment(pack); + } + catch (JavaModelException e) + { + StudioLogger.error(NewBuildingBlocksWizardPage.class, + "Error getting default package fragment.", e); //$NON-NLS-1$ + // do nothing + } + setPackageFragment(pack, true); + handleFieldChanged(NewTypeWizardPage.PACKAGE); + } + } + + /** + * @return A status indicating if the building block label property has been change. + */ + protected IStatus labelChanged() + { + IStatus status = new Status(IStatus.OK, CodeUtilsActivator.PLUGIN_ID, null); + if ((defaultLabelButton != null) && (labelText != null)) + { + if (defaultLabelButton.getSelection()) + { + labelText.setText(""); //$NON-NLS-1$ + + } + labelText.setEnabled(!defaultLabelButton.getSelection()); + getBuildBlock().setLabel(getLabel()); + } + return status; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#typeNameChanged() + */ + @Override + protected IStatus typeNameChanged() + { + IStatus superStatus = super.typeNameChanged(); + IStatus status = + new Status(superStatus.getSeverity(), CodeUtilsActivator.PLUGIN_ID, + superStatus.getMessage()); + + Pattern pattern = Pattern.compile("([A-Za-z0-9_]+)"); //$NON-NLS-1$ + + if (superStatus.getSeverity() != IStatus.ERROR) + { + Matcher matcher = pattern.matcher(getTypeName()); + + if (!matcher.matches() || !matcher.group().equals(getTypeName())) + { + String errMsg = + NLS.bind(CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_InvalidTypeName, + getTypeName()); + + status = new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, errMsg); + } + else if (packageAndClassExist()) + { + status = + new Status( + IStatus.ERROR, + CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_PackageAndClassAlreadyExist); + } + else if (isTooLongOnFileSystem()) + { + status = + new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_FileNameTooLong); + } + } + + labelChanged(); + return status; + } + + /** + * Returns the building block label property value. + * + * @return the building block label property value. + */ + protected String getLabel() + { + String label; + if (defaultLabelButton.getSelection()) + { + label = ""; //$NON-NLS-1$ + } + else + { + label = labelText.getText(); + } + return label; + } + + /** + * Returns the building block model + * + * @return the building block model + */ + public BuildingBlockModel getBuildBlock() + { + return buildBlock; + } + + public void setBuildBlock(BuildingBlockModel buildBlock) + { + this.buildBlock = buildBlock; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#packageChanged() + */ + @Override + protected IStatus packageChanged() + { + IStatus superStatus = super.packageChanged(); + IStatus status = + new Status(superStatus.getSeverity(), CodeUtilsActivator.PLUGIN_ID, + superStatus.getMessage()); + + // The package name is being get by getPackageText because the method + // getPackageFragment + // (from super class) is not returning the right value in some cases + String packageName = getPackageText(); + + if (status.getCode() != IStatus.ERROR) + { + if (packageName != null) + { + Pattern pattern = Pattern.compile("[A-Za-z0-9_\\.]+"); //$NON-NLS-1$ + Matcher matcher = pattern.matcher(packageName); + + if (packageName.indexOf('.') == -1) + { + status = + new Status( + IStatus.ERROR, + CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_PackageMustHaveAtLeastTwoIdentifiers); + } + else if (!matcher.matches()) + { + String errMsg = + NLS.bind( + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_InvalidPackageName, + packageName); + status = new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, errMsg); + } + else if (packageAndClassExist()) + { + status = + new Status( + IStatus.ERROR, + CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_PackageAndClassAlreadyExist); + } + else if (isTooLongOnFileSystem()) + { + status = + new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_FileNameTooLong); + } + } + + } + + return status; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#containerChanged() + */ + @Override + protected IStatus containerChanged() + { + IStatus superStatus = super.containerChanged(); + IStatus status = + new Status(superStatus.getSeverity(), CodeUtilsActivator.PLUGIN_ID, + superStatus.getMessage()); + + boolean hasNature = false; + + if (status.getCode() != IStatus.ERROR) + { + try + { + if ((getPackageFragmentRoot() != null) + && (getPackageFragmentRoot().getJavaProject() != null)) + { + hasNature = + getPackageFragmentRoot().getJavaProject().getProject() + .hasNature(IAndroidConstants.ANDROID_NATURE); + } + } + catch (CoreException ce) + { + StudioLogger.error(NewBuildingBlocksWizardPage.class, + "Error getting the project nature.", ce); //$NON-NLS-1$ + hasNature = false; + } + + if ((getPackageFragmentRoot() != null) && !hasNature) + { + status = + new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_SelectAnAndroidProject); + } + else if ((getPackageFragmentRoot() == null) + || (getPackageFragmentRoot().getResource().getType() == IResource.PROJECT) + || ((getPackageFragmentRoot().getElementType() & IPackageFragmentRoot.K_SOURCE) != IPackageFragmentRoot.K_SOURCE)) + { + status = + new Status( + IStatus.ERROR, + CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_SelectAValidSourceFolder); + } + else if (getPackageFragmentRoot().getElementName().equals( + IAndroidConstants.GEN_SRC_FOLDER) + && (getPackageFragmentRoot().getParent() instanceof IJavaProject)) + { + status = + new Status( + IStatus.ERROR, + CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_CannotUseTheGenFolderAsSourceFolder); + } + else if (isTooLongOnFileSystem()) + { + status = + new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_FileNameTooLong); + } + } + + return status; + } + + /** + * Checks for cross package/class collision among source folders + * + * @return true if there is any collision or false otherwise + */ + private boolean packageAndClassExist() + { + boolean exists = false; + + try + { + if ((getJavaProject() != null) && getJavaProject().isOpen()) + { + IPackageFragmentRoot[] roots = getJavaProject().getPackageFragmentRoots(); + + if (roots != null) + { + for (IPackageFragmentRoot root : roots) + { + if ((root.getKind() & IPackageFragmentRoot.K_SOURCE) == IPackageFragmentRoot.K_SOURCE) + { + IPackageFragment pack = root.getPackageFragment(getPackageText()); + + if ((pack != null) && pack.exists()) + { + IJavaElement classes[] = pack.getChildren(); + + if (classes != null) + { + for (IJavaElement clazz : classes) + { + if (clazz.getElementName().equals( + getTypeName() + JAVA_EXTENSION)) + { + exists = true; + break; + } + } + } + } + } + + if (exists) + { + break; + } + } + } + } + } + catch (JavaModelException e) + { + // Do nothing + StudioLogger.error(NewBuildingBlocksWizardPage.class, e.getLocalizedMessage(), e); + } + + return exists; + } + + /** + * Checks if the current building block that is being created can be written + * to the file system without throw a "file name too long" error + * + * @return true if the building block can be written or false otherwise + */ + private boolean isTooLongOnFileSystem() + { + boolean isTooLong = false; + + if (getPackageFragment() != null) + { + String javaFileName = + getPackageFragment().getCompilationUnit(getTypeName() + JAVA_EXTENSION) + .getResource().getLocation().toFile().getPath(); + + isTooLong = javaFileName.length() > MAX_PATH_SIZE; + } + + return isTooLong; + } + + /** + * Checks if the wizard can be opened. If the wizard cannot be opened, an + * error message is displayed. + * + * @return true if the wizard can be opened or false otherwise. + */ + private boolean canOpen() + { + boolean canOpen = true; + + if (getBuildBlock().getProject() != null) + { + IStatus status = null; + + try + { + AndroidManifestFile manifestFile = + AndroidProjectManifestFile.getFromProject(getBuildBlock().getProject()); + + if (manifestFile.hasErrors()) + { + status = + new MultiStatus( + CodeUtilsActivator.PLUGIN_ID, + IStatus.ERROR, + manifestFile.getErrors(), + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_OneOrMoreErrorsWhenParsingManifest, + null); + } + } + catch (AndroidException e) + { + status = + new Status(IStatus.ERROR, CodeUtilsActivator.PLUGIN_ID, + e.getLocalizedMessage()); + } + catch (CoreException e) + { + status = e.getStatus(); + } + + if (status != null) + { + canOpen = false; + + EclipseUtils + .showErrorDialog( + CodeUtilsNLS.UI_GenericErrorDialogTitle, + CodeUtilsNLS.ERR_NewBuildingBlocksWizardPage_CannotProceedWithTheBuildingBlockCreation, + status); + } + } + + return canOpen; + } +} |