]> git.uio.no Git - ifi-stolz-refaktor.git/blobdiff - case-study/refaktor-before/src/no/uio/ifi/refaktor/analyze/analyzers/ExtractAndMoveMethodAnalyzer.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / refaktor-before / src / no / uio / ifi / refaktor / analyze / analyzers / ExtractAndMoveMethodAnalyzer.java
diff --git a/case-study/refaktor-before/src/no/uio/ifi/refaktor/analyze/analyzers/ExtractAndMoveMethodAnalyzer.java b/case-study/refaktor-before/src/no/uio/ifi/refaktor/analyze/analyzers/ExtractAndMoveMethodAnalyzer.java
new file mode 100644 (file)
index 0000000..7df5c04
--- /dev/null
@@ -0,0 +1,124 @@
+package no.uio.ifi.refaktor.analyze.analyzers;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import no.uio.ifi.refaktor.analyze.CollectorManager;
+import no.uio.ifi.refaktor.analyze.checkers.LegalStatementsChecker;
+import no.uio.ifi.refaktor.analyze.collectors.PrefixesCollector;
+import no.uio.ifi.refaktor.analyze.collectors.UnfixesCollector;
+import no.uio.ifi.refaktor.analyze.exceptions.NoTargetFoundException;
+import no.uio.ifi.refaktor.analyze.exceptions.RefaktorAnalyzerException;
+import no.uio.ifi.refaktor.change.changers.ExtractAndMoveMethodChanger;
+import no.uio.ifi.refaktor.prefix.Prefix;
+import no.uio.ifi.refaktor.prefix.PrefixSet;
+import no.uio.ifi.refaktor.textselection.CompilationUnitTextSelection;
+
+import org.eclipse.jdt.core.dom.IVariableBinding;
+
+//TODO: rewrite docs
+/**
+ * A property extractor that collects all the expression prefixes within a selection
+ * (see {@link PrefixesCollector}) that forms the base for calculating the
+ * candidates for the move refactoring, and also the unfixes 
+ * that are non-candidates for the move refactoring. 
+ * 
+ * The set of prefixes that are not enclosing any unfixes is put in the set of safe prefixes.
+ * This set is used by an Extract and Move Method refactoring to find a suitable target
+ * for the Move Method. 
+ * 
+ * The class is typically used by the {@link ExtractAndMoveMethodChanger}.
+ */
+public class ExtractAndMoveMethodAnalyzer implements Analyzer {
+
+       private final CompilationUnitTextSelection selection;
+       private final PrefixesCollector prefixesCollector;
+       private final UnfixesCollector unfixesCollector;
+
+       public ExtractAndMoveMethodAnalyzer(CompilationUnitTextSelection selection) {
+               this.selection = selection;
+               prefixesCollector = new PrefixesCollector(selection);
+               unfixesCollector = new UnfixesCollector(selection);
+       }
+
+       public PrefixSet calculateSafePrefixes() {
+               PrefixSet safePrefixes = prefixesCollector.getPrefixes().minusEnclosedPrefixesFrom(unfixesCollector.getUnfixes());
+               removeUnusablePrefixes(safePrefixes);
+               return safePrefixes;
+       }
+
+       private void removeUnusablePrefixes(PrefixSet safePrefixes) {
+               for (Iterator<Prefix> iter = safePrefixes.iterator(); iter.hasNext();) {
+                       if (prefixHasSimpleExpressionAndOnlyOneOccurrence(iter.next()))
+                               iter.remove();
+               }
+       }
+
+       private boolean prefixHasSimpleExpressionAndOnlyOneOccurrence(Prefix prefix) {
+               return prefix.getNumberOfSegments() == 1 && prefix.getCount() == 1;
+       }
+       
+       protected PrefixSet getPrefixes() {
+               return prefixesCollector.getPrefixes();
+       }
+
+       public PrefixSet getUnfixes() {
+               return unfixesCollector.getUnfixes();
+       }
+
+       public void checkPreconditions() throws RefaktorAnalyzerException {
+               SelectionValidator.checkIfSelectionIsValid(selection);
+               analyze();
+               checkIfUsefulTargetFound();
+       }
+
+       private void checkIfUsefulTargetFound() {
+               if (!hasUsefulResults())
+                       throw new NoTargetFoundException();
+       }
+
+       public boolean hasUsefulResults() {
+               return !calculateSafePrefixes().isEmpty();
+       }
+
+       @Override
+       public void analyze() throws RefaktorAnalyzerException {
+               LegalStatementsChecker legalStatementsChecker = new LegalStatementsChecker(selection);
+               if (legalStatementsChecker.allStatementsAreLegal())
+                       CollectorManager.collectProperties(selection, prefixesCollector, unfixesCollector);
+       }
+
+       public IVariableBinding calculateOriginalTarget() {
+               return calculateMostFrequentPrefix().getVariableBindingOfFirstExpression();
+       }
+
+       public Prefix calculateMostFrequentPrefix() {
+               LinkedList<Prefix> listOfSafePrefixes = calculateListOfSafePrefixes();
+               sortAscendingByCountAndLength(listOfSafePrefixes);
+               return listOfSafePrefixes.getLast();
+       }
+
+       private LinkedList<Prefix> calculateListOfSafePrefixes() {
+               return calculateSafePrefixes().toList();
+       }
+
+       private void sortAscendingByCountAndLength(LinkedList<Prefix> values) {
+               Collections.sort(values, new Comparator<Prefix>() {
+                       @Override
+                       public int compare(Prefix p1, Prefix p2) {
+                               if (p1.getCount() > p2.getCount()) {
+                                       return 1;
+                               } else if (p1.getCount() < p2.getCount()) {
+                                       return -1;
+                               } else if (p1.length() > p2.length()) {
+                                       return 1;
+                               } else if (p1.length() < p2.length()) {
+                                       return -1;
+                               }
+                               return 0;
+                       }
+               });
+       }
+}