title: Refactoring generic compareTo method
body: <h2>What am I doing:</h2>
  
  <p>I have a container class named <code>Os</code>, that can contains different type elements and also instances of class <code>Os</code>. When I compare this class, I want to see :</p>
  
  <ul>
  <li>shallow equals for elements</li>
  <li>deep equals for <code>Os</code> elements</li>
  </ul>
  
  <p>I have ensured, that every single element contained in class:</p>
  
  <ul>
  <li>Can not be null.</li>
  <li>Is comparable to same type elements.</li>
  <li>Is immutable. Well, at least part that I'm checking.</li>
  </ul>
  
  <p>Following is what I have at the moment. </p>
  
  <h2>Example:</h2>
  
  <p>For example, this test case will pass.</p>
  
  <pre><code>    Os o1 = Os.of(3, 4d, Os.of("-"));
      Os o2 = Os.of(Os.of(Character.toString('-')), 4.0, new Integer(3));
  
      assertEquals(o1.toString(), "[3, 4.0, [-]]");
      assertEquals(o2.toString(), "[[-], 4.0, 3]");
      assertTrue(o1.reverse().compareTo(o2) == 0);
  </code></pre>
  
  <h2>Code example:</h2>
  
  <p><code>compareTo</code> method:</p>
  
  <pre><code>@Override
  public int compareTo(final Os that) {
      final int BEFORE = -1;
      final int EQUAL = 0;
      final int AFTER = 1;
      int subresult = 0;
      Comparable&lt;?&gt; othis;
      Comparable&lt;?&gt; othat;
  
      if (that == null)
          return AFTER;
      if (this == that)
          return EQUAL;
  
      subresult = ((Integer) this.o.size()).compareTo(that.o.size());
      if (subresult &lt; 0)
          return BEFORE;
      else if (subresult &gt; 0)
          return AFTER;
  
      try {
          for (int i = 0; i &lt; this.o.size(); i++) {
              othis = this.o.get(i);
              othat = that.o.get(i);
  
              if (othis.getClass() == othat.getClass()) {
                  if (othat instanceof Os) {
                      subresult = ((Os) othis).compareTo(((Os) othat));
                      if (subresult &lt; 0)
                          return BEFORE;
                      else if (subresult &gt; 0)
                          return AFTER;
                  } else {
                      subresult = hackCMP(othis, othat);
                      if (subresult &lt; 0)
                          return BEFORE;
                      else if (subresult &gt; 0)
                          return AFTER;
                  }
              } else {
                  subresult = othis.getClass().getName()
                          .compareTo(othat.getClass().getName());
                  if (subresult &lt; 0)
                      return BEFORE;
                  else if (subresult &gt; 0)
                      return AFTER;
              }
          }
          return EQUAL;
      } catch (SecurityException e) {
          e.printStackTrace();
      } catch (IllegalArgumentException e) {
          e.printStackTrace();
      } catch (NoSuchMethodException e) {
          e.printStackTrace();
      } catch (IllegalAccessException e) {
          e.printStackTrace();
      } catch (InvocationTargetException e) {
          e.printStackTrace();
      }
      return BEFORE;
  }
  
  private static int hackCMP(Object val, Object val2)
          throws SecurityException, NoSuchMethodException,
          IllegalArgumentException, IllegalAccessException,
          InvocationTargetException {
      Method m = val.getClass().getMethod("compareTo", val.getClass());
      return (Integer) m.invoke(val, val2);
  }
  </code></pre>
  
  <h2>Question:</h2>
  
  <p>I would like to refactor the code. </p>
  
  <p>For example: </p>
  
  <ul>
  <li>I would prefer not using <code>hackCMP</code> method, if possible.</li>
  <li><p>Following code segment seems to repeat itself a lot. Can I replace it with something?</p>
  
  <pre><code>        subresult = &lt;expression&gt;;
          if (subresult &lt; 0)
              return BEFORE;
          else if (subresult &gt; 0)
              return AFTER;
          //else ...
  </code></pre></li>
  </ul>
  
  <p>What can I refactor and how to do it? </p>
  
  <h2>Edit:</h2>
  
  <p>@wolfcastle : Data is stored in <code>private final ImmutableList&lt;Comparable&lt;?&gt;&gt; o;</code>.</p>
  
  <p>I'd like to mention, that every answer was useful. Following seems to work:</p>
  
  <pre><code>@Override
  public int compareTo(final Os that) {
      Ordering&lt;Iterable&lt;Comparable&lt;?&gt;&gt;&gt; order = //
      Ordering.natural().&lt;Comparable&lt;?&gt;&gt; lexicographical();
      int result = -1;
  
      try {
          result = ComparisonChain.start()
                  .compare(this.o.size(), that.o.size())
                  .compare(this.o, that.o, order).result();
      } catch (Exception e) { //ignore: type mismatch
      }
  
      return result;
  }
  </code></pre>