ingo@1115: /* ingo@1115: * Copyright (c) 2010 by Intevation GmbH ingo@1115: * ingo@1115: * This program is free software under the LGPL (>=v2.1) ingo@1115: * Read the file LGPL.txt coming with the software for details ingo@1115: * or visit http://www.gnu.org/licenses/ if it does not exist. ingo@1115: */ ingo@1115: ingo@617: package de.intevation.gnv.histogram; ingo@617: ingo@1081: import de.intevation.artifacts.CallContext; ingo@1081: ingo@1081: import de.intevation.gnv.artifacts.ressource.RessourceFactory; ingo@1081: ingo@1081: import de.intevation.gnv.chart.ChartLabels; ingo@1081: ingo@617: import de.intevation.gnv.geobackend.base.Result; ingo@617: import de.intevation.gnv.geobackend.base.ResultDescriptor; ingo@617: ingo@617: import de.intevation.gnv.state.describedata.KeyValueDescibeData; ingo@617: ingo@617: import java.util.ArrayList; ingo@617: import java.util.Collection; ingo@617: import java.util.Iterator; ingo@617: import java.util.List; ingo@1081: import java.util.Locale; ingo@617: ingo@617: import org.apache.log4j.Logger; ingo@617: ingo@617: /** ingo@770: * This class supports some helper methods for histogram charts. ingo@770: * ingo@770: * @author Ingo Weinzierl ingo@617: */ ingo@617: public class HistogramHelper { ingo@617: ingo@770: /** ingo@770: * Logger used for logging with log4j. ingo@770: */ ingo@617: private static Logger logger = Logger.getLogger(HistogramHelper.class); ingo@617: ingo@617: ingo@770: /** ingo@770: * Disabled HistogramHelper constructor. This is a helper class and no ingo@770: * instance should be instantiated from this class. ingo@770: */ ingo@617: private HistogramHelper() { ingo@617: } ingo@617: ingo@617: ingo@770: /** ingo@770: * This function prepare some input data and turns it into an array which is ingo@770: * taken by {@link de.intevation.gnv.chart.DefaultHistogram}. ingo@770: * ingo@770: * @param input A collection with the data used to be displayed in a ingo@770: * histogram ingo@770: * @param parameters A collection with a bunch of parameters ingo@770: * @param measurements A collection with a bunch of measurements ingo@770: * @param dates A collection with a bunch of dates ingo@770: * ingo@770: * @return Object[][] containing raw data which can be used to create ingo@770: * histograms ingo@770: */ ingo@617: public static Object[][] prepareHistogramData( ingo@617: Collection input, ingo@617: Collection parameters, ingo@617: Collection measurements, ingo@617: Collection dates ingo@617: ) { ingo@617: List names = new ArrayList(); ingo@617: List data = new ArrayList(); ingo@617: ingo@617: if (logger.isDebugEnabled()) { ingo@617: logger.debug("############ prepare histogram data ##########"); ingo@617: logger.debug("Input data size: " + input.size()); ingo@617: } ingo@617: ingo@617: if (input == null) { ingo@617: return new Object[0][0]; ingo@617: } ingo@617: ingo@617: String break1, break2, break3; ingo@617: int b1Idx = -1; ingo@617: int b2Idx = -1; ingo@617: int b3Idx = -1; ingo@617: int yIdx = -1; ingo@617: try { ingo@617: Iterator iter = input.iterator(); ingo@617: ingo@617: if (iter.hasNext()) { ingo@617: Result row = (Result) iter.next(); ingo@617: Result previousRow = row; ingo@617: ingo@617: if (b1Idx == -1) { ingo@617: ResultDescriptor rd = row.getResultDescriptor(); ingo@617: b1Idx = rd.getColumnIndex("GROUP1"); ingo@617: b2Idx = rd.getColumnIndex("GROUP2"); ingo@617: b3Idx = rd.getColumnIndex("GROUP3"); ingo@617: yIdx = rd.getColumnIndex("YORDINATE"); ingo@617: ingo@617: if (b1Idx == -1 || b2Idx == -1 || b3Idx == -1 || yIdx == -1) { ingo@617: return new Object[0][0]; ingo@617: } ingo@617: } ingo@617: break1 = row.getString(b1Idx); ingo@617: break2 = row.getString(b2Idx); ingo@617: break3 = row.getString(b3Idx); ingo@617: ingo@617: List values = new ArrayList(); ingo@617: while (iter.hasNext()) { ingo@617: ingo@617: // found new series ingo@617: if (!break1.equals(row.getString(b1Idx)) ingo@617: || !break2.equals(row.getString(b2Idx)) ingo@617: || !break3.equals(row.getString(b3Idx)) ingo@617: ) { ingo@617: ingo@617: // get parameter name ingo@617: String name = generateName( ingo@617: break1, break2, break3, ingo@617: parameters, measurements, dates ingo@617: ); ingo@617: ingo@617: // add values and parameter name ingo@617: data.add((Double[]) values.toArray(new Double[values.size()])); ingo@617: names.add(name); ingo@617: ingo@617: if (logger.isDebugEnabled()) { ingo@617: logger.debug(" --- series name: " + name); ingo@617: logger.debug(" --- series items: " + values.size()); ingo@617: } ingo@617: ingo@617: values.clear(); ingo@617: ingo@617: Double yValue = row.getDouble(yIdx); ingo@617: if (yValue != null) ingo@617: values.add(yValue); ingo@617: ingo@617: // set new conditions to find new series ingo@617: break1 = row.getString(b1Idx); ingo@617: break2 = row.getString(b2Idx); ingo@617: break3 = row.getString(b3Idx); ingo@617: ingo@617: previousRow = row; ingo@617: row = (Result) iter.next(); ingo@617: } else { ingo@617: ingo@617: Double value = row.getDouble(yIdx); ingo@617: if (value != null) ingo@617: values.add(value); ingo@617: ingo@617: row = (Result) iter.next(); ingo@617: } ingo@617: } ingo@617: ingo@617: Double yValue = row.getDouble(yIdx); ingo@617: if (yValue != null) ingo@617: values.add(yValue); ingo@617: ingo@617: String name = generateName( ingo@617: break1, break2, break3, parameters, measurements, dates); ingo@617: ingo@617: if (logger.isDebugEnabled()) { ingo@617: logger.debug(" --- series name: " + name); ingo@617: logger.debug(" --- series items: " + values.size()); ingo@617: } ingo@617: ingo@617: data.add((Double[]) values.toArray(new Double[values.size()])); ingo@617: names.add(name); ingo@617: } ingo@617: } ingo@617: catch (Exception e) { ingo@617: logger.error(e.getMessage(), e); ingo@617: } ingo@617: ingo@617: int series = data.size(); ingo@617: logger.debug(" === Found total: " + series); ingo@617: Object[][] obj = new Object[series][2]; ingo@617: for (int i = 0; i < series; i++) { ingo@617: obj[i][0] = names.get(i); ingo@617: obj[i][1] = (Double[]) data.get(i); ingo@617: } ingo@617: ingo@617: return obj; ingo@617: } ingo@617: ingo@617: ingo@770: /** ingo@770: * This method generates a string made up of parameter name and a ingo@770: * measurement. ingo@770: * ingo@770: * @param break1 Id of a parameter. ingo@770: * @param break2 Id of a measurement. ingo@770: * @param break3 Id of a date. ingo@770: * @param parameters A collection with a bunch of parameters. ingo@770: * @param measurements A collection with a bunch of measurements. ingo@770: * @param dates A collection with a bunch of dates. ingo@770: * ingo@770: * @return Concatenated string (${parametername} + ${measurement} + m). ingo@770: */ ingo@617: protected static String generateName( ingo@617: String break1, String break2, String break3, ingo@617: Collection parameters, Collection measurements, Collection dates) ingo@617: { ingo@617: return findValueTitle(parameters,break1) + " " + ingo@617: findValueTitle(measurements,break2) + "m"; ingo@617: } ingo@617: ingo@617: ingo@770: /** ingo@770: * Find a value with the given id and return its description. ingo@770: * ingo@770: * @param values A collection which contains the value we are searching for ingo@770: * @param id Id of the value ingo@770: * ingo@770: * @return String representation of the value. An empty string is returned ingo@770: * if no value have been found with the given id. ingo@770: */ ingo@617: protected static String findValueTitle(Collection values, String id) { ingo@617: if (values != null) { ingo@617: Iterator it = values.iterator(); ingo@617: ingo@617: while (it.hasNext()) { ingo@617: KeyValueDescibeData data = (KeyValueDescibeData) it.next(); ingo@617: ingo@617: if (id.equals(data.getKey())) { ingo@617: return data.getValue(); ingo@617: } ingo@617: } ingo@617: } ingo@617: return ""; ingo@617: } ingo@1080: ingo@1080: ingo@1080: /** ingo@1080: * Creates and returns labels to decorate histograms. ingo@1080: * ingo@1080: * @param uuid The UUID of the current artifact. ingo@1080: * @param context The CallContext object. ingo@1080: * @param data An array storing strings. ingo@1080: * @return A ChartLabels object with the 1st string in data as title. ingo@1080: */ ingo@1080: public static ChartLabels createHistogramLabels( ingo@1080: String uuid, CallContext context, Locale locale, Object[] data) ingo@1080: { ingo@1080: RessourceFactory fac = RessourceFactory.getInstance(); ingo@1080: ingo@1080: return new ChartLabels( ingo@1080: (String) data[0], ingo@1080: "", ingo@1080: "", ingo@1080: fac.getRessource(locale, "histogram.axis.range.title", "")); ingo@1080: } ingo@1081: ingo@1081: ingo@1081: public static Object[][] prepareVectorialHistogramData(Collection input) { ingo@1081: List names = new ArrayList(); ingo@1081: List data = new ArrayList(); ingo@1081: ingo@1081: if (logger.isDebugEnabled()) { ingo@1081: logger.debug("######### prepare vectorial histogram data #######"); ingo@1081: logger.debug("Input data size: " + input.size()); ingo@1081: } ingo@1081: ingo@1081: if (input == null) { ingo@1081: return new Object[0][0]; ingo@1081: } ingo@1081: ingo@1081: int sIdx = -1; ingo@1081: int yIdx = -1; ingo@1081: ingo@1081: String series = null; ingo@1081: ingo@1081: try { ingo@1081: Iterator iter = input.iterator(); ingo@1081: ingo@1081: if (iter.hasNext()) { ingo@1081: Result row = (Result) iter.next(); ingo@1081: Result previousRow = row; ingo@1081: ingo@1081: if (sIdx == -1 || yIdx == -1) { ingo@1081: ResultDescriptor rd = row.getResultDescriptor(); ingo@1081: sIdx = rd.getColumnIndex("SERIES"); ingo@1081: yIdx = rd.getColumnIndex("YORDINATE"); ingo@1081: ingo@1081: if (sIdx == -1 || yIdx == -1) { ingo@1081: return new Object[0][0]; ingo@1081: } ingo@1081: } ingo@1081: ingo@1081: List values = new ArrayList(); ingo@1081: while (iter.hasNext()) { ingo@1081: row = (Result) iter.next(); ingo@1081: ingo@1081: // found new series ingo@1081: if (series != null && !series.equals(row.getString(sIdx))) { ingo@1081: ingo@1081: // add values and parameter name ingo@1081: data.add((Double[]) ingo@1081: values.toArray(new Double[values.size()])); ingo@1081: names.add(series); ingo@1081: ingo@1081: if (logger.isDebugEnabled()) { ingo@1081: logger.debug(" --- series name: " + series); ingo@1081: logger.debug(" --- series items: " + values.size()); ingo@1081: } ingo@1081: ingo@1081: values.clear(); ingo@1081: } ingo@1081: ingo@1081: Double value = row.getDouble(yIdx); ingo@1081: if (value != null) ingo@1081: values.add(value); ingo@1081: ingo@1081: series = row.getString(sIdx); ingo@1081: } ingo@1081: ingo@1081: if (logger.isDebugEnabled()) { ingo@1081: logger.debug(" --- series name: " + series); ingo@1081: logger.debug(" --- series items: " + values.size()); ingo@1081: } ingo@1081: ingo@1081: data.add((Double[]) values.toArray(new Double[values.size()])); ingo@1081: names.add(series); ingo@1081: } ingo@1081: } ingo@1081: catch (Exception e) { ingo@1081: logger.error(e.getMessage(), e); ingo@1081: } ingo@1081: ingo@1081: int count = data.size(); ingo@1081: logger.debug(" === Found total: " + count); ingo@1081: Object[][] obj = new Object[count][2]; ingo@1081: for (int i = 0; i < count; i++) { ingo@1081: obj[i][0] = names.get(i); ingo@1081: obj[i][1] = (Double[]) data.get(i); ingo@1081: } ingo@1081: ingo@1081: return obj; ingo@1081: } ingo@617: } ingo@617: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :