Java tutorial
/* * Copyright (C) 2016 Bruce Beisel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.bdb.weather.display.freeplot; import java.awt.Color; import java.awt.Stroke; import java.time.temporal.TemporalAccessor; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.function.Function; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Parent; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.DefaultXYItemRenderer; import com.bdb.util.jdbc.DBConnection; import com.bdb.weather.common.SpeedBin; import com.bdb.weather.common.SummaryRecord; import com.bdb.weather.common.TemperatureBinMgr; import com.bdb.weather.common.WeatherStation; import com.bdb.weather.common.db.TemperatureBinTable; import com.bdb.weather.common.measurement.Depth; import com.bdb.weather.common.measurement.Humidity; import com.bdb.weather.common.measurement.Pressure; import com.bdb.weather.common.measurement.SolarRadiation; import com.bdb.weather.common.measurement.Speed; import com.bdb.weather.common.measurement.Temperature; import com.bdb.weather.display.axis.HumidityRangeAxis; import com.bdb.weather.display.axis.PressureRangeAxis; import com.bdb.weather.display.axis.RainRangeAxis; import com.bdb.weather.display.axis.SolarRadiationAxis; import com.bdb.weather.display.axis.TemperatureRangeAxis; import com.bdb.weather.display.axis.WindSpeedRangeAxis; import com.bdb.weather.display.freeplot.FreePlot.SeriesCollectionFactory; import com.bdb.weather.display.freeplot.FreePlotSeriesCollection.SeriesFactory; /** * Abstract class for implementing the Free Plot of summary data. * * @author Bruce * */ public abstract class SummaryFreePlot implements SeriesFactory<SummaryRecord>, SeriesCollectionFactory { private static final String TEMPERATURE_COLLECTION_NAME = "Temperature"; private static final String HUMIDITY_COLLECTION_NAME = "Humidity"; private static final String PRESSURE_COLLECTION_NAME = "Pressure"; private static final String WIND_COLLECTION_NAME = "Wind"; private static final String RAIN_COLLECTION_NAME = "Rain"; private static final String SOLAR_COLLECTION_NAME = "Solar"; private static final int NUM_COLLECTIONS = 6; private static final String HIGH_TEMPERATURE_SERIES_NAME = "High Temperature"; private static final String LOW_TEMPERATURE_SERIES_NAME = "Low Temperature"; private static final String MEAN_TEMPERATURE_SERIES_NAME = "Mean Temperature"; private static final String MAX_OUTDOOR_HUMIDITY_SERIES_NAME = "Max Outdoor Humidity"; private static final String MIN_OUTDOOR_HUMIDITY_SERIES_NAME = "Min Outdoor Humidity"; private static final String MEAN_OUTDOOR_HUMIDITY_SERIES_NAME = "Mean Outdoor Humidity"; private static final String MAX_BARO_PRESSURE_SERIES_NAME = "Max Barometric Pressure"; private static final String MIN_BARO_PRESSURE_SERIES_NAME = "Min Barometric Pressure"; private static final String MEAN_BARO_PRESSURE_SERIES_NAME = "Mean Barometric Pressure"; private static final String AVG_WIND_SERIES_NAME = "Avg Wind Speed"; private static final String MAX_WIND_SERIES_NAME = "Max Wind Speed"; private static final String MAX_GUST_SERIES_NAME = "Max Wind Gust"; private static final String RAIN_SERIES_NAME = "Rainfall Total"; private static final String ET_SERIES_NAME = "ET Total"; private static final String MAX_SOLAR_RADIATION_NAME = "Max Solar Radiation"; private static final String MEAN_SOLAR_RADIATION_NAME = "Mean Solar Radiation"; private static final String MAX_UV_INDEX_NAME = "Max UV Index"; private static final String MEAN_UV_INDEX_NAME = "Mean UV Index"; private final FreePlot freePlot; private final WeatherStation ws; private final List<SpeedBin> speedBins; private final TemperatureBinMgr temperatureBinMgr; private final TemperatureBinTable temperatureBinTable; private final Class<?> period; private Function<SummaryRecord, TemporalAccessor> dateMethod; /** * Constructor. * * @param ws The weather station for which this window will display data * @param connection Connection to the database * @param period The time period of the graph */ protected SummaryFreePlot(WeatherStation ws, DBConnection connection, Class<?> period) { freePlot = new FreePlot(this); this.period = period; temperatureBinTable = new TemperatureBinTable(connection); this.ws = ws; speedBins = ws.getWindParameters().getSpeedBinList(); temperatureBinMgr = new TemperatureBinMgr(connection); temperatureBinMgr.refresh(); } /** * Return the JavaFX node that is the container for this plot. * * @return The JavaFX Node */ public Parent getNode() { return freePlot; } /* * (non-Javadoc) * @see com.bdb.weather.display.freeplot.FreePlot.SeriesCollectionFactory#createSeriesGroupControls(java.awt.event.ActionListener) */ @Override public Map<String, SeriesGroupControl> createSeriesGroupControls(EventHandler<ActionEvent> listener) { Map<String, SeriesGroupControl> list = new TreeMap<>(); SeriesGroupControl groupControl = new SeriesGroupControl(TEMPERATURE_COLLECTION_NAME, TemperatureRangeAxis.create(), listener); groupControl.addSeriesControl(new SeriesControl(HIGH_TEMPERATURE_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(LOW_TEMPERATURE_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MEAN_TEMPERATURE_SERIES_NAME, listener)); list.put(groupControl.getGroupName(), groupControl); groupControl = new SeriesGroupControl(HUMIDITY_COLLECTION_NAME, HumidityRangeAxis.create(), listener); groupControl.addSeriesControl(new SeriesControl(MAX_OUTDOOR_HUMIDITY_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MIN_OUTDOOR_HUMIDITY_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MEAN_OUTDOOR_HUMIDITY_SERIES_NAME, listener)); list.put(groupControl.getGroupName(), groupControl); groupControl = new SeriesGroupControl(PRESSURE_COLLECTION_NAME, PressureRangeAxis.create(), listener); groupControl.addSeriesControl(new SeriesControl(MAX_BARO_PRESSURE_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MIN_BARO_PRESSURE_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MEAN_BARO_PRESSURE_SERIES_NAME, listener)); list.put(groupControl.getGroupName(), groupControl); groupControl = new SeriesGroupControl(WIND_COLLECTION_NAME, WindSpeedRangeAxis.create(), listener); groupControl.addSeriesControl(new SeriesControl(AVG_WIND_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MAX_WIND_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MAX_GUST_SERIES_NAME, listener)); list.put(groupControl.getGroupName(), groupControl); groupControl = new SeriesGroupControl(RAIN_COLLECTION_NAME, RainRangeAxis.create(), listener); groupControl.addSeriesControl(new SeriesControl(RAIN_SERIES_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(ET_SERIES_NAME, listener)); list.put(groupControl.getGroupName(), groupControl); groupControl = new SeriesGroupControl(SOLAR_COLLECTION_NAME, SolarRadiationAxis.create(), listener); groupControl.addSeriesControl(new SeriesControl(MEAN_SOLAR_RADIATION_NAME, listener)); groupControl.addSeriesControl(new SeriesControl(MAX_SOLAR_RADIATION_NAME, listener)); list.put(groupControl.getGroupName(), groupControl); return list; } /* * (non-Javadoc) * @see com.bdb.weather.display.freeplot.FreePlotSeriesCollection.SeriesFactory#createSeriesGroup(java.lang.String, java.awt.Stroke) */ @Override public List<FreePlotSeries<SummaryRecord>> createSeriesGroup(String groupName, Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); dateMethod = SummaryRecord::getDate; switch (groupName) { case TEMPERATURE_COLLECTION_NAME: list = createTemperatureSeries(stroke); break; case HUMIDITY_COLLECTION_NAME: list = createHumiditySeries(stroke); break; case PRESSURE_COLLECTION_NAME: list = createPressureSeries(stroke); break; case WIND_COLLECTION_NAME: list = createWindSeries(stroke); break; case RAIN_COLLECTION_NAME: list = createRainSeries(stroke); break; case SOLAR_COLLECTION_NAME: list = createSolarRadiationSeries(stroke); break; } return list; } /* * (non-Javadoc) * @see com.bdb.weather.display.freeplot.FreePlot.SeriesCollectionFactory#createSeriesCollections(org.jfree.chart.plot.XYPlot, int, java.awt.Stroke) */ @Override public List<FreePlotSeriesCollection> createSeriesCollections(XYPlot plot, int domainAxisIndex, Stroke stroke) { List<FreePlotSeriesCollection> list = new ArrayList<>(); list.add(new FreePlotSeriesCollection(TEMPERATURE_COLLECTION_NAME, Temperature.getDefaultUnit(), (NUM_COLLECTIONS * domainAxisIndex) + 0, domainAxisIndex, plot, stroke, this)); list.add(new FreePlotSeriesCollection(HUMIDITY_COLLECTION_NAME, Humidity.Unit.RELATIVE_HUMIDITY, (NUM_COLLECTIONS * domainAxisIndex) + 1, domainAxisIndex, plot, stroke, this)); list.add(new FreePlotSeriesCollection(PRESSURE_COLLECTION_NAME, Pressure.getDefaultUnit(), (NUM_COLLECTIONS * domainAxisIndex) + 2, domainAxisIndex, plot, stroke, this)); list.add(new FreePlotSeriesCollection(WIND_COLLECTION_NAME, Speed.getDefaultUnit(), (NUM_COLLECTIONS * domainAxisIndex) + 3, domainAxisIndex, plot, stroke, this)); list.add(new FreePlotSeriesCollection(RAIN_COLLECTION_NAME, Depth.getDefaultUnit(), (NUM_COLLECTIONS * domainAxisIndex) + 4, domainAxisIndex, plot, stroke, this)); list.add(new FreePlotSeriesCollection(SOLAR_COLLECTION_NAME, SolarRadiation.getDefaultUnit(), (NUM_COLLECTIONS * domainAxisIndex) + 5, domainAxisIndex, plot, stroke, this)); return list; } /* * (non-Javadoc) * @see com.bdb.weather.display.freeplot.FreePlotSeriesCollection.SeriesFactory#updateRenderer(com.bdb.weather.display.freeplot.FreePlotSeries, org.jfree.chart.renderer.xy.DefaultXYItemRenderer) */ @Override public void updateRenderer(FreePlotSeries series, DefaultXYItemRenderer renderer) { } // TODO Change the paints to use preferences /** * Create the JFreeChart series for the temperature values. * * @param stroke The stroke for the series */ private List<FreePlotSeries<SummaryRecord>> createTemperatureSeries(Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); int n = 0; list.add(new FreePlotSeries<>(HIGH_TEMPERATURE_SERIES_NAME, n++, Color.RED, stroke, SummaryRecord::getMaxOutdoorTemp, dateMethod, period)); list.add(new FreePlotSeries<>(LOW_TEMPERATURE_SERIES_NAME, n++, Color.BLUE, stroke, SummaryRecord::getMinOutdoorTemp, dateMethod, period)); list.add(new FreePlotSeries<>(MEAN_TEMPERATURE_SERIES_NAME, n++, Color.CYAN, stroke, SummaryRecord::getAvgOutdoorTemp, dateMethod, period)); return list; } /** * Create the JFreeChart series for the humidity values. * * @param stroke The stroke for the series */ private List<FreePlotSeries<SummaryRecord>> createHumiditySeries(Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); int n = 0; list.add(new FreePlotSeries<>(MAX_OUTDOOR_HUMIDITY_SERIES_NAME, n++, Color.GRAY, stroke, SummaryRecord::getMaxOutdoorHumidity, dateMethod, period)); list.add(new FreePlotSeries<>(MIN_OUTDOOR_HUMIDITY_SERIES_NAME, n++, Color.BLACK, stroke, SummaryRecord::getMinOutdoorHumidity, dateMethod, period)); list.add(new FreePlotSeries<>(MEAN_OUTDOOR_HUMIDITY_SERIES_NAME, n++, Color.BLACK, stroke, SummaryRecord::getAvgOutdoorHumidity, dateMethod, period)); return list; } /** * Create the JFreeChart series for the pressure values. * * @param stroke The stroke for the series */ private List<FreePlotSeries<SummaryRecord>> createPressureSeries(Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); int n = 0; list.add(new FreePlotSeries<>(MAX_BARO_PRESSURE_SERIES_NAME, n++, Color.ORANGE, stroke, SummaryRecord::getMaxBaroPressure, dateMethod, period)); list.add(new FreePlotSeries<>(MIN_BARO_PRESSURE_SERIES_NAME, n++, Color.PINK, stroke, SummaryRecord::getMinBaroPressure, dateMethod, period)); list.add(new FreePlotSeries<>(MEAN_BARO_PRESSURE_SERIES_NAME, n++, Color.PINK, stroke, SummaryRecord::getAvgBaroPressure, dateMethod, period)); return list; } /** * Create the JFreeChart series for the wind values. * * @param stroke The stroke for the series */ private List<FreePlotSeries<SummaryRecord>> createWindSeries(Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); int n = 0; list.add(new FreePlotSeries<>(AVG_WIND_SERIES_NAME, n++, Color.CYAN, stroke, SummaryRecord::getAvgWindSpeed, dateMethod, period)); list.add(new FreePlotSeries<>(MAX_WIND_SERIES_NAME, n++, Color.yellow, stroke, SummaryRecord::getMaxWindSpeed, dateMethod, period)); list.add(new FreePlotSeries<>(MAX_GUST_SERIES_NAME, n++, Color.yellow, stroke, SummaryRecord::getMaxWindGust, dateMethod, period)); return list; } /** * Create the JFreeChart series for the rain values. * * @param stroke The stroke for the series */ private List<FreePlotSeries<SummaryRecord>> createRainSeries(Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); int n = 0; list.add(new FreePlotSeries<>(RAIN_SERIES_NAME, n++, Color.BLUE, stroke, SummaryRecord::getTotalRainfall, dateMethod, period)); list.add(new FreePlotSeries<>(ET_SERIES_NAME, n++, Color.RED, stroke, SummaryRecord::getTotalET, dateMethod, period)); return list; } /** * Create the JFreeChart series for the Solar Radiation values. * * @param stroke The stroke for the series */ private List<FreePlotSeries<SummaryRecord>> createSolarRadiationSeries(Stroke stroke) { List<FreePlotSeries<SummaryRecord>> list = new ArrayList<>(); int n = 0; list.add(new FreePlotSeries<>(MAX_SOLAR_RADIATION_NAME, n++, Color.ORANGE, stroke, SummaryRecord::getMaxSolarRadiation, dateMethod, period)); list.add(new FreePlotSeries<>(MEAN_SOLAR_RADIATION_NAME, n++, Color.PINK, stroke, SummaryRecord::getAvgSolarRadiation, dateMethod, period)); return list; } /** * Get the speed bins that correspond to the weather station of this plot * * @return The speed bins */ protected List<SpeedBin> getSpeedBins() { return speedBins; } /** * Get the temperature bins that correspond to the weather station of this plot * * @return The temperature bins */ protected TemperatureBinMgr getTemperatureBinMgr() { return temperatureBinMgr; } }