Package org.aspectj.org.eclipse.jdt.internal.core

Source Code of org.aspectj.org.eclipse.jdt.internal.core.CreateElementInCUOperation

/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.core;

import java.util.Map;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.aspectj.org.eclipse.jdt.core.ICompilationUnit;
import org.aspectj.org.eclipse.jdt.core.IJavaElement;
import org.aspectj.org.eclipse.jdt.core.IJavaModelStatus;
import org.aspectj.org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.aspectj.org.eclipse.jdt.core.JavaModelException;
import org.aspectj.org.eclipse.jdt.core.dom.AST;
import org.aspectj.org.eclipse.jdt.core.dom.ASTNode;
import org.aspectj.org.eclipse.jdt.core.dom.ASTParser;
import org.aspectj.org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.aspectj.org.eclipse.jdt.core.dom.CompilationUnit;
import org.aspectj.org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.aspectj.org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.aspectj.org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.aspectj.org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;

/**
* <p>This abstract class implements behavior common to <code>CreateElementInCUOperations</code>.
* To create a compilation unit, or an element contained in a compilation unit, the
* source code for the entire compilation unit is updated and saved.
*
* <p>The element being created can be positioned relative to an existing
* element in the compilation unit via the methods <code>#createAfter</code>
* and <code>#createBefore</code>. By default, the new element is positioned
* as the last child of its parent element.
*
*/
public abstract class CreateElementInCUOperation extends JavaModelOperation {
  /**
   * The compilation unit AST used for this operation
   */
  protected CompilationUnit cuAST;   
  /**
   * A constant meaning to position the new element
   * as the last child of its parent element.
   */
  protected static final int INSERT_LAST = 1;
  /**
   * A constant meaning to position the new element
   * after the element defined by <code>fAnchorElement</code>.
   */
  protected static final int INSERT_AFTER = 2;

  /**
   * A constant meaning to position the new element
   * before the element defined by <code>fAnchorElement</code>.
   */
  protected static final int INSERT_BEFORE = 3;
  /**
   * One of the position constants, describing where
   * to position the newly created element.
   */
  protected int insertionPolicy = INSERT_LAST;
  /**
   * The element that the newly created element is
   * positioned relative to, as described by
   * <code>fInsertPosition</code>, or <code>null</code>
   * if the newly created element will be positioned
   * last.
   */
  protected IJavaElement anchorElement = null;
  /**
   * A flag indicating whether creation of a new element occurred.
   * A request for creating a duplicate element would request in this
   * flag being set to <code>false</code>. Ensures that no deltas are generated
   * when creation does not occur.
   */
  protected boolean creationOccurred = true;
  /**
   * Constructs an operation that creates a Java Language Element with
   * the specified parent, contained within a compilation unit.
   */
  public CreateElementInCUOperation(IJavaElement parentElement) {
    super(null, new IJavaElement[]{parentElement});
    initializeDefaultPosition();
  }
  protected void apply(ASTRewrite rewriter, IDocument document, Map options) throws JavaModelException {
    TextEdit edits = rewriter.rewriteAST(document, options);
     try {
       edits.apply(document);
     } catch (BadLocationException e) {
       throw new JavaModelException(e, IJavaModelStatusConstants.INVALID_CONTENTS);
     }
  }
  /**
   * Only allow cancelling if this operation is not nested.
   */
  protected void checkCanceled() {
    if (!isNested) {
      super.checkCanceled();
    }
  }
  /**
   * Instructs this operation to position the new element after
   * the given sibling, or to add the new element as the last child
   * of its parent if <code>null</code>.
   */
  public void createAfter(IJavaElement sibling) {
    setRelativePosition(sibling, INSERT_AFTER);
  }
  /**
   * Instructs this operation to position the new element before
   * the given sibling, or to add the new element as the last child
   * of its parent if <code>null</code>.
   */
  public void createBefore(IJavaElement sibling) {
    setRelativePosition(sibling, INSERT_BEFORE);
  }
  /**
   * Execute the operation - generate new source for the compilation unit
   * and save the results.
   *
   * @exception JavaModelException if the operation is unable to complete
   */
  protected void executeOperation() throws JavaModelException {
    try {
      beginTask(getMainTaskName(), getMainAmountOfWork());
      JavaElementDelta delta = newJavaElementDelta();
      ICompilationUnit unit = getCompilationUnit();
      generateNewCompilationUnitAST(unit);
      if (this.creationOccurred) {
        //a change has really occurred
        unit.save(null, false);
        boolean isWorkingCopy = unit.isWorkingCopy();
        if (!isWorkingCopy)
          setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
        worked(1);
        resultElements = generateResultHandles();
        if (!isWorkingCopy // if unit is working copy, then save will have already fired the delta
            && !Util.isExcluded(unit)
            && unit.getParent().exists()) {
          for (int i = 0; i < resultElements.length; i++) {
            delta.added(resultElements[i]);
          }
          addDelta(delta);
        } // else unit is created outside classpath
          // non-java resource delta will be notified by delta processor
      }
    } finally {
      done();
    }
  }
 
  /*
   * Returns the property descriptor for the element being created.
   */
  protected abstract StructuralPropertyDescriptor getChildPropertyDescriptor(ASTNode parent);
 
  /*
   * Returns an AST node for the element being created.
   */
  protected abstract ASTNode generateElementAST(ASTRewrite rewriter, IDocument document, ICompilationUnit cu) throws JavaModelException;
  /*
   * Generates a new AST for this operation and applies it to the given cu
   */
  protected void generateNewCompilationUnitAST(ICompilationUnit cu) throws JavaModelException {
    this.cuAST = parse(cu);
   
    AST ast = this.cuAST.getAST();
    ASTRewrite rewriter = ASTRewrite.create(ast);
    IDocument document = getDocument(cu);
    ASTNode child = generateElementAST(rewriter, document, cu);
    if (child != null) {
      ASTNode parent = ((JavaElement) getParentElement()).findNode(this.cuAST);
      if (parent == null)
        parent = this.cuAST;
      insertASTNode(rewriter, parent, child);
      apply(rewriter, document, cu.getJavaProject().getOptions(true));
    }
    worked(1);
  }
  /**
   * Creates and returns the handle for the element this operation created.
   */
  protected abstract IJavaElement generateResultHandle();
  /**
   * Creates and returns the handles for the elements this operation created.
   */
  protected IJavaElement[] generateResultHandles() {
    return new IJavaElement[]{generateResultHandle()};
  }
  /**
   * Returns the compilation unit in which the new element is being created.
   */
  protected ICompilationUnit getCompilationUnit() {
    return getCompilationUnitFor(getParentElement());
  }
  /**
   * Returns the amount of work for the main task of this operation for
   * progress reporting.
   */
  protected int getMainAmountOfWork(){
    return 2;
  }
  /**
   * Returns the name of the main task of this operation for
   * progress reporting.
   */
  public abstract String getMainTaskName();

  protected ISchedulingRule getSchedulingRule() {
    IResource resource = getCompilationUnit().getResource();
    IWorkspace workspace = resource.getWorkspace();
    return workspace.getRuleFactory().modifyRule(resource);
  }
  /**
   * Sets the default position in which to create the new type
   * member.
   * Operations that require a different default position must
   * override this method.
   */
  protected void initializeDefaultPosition() {
    // By default, the new element is positioned as the
    // last child of the parent element in which it is created.
  }
  /**
   * Inserts the given child into the given AST,
   * based on the position settings of this operation.
   *
   * @see #createAfter(IJavaElement)
   * @see #createBefore(IJavaElement)
   */
  protected void insertASTNode(ASTRewrite rewriter, ASTNode parent, ASTNode child) throws JavaModelException {
    StructuralPropertyDescriptor propertyDescriptor = getChildPropertyDescriptor(parent);
    if (propertyDescriptor instanceof ChildListPropertyDescriptor) {
      ChildListPropertyDescriptor childListPropertyDescriptor = (ChildListPropertyDescriptor) propertyDescriptor;
       ListRewrite rewrite = rewriter.getListRewrite(parent, childListPropertyDescriptor);
       switch (this.insertionPolicy) {
         case INSERT_BEFORE:
           ASTNode element = ((JavaElement) this.anchorElement).findNode(this.cuAST);
           if (childListPropertyDescriptor.getElementType().isAssignableFrom(element.getClass()))
             rewrite.insertBefore(child, element, null);
           else
             // case of an empty import list: the anchor element is the top level type and cannot be used in insertBefore as it is not the same type
             rewrite.insertLast(child, null);
           break;
         case INSERT_AFTER:
           element = ((JavaElement) this.anchorElement).findNode(this.cuAST);
           if (childListPropertyDescriptor.getElementType().isAssignableFrom(element.getClass()))
             rewrite.insertAfter(child, element, null);
           else
             // case of an empty import list: the anchor element is the top level type and cannot be used in insertAfter as it is not the same type
             rewrite.insertLast(child, null);
           break;
         case INSERT_LAST:
           rewrite.insertLast(child, null);
           break;
       }
    } else {
      rewriter.set(parent, propertyDescriptor, child, null);
    }
   }
  protected CompilationUnit parse(ICompilationUnit cu) throws JavaModelException {
    // ensure cu is consistent (noop if already consistent)
    cu.makeConsistent(this.progressMonitor);
    // create an AST for the compilation unit
    ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setSource(cu);
    return (CompilationUnit) parser.createAST(this.progressMonitor);
  }
  /**
   * Sets the name of the <code>DOMNode</code> that will be used to
   * create this new element.
   * Used by the <code>CopyElementsOperation</code> for renaming.
   * Only used for <code>CreateTypeMemberOperation</code>
   */
  protected void setAlteredName(String newName) {
    // implementation in CreateTypeMemberOperation
  }
  /**
   * Instructs this operation to position the new element relative
   * to the given sibling, or to add the new element as the last child
   * of its parent if <code>null</code>. The <code>position</code>
   * must be one of the position constants.
   */
  protected void setRelativePosition(IJavaElement sibling, int policy) throws IllegalArgumentException {
    if (sibling == null) {
      this.anchorElement = null;
      this.insertionPolicy = INSERT_LAST;
    } else {
      this.anchorElement = sibling;
      this.insertionPolicy = policy;
    }
  }
  /**
   * Possible failures: <ul>
   <li>NO_ELEMENTS_TO_PROCESS - the compilation unit supplied to the operation is
   *     <code>null</code>.
   *  <li>INVALID_NAME - no name, a name was null or not a valid
   *     import declaration name.
   *  <li>INVALID_SIBLING - the sibling provided for positioning is not valid.
   * </ul>
   * @see IJavaModelStatus
   * @see org.aspectj.org.eclipse.jdt.core.JavaConventions
   */
  public IJavaModelStatus verify() {
    if (getParentElement() == null) {
      return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
    }
    if (this.anchorElement != null) {
      IJavaElement domPresentParent = this.anchorElement.getParent();
      if (domPresentParent.getElementType() == IJavaElement.IMPORT_CONTAINER) {
        domPresentParent = domPresentParent.getParent();
      }
      if (!domPresentParent.equals(getParentElement())) {
        return new JavaModelStatus(IJavaModelStatusConstants.INVALID_SIBLING, this.anchorElement);
      }
    }
    return JavaModelStatus.VERIFIED_OK;
  }
}
TOP

Related Classes of org.aspectj.org.eclipse.jdt.internal.core.CreateElementInCUOperation

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.