~/home of geeks

Dynamischer Bohnenvergleich

· 355 Wörter · 2 Minute(n) Lesedauer

Häufig muss man Datenstrukturen sortieren. Hierbei bedient sich Java der Implementierungen des Interfaces java.util.Comparator. Möchte man ein Array von Objekten nach einer Property sortieren, so kann man den Vergleich dieser implementieren. Oder man bedient sich des Werkzeugkastens Commons-BeanUtils von Apache und schreibt einen PropertyComparator, der die zu vergleichende Property einfach als String entgegennimmt.

Der folgende Comparator benutzt mehrere Strategien, um die Properties zweier Beans miteinander zu vergleichen. Dabei wird die zu vergleichende Property als String übergeben:

Collections.sort(domainobjects, new BeanPropertyComparator("id"));

Sind die verglichenen Attribute (hier “id”, z. B. Long) ermittelt, kann z. B. ein im Konstruktor mit übergebener Comparator auf die Attributwerte angewendet werden:

Collections.sort(domainobjects, new BeanPropertyComparator("id", new LongComparator()));

Ist kein eigener Comparator für die Attributwerte gegeben, wird zuerst untersucht, ob die Attribute das Interface Comparable implementieren. Ist dies der Fall, wird über dieses Interface verglichen. Ansonsten wird versucht, einen PropertyEditor zu finden, der den Attributwert in einen String umwandelt, um diese per Collator zu vergleichen. Geht dies auch nicht, wird einfach per String.valueOf() eine String-Repräsentation des Attributwertes erstellt und diese per Collator verglichen.

import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import org.apache.commons.beanutils.PropertyUtils;
import java.text.Collator;
import java.util.Comparator;

/**
 * @author M. Serhat Cinar
 */
public class BeanPropertyComparator implements Comparator {
  private Comparator propertyComparator;
  private String property;
  private Collator collator = Collator.getInstance();
  
  public BeanPropertyComparator(String property){
    this.property = property;
  }
  
  public BeanPropertyComparator(String property, Comparator propertyComparator){
    this.property = property;
    this.propertyComparator = propertyComparator;
  }
  
  /**
   * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
   * @throws RuntimeException
   */
  @SuppressWarnings({ "unchecked", "cast" })
  public int compare(Object o1, Object o2) {
    try {
      final Object p1 = PropertyUtils.getProperty(o1, property);
      final Object p2 = PropertyUtils.getProperty(o2, property);
      if (p1==null && p2==null){
        return 0;
      }
      if (p1==null){
        return -1;
      }
      if (p2==null){
        return +1;
      }
      if (propertyComparator!=null){
        return propertyComparator.compare(p1, p2);
      }
      if (p1 instanceof Comparable && p2 instanceof Comparable){
        return ((Comparable) p1).compareTo((Comparable)p2);
      }
      final Object value1 = PropertyUtils.getProperty(o1, property);
      final Object value2 = PropertyUtils.getProperty(o2, property);
      final PropertyEditor pe1 = 
        PropertyEditorManager.findEditor(value1.getClass());
      final PropertyEditor pe2 = 
        PropertyEditorManager.findEditor(value2.getClass());
      String s1, s2;
      if (pe1!=null && pe2!=null){
        pe1.setValue(value1);
        s1 = pe1.getAsText();
        pe2.setValue(value2);
        s2 = pe2.getAsText();
      }
      else{
        s1 = String.valueOf(value1);
        s2 = String.valueOf(value2);
      }
      return collator.compare(s1, s2);
    }
    catch(Exception e){
      throw new RuntimeException(e);
    }
  }
}