GenerateToStringOperation.java :  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » corext » codemanipulation » tostringgeneration » Java Open Source

Java Open Source » IDE Eclipse » jdt 
jdt » org » eclipse » jdt » internal » corext » codemanipulation » tostringgeneration » GenerateToStringOperation.java
/*******************************************************************************
 * Copyright (c) 2009 Mateusz Matela 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:
 *     Mateusz Matela <mateusz.matela@gmail.com> - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070
 *     Mateusz Matela <mateusz.matela@gmail.com> - [toString] finish toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=267710
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;

import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTMatcher;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;

import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationMessages;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;


/**
 * <p>
 * A workspace runnable to add implementation for <code>{@link java.lang.Object#toString()}</code>
 * </p>
 * 
 * @since 3.5
 */
public class GenerateToStringOperation implements IWorkspaceRunnable {

  /** The insertion point, or <code>null</code> */
  private IJavaElement fInsert;

  private CompilationUnitRewrite fRewrite;

  private ToStringGenerationContext fContext;

  private AbstractToStringGenerator fGenerator;

  private CompilationUnit fUnit;

  private GenerateToStringOperation(IJavaElement insert, ToStringGenerationContext context, AbstractToStringGenerator generator, CompilationUnit unit, CompilationUnitRewrite rewrite) {
    fInsert= insert;
    fContext= context;
    fRewrite= rewrite;
    fUnit= unit;
    fGenerator= generator;
  }

  public void run(IProgressMonitor monitor) throws CoreException {
    if (monitor == null)
      monitor= new NullProgressMonitor();
    try {
      monitor.beginTask("", 1); //$NON-NLS-1$
      monitor.setTaskName(CodeGenerationMessages.GenerateToStringOperation_description);


      AbstractTypeDeclaration declaration= (AbstractTypeDeclaration)ASTNodes.findDeclaration(fContext.getTypeBinding(), fRewrite.getRoot());
      ListRewrite rewriter= fRewrite.getASTRewrite().getListRewrite(declaration, declaration.getBodyDeclarationsProperty());
      if (fContext.getTypeBinding() != null && rewriter != null) {

        MethodDeclaration toStringMethod= fGenerator.generateToStringMethod();

        final List list= (List)declaration.getStructuralProperty(declaration.getBodyDeclarationsProperty());
        BodyDeclaration replace= findMethodToReplace(list, toStringMethod);
        if (replace == null || ((Boolean)toStringMethod.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)).booleanValue())
          insertMethod(toStringMethod, rewriter, replace);

        List helperMethods= fGenerator.generateHelperMethods();
        for (Iterator iterator= helperMethods.iterator(); iterator.hasNext();) {
          MethodDeclaration method= (MethodDeclaration)iterator.next();
          replace= findMethodToReplace(list, method);
          if (replace == null || ((Boolean)method.getProperty(AbstractToStringGenerator.OVERWRITE_METHOD_PROPERTY)).booleanValue()) {
            insertMethod(method, rewriter, replace);
          }
        }

        JavaModelUtil.applyEdit((ICompilationUnit)fUnit.getJavaElement(), fRewrite.createChange().getEdit(), false, monitor);
      }

    } finally {
      monitor.done();
    }
  }

  /**
   * @return RefactoringStatus with eventual errors and warnings
   */
  public RefactoringStatus checkConditions() {
    return fGenerator.checkConditions();
  }



  protected void insertMethod(MethodDeclaration method, ListRewrite rewriter, BodyDeclaration replace) throws JavaModelException {
    if (replace != null) {
      rewriter.replace(replace, method, null);
    } else {
      ASTNode insertion= StubUtility2.getNodeToInsertBefore(rewriter, fInsert);
      if (insertion != null)
        rewriter.insertBefore(method, insertion, null);
      else
        rewriter.insertLast(method, null);
    }
  }

  /**
   * Determines if given method exists in a given list
   * 
   * @param list list of method to search through
   * @param method method to find
   * @return declaration of method from the list that has the same name and parameter types, or
   *         null if not found
   */
  protected BodyDeclaration findMethodToReplace(final List list, MethodDeclaration method) {
    for (final Iterator iterator= list.iterator(); iterator.hasNext();) {
      final BodyDeclaration bodyDecl= (BodyDeclaration)iterator.next();
      if (bodyDecl instanceof MethodDeclaration) {
        final MethodDeclaration method2= (MethodDeclaration)bodyDecl;
        if (method2.getName().getIdentifier().equals(method.getName().getIdentifier()) && method2.parameters().size() == method.parameters().size()) {
          Iterator iterator1= method.parameters().iterator();
          Iterator iterator2= method2.parameters().iterator();
          boolean ok= true;
          while (iterator1.hasNext()) {
            if (!((SingleVariableDeclaration)iterator1.next()).getType().subtreeMatch(new ASTMatcher(), ((SingleVariableDeclaration)iterator2.next()).getType())) {
              ok= false;
              break;
            }
          }
          if (ok)
            return method2;
        }
      }
    }
    return null;
  }

  public ISchedulingRule getSchedulingRule() {
    return ResourcesPlugin.getWorkspace().getRoot();
  }

  public static final int STRING_CONCATENATION= 0;

  public static final int STRING_BUILDER= 1;

  public static final int STRING_BUILDER_CHAINED= 2;

  public static final int STRING_FORMAT= 3;

  public static final int CUSTOM_BUILDER= 4;

  private final static String[] hardcoded_styles= {
      CodeGenerationMessages.GenerateToStringOperation_stringConcatenation_style_name,
      CodeGenerationMessages.GenerateToStringOperation_stringBuilder_style_name,
      CodeGenerationMessages.GenerateToStringOperation_StringBuilder_chained_style_name,
      CodeGenerationMessages.GenerateToStringOperation_string_format_style_name,
      CodeGenerationMessages.GenerateToStringOperation_customStringBuilder_style_name
      };

  /**
   * @return Array containing names of implemented code styles
   */
  public static String[] getStyleNames() {
    return hardcoded_styles;
  }

  /**
   * 
   * @param toStringStyle id number of the code style (its position in the array returned by
   *            {@link #getStyleNames()}
   * @return a toString() generator implementing given code style
   */
  private static AbstractToStringGenerator createToStringGenerator(int toStringStyle) {
    switch (toStringStyle) {
      case STRING_CONCATENATION:
        return new StringConcatenationGenerator();
      case STRING_BUILDER:
        return new StringBuilderGenerator();
      case STRING_BUILDER_CHAINED:
        return new StringBuilderChainGenerator();
      case STRING_FORMAT:
        return new StringFormatGenerator();
      case CUSTOM_BUILDER:
        return new CustomBuilderGenerator();
      default:
        throw new IllegalArgumentException("Undefined toString() code style: " + toStringStyle); //$NON-NLS-1$
    }
  }

  /**
   * @param toStringStyle id number of the style (its position in the array returned by
   *            {@link #getStyleNames()}
   * @return a template parser that should be used with given code style
   */
  public static ToStringTemplateParser createTemplateParser(int toStringStyle) {
    return new ToStringTemplateParser();
  }

  /**
   * Creates new <code>GenerateToStringOperation</code>, using <code>settings.toStringStyle</code>
   * field to choose the right subclass.
   * 
   * @param typeBinding binding for the type for which the toString() method will be created
   * @param selectedBindings bindings for the typetype's members to be used in created method
   * @param unit a compilation unit containing the type
   * @param elementPosition at this position in the compilation unit created method will be added
   * @param settings the settings for toString() generator
   * @return a ready to use <code>GenerateToStringOperation</code> object
   */
  public static GenerateToStringOperation createOperation(ITypeBinding typeBinding, Object[] selectedBindings, CompilationUnit unit, IJavaElement elementPosition,
      ToStringGenerationSettings settings) {
    AbstractToStringGenerator generator= createToStringGenerator(settings.toStringStyle);
    ToStringTemplateParser parser= createTemplateParser(settings.toStringStyle);
    parser.parseTemplate(settings.stringFormatTemplate);
    CompilationUnitRewrite rewrite= new CompilationUnitRewrite((ICompilationUnit)unit.getTypeRoot(), unit);
    ToStringGenerationContext context= new ToStringGenerationContext(parser, selectedBindings, settings, typeBinding, rewrite);
    generator.setContext(context);
    return new GenerateToStringOperation(elementPosition, context, generator, unit, rewrite);
  }


}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.