Author: bleny Date: 2014-06-12 10:20:27 +0200 (Thu, 12 Jun 2014) New Revision: 2024 Url: http://forge.codelutin.com/projects/wao/repository/revisions/2024 Log: fixes #4493 add printable synthesis charts made with jfreechart Added: trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/JFreeChartToImgTagConverter.java Modified: trunk/pom.xml trunk/wao-services/pom.xml trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerSynthesis.java trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/SynthesisService.java trunk/wao-web/pom.xml trunk/wao-web/src/main/resources/fr/ifremer/wao/services/service/ObsMerSynthesis-conversion.properties trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/synthesis.jsp Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/pom.xml 2014-06-12 08:20:27 UTC (rev 2024) @@ -112,6 +112,7 @@ <mustacheVersion>0.8.15</mustacheVersion> <commonsCodecVersion>1.9</commonsCodecVersion> <ehCacheVersion>2.6.9</ehCacheVersion> + <jFreeChartVersion>1.0.13</jFreeChartVersion> <nuitonWebVersion>1.16</nuitonWebVersion> <nuitonI18nVersion>3.1</nuitonI18nVersion> @@ -371,6 +372,12 @@ <version>${jsoupVersion}</version> </dependency> + <dependency> + <groupId>jfree</groupId> + <artifactId>jfreechart</artifactId> + <version>${jFreeChartVersion}</version> + </dependency> + </dependencies> </dependencyManagement> Modified: trunk/wao-services/pom.xml =================================================================== --- trunk/wao-services/pom.xml 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/wao-services/pom.xml 2014-06-12 08:20:27 UTC (rev 2024) @@ -92,6 +92,11 @@ </dependency> <dependency> + <groupId>jfree</groupId> + <artifactId>jfreechart</artifactId> + </dependency> + + <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> </dependency> Modified: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerSynthesis.java =================================================================== --- trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerSynthesis.java 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerSynthesis.java 2014-06-12 08:20:27 UTC (rev 2024) @@ -1,7 +1,7 @@ package fr.ifremer.wao.services.service; import fr.ifremer.wao.entity.Boat; -import fr.ifremer.wao.services.utils.BarChartData; +import org.jfree.chart.JFreeChart; import java.util.HashMap; import java.util.LinkedHashSet; @@ -11,9 +11,9 @@ public class ObsMerSynthesis { - protected BarChartData expectedVsActualObservationsByMonthsBarChartData; + protected JFreeChart expectedVsActualObservationsByMonthsChart; - protected BarChartData boardingBoatsBarChartData; + protected JFreeChart boardingBoatsChart; protected int maxBoardingValue; @@ -33,20 +33,20 @@ return companySyntheses; } - public BarChartData getExpectedVsActualObservationsByMonthsBarChartData() { - return expectedVsActualObservationsByMonthsBarChartData; + public JFreeChart getExpectedVsActualObservationsByMonthsChart() { + return expectedVsActualObservationsByMonthsChart; } - public void setExpectedVsActualObservationsByMonthsBarChartData(BarChartData expectedVsActualObservationsByMonthsBarChartData) { - this.expectedVsActualObservationsByMonthsBarChartData = expectedVsActualObservationsByMonthsBarChartData; + public void setExpectedVsActualObservationsByMonthsChart(JFreeChart expectedVsActualObservationsByMonthsChart) { + this.expectedVsActualObservationsByMonthsChart = expectedVsActualObservationsByMonthsChart; } - public BarChartData getBoardingBoatsBarChartData() { - return boardingBoatsBarChartData; + public JFreeChart getBoardingBoatsChart() { + return boardingBoatsChart; } - public void setBoardingBoatsBarChartData(BarChartData boardingBoatsBarChartData) { - this.boardingBoatsBarChartData = boardingBoatsBarChartData; + public void setBoardingBoatsChart(JFreeChart boardingBoatsChart) { + this.boardingBoatsChart = boardingBoatsChart; } public int getMaxBoardingValue() { Modified: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/SynthesisService.java =================================================================== --- trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/SynthesisService.java 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/SynthesisService.java 2014-06-12 08:20:27 UTC (rev 2024) @@ -11,12 +11,21 @@ import fr.ifremer.wao.entity.SampleRowTopiaDao; import fr.ifremer.wao.entity.SynthesisId; import fr.ifremer.wao.services.AuthenticatedWaoUser; -import fr.ifremer.wao.services.utils.BarChartData; -import fr.ifremer.wao.services.utils.ChartDataAxis; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.AbstractCategoryItemRenderer; +import org.jfree.chart.renderer.category.BarRenderer; +import org.jfree.data.category.DefaultCategoryDataset; +import org.jfree.ui.RectangleInsets; import org.nuiton.i18n.I18n; import org.nuiton.util.DateUtil; @@ -181,47 +190,39 @@ SortedMap<Date, Integer> actualObservationsMyMonths = contactDao.getActualObservationsByMonths(periodFromMonth, periodToMonth, filter); -// if (log.isTraceEnabled()) { -// DateFormat dateFormat = new SimpleDateFormat(monthsPeriod.getPattern()); -// for (Date month : monthsPeriod.getMonths()) { -// log.trace("for month " + dateFormat.format(month) -// + " expected is " + expectedObservationsByMonths.get(month) -// + " actual is " + actualObservationsMyMonths.get(month)); -// } -// } + DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - BarChartData.BarChartDataSeries expectedObservationsByMonthsBarChartDataSeries = - new BarChartData.BarChartDataSeries(); - expectedObservationsByMonthsBarChartDataSeries.setLabel(I18n.l(locale, "wao.synthesis.planned")); - for (Map.Entry<Date, Integer> expectedObservationMonth : expectedObservationsByMonths.entrySet()) { - Date month = expectedObservationMonth.getKey(); - String tick = WaoUtils.formatMonth(locale, month); - double value = expectedObservationMonth.getValue().doubleValue(); - expectedObservationsByMonthsBarChartDataSeries.addValue(tick, value); + for (Map.Entry<Date, Integer> entry : expectedObservationsByMonths.entrySet()) { + Date month = entry.getKey(); + Integer expected = entry.getValue(); + dataset.setValue(expected, I18n.l(locale, "wao.synthesis.planned"), WaoUtils.formatMonth(locale, month)); } - - BarChartData.BarChartDataSeries actualObservationsMyMonthsBarChartDataSeries = - new BarChartData.BarChartDataSeries(); - actualObservationsMyMonthsBarChartDataSeries.setLabel(I18n.l(locale, "wao.ui.samplingPlan.Actual")); - for (Map.Entry<Date, Integer> actualObservationsMyMonth : actualObservationsMyMonths.entrySet()) { - Date month = actualObservationsMyMonth.getKey(); - String tick = WaoUtils.formatMonth(locale, month); - double value = actualObservationsMyMonth.getValue().doubleValue(); - actualObservationsMyMonthsBarChartDataSeries.addValue(tick, value); + for (Map.Entry<Date, Integer> entry : actualObservationsMyMonths.entrySet()) { + Date month = entry.getKey(); + Integer actual = entry.getValue(); + dataset.setValue(actual, I18n.l(locale, "wao.ui.samplingPlan.Actual"), WaoUtils.formatMonth(locale, month)); } - BarChartData expectedVsActualObservationsByMonthsBarChartData = - new BarChartData(I18n.l(locale, SynthesisId.GRAPH_SAMPLING.getI18nKey())); + // Axises + CategoryAxis categoryAxis = new CategoryAxis(""); - ChartDataAxis yAxis = expectedVsActualObservationsByMonthsBarChartData.getYAxis(); - yAxis.setLabel(I18n.l(locale, "wao.synthesis.observationsCount")); - yAxis.setStep(10); + ValueAxis valueAxis = new NumberAxis(I18n.l(locale, "wao.synthesis.observationsCount")); + valueAxis.setUpperMargin(0.15); - expectedVsActualObservationsByMonthsBarChartData.addDotChartDataSeries(expectedObservationsByMonthsBarChartDataSeries); - expectedVsActualObservationsByMonthsBarChartData.addDotChartDataSeries(actualObservationsMyMonthsBarChartDataSeries); + // Renderer for Category + AbstractCategoryItemRenderer renderer = new BarRenderer(); + // Show labels on each element + renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); + renderer.setBaseItemLabelsVisible(Boolean.TRUE); - obsMerSynthesis.setExpectedVsActualObservationsByMonthsBarChartData(expectedVsActualObservationsByMonthsBarChartData); + CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + plot.setAxisOffset(RectangleInsets.ZERO_INSETS); + JFreeChart expectedVsActualObservationsByMonthsChart = + new JFreeChart(I18n.l(locale, SynthesisId.GRAPH_SAMPLING.getI18nKey()), JFreeChart.DEFAULT_TITLE_FONT, plot, true); + obsMerSynthesis.setExpectedVsActualObservationsByMonthsChart(expectedVsActualObservationsByMonthsChart); + } /** @@ -312,30 +313,38 @@ } } - BarChartData.BarChartDataSeries numberOfBoatsWithBoardingsBarChartDataSeries = - new BarChartData.BarChartDataSeries(); - numberOfBoatsWithBoardingsBarChartDataSeries.setLabel(I18n.l(locale, "wao.ui.chart.numberOfBoatsWithBoardings")); + obsMerSynthesis.setMaxBoardingValue(maxBoardingCount); + obsMerSynthesis.setMaxBoardingBoat(maxBoardingBoat); + obsMerSynthesis.setBoardingsCount(boardingTotal); + obsMerSynthesis.setInvalidBoardingsCount(invalidBoardingTotal); + obsMerSynthesis.setValidBoardingsCount(boardingTotal - invalidBoardingTotal); + DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + for (Map.Entry<Integer, Integer> entry : mapBoarding.entrySet()) { - numberOfBoatsWithBoardingsBarChartDataSeries.addValue(String.valueOf(entry.getKey()), entry.getValue()); + dataset.setValue(entry.getValue(), I18n.l(locale, "wao.ui.chart.numberOfBoatsWithBoardings"), String.valueOf(entry.getKey())); } - BarChartData boardingBoatsBarChartData = - new BarChartData(I18n.l(locale, SynthesisId.GRAPH_BOARDING.getI18nKey())); + // Axises + CategoryAxis categoryAxis = new CategoryAxis(I18n.l(locale, "wao.ui.chart.numberOfBoatsWithBoardings")); - ChartDataAxis yAxis = boardingBoatsBarChartData.getYAxis(); - yAxis.setLabel(I18n.l(locale, "wao.ui.chart.numberBoats")); - yAxis.setStep(10); + ValueAxis valueAxis = new NumberAxis(I18n.l(locale, "wao.ui.chart.numberBoats")); + valueAxis.setUpperMargin(0.15); - boardingBoatsBarChartData.addDotChartDataSeries(numberOfBoatsWithBoardingsBarChartDataSeries); + // Renderer for Category + AbstractCategoryItemRenderer renderer = new BarRenderer(); + // Show labels on each element + renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); + renderer.setBaseItemLabelsVisible(Boolean.TRUE); - obsMerSynthesis.setMaxBoardingValue(maxBoardingCount); - obsMerSynthesis.setMaxBoardingBoat(maxBoardingBoat); - obsMerSynthesis.setBoardingsCount(boardingTotal); - obsMerSynthesis.setInvalidBoardingsCount(invalidBoardingTotal); - obsMerSynthesis.setValidBoardingsCount(boardingTotal - invalidBoardingTotal); + CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + plot.setAxisOffset(RectangleInsets.ZERO_INSETS); - obsMerSynthesis.setBoardingBoatsBarChartData(boardingBoatsBarChartData); + JFreeChart boardingBoatsChart = + new JFreeChart(I18n.l(locale, SynthesisId.GRAPH_BOARDING.getI18nKey()), JFreeChart.DEFAULT_TITLE_FONT, plot, true); + obsMerSynthesis.setBoardingBoatsChart(boardingBoatsChart); + } } Modified: trunk/wao-web/pom.xml =================================================================== --- trunk/wao-web/pom.xml 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/wao-web/pom.xml 2014-06-12 08:20:27 UTC (rev 2024) @@ -163,6 +163,11 @@ <artifactId>jsoup</artifactId> </dependency> + <dependency> + <groupId>jfree</groupId> + <artifactId>jfreechart</artifactId> + </dependency> + </dependencies> <build> Added: trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/JFreeChartToImgTagConverter.java =================================================================== --- trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/JFreeChartToImgTagConverter.java (rev 0) +++ trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/JFreeChartToImgTagConverter.java 2014-06-12 08:20:27 UTC (rev 2024) @@ -0,0 +1,48 @@ +package fr.ifremer.wao.web.converter; + +import com.google.common.io.BaseEncoding; +import fr.ifremer.wao.WaoTechnicalException; +import org.apache.struts2.util.StrutsTypeConverter; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Map; + +public class JFreeChartToImgTagConverter extends StrutsTypeConverter { + + @Override + public Object convertFromString(Map context, String[] values, Class toClass) { + throw new UnsupportedOperationException(); + } + + @Override + public String convertToString(Map context, Object o) { + + if (o instanceof JFreeChart) { + + JFreeChart chart = (JFreeChart) o; + + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + try { + ChartUtilities.writeChartAsPNG(output, chart, 1000, 600); + } catch (IOException e) { + throw new WaoTechnicalException("unable to write chart to PNG", e); + } + + byte[] bytes = output.toByteArray(); + + String base64code = BaseEncoding.base64().encode(bytes); + + String html = "<img alt=\"" + chart.getTitle() + "\" src=\"data:image/png;base64," + base64code + "\" />"; + + return html; + + } else { + throw new WaoTechnicalException("unable to convert " + o); + } + } + +} Modified: trunk/wao-web/src/main/resources/fr/ifremer/wao/services/service/ObsMerSynthesis-conversion.properties =================================================================== --- trunk/wao-web/src/main/resources/fr/ifremer/wao/services/service/ObsMerSynthesis-conversion.properties 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/wao-web/src/main/resources/fr/ifremer/wao/services/service/ObsMerSynthesis-conversion.properties 2014-06-12 08:20:27 UTC (rev 2024) @@ -1,2 +1,2 @@ -expectedVsActualObservationsByMonthsBarChartData=fr.ifremer.wao.web.converter.BarChartDataConverter -boardingBoatsBarChartData=fr.ifremer.wao.web.converter.BarChartDataConverter +expectedVsActualObservationsByMonthsChart=fr.ifremer.wao.web.converter.JFreeChartToImgTagConverter +boardingBoatsChart=fr.ifremer.wao.web.converter.JFreeChartToImgTagConverter Modified: trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/synthesis.jsp =================================================================== --- trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/synthesis.jsp 2014-06-12 07:21:00 UTC (rev 2023) +++ trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/synthesis.jsp 2014-06-12 08:20:27 UTC (rev 2024) @@ -30,17 +30,6 @@ <s:text name="wao.ui.page.Synthesis.title"/> </title> - <script src="<s:url value="/jqplot-1.0.8/jquery.jqplot.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.categoryAxisRenderer.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.pointLabels.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.canvasTextRenderer.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.canvasAxisLabelRenderer.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.canvasAxisTickRenderer.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.enhancedLegendRenderer.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.barRenderer.js" />"></script> - <script src="<s:url value="/jqplot-1.0.8/plugins/jqplot.barRenderer.js" />"></script> - <link rel="stylesheet" href="<s:url value="/jqplot-1.0.8/jquery.jqplot.css" />" /> - <script type="text/javascript"> $(document).ready(function() { @@ -106,9 +95,6 @@ contactsFilterController2 = new FilterController2(contactsFilterMappings, filter, WAO.OBSMER_CONTACTS_FILTER_VALUES_JSON_URL, $('#synthesis-filters-form fieldset.extra-filters')); contactsFilterController2.init(); - $.jqplot('expected-vs-actual-observations-by-months-chart', <s:property value="synthesis.expectedVsActualObservationsByMonthsBarChartData" escapeHtml="false"/>); - $.jqplot('boarding-boats-chart', <s:property value="synthesis.boardingBoatsBarChartData" escapeHtml="false"/>); - }); </script> @@ -181,7 +167,7 @@ <s:text name="SynthesisId.GRAPH_SAMPLING"/> </h2> - <div id="expected-vs-actual-observations-by-months-chart" class="chart"></div> + <s:property value="synthesis.expectedVsActualObservationsByMonthsChart" escapeHtml="false"/> </article> <article> @@ -189,7 +175,7 @@ <s:text name="SynthesisId.GRAPH_BOARDING"/> </h2> - <div id="boarding-boats-chart" class="chart"></div> + <s:property value="synthesis.boardingBoatsChart" escapeHtml="false"/> <p> <s:text name="wao.ui.synthesis.boarding.description"/>