Package edu.ohio_state.khatchad.refactoring.core

Source Code of edu.ohio_state.khatchad.refactoring.core.EnumerizationComputer

package edu.ohio_state.khatchad.refactoring.core;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;

import edu.ohio_state.khatchad.refactoring.exceptions.DefinitelyNotEnumerizableException;
import edu.ohio_state.khatchad.refactoring.exceptions.NonEnumerizableException;

public class EnumerizationComputer {
  /**
   * @param candidateSets
   * @return
   * @throws JavaModelException
   */
  public static Collection filterSetsAccordingToMemberConstraints(
      final Collection candidateSets) throws JavaModelException {

    final Collection ret = new LinkedHashSet(candidateSets);

    // make sure the values are distinct.
    final Collection distinctEnumerizableElementSets = Util
        .getDistinctSets(candidateSets);
    ret.retainAll(distinctEnumerizableElementSets);

    // make sure the fields have a consistent visibility.
    final Collection consistentEnumerizableElementSets = Util
        .getConsistentlyVisibleSets(candidateSets);
    ret.retainAll(consistentEnumerizableElementSets);

    // make sure the fields are named uniquely.
    final Collection uniquelyNamedEnumerizableElementSets = Util
        .getUniquelyNamedSets(candidateSets);
    ret.retainAll(uniquelyNamedEnumerizableElementSets);

    return ret;
  }

  private final Collection constFields;
  private final Collection defNotEnumConstants = new LinkedHashSet();

  private final Map elemToLegalInfixExpressionSourceRangeMap = new LinkedHashMap();

  private Collection enumerizationForest;

  private final IProgressMonitor monitor;

  private final Collection nonEnumerizableList = new LinkedHashSet();

  private final IJavaSearchScope scope;

  private final SearchEngine searchEngine = new SearchEngine();

  private final Worklist wl = new Worklist();

  /**
   * @param constFields
   * @param scope
   * @param monitor
   * @throws JavaModelException
   */
  public EnumerizationComputer(Collection constFields,
      IJavaSearchScope scope, IProgressMonitor monitor)
      throws JavaModelException {
    this.constFields = constFields;
    this.scope = scope;
    this.monitor = monitor;
  }

  public void compute() throws CoreException {
    this.reset();
    this.wl.addAll(this.constFields);
    while (this.wl.hasNext()) {
      final IJavaElement je = (IJavaElement) this.wl.next();
      final SearchPattern pattern = SearchPattern.createPattern(je,
          IJavaSearchConstants.ALL_OCCURRENCES,
          SearchPattern.R_EXACT_MATCH);
      final SearchRequestor requestor = new SearchRequestor() {
        public void acceptSearchMatch(SearchMatch match)
            throws CoreException {
          if (match.getAccuracy() == SearchMatch.A_ACCURATE
              && !match.isInsideDocComment()) {
            ASTNode node = Util.getExactASTNode(match,
                EnumerizationComputer.this.monitor);
            ASTNodeProcessor processor = new ASTNodeProcessor(node,
                EnumerizationComputer.this.constFields,
                EnumerizationComputer.this.scope,
                EnumerizationComputer.this.monitor);
            processor.process();
            EnumerizationComputer.this.wl.addAll(processor
                .getFound());
            Collection infixCol = (Collection) EnumerizationComputer.this.elemToLegalInfixExpressionSourceRangeMap
                .get(je);
            if (infixCol == null)
              EnumerizationComputer.this.elemToLegalInfixExpressionSourceRangeMap
                  .put(
                      je,
                      processor
                          .getLegalEncounteredInfixExpressionSourceLocations());
            else
              infixCol
                  .addAll(processor
                      .getLegalEncounteredInfixExpressionSourceLocations());
          }
        }
      };

      try {
        this.searchEngine.search(pattern,
            new SearchParticipant[] { SearchEngine
                .getDefaultSearchParticipant() }, this.scope,
            requestor, new SubProgressMonitor(this.monitor, 1,
                SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));

        // Work around for bug 164121. Force match for formal
        // parameters.
        if (je.getElementType() == IJavaElement.LOCAL_VARIABLE) {
          final ISourceRange isr = ((ILocalVariable) je)
              .getNameRange();
          final SearchMatch match = new SearchMatch(je,
              SearchMatch.A_ACCURATE, isr.getOffset(), isr
                  .getLength(), SearchEngine
                  .getDefaultSearchParticipant(), je
                  .getResource());
          requestor.acceptSearchMatch(match);
        }
      } catch (final DefinitelyNotEnumerizableException E) {
        this.defNotEnumConstants.addAll(this.wl
            .getCurrentComputationTreeElements());
        this.nonEnumerizableList.addAll(this.wl
            .getCurrentComputationTreeElements());
        this.wl.removeAll(this.nonEnumerizableList);
        for (final Iterator it = this.wl
            .getCurrentComputationTreeElements().iterator(); it
            .hasNext();) {
          final IJavaElement elem = (IJavaElement) it.next();
          this.elemToLegalInfixExpressionSourceRangeMap.remove(elem);
        }
        continue;
      }

      catch (final NonEnumerizableException E) {
        this.nonEnumerizableList.addAll(this.wl
            .getCurrentComputationTreeElements());
        this.wl.removeAll(this.nonEnumerizableList);
        for (final Iterator it = this.wl
            .getCurrentComputationTreeElements().iterator(); it
            .hasNext();) {
          final IJavaElement elem = (IJavaElement) it.next();
          this.elemToLegalInfixExpressionSourceRangeMap.remove(elem);
        }
        continue;
      }
    }

    this.defNotEnumConstants.retainAll(this.constFields);
    final Collection computationForest = Util.trimForest(this.wl
        .getComputationForest(), this.nonEnumerizableList);

    final Collection candidateSets = Util
        .getElementForest(computationForest);
   
    //[rk] HACK: merge sets for now into one big set.
    //TODO [rk] This plugin has the capability to make more than one enum type out of the input
    //constants. We should leverage that. The idea is that one button should refactor the entire
    //project.
    Collection oneBigSet = new LinkedHashSet();
    oneBigSet.add(Util.flattenForest(candidateSets));
    this.enumerizationForest = filterSetsAccordingToMemberConstraints(oneBigSet);
  }

  /**
   * @return the defNotEnumConstants
   */
  public Collection getDefNotEnumConstants() {
    return this.defNotEnumConstants;
  }

  public Map getElemToLegalInfixExpressionSourceRangeMap() {
    return this.elemToLegalInfixExpressionSourceRangeMap;
  }

  /**
   * @return the enumerizationForest
   */
  public Collection getEnumerizationForest() {
    return this.enumerizationForest;
  }

  public Collection getLegalEncounteredInfixExpressionSourceRanges() {
    final Collection ret = new LinkedHashSet();
    for (final Iterator cit = this.elemToLegalInfixExpressionSourceRangeMap
        .values().iterator(); cit.hasNext();) {
      final Collection col = (Collection) cit.next();
      ret.addAll(col);
    }
    return ret;
  }

  /**
   * @return the nonEnumerizableList
   */
  public Collection getNonEnumerizableList() {
    return this.nonEnumerizableList;
  }

  private void reset() {
    this.wl.clear();
    this.nonEnumerizableList.clear();
    this.defNotEnumConstants.clear();
  }
}
TOP

Related Classes of edu.ohio_state.khatchad.refactoring.core.EnumerizationComputer

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.