Package ch.ethz.prose.eclipse.internal.wizards

Source Code of ch.ethz.prose.eclipse.internal.wizards.NewAspectWizardPage

//
//  This file is part of the Prose Development Tools for Eclipse package.
//
//  The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (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.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS" basis,
//  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
//  for the specific language governing rights and limitations under the
//  License.
//
//  The Original Code is Prose Development Tools for Eclipse.
//
//  The Initial Developer of the Original Code is Angela Nicoara. Portions
//  created by Angela Nicoara are Copyright (C) 2006 Angela Nicoara.
//  All Rights Reserved.
//
//  Contributor(s):
//  $Id: NewAspectWizardPage.java,v 1.1 2008/11/18 12:26:05 anicoara Exp $
//  ==============================================================================
//

package ch.ethz.prose.eclipse.internal.wizards;

import java.util.ArrayList;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.dom.TokenScanner;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ComboDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.Separator;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.wizards.NewContainerWizardPage;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;

/**
* Wizard page to create a new Prose aspect.
*
* @author Angela Nicoara
* @author Johann Gyger
* @version $Id: NewAspectWizardPage.java,v 1.1 2008/11/18 12:26:05 anicoara Exp $
*/
public class NewAspectWizardPage extends NewContainerWizardPage {

  /** MethodCut type */
  public static final int METHOD_CUT_TYPE = 0;
  /** MethodRedefineCut type */
  public static final int METHOD_REDEFINE_CUT_TYPE = 1;
  /** GetCut type */
  public static final int GET_CUT_TYPE = 2;
  /** SetCut type */
  public static final int SET_CUT_TYPE = 3;
  /** ThrowCut type */
  public static final int THROW_CUT_TYPE = 4;
  /** CatchCut type */
  public static final int CATCH_CUT_TYPE = 5;

  protected static final String PAGE_NAME = "NewAspectWizardPage"; //$NON-NLS-1$
  protected static final String PACKAGE = PAGE_NAME + ".package"; //$NON-NLS-1$
  protected static final String ASPECT_NAME = PAGE_NAME + ".aspect_name"; //$NON-NLS-1$
  protected static final String CROSSCUT_NAME = PAGE_NAME + ".crosscut_name"; //$NON-NLS-1$
  protected static final String CROSSCUT_TYPE = PAGE_NAME + ".crosscut_type"; //$NON-NLS-1$
  protected static final String POINT_CUTTER = PAGE_NAME + ".point_cutter"; //$NON-NLS-1$

  protected static final String[] PC_GENERIC = {"(none)", "NOT", "AND", "OR"};
  protected static final String[] PC_ALL = {
    "Within.method(\"methodNamePattern\")",
    "Within.type(\"ClassNamePattern\")",
    "Within.type(Object.class)",
    "Within.subType(Object.class)",
    "Within.superType(Object.class)",
    "Within.packageTypes(\"package.name.pattern\")"
  };
  protected static final String[] PC_METHOD = {
    "Executions.before()",
    "Executions.after()"
  };
  protected static final String[] PC_FIELD = {
    "Fields.named(\"fieldNamePattern\")",
    "Fields.declaredInClass(\"ClassNamePattern\")",
    "Fields.declaredInClass(Object.class)",
    "Fields.declaredInSubClass(Object.class)",
    "Fields.declaredInSuperClass(Object.class)",
  };
  protected static final String[] PC_EXCEPTION = {
    "Exceptions.type(\"ExceptionNamePattern\")",
    "Exceptions.type(Throwable.class)",
    "Exceptions.subtypeOf(Throwable.class)",
    "Exceptions.supertypeOf(Throwable.class)",
    "Exceptions.withMessage(\"message\")",
  };
  protected static final String[] PC_GENERIC_ALL = concat(PC_GENERIC, PC_ALL);

  protected StringButtonStatusDialogField fPackageDialogField;
  protected StringDialogField fAspectNameDialogField;
  protected ComboDialogField fCrosscutTypeDialogField;
  protected ComboDialogField fPointCutterDialogField;
  protected ComboDialogField fPointCutter1DialogField;
  protected ComboDialogField fPointCutter2DialogField;   

  protected IStatus fPackageStatus = new StatusInfo();
  protected IStatus fAspectNameStatus = new StatusInfo();
  protected IStatus fCrosscutTypeStatus = new StatusInfo();
  protected IStatus fPointCutterStatus = new StatusInfo();

  protected IPackageFragment fPackageFragment;
  protected IType fAspect;
  protected NewCrosscutWizardPage fCrosscutPage;

  /**
   * Concatenate two String arrays.
   *
   * @param strings1 First array
   * @param strings2 Second array
   * @return Concatenated array
   */
  protected static String[] concat(String[] strings1, String[] strings2) {
    String[] result = new String[strings1.length + strings2.length];
    System.arraycopy(strings1, 0, result, 0, strings1.length);
    System.arraycopy(strings2, 0, result, strings1.length, strings2.length);
    return result;
  }

  /**
   * Create a new <code>NewAspectWizardPage</code>.
   */
  public NewAspectWizardPage() {
    super(PAGE_NAME);
    setTitle("Prose Aspect");
    setDescription("Create or extend a Prose aspect.");

    fPackageDialogField = new StringButtonStatusDialogField(new IStringButtonAdapter() {
      public void changeControlPressed(DialogField field) {
        IPackageFragment pack= choosePackage()
        if (pack != null) {
          fPackageDialogField.setText(pack.getElementName());
        }
      }
    });
    fPackageDialogField.setDialogFieldListener(new IDialogFieldListener() {
      public void dialogFieldChanged(DialogField field) {
        fPackageStatus = updatePackage();
        fAspectNameStatus = updateAspectName();
        handleFieldChanged(PACKAGE);
      }
    });
    fPackageDialogField.setLabelText("Package");
    fPackageDialogField.setButtonLabel("Browse...");
    fPackageDialogField.setStatusWidthHint("(default)");

    fAspectNameDialogField = new StringDialogField();
    fAspectNameDialogField.setDialogFieldListener(new IDialogFieldListener() {
      public void dialogFieldChanged(DialogField field) {
        fAspectNameStatus = updateAspectName();
        handleFieldChanged(ASPECT_NAME);
      }
    });
    fAspectNameDialogField.setLabelText("Aspect Name:");

    fCrosscutTypeDialogField = new ComboDialogField(SWT.READ_ONLY);
    fCrosscutTypeDialogField.setDialogFieldListener(new IDialogFieldListener() {
      public void dialogFieldChanged(DialogField field) {
        fCrosscutTypeStatus = updateCrosscutType();
        handleFieldChanged(CROSSCUT_TYPE);
      }
    });
    fCrosscutTypeDialogField.setLabelText("Crosscut Type:");
    fCrosscutTypeDialogField.setItems(new String[] { "MethodCut", "MethodRedefineCut", "GetCut", "SetCut", "ThrowCut", "CatchCut"});

    fPointCutterDialogField = new ComboDialogField(SWT.READ_ONLY);
    fPointCutterDialogField.setDialogFieldListener(new IDialogFieldListener() {
      public void dialogFieldChanged(DialogField field) {
        fPointCutterStatus = updatePointCutter();
        handleFieldChanged(POINT_CUTTER);
      }
    });
    fPointCutterDialogField.setLabelText("Point Cutter:");

    fPointCutter1DialogField = new ComboDialogField(SWT.READ_ONLY);
    fPointCutter1DialogField.setLabelText("Specifier 1:");
    fPointCutter1DialogField.setEnabled(false);

    fPointCutter2DialogField = new ComboDialogField(SWT.READ_ONLY);
    fPointCutter2DialogField.setLabelText("Specifier 2:");
    fPointCutter2DialogField.setEnabled(false);
  }

  /**
   * Initialize all fields provided by the page with a given selection.
   *
   * @param elem Java element used to initialize this page or <code>null</code>
   * if no selection was available
   */
  protected void initAspectPage(IJavaElement elem) {
    if (elem != null) {
      IPackageFragment pack = (IPackageFragment) elem.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
      if (pack != null) {
        fPackageDialogField.setText(pack.getElementName());
      }

      IType aspect = null;
      IType typeInCU = (IType) elem.getAncestor(IJavaElement.TYPE);
      if (typeInCU != null) {
        if (typeInCU.getCompilationUnit() != null) {
          aspect = typeInCU;
        }
      } else {
        ICompilationUnit cu = (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
        if (cu != null) {
          aspect = cu.findPrimaryType();
        }
      }
      if (aspect != null) {
        fAspectNameDialogField.setText(aspect.getElementName());
      }
    }
  }

  /**
   * The wizard owning this page is responsible for calling this method with
   * the current selection. The selection is used to initialize the fields of
   * the wizard page.
   *
   * @param selection Selection used to initialize the fields
   */
  public void init(IStructuredSelection selection) {
    IJavaElement jelem = getInitialJavaElement(selection);
    initContainerPage(jelem);
    initAspectPage(jelem);
    doStatusUpdate();
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(java.lang.String)
   */
  protected void handleFieldChanged(String fieldName) {
    super.handleFieldChanged(fieldName);
    if (fieldName == CONTAINER) {
      fPackageStatus = updatePackage();
      fAspectNameStatus = updateAspectName();
    }
    doStatusUpdate();
  }

  /**
   * Collect the status objects and update the whole status.
   */
  private void doStatusUpdate() {
    IStatus[] status = new IStatus[] { fContainerStatus, fPackageStatus, fAspectNameStatus, fCrosscutTypeStatus,
        fPointCutterStatus};
    updateStatus(status);
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
   */
  public void createControl(Composite parent) {
    initializeDialogUnits(parent);

    Composite composite = new Composite(parent, SWT.NONE);
    int nColumns = 4;
    GridLayout layout = new GridLayout();
    layout.numColumns = nColumns;
    composite.setLayout(layout);

    createContainerControls(composite, nColumns);
    createPackageControls(composite, nColumns);
    createSeparator(composite, nColumns);
    createAspectNameControls(composite, nColumns);
    createCrosscutTypeControls(composite, nColumns);
    createSeparator(composite, nColumns);
    createPointCutterControls(composite, nColumns);

    setControl(composite);

    Dialog.applyDialogFont(composite);
  }

  protected void createPackageControls(Composite parent, int nColumns) {
    fPackageDialogField.doFillIntoGrid(parent, nColumns);
    Text text = fPackageDialogField.getTextControl(null);
    LayoutUtil.setWidthHint(text, getMaxFieldWidth());
    LayoutUtil.setHorizontalGrabbing(text);
  }

  protected void createAspectNameControls(Composite parent, int nColumns) {
    fAspectNameDialogField.doFillIntoGrid(parent, nColumns - 1);
    LayoutUtil.setWidthHint(fAspectNameDialogField.getTextControl(null), getMaxFieldWidth());
    DialogField.createEmptySpace(parent);
  }

  protected void createCrosscutTypeControls(Composite parent, int nColumns) {
    fCrosscutTypeDialogField.doFillIntoGrid(parent, nColumns - 1);
    fCrosscutTypeDialogField.selectItem(0);
    DialogField.createEmptySpace(parent);
  }

  protected void createPointCutterControls(Composite parent, int nColumns) {
    fPointCutterDialogField.doFillIntoGrid(parent, nColumns - 1);
    fPointCutterDialogField.selectItem(0);
    DialogField.createEmptySpace(parent);

    fPointCutter1DialogField.doFillIntoGrid(parent, nColumns - 1);
    DialogField.createEmptySpace(parent);

    fPointCutter2DialogField.doFillIntoGrid(parent, nColumns - 1);
    DialogField.createEmptySpace(parent);
  }

  /**
   * Create a separator line.
   *
   * @param composite Parent composite
   * @param nColumns Number of columns to span (at least one)
   */
  protected void createSeparator(Composite composite, int nColumns) {
    (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1));
  }

  /**
   * @return Text of package input field
   */
  public String getPackage() {
    return fPackageDialogField.getText();
  }

  /**
   * @return Text of aspect name input field
   */
  public String getAspectName() {
    return fAspectNameDialogField.getText();
  }

  /**
   * @return Package fragment
   */
  public IPackageFragment getPackageFragment() {
    return fPackageFragment;
  }

  /**
   * @return Aspect type, or <code>null</code>
   */
  public IType getAspect() {
    return fAspect;
  }

  /**
   * @return Resource handle that corresponds to the compilation unit (aspect)
   * that has been created or modified
   */
  public IResource getModifiedResource() {
    IPackageFragment pack = getPackageFragment();
    return pack != null ? pack.getCompilationUnit(getAspectName() + ".java").getResource() : null; //$NON-NLS-1$
  }

  /*
   * (non-Javadoc)
   * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
   */
  public void setVisible(boolean visible) {
    super.setVisible(visible);
    if (visible) {
      setFocus();
    }
  }

  /* (non-Javadoc)
   * @see org.eclipse.jface.wizard.IWizardPage#getNextPage()
   */
  public IWizardPage getNextPage() {
    return fCrosscutPage;
  }

  /**
   * Set the focus on the aspect name input field.
   */
  protected void setFocus() {
    fAspectNameDialogField.setFocus();
  }

  /**
   * Update modification of package input field.
   *
   * @return Package validation status
   */
  protected IStatus updatePackage() {
    StatusInfo status = new StatusInfo();
    fPackageDialogField.setStatus(getPackage().length() == 0 ? "(default)" : "");
    fPackageDialogField.enableButton(getPackageFragmentRoot() != null);

    String packName = getPackage();
    if (packName.length() > 0) {
      IStatus val = JavaConventions.validatePackageName(packName);
      if (val.getSeverity() == IStatus.ERROR) {
        status.setError("Package name is not valid." + val.getMessage());
        return status;
      } else if (val.getSeverity() == IStatus.WARNING) {
        status.setWarning("This package name is discouraged. " + val.getMessage());
        // continue
      }
    } else {
      status.setWarning("The use of the default package is discouraged.");
    }

    IPackageFragmentRoot root = getPackageFragmentRoot();
    if (root != null) {
      if (root.getJavaProject().exists() && packName.length() > 0) {
        try {
          IPath rootPath = root.getPath();
          IPath outputPath = root.getJavaProject().getOutputLocation();
          if (rootPath.isPrefixOf(outputPath) && !rootPath.equals(outputPath)) {
            // if the bin folder is inside of our root, don't allow
            // to name a package
            // like the bin folder
            IPath packagePath = rootPath.append(packName.replace('.', '/'));
            if (outputPath.isPrefixOf(packagePath)) {
              status.setError("Package clashes with project output folder.");
              return status;
            }
          }
        } catch (JavaModelException e) {
          JavaPlugin.log(e);
          // let pass
        }
      }

      fPackageFragment = root.getPackageFragment(packName);
    } else {
      status.setError(""); //$NON-NLS-1$
    }
    return status;
  }

  /**
   * Update modification of aspect name input field.
   *
   * @return Validation status
   */
  protected IStatus updateAspectName() {
    StatusInfo status = new StatusInfo();
    fAspect = null;
    String aspectName = getAspectName();
    if (aspectName.length() == 0) {
      status.setError("Aspect name is empty.");
      return status;
    }
    if (aspectName.indexOf('.') != -1) {
      status.setError("Aspect name must not be qualified.");
      return status;
    }

    IStatus val = JavaConventions.validateJavaTypeName(aspectName);
    if (val.getSeverity() == IStatus.ERROR) {
      status.setError("Aspect name is not valid. " + val.getMessage());
      return status;
    } else if (val.getSeverity() == IStatus.WARNING) {
      status.setWarning("Aspect name is discouraged. " + val.getMessage());
    }

    IPackageFragment pack = getPackageFragment();
    if (pack != null) {
      ICompilationUnit cu = pack.getCompilationUnit(aspectName + ".java"); //$NON-NLS-1$
      IResource resource = cu.getResource();
      if (resource.exists()) {
        status.setWarning("Aspect already exits. Only the crosscut will be created.");
        // TODO Check if aspect is a subclass of
        // ch.ethz.prose.DefaultAspect.
      }
      fAspect = cu.findPrimaryType();
    }

    return status;
  }

  /**
   * Update modification of crosscut type input field.
   *
   * @return Validation status
   */
  protected IStatus updateCrosscutType() {
    StatusInfo status = new StatusInfo();

    NewAspectCreationWizard wizard = (NewAspectCreationWizard) getWizard();
    String[] subItems = null;
    if (wizard == null) return status;
    switch (fCrosscutTypeDialogField.getSelectionIndex()) {
    case 0:
      fCrosscutPage = wizard.getMethodPage();
      fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_METHOD));
      subItems = concat(PC_ALL, PC_METHOD);
      break;
    case 1:
    fCrosscutPage = wizard.getMethodRedefinePage();
    fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_METHOD));
    subItems = concat(PC_ALL, PC_METHOD);
    break;
    case 2:
    case 3:
      fCrosscutPage = wizard.getFieldPage();
      fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_FIELD));
      subItems = concat(PC_ALL, PC_FIELD);
      break;
    case 4:
    case 5:
      fCrosscutPage = wizard.getExceptionPage();
      fPointCutterDialogField.setItems(concat(PC_GENERIC_ALL, PC_EXCEPTION));
      subItems = concat(PC_ALL, PC_EXCEPTION);
      break;
    default:
      status.setError("Unknown crosscut type.");
    fCrosscutPage = null;
    return status;
    }
    fPointCutter1DialogField.setItems(subItems);
    fPointCutter2DialogField.setItems(subItems);
    fPointCutterDialogField.selectItem(0);

    return status;
  }

  /**
   * Update modification of point cutter input field.
   *
   * @return Validation status
   */
  protected IStatus updatePointCutter() {
    StatusInfo status = new StatusInfo();

    switch (fPointCutterDialogField.getSelectionIndex()) {
    case 0: // (none)
      fPointCutter1DialogField.setEnabled(false);
      fPointCutter2DialogField.setEnabled(false);
      break;
    case 1: // NOT
      fPointCutter1DialogField.setEnabled(true);
      fPointCutter1DialogField.selectItem(0);
      fPointCutter2DialogField.setEnabled(false);
      break;
    case 2: // AND
    case 3: // OR
      fPointCutter1DialogField.setEnabled(true);
      fPointCutter1DialogField.selectItem(0);
      fPointCutter2DialogField.setEnabled(true);
      fPointCutter2DialogField.selectItem(0);
      break;
    default:
      fPointCutter1DialogField.setEnabled(false);
    fPointCutter2DialogField.setEnabled(false);
    break;
    }

    return status;
  }

  /**
   * @return Package selected by the user in a separate dialog
   */
  protected IPackageFragment choosePackage() {
    IPackageFragmentRoot froot = getPackageFragmentRoot();
    IJavaElement[] packages = null;
    try {
      if (froot != null && froot.exists()) {
        packages = froot.getChildren();
      }
    } catch (JavaModelException e) {
      JavaPlugin.log(e);
    }
    if (packages == null) {
      packages = new IJavaElement[0];
    }

    ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), new JavaElementLabelProvider(
        JavaElementLabelProvider.SHOW_DEFAULT));
    dialog.setIgnoreCase(false);
    dialog.setTitle("Package Selection");
    dialog.setMessage("&Choose a folder:");
    dialog.setEmptyListMessage("Cannot find packages to select.");
    dialog.setElements(packages);
    IPackageFragment pack = getPackageFragment();
    if (pack != null) {
      dialog.setInitialSelections(new Object[] { pack});
    }

    if (dialog.open() == Window.OK) {
      return (IPackageFragment) dialog.getFirstResult();
    }
    return null;
  }

  /**
   * Create the aspect using the entered field values.
   *
   * @param monitor Progress monitor
   * @throws CoreException
   * @throws InterruptedException
   */
  public void createAspect(IProgressMonitor monitor) throws CoreException, InterruptedException {
    if (monitor == null) {
      monitor = new NullProgressMonitor();
    }
    monitor.beginTask("Creating aspect...", 10);

    ICompilationUnit createdWorkingCopy = null;
    try {
      // Step 1: Process package fragment.
      IPackageFragmentRoot root = getPackageFragmentRoot();
      IPackageFragment pack = getPackageFragment();
      if (pack == null) {
        pack = root.getPackageFragment(""); //$NON-NLS-1$
      }
      if (!pack.exists()) {
        String packName = pack.getElementName();
        pack = root.createPackageFragment(packName, true, null);
      }
      monitor.worked(1);

      // Step 2: Create aspect if not already existent.
      boolean needsCommit = false;
      String lineDelimiter = null;
      String aspectName = getAspectName();
      IType aspect = getAspect();
      if (aspect == null) {
        lineDelimiter = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$

        ICompilationUnit parentCU = pack.createCompilationUnit(
            aspectName + ".java", "", false, new SubProgressMonitor(monitor, 2)); //$NON-NLS-1$ //$NON-NLS-2$
        // create a working copy with a new owner
        createdWorkingCopy = parentCU.getWorkingCopy(null);

        // use the compiler template a first time to read the imports
        String content = CodeGeneration.getCompilationUnitContent(createdWorkingCopy, null, "", lineDelimiter); //$NON-NLS-1$
        if (content != null) {
          createdWorkingCopy.getBuffer().setContents(content);
        }

        ImportsManager imports = new ImportsManager(createdWorkingCopy);
        // add an import that will be removed again. Having this import solves 14661
        imports.addImport(JavaModelUtil.concatenateName(pack.getElementName(), aspectName));

        String typeContent = writeBasicAspect(imports, lineDelimiter);
        String cuContent = constructCUContent(parentCU, typeContent, lineDelimiter);
        createdWorkingCopy.getBuffer().setContents(cuContent);
        if (monitor.isCanceled()) {
          throw new InterruptedException();
        }

        imports.create(false, new SubProgressMonitor(monitor, 1));
        JavaModelUtil.reconcile(createdWorkingCopy);
        aspect = createdWorkingCopy.getType(aspectName);
        needsCommit = true;
      }
      if (monitor.isCanceled()) {
        throw new InterruptedException();
      }

      ICompilationUnit cu = aspect.getCompilationUnit();
      boolean needsSave = cu.isWorkingCopy();
      ImportsManager imports = new ImportsManager(cu);
      lineDelimiter = StubUtility.getLineDelimiterUsed(aspect);

      // Write crosscut and format it
      IField field = fCrosscutPage.writeCrosscut(aspect, fCrosscutTypeDialogField.getSelectionIndex(), imports,
          new SubProgressMonitor(monitor, 2), lineDelimiter);
      ISourceRange range = field.getSourceRange();
      IBuffer buf = cu.getBuffer();
      String originalContent = buf.getText(range.getOffset(), range.getLength());
      String formattedContent = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, 1, null,
          lineDelimiter, field.getJavaProject());
      buf.replace(range.getOffset(), range.getLength(), formattedContent);
      if (!cu.isWorkingCopy())
        buf.save(null, false);

      imports.create(needsSave, new SubProgressMonitor(monitor, 1));
      removeUnusedImports(cu, needsSave);
      if (needsCommit)
        cu.commitWorkingCopy(false, new SubProgressMonitor(monitor, 1));
    } finally {
      if (createdWorkingCopy != null) {
        createdWorkingCopy.discardWorkingCopy();
      }
      monitor.done();
    }
  }

  /**
   * Write the body of the pointCutter() method.
   *
   * @param source Buffer to append the source
   * @param imports Imports manager
   * @param nl Line delimiter
   */
  public void writePointCutterBody(StringBuffer source, ImportsManager imports, String nl) {
    source.append("return ");
    switch (fPointCutterDialogField.getSelectionIndex()) {
    case 0: // (none)
      source.append("null;");
      return;
    case 1: // NOT
      source.append("new NegatingPointCutter(");
      source.append(fPointCutter1DialogField.getText());
      source.append(");");
      break;
    case 2: // AND
      source.append('(');
      source.append(fPointCutter1DialogField.getText());
      source.append(").AND(");
      source.append(fPointCutter2DialogField.getText());
      source.append(");");
      break;
    case 3: // OR
      source.append('(');
      source.append(fPointCutter1DialogField.getText());
      source.append(").OR(");
      source.append(fPointCutter2DialogField.getText());
      source.append(");");
      break;
    default:
      source.append(fPointCutterDialogField.getText());
    source.append(';');
    break;
    }
    imports.addImport("ch.ethz.prose.filter.*");
  }

  /**
   * Write basic aspect class without any decorations like comments
   *
   * @param imports Imports manager
   * @param lineDelimiter Line separator
   * @return Source for this aspect
   */
  protected String writeBasicAspect(ImportsManager imports, String lineDelimiter) {
    imports.addImport("ch.ethz.prose.DefaultAspect");
    StringBuffer buf = new StringBuffer();
    buf.append("public class "); //$NON-NLS-1$
    buf.append(getAspectName());
    buf.append(" extends DefaultAspect {");
    buf.append(lineDelimiter);
    buf.append(lineDelimiter);
    buf.append('}');
    buf.append(lineDelimiter);
    return buf.toString();
  }

  /**
   * Uses the New Java file template from the code template page to generate a
   * compilation unit with the given type content.
   *
   * @param cu The new created compilation unit
   * @param typeContent The content of the type, including signature and type
   * body.
   * @param lineDelimiter The line delimiter to be used.
   * @return String Returns the result of evaluating the new file template
   * with the given type content.
   * @throws CoreException
   */
  protected String constructCUContent(ICompilationUnit cu, String typeContent, String lineDelimiter) throws CoreException {
    String typeComment = getTypeComment(cu, lineDelimiter);
    IPackageFragment pack = (IPackageFragment) cu.getParent();
    String content = CodeGeneration.getCompilationUnitContent(cu, typeComment, typeContent, lineDelimiter);
    if (content != null) {
      ASTParser parser = ASTParser.newParser(AST.JLS2);
      parser.setSource(content.toCharArray());
      CompilationUnit unit = (CompilationUnit) parser.createAST(null);
      if ((pack.isDefaultPackage() || unit.getPackage() != null) && !unit.types().isEmpty()) { return content; }
    }
    StringBuffer buf = new StringBuffer();
    if (!pack.isDefaultPackage()) {
      buf.append("package ").append(pack.getElementName()).append(';'); //$NON-NLS-1$
    }
    buf.append(lineDelimiter).append(lineDelimiter);
    if (typeComment != null) {
      buf.append(typeComment).append(lineDelimiter);
    }
    buf.append(typeContent);
    return buf.toString();
  }

  /**
   * Get new Java file template comment.
   *
   * @param parentCU Parent compilation unit
   * @param lineDelimiter Line separator
   * @return Content of the `type comment' template
   */
  protected String getTypeComment(ICompilationUnit parentCU, String lineDelimiter) {
    try {
      StringBuffer aspectName = new StringBuffer();
      aspectName.append(getAspectName());
      String comment = CodeGeneration.getTypeComment(parentCU, aspectName.toString(), lineDelimiter);
      if (comment != null && isValidComment(comment)) { return comment; }
    } catch (CoreException e) {
      JavaPlugin.log(e);
    }
    return null;
  }

  /**
   * @param template Generated comment
   * @return Is `template' a valid comment?
   */
  protected boolean isValidComment(String template) {
    IScanner scanner = ToolFactory.createScanner(true, false, false, false);
    scanner.setSource(template.toCharArray());
    try {
      int next = scanner.getNextToken();
      while (TokenScanner.isComment(next)) {
        next = scanner.getNextToken();
      }
      return next == ITerminalSymbols.TokenNameEOF;
    } catch (InvalidInputException e) {
    }
    return false;
  }

  /**
   * Remove unused imports from compilation unit.
   *
   * @param cu Compilation unit that is processed
   * @param needsSave Save needed?
   * @throws CoreException
   */
  protected void removeUnusedImports(ICompilationUnit cu, boolean needsSave) throws CoreException {
    ASTParser parser = ASTParser.newParser(AST.JLS2);
    parser.setSource(cu);
    parser.setResolveBindings(true);
    CompilationUnit root = (CompilationUnit) parser.createAST(null);
    IProblem[] problems = root.getProblems();
    ArrayList res = new ArrayList();
    for (int i = 0; i < problems.length; i++) {
      if (problems[i].getID() == IProblem.UnusedImport) {
        String imp = problems[i].getArguments()[0];
        res.add(imp);
      }
    }
    if (!res.isEmpty()) {
      ImportsManager imports = new ImportsManager(cu);
      for (int i = 0; i < res.size(); i++) {
        String curr = (String) res.get(i);
        imports.removeImport(curr);
      }
      imports.create(needsSave, null);
    }
  }

}
TOP

Related Classes of ch.ethz.prose.eclipse.internal.wizards.NewAspectWizardPage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.