package de.lmu.ifi.dbs.elki.utilities.pairs;

import java.util.Comparator;

/**
 * Pair with canonical comparison function derived from generics.
 * 
 * @author Erich Schubert
 * 
 * @param <FIRST> first type
 * @param <SECOND> second type
 */
public class CPair<FIRST extends Comparable<FIRST>, SECOND extends Comparable<SECOND>> extends FCPair<FIRST, SECOND> {
  /**
   * Initialize pair
   * 
   * @param first first parameter
   * @param second second parameter
   */
  public CPair(FIRST first, SECOND second) {
    super(first, second);
  }

  /**
   * Generic derived compare function.
   * 
   * @param other Object to compare to
   * @return comparison result
   */
  public int compareTo(CPair<FIRST, SECOND> other) {
    // try comparing by first
    int delta1 = super.compareTo(other);
    if (delta1 != 0) {
      return delta1;
    }
    // try comparing by second
    if(this.second != null) {
      if(other.second == null) {
        return -1;
      }
      int delta2 = this.second.compareTo(other.second);
      if(delta2 != 0) {
        return delta2;
      }
    }
    else if(other.second != null) {
      return +1;
    }
    return 0;
  }

  /**
   * Generic derived compare function, with swapped components.
   * 
   * @param other Object to compare to
   * @return comparison result
   */
  public int compareSwappedTo(CPair<FIRST, SECOND> other) {
    // try comparing by second
    if(this.second != null) {
      if(other.second == null) {
        return -1;
      }
      int delta2 = this.second.compareTo(other.second);
      if(delta2 != 0) {
        return delta2;
      }
    }
    else if(other.second != null) {
      return +1;
    }
    // try comparing by first
    return super.compareTo(other);
  }

  /**
   * Array constructor for generics
   * 
   * @param <F> First type
   * @param <S> Second type
   * @param size Size of array to be constructed
   * @return New array of requested size
   */
  @SuppressWarnings("unchecked")
  public static final <F extends Comparable<F>, S extends Comparable<S>> CPair<F, S>[] newArray(int size) {
    return new CPair[size];
  }
  
  /**
   * Class to do a canonical swapped comparison on this class.
   * 
   * @param <FIRST>
   * @param <SECOND>
   */
  public final static class CompareSwapped<FIRST extends Comparable<FIRST>, SECOND extends Comparable<SECOND>> implements Comparator<CPair<FIRST,SECOND>> {
    /**
     * Compare by second component, using the ComparableSwapped interface.
     * 
     * @param o1 First object
     * @param o2 Second object
     */
    @Override
    public int compare(CPair<FIRST,SECOND> o1, CPair<FIRST,SECOND> o2) {
      return o1.compareSwappedTo(o2);
    }

  }
}

@@ -332,17 +332,58 @@
 extends 
-F
+Pair%3CFIRST, SECOND%3E implements Comparable%3C
 CPair%3CFI
@@ -386,24 +386,24 @@
 r%3CFIRST,
- 
 SECOND%3E
+%3E
  %7B%0A  /**
@@ -788,24 +788,114 @@
 ng by first%0A
+    if(this.first != null) %7B%0A      if(other.first == null) %7B%0A        return -1;%0A      %7D%0A  
     int delt
@@ -899,21 +899,26 @@
 elta1 = 
-super
+this.first
 .compare
@@ -929,18 +929,25 @@
 ther
+.first
 );%0A    
+  
 if
- 
 (del
@@ -954,24 +954,26 @@
 ta1 != 0) %7B%0A
+  
       return
@@ -981,16 +981,82 @@
 delta1;%0A
+      %7D%0A    %7D%0A    else if(other.first != null) %7B%0A      return +1;%0A
     %7D%0A  
@@ -1916,37 +1916,277 @@
     
-return super.compareTo(other)
+if(this.first != null) %7B%0A      if(other.first == null) %7B%0A        return -1;%0A      %7D%0A      int delta1 = this.first.compareTo(other.first);%0A      if(delta1 != 0) %7B%0A        return delta1;%0A      %7D%0A    %7D%0A    else if(other.first != null) %7B%0A      return +1;%0A    %7D%0A    return 0
 ;%0A  
@@ -2564,11 +2564,9 @@
   %7D%0A
-  
 %0A
+
   /*
@@ -2820,32 +2820,33 @@
 tor%3CCPair%3CFIRST,
+ 
 SECOND%3E%3E %7B%0A    /
@@ -3041,32 +3041,33 @@
 are(CPair%3CFIRST,
+ 
 SECOND%3E o1, CPai
@@ -3070,24 +3070,25 @@
 CPair%3CFIRST,
+ 
 SECOND%3E o2) 

Fix CPair comparable (can not be a subclass of FCPair!)