tim@335: package de.intevation.gnv.state.profile.horizontal;
tim@335:
tim@335: import java.io.IOException;
tim@335: import java.io.OutputStream;
tim@335: import java.io.UnsupportedEncodingException;
ingo@740: import java.text.ParseException;
tim@335: import java.text.SimpleDateFormat;
tim@335: import java.util.Collection;
tim@335: import java.util.Date;
tim@335: import java.util.Iterator;
tim@335: import java.util.Locale;
tim@335:
tim@335: import org.apache.log4j.Logger;
tim@823: import org.jfree.chart.ChartTheme;
tim@335:
tim@823: import de.intevation.artifacts.CallContext;
tim@823: import de.intevation.gnv.chart.Chart;
tim@823: import de.intevation.gnv.chart.ChartLabels;
tim@823: import de.intevation.gnv.chart.HorizontalProfileChart;
tim@823: import de.intevation.gnv.exports.DefaultExport;
tim@823: import de.intevation.gnv.exports.DefaultProfile;
tim@823: import de.intevation.gnv.exports.ShapeDataCollector;
tim@823: import de.intevation.gnv.exports.Export.Profile;
tim@823: import de.intevation.gnv.geobackend.base.Result;
tim@823: import de.intevation.gnv.state.InputData;
tim@823: import de.intevation.gnv.state.describedata.KeyValueDescibeData;
tim@823: import de.intevation.gnv.state.exception.StateException;
tim@823: import de.intevation.gnv.state.timeseries.TimeSeriesOutputState;
tim@823: import de.intevation.gnv.statistics.HorizontalProfileStatistics;
tim@823: import de.intevation.gnv.statistics.Statistics;
tim@823: import de.intevation.gnv.utils.InputValidator;
tim@823: import de.intevation.gnv.utils.WKTUtils;
ingo@358:
tim@335: /**
ingo@811: * This OutputState
is used for 'Horizontalprofile' products.
ingo@811: *
sascha@780: * @author Tim Englich
sascha@780: * @author Ingo Weinzierl
tim@335: */
ingo@368: public class HorizontalProfileOutputState
ingo@368: extends TimeSeriesOutputState
sascha@778: {
tim@762: public static final String [] HORIZONTAL_PROFILE_MESH_COLUMNS = {
ingo@368: "SHAPE",
ingo@368: "YORDINATE",
tim@762: "GROUP1",
tim@762: "MESHID"
tim@762: };
sascha@778:
tim@762: public static final String [] HORIZONTAL_PROFILE_MEASUREMENT_COLUMNS = {
tim@762: "SHAPE",
tim@762: "YORDINATE",
tim@762: "GROUP1",
tim@762: "SURVEYID"
ingo@368: };
ingo@368:
ingo@368:
ingo@368: public static final String [] HORIZONTAL_MESH_CSV_COLUMN_LABEL = {
ingo@368: "Longitude",
ingo@368: "Latitude",
ingo@368: "Value",
ingo@368: "ParameterID",
tim@762: "MeshID"
ingo@368: };
ingo@368:
ingo@368:
ingo@368: public static final String [] HORIZONTAL_MEASUREMENT_CSV_COLUMN_LABEL = {
ingo@368: "Longitude",
ingo@368: "Latitude",
ingo@368: "Value",
ingo@368: "ParameterID",
tim@762: "SurveyID"
ingo@368: };
sascha@778:
tim@335: /**
tim@335: * The UID of this class
tim@335: */
tim@335: private static final long serialVersionUID = 4401516087492028840L;
tim@335:
tim@335: private static Logger log = Logger
tim@335: .getLogger(HorizontalProfileOutputState.class);
tim@335:
tim@335: public static final String DATE_FORMAT = "yyyy.MM.dd HH:mm:ss";
tim@335:
tim@335: public static final String [] CHART_TITLE_META = {
tim@335: "CRUISE",
tim@335: "DEPTH",
tim@335: "SHAPE"
tim@335: };
tim@335:
tim@335:
tim@335: public static final String [] CHART_TITLE_META_RESSOURCES = {
tim@335: "cruiseid",
tim@335: "depth",
tim@335: "coordinate"
tim@335: };
tim@335:
tim@335: public static final String [] TIMESERIES_CSV_PROFILE_NAMES = {
tim@335: "SHAPE",
tim@335: "YORDINATE",
tim@335: "GROUP1",
tim@335: "GROUP2",
tim@335: "GROUP3"
tim@335: };
tim@335:
tim@335: public static final Profile TIMESERIES_CSV_PROFILE =
tim@335: new DefaultProfile(
tim@335: null,
tim@335: ',',
tim@335: '"',
tim@335: '"',
tim@335: "CSV",
tim@335: "ISO-8859-1");
tim@335:
tim@335: /**
tim@335: * Constructor
tim@335: */
tim@335: public HorizontalProfileOutputState() {
tim@335: super();
ingo@343: super.domainLable = "chart.horizontalprofile.title.xaxis";
tim@335: }
tim@335:
tim@335:
ingo@811: /**
ingo@811: * This method creates a chart and returns it.
ingo@811: *
ingo@811: * @param chartLables Labels used to decorate the chart.
ingo@811: * @param theme The theme used to adjust the look of the chart.
ingo@811: * @param parameters A collection with parameters this chart contains.
ingo@811: * @param measurements A collection with measurement this chart contains.
ingo@811: * @param dates A collection with dates this chart contains.
ingo@811: * @param result The data collection used to be displayed in this chart.
ingo@811: * @param locale The Locale used to determine the language.
ingo@811: * @param uuid The uuid of the current artifact.
ingo@811: * @param linesVisible A boolean property to determine the visibility of
ingo@811: * lines connecting two points in a chart (not used in this chart type).
ingo@811: * @param shapesVisible A boolean property to determine the visiblity of
ingo@811: * datapoints in this chart (not used in this chart type).
ingo@811: * @param callContext The CallContext object.
ingo@811: * @return a HorizontalProfileChart
.
ingo@811: */
tim@335: @Override
tim@335: protected Chart getChart(
tim@335: ChartLabels chartLables,
ingo@358: ChartTheme theme,
tim@335: Collection parameters,
tim@335: Collection measurements,
tim@335: Collection dates,
ingo@429: Object result,
tim@335: Locale locale,
tim@335: String uuid,
tim@335: boolean linesVisible,
sascha@439: boolean shapesVisible,
sascha@439: CallContext callContext
tim@335: ) {
tim@335: Chart chart = null;
tim@335:
tim@335: if (CACHE_CHART) {
tim@335: log.info("Try to get horizontalprofile chart from cache.");
sascha@439: chart = (Chart) getChartFromCache(uuid, callContext);
tim@335: }
tim@335:
tim@335: if (chart != null)
tim@335: return chart;
tim@335:
tim@335: log.info("Chart not in cache yet.");
tim@335: chart = new HorizontalProfileChart(
tim@335: chartLables,
ingo@358: theme,
tim@335: parameters,
tim@335: measurements,
tim@335: dates,
ingo@429: (Collection)result,
tim@335: null,
tim@335: locale,
tim@335: linesVisible,
tim@335: shapesVisible
tim@335: );
tim@335: chart.generateChart();
tim@335:
tim@335: if (CACHE_CHART) {
tim@335: log.info("Put chart into cache.");
tim@335: purifyChart(chart, uuid);
tim@335: }
tim@335:
tim@335: return chart;
tim@335: }
tim@335:
tim@335:
tim@335: @Override
tim@335: protected Statistics getStatisticsGenerator() {
tim@335: return new HorizontalProfileStatistics();
tim@335: }
tim@335:
ingo@368:
tim@335: @Override
ingo@368: protected void createCSV(OutputStream out, Collection results)
ingo@368: throws UnsupportedEncodingException, IOException, StateException
ingo@368: {
ingo@368: log.debug("Create csv export for horizontal profiles.");
ingo@368: Iterator iter = results.iterator();
ingo@368: Result res = iter.hasNext() ? (Result) iter.next() : null;
ingo@368:
ingo@368: if (res == null)
ingo@368: return;
ingo@368:
ingo@368: Profile profile = null;
ingo@368: int dataid = res.getInteger("DATAID").intValue();
tim@762: DefaultExport export = null;
ingo@368: // on meshes
ingo@368: if (dataid == 2) {
ingo@368: profile = new DefaultProfile(
ingo@368: HORIZONTAL_MESH_CSV_COLUMN_LABEL,
ingo@368: ',',
ingo@368: '"',
ingo@368: '"',
ingo@368: "CSV",
ingo@368: "ISO-8859-1");
tim@762: export = new DefaultExport(
tim@762: new ShapeDataCollector(HORIZONTAL_PROFILE_MESH_COLUMNS));
ingo@368: }
ingo@368:
ingo@368: // on measurements
ingo@368: else {
ingo@368: profile = new DefaultProfile(
ingo@368: HORIZONTAL_MEASUREMENT_CSV_COLUMN_LABEL,
ingo@368: ',',
ingo@368: '"',
ingo@368: '"',
ingo@368: "CSV",
ingo@368: "ISO-8859-1");
tim@762: export = new DefaultExport(
tim@762: new ShapeDataCollector(HORIZONTAL_PROFILE_MEASUREMENT_COLUMNS));
ingo@368: }
ingo@368:
sascha@778:
ingo@368: export.create(profile, out, results);
tim@335: }
tim@335:
tim@335:
ingo@811: /**
ingo@811: * Creates and returns the chart title.
ingo@811: *
ingo@811: * @param locale The Locale used to adjust the language of the title.
ingo@811: * @param uuid The UUID of the current artifact.
ingo@811: * @return the name of the selected fis.
ingo@811: */
ingo@811: @Override
tim@335: protected String createChartTitle(Locale locale, String uuid) {
tim@335: String fisName = getFisName(locale);
tim@335: log.debug("created title for horizontal profile chart: " + fisName);
tim@335:
tim@335: return fisName;
tim@335: }
tim@335:
tim@335:
ingo@811: /**
ingo@811: * Creates and returns the subtitle of a chart.
ingo@811: *
ingo@811: * @param locale The Locale used to adjust the language of the subtitle.
ingo@811: * @param uuid The UUID of the current artifact.
ingo@811: * @return the timeperiod of this chart and the start coordinate.
ingo@811: */
ingo@811: @Override
tim@335: protected String createChartSubtitle(Locale locale, String uuid) {
tim@335: log.debug("create chart subtitle.");
tim@335: String subtitle = createTimePeriod(locale, uuid);
tim@335:
tim@335: // ODV results contain meta information about cruise, station and so on
tim@335: Collection results = getODVResult(uuid);
tim@335: if (results != null) {
tim@335: Iterator iter = results.iterator();
tim@335: Result result = iter.hasNext() ? (Result) iter.next() : null;
tim@335:
tim@335: subtitle += subtitle.length() != 0 ? "\n" : "";
tim@335: subtitle += createMetaChartSubtitle(locale, result);
tim@335: }
tim@335:
tim@335: return subtitle;
tim@335: }
tim@335:
tim@335:
ingo@811: /**
ingo@811: * Create meta information used in subtitles.
ingo@811: *
ingo@811: * @param locale The Locale used to adjust the language of the subtitle.
ingo@811: * @param result A data object.
ingo@811: * @return the start coordinate as human readable string.
ingo@811: */
tim@335: protected String createMetaChartSubtitle(Locale locale, Result result) {
tim@335: log.debug("Fetch meta information and put it into subtitle.");
tim@335: if (result == null)
tim@335: return "";
tim@335:
tim@335: StringBuilder meta = new StringBuilder();
tim@335:
tim@335: for (int i = 0; i < CHART_TITLE_META.length; i++) {
tim@335: String qry = CHART_TITLE_META[i];
tim@335:
tim@335: if (qry.equals("SHAPE")) {
ingo@740: try {
ingo@740: InputData data = getInputDataByName("mesh_coordinate");
ingo@740: if (data == null) {
ingo@740: continue;
ingo@740: }
ingo@740: String wktPoint = data.getValue();
ingo@740: meta.append(getMessage(locale,"coordinate","coordinate"));
ingo@740: meta.append(": ");
ingo@740: meta.append(WKTUtils.toText(
ingo@740: locale,
ingo@811: InputValidator.getPointValue(wktPoint)));
ingo@740: }
ingo@740: catch (Exception e) {
ingo@740: log.error(e, e);
ingo@740: }
tim@335: }
tim@335: else {
tim@335: log.debug(
tim@335: "Add " + qry + " to meta information of subtitle: "
tim@335: + result.getString(qry)
tim@335: );
tim@335: meta.append(getMessage(
tim@335: locale,
tim@335: CHART_TITLE_META_RESSOURCES[i],
tim@335: CHART_TITLE_META_RESSOURCES[i]
tim@335: ));
tim@335: meta.append(": ");
tim@335: meta.append(result.getString(qry));
tim@335: }
tim@335:
tim@335: if (i != CHART_TITLE_META.length-1)
tim@335: meta.append("\n");
tim@335: }
tim@335:
tim@335: log.debug("Meta title for chart: " + meta.toString());
tim@335: return meta.toString();
tim@335: }
tim@335:
tim@335:
ingo@811: /**
ingo@811: * Creates a timeperiod taking account for all data items used in charts.
ingo@811: *
ingo@811: * @param locale The Locale used to adjust the language of the subtitle.
ingo@811: * @param uuid The UUID of the current artifact.
ingo@811: * @return a human readable timeperiod.
ingo@811: */
tim@335: protected String createTimePeriod(Locale locale, String uuid) {
tim@335: log.debug("create time period for chart subtitle.");
tim@335: String subTitle = null;
tim@335: Date startDate = null;
tim@335: Date endDate = null;
tim@335:
tim@335: Collection dates = getDates(uuid);
tim@335: if (dates == null) {
tim@335: log.debug("No time period for subtitle.");
tim@335: return "";
tim@335: }
tim@335:
tim@335: SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
tim@335: KeyValueDescibeData data = null;
tim@335:
tim@335: Iterator iter = dates.iterator();
tim@335: while (iter.hasNext()) {
tim@335: try {
tim@335: data = (KeyValueDescibeData)iter.next();
tim@335:
tim@335: if (!data.isSelected())
tim@335: continue;
tim@335:
tim@335: Date current = format.parse(data.getValue());
tim@335: long time = current.getTime();
tim@335:
tim@335: if (startDate == null) {
tim@335: startDate = current;
tim@335: endDate = current;
tim@335: }
tim@335: else if (time < startDate.getTime()) {
tim@335: startDate = current;
tim@335: }
tim@335: else if (time > endDate.getTime()) {
tim@335: endDate = current;
tim@335: }
tim@335: }
ingo@740: catch (ParseException pe) {
tim@335: log.warn("Error while parsing date: " + data.getValue(), pe);
tim@335: }
tim@335: }
tim@335:
ingo@348: if (startDate != null && endDate != null)
ingo@348: subTitle = format.format(startDate)+" - "+format.format(endDate);
ingo@348:
ingo@348: subTitle = subTitle == null ? "" : subTitle;
ingo@348:
tim@335: log.debug("created title for horizontal profile chart: " + subTitle);
tim@335:
tim@335: return subTitle;
tim@335: }
tim@335: }
ingo@811: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :