View Javadoc
1   /*
2    * Copyright 2014 James Pether Sörling
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   *	$Id$
17   *  $HeadURL$
18   */
19  package com.hack23.cia.web.impl.ui.application.views.common.chartfactory.impl;
20  
21  import java.text.SimpleDateFormat;
22  import java.util.ArrayList;
23  import java.util.Calendar;
24  import java.util.List;
25  import java.util.Locale;
26  import java.util.Map;
27  import java.util.Map.Entry;
28  import java.util.Objects;
29  import java.util.Optional;
30  import java.util.stream.Collectors;
31  
32  import org.apache.commons.lang3.time.DateUtils;
33  import org.dussan.vaadin.dcharts.DCharts;
34  import org.dussan.vaadin.dcharts.base.elements.XYseries;
35  import org.dussan.vaadin.dcharts.data.DataSeries;
36  import org.dussan.vaadin.dcharts.options.Series;
37  import org.springframework.beans.factory.annotation.Autowired;
38  import org.springframework.stereotype.Service;
39  
40  import com.hack23.cia.model.internal.application.data.committee.impl.RiksdagenVoteDataBallotPartyPeriodSummaryEmbeddedId;
41  import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPartySummaryDaily;
42  import com.hack23.cia.service.api.ApplicationManager;
43  import com.hack23.cia.service.api.DataContainer;
44  import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.ChartOptions;
45  import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.PartyChartDataManager;
46  import com.vaadin.ui.AbstractOrderedLayout;
47  
48  /**
49   * The Class ChartDataManagerImpl.
50   */
51  @Service
52  public final class PartyChartDataManagerImpl extends AbstractChartDataManagerImpl implements PartyChartDataManager {
53  
54  
55  	/** The Constant PARTY_ABSENT. */
56  	private static final String PARTY_ABSENT = "Party Absent";
57  
58  	/** The Constant PARTY_WON. */
59  	private static final String PARTY_WON = "Party Won";
60  
61  	/** The Constant NUMBER_BALLOTS. */
62  	private static final String NUMBER_BALLOTS = "Number ballots";
63  
64  	/** The Constant DD_MMM_YYYY. */
65  	private static final String DD_MMM_YYYY = "dd-MMM-yyyy";
66  
67  	/** The application manager. */
68  	@Autowired
69  	private ApplicationManager applicationManager;
70  
71  	/** The chart options. */
72  	@Autowired
73  	private ChartOptions chartOptions;
74  
75  
76  	/** The party map. */
77  	private Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> partyMap;
78  
79  	/**
80  	 * Instantiates a new party chart data manager impl.
81  	 */
82  	public PartyChartDataManagerImpl() {
83  		super();
84  	}
85  
86  
87  	/**
88  	 * Gets the max size view riksdagen vote data ballot party summary daily.
89  	 *
90  	 * @return the max size view riksdagen vote data ballot party summary daily
91  	 */
92  	private List<ViewRiksdagenVoteDataBallotPartySummaryDaily> getMaxSizeViewRiksdagenVoteDataBallotPartySummaryDaily() {
93  		initPartyMap();
94  
95  		final Optional<Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>>> first = partyMap.entrySet()
96  				.stream().sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size())
97  
98  		).findFirst();
99  
100 		if (first.isPresent()) {
101 			return first.get().getValue();
102 		} else {
103 			return new ArrayList<>();
104 		}
105 	}
106 
107 
108 	/**
109 	 * Gets the party map.
110 	 *
111 	 * @return the party map
112 	 */
113 	private Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> getPartyMap() {
114 		initPartyMap();
115 
116 		return partyMap;
117 	}
118 
119 
120 
121 
122 
123 	/**
124 	 * Inits the party map.
125 	 */
126 	private void initPartyMap() {
127 		if (partyMap == null) {
128 			final DataContainer<ViewRiksdagenVoteDataBallotPartySummaryDaily, RiksdagenVoteDataBallotPartyPeriodSummaryEmbeddedId> partyBallotSummaryDailyDataContainer = applicationManager
129 					.getDataContainer(ViewRiksdagenVoteDataBallotPartySummaryDaily.class);
130 
131 			partyMap = partyBallotSummaryDailyDataContainer.getAll().parallelStream().filter(Objects::nonNull)
132 					.collect(Collectors.groupingBy(t -> t.getEmbeddedId().getParty()));
133 		}
134 	}
135 
136 	@Override
137 	public void createPartyWinnerChart(final AbstractOrderedLayout content) {
138 
139 		final Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> map = getPartyMap();
140 
141 		final DataSeries dataSeries = new DataSeries();
142 
143 		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);
144 
145 		final Series series = new Series();
146 
147 		for (final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry : map.entrySet()) {
148 
149 			series.addSeries(new XYseries().setLabel(getPartyName(entry.getKey())));
150 
151 			dataSeries.newSeries();
152 			final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = entry.getValue();
153 			for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
154 				if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
155 					dataSeries.add(
156 							simpleDateFormat
157 									.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
158 							viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyWonPercentage());
159 				}
160 			}
161 
162 		}
163 
164 		series.addSeries(new XYseries().setLabel(NUMBER_BALLOTS));
165 
166 		dataSeries.newSeries();
167 		final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = getMaxSizeViewRiksdagenVoteDataBallotPartySummaryDaily();
168 		for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
169 			if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
170 				dataSeries.add(
171 						simpleDateFormat
172 								.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
173 						viewRiksdagenVoteDataBallotPartySummaryDaily.getNumberBallots());
174 			}
175 		}
176 
177 		addChart(content,"Party winner by daily ballot average", new DCharts().setDataSeries(dataSeries).setOptions(chartOptions.createOptionsXYDateFloatLegendOutside(series)).show());
178 	}
179 
180 	/**
181 	 * Gets the view riksdagen vote data ballot party summary daily.
182 	 *
183 	 * @param party
184 	 *            the party
185 	 * @return the view riksdagen vote data ballot party summary daily
186 	 */
187 	private List<ViewRiksdagenVoteDataBallotPartySummaryDaily> getViewRiksdagenVoteDataBallotPartySummaryDaily(
188 			final String party) {
189 		initPartyMap();
190 
191 		return partyMap.get(party);
192 	}
193 
194 
195 	@Override
196 	public void createPartyLineChart(final AbstractOrderedLayout content,final String partyId) {
197 
198 		final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = getViewRiksdagenVoteDataBallotPartySummaryDaily(
199 				partyId);
200 
201 		final Series series = new Series().addSeries(new XYseries().setLabel(PARTY_WON))
202 				.addSeries(new XYseries().setLabel(PARTY_ABSENT));
203 
204 		final DataSeries dataSeries = new DataSeries().newSeries();
205 
206 		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);
207 
208 		if (list != null) {
209 
210 			for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
211 				if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
212 					dataSeries.add(
213 							simpleDateFormat
214 									.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
215 							viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyWonPercentage());
216 				}
217 			}
218 
219 			dataSeries.newSeries();
220 
221 			for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
222 				if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
223 					dataSeries.add(
224 							simpleDateFormat
225 									.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
226 							viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyPercentageAbsent());
227 				}
228 			}
229 		}
230 
231 		addChart(content,"Party result by", new DCharts().setDataSeries(dataSeries).setOptions(chartOptions.createOptionsPartyLineChart(series)).show());
232 	}
233 
234 
235 	@Override
236 	public void createPartyGenderChart(final AbstractOrderedLayout content) {
237 
238 		createPartyBallotChart(content,viewRiksdagenVoteDataBallotPartySummaryDaily -> 100 - viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyAvgPercentageMale().intValue());
239 
240 	}
241 
242 
243 	@Override
244 	public void createPartyAgeChart(final AbstractOrderedLayout content) {
245 		createPartyBallotChart(content,viewRiksdagenVoteDataBallotPartySummaryDaily -> (DateUtils.toCalendar(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()).get(Calendar.YEAR)) - viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyAvgBornYear().intValue());
246 	}
247 
248 
249 
250 	/**
251 	 * Creates the party ballot chart.
252 	 *
253 	 * @param dataValueCalculator
254 	 *            the data value calculator
255 	 * @return the d charts
256 	 */
257 	private void createPartyBallotChart(final AbstractOrderedLayout content,final DataValueCalculator dataValueCalculator) {
258 		final Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> map = getPartyMap();
259 
260 		final DataSeries dataSeries = new DataSeries();
261 
262 		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DD_MMM_YYYY, Locale.ENGLISH);
263 
264 		final Series series = new Series();
265 
266 		for (final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry : map.entrySet()) {
267 
268 			if (!"-".equals(entry.getKey())) {
269 				series.addSeries(new XYseries().setLabel(getPartyName(entry.getKey())));
270 
271 				dataSeries.newSeries();
272 				final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = entry.getValue();
273 				for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
274 					if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
275 						dataSeries.add(
276 								simpleDateFormat
277 										.format(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
278 										dataValueCalculator.getDataValue(viewRiksdagenVoteDataBallotPartySummaryDaily));
279 					}
280 				}
281 			}
282 		}
283 
284 		addChart(content,"Party ballot chart", new DCharts().setDataSeries(dataSeries).setOptions(chartOptions.createOptionsXYDateFloatLegendOutside(series)).show());
285 	}
286 
287 	/**
288 	 * The Interface DataValueCalculator.
289 	 */
290 	@FunctionalInterface
291 	interface DataValueCalculator {
292 
293 		/**
294 		 * Gets the data value.
295 		 *
296 		 * @param item
297 		 *            the item
298 		 * @return the data value
299 		 */
300 		Object getDataValue(ViewRiksdagenVoteDataBallotPartySummaryDaily item);
301 	}
302 
303 
304 }