/**
  * Called after top level methods (and other items) have been moved from entries to
  * ruleInstanceList. Task now is to scan ruleInstanceList looking for MethodEntry objects with
  * dependent (related, extracted) methods. Move these from the entries list to the correct place
  * in the ruleInstanceList list.
  *
  * @param entries Remaining (unarranged) items, including all dependent (extracted) methods.
  * @param ruleInstance Rule containing parents (callers) of potentially related methods
  */
 public static void rearrangeRelatedItems(
     List<ClassContentsEntry> entries, RuleInstance ruleInstance, RelatedMethodsSettings rms) {
   List<RangeEntry> parentEntries = new ArrayList<RangeEntry>(ruleInstance.getMatches());
   for (RangeEntry o : parentEntries) {
     if (o instanceof RelatableEntry) {
       MethodEntry me = (MethodEntry) o;
       if (me.isGetter()) {
         if (me.myKeptWithProperty) {
           if (me.getMatchedRule() != null && me.getMatchedRule().getMatches() != null) {
             // prevent the getter from appearing under a rule it matches; it will be placed under
             // the property
             me.getMatchedRule().getMatches().remove(me);
           }
         }
         for (MethodEntry theSetter : me.myCorrespondingGetterSetters) {
           final RuleInstance theRule = theSetter.getMatchedRule();
           LOG.debug(
               "rearrangeRelatedItems: for getter method "
                   + me
                   + ", corresponding setter is "
                   + theSetter);
           if (theRule != null && theRule.getMatches() != null) {
             LOG.debug(
                 "remove entry "
                             + theSetter.myEnd
                             + " from matched rule"
                             + theRule
                             + "; matches = "
                             + ((java.util.List) theRule.getMatches())
                         == null
                     ? "null"
                     : "");
             theRule.getMatches().remove(theSetter);
           }
         }
       }
       if (me.myCalledMethods.size() > 0) {
         List<MethodEntry> parents = new LinkedList<MethodEntry>();
         parents.add(me);
         moveRelatedItems(
             entries,
             parents,
             rms,
             ((PsiMethod) me.myEnd).getName(),
             ((PsiMethod) me.myEnd).getName() + "()",
             1);
         if (LOG.isDebugEnabled()) {
           // dump sorted children recursively
           me.dumpChild(0);
         }
         me.assignComments(rms);
       }
     }
   }
 }
 /**
  * Move methods related to this one underneath it (beginning at the index specified.) Do so in
  * depth-first or breadth-first order, as configured. At each level, do alphabetical, original
  * order, or call order sorting.
  *
  * @param entries list of global (all rule) unmatched items including dependent methods
  * @param parents contains a list of items to be handled; order is depth or breadth-first.
  */
 private static void moveRelatedItems(
     List<ClassContentsEntry> entries,
     List<MethodEntry> parents,
     RelatedMethodsSettings rms,
     String topLevelMethodName,
     String allMethodNames,
     int level) {
   allMethodNames = buildAllMethodNamesString(allMethodNames, parents);
   /** First, identify all dependent methods. Move them to parents in the specified order. */
   List<MethodEntry> children = ((MethodEntry) parents.get(parents.size() - 1)).sortedMethods;
   //        if (rms.isDepthFirstOrdering())
   //        {
   switch (rms.getOrdering()) {
     case RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER:
       {
         /**
          * iterate through entries looking for those that are called by method(s) in the set of
          * parent methods. Add these to the list of children in order seen in entries.
          */
         ListIterator li = entries.listIterator();
         while (li.hasNext()) {
           Object o = li.next();
           if (o instanceof RelatableEntry) {
             MethodEntry me = (MethodEntry) o;
             for (MethodEntry entry : parents) {
               if (me.myCalledByMethods.contains(entry)) {
                 children.add(me);
                 li.remove();
                 break;
               }
             }
           }
         }
       }
       break;
     case RelatedMethodsSettings.ALPHABETICAL_ORDER:
       {
         /**
          * iterate through entries looking for those that are called by method(s) in the set of
          * parent methods. Add these to the list of children alphabetically.
          */
         ListIterator li = entries.listIterator();
         while (li.hasNext()) {
           Object o = li.next();
           if (o instanceof RelatableEntry) {
             MethodEntry me = (MethodEntry) o;
             for (MethodEntry entry : parents) {
               if (me.myCalledByMethods.contains(entry)) {
                 me.insertAlphabetically(children);
                 li.remove();
                 break;
               }
             }
           }
         }
       }
       break;
     case RelatedMethodsSettings.INVOCATION_ORDER:
       /**
        * iterate through calling methods, looking for remaining unmatched methods (in 'entries'
        * list). Add these to the list of children in order of invocation.
        */
       for (MethodEntry me : parents) {
         for (MethodEntry child : me.myCalledMethods) {
           if (entries.contains(child)) {
             children.add(child);
             entries.remove(child);
           }
         }
       }
       break;
   }
   /**
    * now children contains all the children of the parents for this level, and all these children
    * have been removed from "entries". Move these to the rearranged list. Then: If depth-first,
    * recurse setting the parent list to each of the children in turn. If breadth first, recurse
    * setting the parent list to all of the children.
    */
   if (children.size() > 0) {
     if (rms.isDepthFirstOrdering()) {
       for (MethodEntry entry : children) {
         if (entry.myCalledMethods.size() == 0) {
           continue;
         }
         List<MethodEntry> parent = new LinkedList<MethodEntry>();
         parent.add(entry);
         moveRelatedItems(
             entries,
             parent,
             rms,
             topLevelMethodName,
             allMethodNames + "." + ((PsiMethod) entry.myEnd).getName() + "()",
             level + 1);
       }
     } else {
       moveRelatedItems(
           entries,
           children,
           rms,
           topLevelMethodName,
           allMethodNames + ".Depth " + level,
           level + 1);
     }
   }
 }