teichmann@5829: package org.dive4elements.river.model; sascha@2382: sascha@2382: import java.util.Comparator; sascha@2382: import java.util.ArrayList; sascha@2382: import java.util.List; sascha@2382: import java.util.Arrays; sascha@2382: import java.util.HashMap; sascha@2382: import java.util.Iterator; sascha@2382: import java.util.NoSuchElementException; sascha@2382: sascha@2382: import java.io.Serializable; sascha@2382: sascha@2382: import org.hibernate.Session; sascha@2382: import org.hibernate.SQLQuery; sascha@2382: sascha@2382: import org.hibernate.type.StandardBasicTypes; sascha@2382: teichmann@5829: import org.dive4elements.river.backend.SessionHolder; sascha@2382: sascha@2382: public class FastAnnotations sascha@2382: implements Serializable sascha@2382: { sascha@2382: public static final String SQL_BY_RIVER_NAME = sascha@2382: "SELECT r.a AS a, r.b AS b, p.value AS position, " + sascha@2382: "at.value AS attribute, ant.name AS name, " + sascha@2382: "e.top AS top, e.bottom AS bottom " + sascha@2382: "FROM annotations an " + sascha@2382: "JOIN ranges r " + sascha@2382: "ON an.range_id = r.id " + sascha@2382: "JOIN attributes at " + sascha@2382: "ON an.attribute_id = at.id " + sascha@2382: "JOIN positions p " + sascha@2382: "ON an.position_id = p.id " + sascha@2382: "JOIN rivers riv " + sascha@2382: "ON r.river_id = riv.id " + sascha@2382: "LEFT JOIN annotation_types ant " + sascha@2382: "ON an.type_id = ant.id " + sascha@2382: "LEFT JOIN edges e " + sascha@2382: "ON an.edge_id = e.id " + sascha@2382: "WHERE riv.name = :river_name " + sascha@2382: "ORDER BY r.a"; sascha@2382: sascha@2382: public static final String SQL_BY_RIVER_ID = sascha@2382: "SELECT r.a AS a, r.b AS b, p.value AS position, " + sascha@2382: "at.value AS attribute, ant.name AS name, " + sascha@2382: "e.top AS top, e.bottom AS bottom " + sascha@2382: "FROM annotations an " + sascha@2382: "JOIN ranges r " + sascha@2382: "ON an.range_id = r.id " + sascha@2382: "JOIN attributes at " + sascha@2382: "ON an.attribute_id = at.id " + sascha@2382: "JOIN positions p " + sascha@2382: "ON an.position_id = p.id " + sascha@2382: "LEFT JOIN annotation_types ant " + sascha@2382: "ON an.type_id = ant.id " + sascha@2382: "LEFT JOIN edges e " + sascha@2382: "ON an.edge_id = e.id " + sascha@2382: "WHERE r.id = :river_id " + sascha@2382: "ORDER BY r.a"; sascha@2382: sascha@2382: public static final double EPSILON = 1e-5; sascha@2382: sascha@2382: public static final Comparator KM_CMP = sascha@2382: new Comparator() { sascha@2382: @Override sascha@2382: public int compare(Annotation a, Annotation b) { sascha@2382: double diff = a.a - b.a; sascha@2382: if (diff < -EPSILON) return -1; sascha@2382: if (diff > +EPSILON) return +1; sascha@2382: return 0; sascha@2382: } sascha@2382: }; sascha@2382: sascha@2382: public static final class Annotation sascha@2382: implements Serializable sascha@2382: { sascha@2382: private double a; sascha@2382: private double b; sascha@2382: private String position; sascha@2382: private String attribute; sascha@2382: private String name; sascha@2382: private double top; sascha@2382: private double bottom; sascha@2382: sascha@2382: public Annotation() { sascha@2382: } sascha@2382: sascha@2382: public Annotation(double a) { sascha@2382: this.a = a; sascha@2382: } sascha@2382: sascha@2382: public Annotation( sascha@2382: double a, sascha@2382: double b, sascha@2382: String position, sascha@2382: String attribute, sascha@2382: String name, sascha@2382: double top, sascha@2382: double bottom sascha@2382: ) { sascha@2382: this.a = a; sascha@2382: this.b = b; sascha@2382: this.position = position; sascha@2382: this.attribute = attribute; sascha@2382: this.name = name; sascha@2382: this.top = top; sascha@2382: this.bottom = bottom; sascha@2382: } sascha@2382: sascha@2382: public double getA() { sascha@2382: return a; sascha@2382: } sascha@2382: sascha@2382: public double getB() { sascha@2382: return b; sascha@2382: } sascha@2382: sascha@2382: public String getPosition() { sascha@2382: return position; sascha@2382: } sascha@2382: sascha@2382: public String getAttribute() { sascha@2382: return attribute; sascha@2382: } sascha@2382: sascha@2382: public String getName() { sascha@2382: return name; sascha@2382: } sascha@2382: sascha@2382: public double getTop() { sascha@2382: return top; sascha@2382: } sascha@2382: sascha@2382: public double getBottom() { sascha@2382: return bottom; sascha@2382: } sascha@3653: sascha@3653: @Override sascha@3653: public String toString() { sascha@3653: return "[a=" + a + ";b=" + b + sascha@3653: ";pos=" + position + ";attr=" + attribute + sascha@3653: ";name=" + name + ";top=" + top + sascha@3653: ";bot=" + bottom + "]"; sascha@3653: } felix@3323: } // class Annotation sascha@2382: sascha@2382: public interface Filter { sascha@2382: sascha@2382: boolean accept(Annotation annotation); sascha@2382: sascha@2382: } // interface Filter sascha@2382: sascha@3325: public static class NameFilter implements Filter { raimund@3324: raimund@3324: private String name; raimund@3324: sascha@3325: public NameFilter(String name) { raimund@3324: this.name = name; raimund@3324: } raimund@3324: sascha@3325: @Override sascha@3325: public boolean accept(Annotation annotation) { raimund@3324: return annotation.getName().contains(name); raimund@3324: } sascha@3325: } // class NameFilter raimund@3324: sascha@2382: public static final Filter ALL = new Filter() { sascha@2382: @Override sascha@2382: public boolean accept(Annotation annotation) { sascha@2382: return true; sascha@2382: } sascha@2382: }; sascha@2382: sascha@2382: public static final Filter IS_POINT = new Filter() { sascha@2382: @Override sascha@2382: public boolean accept(Annotation annotation) { sascha@2382: return Double.isNaN(annotation.getB()); sascha@2382: } sascha@2382: }; sascha@2382: sascha@2382: public static final Filter IS_RANGE = new Filter() { sascha@2382: @Override sascha@2382: public boolean accept(Annotation annotation) { sascha@2382: return !Double.isNaN(annotation.getB()); sascha@2382: } sascha@2382: }; sascha@2382: sascha@2382: private Annotation [] annotations; sascha@2382: sascha@2382: public FastAnnotations() { sascha@2382: } sascha@2382: sascha@2382: public FastAnnotations(Annotation [] annotations) { sascha@2382: this.annotations = annotations; sascha@2382: } sascha@2382: sascha@2382: public FastAnnotations(String riverName) { sascha@2382: this(loadByRiverName(riverName)); sascha@2382: } sascha@2382: sascha@2382: public FastAnnotations(int riverId) { sascha@2382: this(loadByRiverId(riverId)); sascha@2382: } sascha@2382: sascha@2382: public FastAnnotations(Iterator iter) { sascha@2382: this(toArray(iter)); sascha@2382: } sascha@2382: sascha@2382: public int size() { sascha@2382: return annotations.length; sascha@2382: } sascha@2382: sascha@2382: public Iterator filter(final Filter filter) { sascha@2382: return new Iterator() { sascha@2382: sascha@2382: private int idx; sascha@2382: private Annotation current = findNext(); sascha@2382: sascha@3334: @Override sascha@2382: public boolean hasNext() { sascha@2382: return current != null; sascha@2382: } sascha@2382: sascha@2382: @Override sascha@2382: public Annotation next() { sascha@2382: if (current == null) { sascha@2382: throw new NoSuchElementException(); sascha@2382: } sascha@2382: Annotation result = current; sascha@2382: current = findNext(); sascha@2382: return result; sascha@2382: } sascha@2382: sascha@2382: private Annotation findNext() { sascha@2382: sascha@2382: while (idx < annotations.length) { sascha@2382: Annotation annotation = annotations[idx++]; sascha@2382: if (filter.accept(annotation)) { sascha@2382: return annotation; sascha@2382: } sascha@2382: } sascha@2382: sascha@2382: return null; sascha@2382: } sascha@2382: sascha@2382: @Override sascha@2382: public void remove() { sascha@2382: throw new UnsupportedOperationException(); sascha@2382: } sascha@2382: }; sascha@2382: } sascha@2382: sascha@2382: public static Annotation [] toArray(Iterator iter) { sascha@2382: sascha@2382: ArrayList list = new ArrayList(); sascha@2382: sascha@2382: while (iter.hasNext()) { sascha@2382: list.add(iter.next()); sascha@2382: } sascha@2382: sascha@2382: return list.toArray(new Annotation[list.size()]); sascha@2382: } sascha@2382: sascha@2382: public Annotation findByKm(double km) { sascha@2382: Annotation key = new Annotation(km); sascha@2382: int idx = Arrays.binarySearch(annotations, key, KM_CMP); sascha@2382: return idx < 0 ? null : annotations[idx]; sascha@2382: } sascha@2382: sascha@2382: private static SQLQuery createQuery(String query) { sascha@2382: Session session = SessionHolder.HOLDER.get(); sascha@2382: sascha@2382: return session.createSQLQuery(query) sascha@2382: .addScalar("a", StandardBasicTypes.DOUBLE) sascha@2382: .addScalar("b", StandardBasicTypes.DOUBLE) sascha@2382: .addScalar("position", StandardBasicTypes.STRING) sascha@2382: .addScalar("attribute", StandardBasicTypes.STRING) sascha@2382: .addScalar("name", StandardBasicTypes.STRING) sascha@2382: .addScalar("top", StandardBasicTypes.DOUBLE) sascha@2382: .addScalar("bottom", StandardBasicTypes.DOUBLE); sascha@2382: } sascha@2382: sascha@2382: private static Annotation [] buildAnnotations(List list) { sascha@2382: Annotation [] anns = new Annotation[list.size()]; sascha@2382: sascha@2382: // Names are likely the same because they are a type sascha@2382: // like 'Pegel' or 'Hafen'. sascha@2382: HashMap names = new HashMap(); sascha@2382: sascha@2382: for (int i = 0; i < anns.length; ++i) { sascha@2382: Object [] data = list.get(i); sascha@2382: double a = ((Double)data[0]); sascha@2382: double b = data[1] != null ? (Double)data[1] : Double.NaN; sascha@2382: String position = (String)data[2]; sascha@2382: String attribute = (String)data[3]; sascha@2382: String name = (String)data[4]; sascha@2382: double top = data[5] != null ? (Double)data[5] : Double.NaN; sascha@2382: double bottom = data[6] != null ? (Double)data[6] : Double.NaN; sascha@2382: sascha@2382: if (name != null) { sascha@2382: String old = names.get(name); sascha@2382: if (old != null) { sascha@2382: name = old; sascha@2382: } sascha@2382: else { sascha@2382: names.put(name, name); sascha@2382: } sascha@2382: } sascha@2382: sascha@2382: anns[i] = new Annotation( sascha@2382: a, b, position, attribute, name, top, bottom); sascha@2382: } sascha@2382: sascha@2382: return anns; sascha@2382: } sascha@2382: sascha@2382: public static Annotation [] loadByRiverName(String riverName) { sascha@2382: sascha@2382: SQLQuery query = createQuery(SQL_BY_RIVER_NAME); sascha@2382: sascha@2382: query.setString("river_name", riverName); sascha@2382: sascha@2382: return buildAnnotations(query.list()); sascha@2382: } sascha@2382: sascha@2382: public static Annotation [] loadByRiverId(int riverId) { sascha@2382: sascha@2382: SQLQuery query = createQuery(SQL_BY_RIVER_ID); sascha@2382: sascha@2382: query.setInteger("river_id", riverId); sascha@2382: sascha@2382: return buildAnnotations(query.list()); sascha@2382: } sascha@2382: } sascha@2382: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :