/** * This method update the chart when any of the selectors change. The data needed (selector values and * bar chart object) is stored in */ protected void updateChart() { // the animation routine is unfortunately buggy and will cause the chart // to not update correctly, so we disable it this.sightingsChart.setAnimated(false); // create the main data series for the bar chart which will contain // all our sighting counts for each time step XYChart.Series series = new XYChart.Series<>(); // clear all old data series from the chart (if there are any) this.sightingsChart.getData().clear(); // add our main data series to the chart this.sightingsChart.getData().add(series); // we give the main series the name "All Sightings" series.setName("All Sightings"); // get the lower and higher bounds and get an iterator as the result of a range query to the skip list Date min = this.minSelectedDate == null ? this.dataSkipList.getSmallestKey() : this.minSelectedDate; Date max = this.maxSelectedDate == null ? this.dataSkipList.getSmallestKey() : this.maxSelectedDate; Iterator iter = this.dataSkipList.getRange(min, max); // create a hash table that we use to store attribute value counts for the selected attribute HashMap attributeValueCount = new HashMap(); // create a hash table to store data series for every value for the selected attribute HashMap> attributeValueSeries = new HashMap>(); Date currentDate = null; int count = 0; while (iter.hasNext()) { SquirrelSighting currentSighting = iter.next(); if (currentDate == null) currentDate = currentSighting.getDateTime(); // create new data points when we jump from one date to another if (currentDate != null && !currentDate.equals(currentSighting.getDateTime())) { // currentDate = currentSighting.getDateTime(); // create a new data point for the main series series.getData().add(new XYChart.Data<>(dateFormat.format(currentDate), count)); // and for every series for attribute values that we found in the data for (String attributeValue : attributeValueCount.keySet()) { if (!attributeValueSeries.containsKey(attributeValue)) { attributeValueSeries.put(attributeValue, new XYChart.Series()); attributeValueSeries.get(attributeValue).setName(this.selectedAttribute + ":" + attributeValue); this.sightingsChart.getData().add(attributeValueSeries.get(attributeValue)); } XYChart.Series attributeSeries = attributeValueSeries.get(attributeValue); attributeSeries.getData().add(new XYChart.Data(dateFormat.format(currentDate), attributeValueCount.get(attributeValue))); } // reset both counts for the main series and all other series count = 0; for (String attributeValue : attributeValueCount.keySet()) { attributeValueCount.put(attributeValue, 0); } currentDate = currentSighting.getDateTime(); } // increase count for main data series count++; // find the selected attribute if (this.selectedAttribute != "none" && this.selectedAttribute != null) { // add the value to the hash table if not present, then increase the count String attributeValue = currentSighting.getAttributeValue(this.selectedAttribute); if (!attributeValueCount.containsKey(attributeValue)) attributeValueCount.put(attributeValue, 0); attributeValueCount.put(attributeValue, attributeValueCount.get(attributeValue) + 1); } } // and once more for the last series series.getData().add(new XYChart.Data<>(dateFormat.format(currentDate), count)); for (String attributeValue : attributeValueCount.keySet()) { if (!attributeValueSeries.containsKey(attributeValue)) { attributeValueSeries.put(attributeValue, new XYChart.Series()); attributeValueSeries.get(attributeValue).setName(this.selectedAttribute + ":" + attributeValue); this.sightingsChart.getData().add(attributeValueSeries.get(attributeValue)); } XYChart.Series attributeSeries = attributeValueSeries.get(attributeValue); attributeSeries.getData().add(new XYChart.Data(dateFormat.format(currentDate), attributeValueCount.get(attributeValue))); } }