From 20a97904517c0adeca9c7c337e16d7ae3eb6d1e6 Mon Sep 17 00:00:00 2001 From: Olivier Maury <Olivier.Maury@inrae.fr> Date: Wed, 27 Sep 2023 14:28:00 +0200 Subject: [PATCH] =?UTF-8?q?Afficher=20les=20valeurs=20de=20meant=20annuel?= =?UTF-8?q?=20pour=20l'ann=C3=A9e=20en=20cours=20au=20chargement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/start_codeserver.sh | 1 + config/pmd-suppressions.properties | 8 +- .../www/client/i18n/AppConstants.java | 18 +- .../www/client/i18n/AppMessages.java | 8 +- .../www/client/presenter/LayoutPresenter.java | 43 +++- .../www/client/presenter/MapPresenter.java | 30 ++- .../www/client/util/DateUtils.java | 29 +++ .../www/client/view/LayoutView.java | 209 +++++++++++------- .../client/i18n/AppConstants_fr.properties | 3 +- .../www/client/i18n/AppMessages_fr.properties | 8 +- .../www/server/dao/DailyValueDao.java | 20 +- .../server/dao/DailyValueDaoHibernate.java | 36 ++- .../www/server/dao/IndicatorDaoHibernate.java | 3 +- .../www/server/rs/IndicatorResource.java | 78 +++++-- .../dao/DailyValueDaoHibernateTest.java | 31 ++- .../www/server/rs/IndicatorResourceTest.java | 17 +- .../agrometinfo/www/shared/dto/ChoiceDTO.java | 31 ++- .../www/shared/dto/ErrorResponseDTO.java | 79 +++++++ .../www/shared/dto/IndicatorDTO.java | 24 +- ...dicatorCategoryDTO.java => PeriodDTO.java} | 12 +- .../www/shared/service/IndicatorService.java | 41 ++-- 21 files changed, 528 insertions(+), 201 deletions(-) create mode 100644 www-client/src/main/java/fr/agrometinfo/www/client/util/DateUtils.java create mode 100644 www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ErrorResponseDTO.java rename www-shared/src/main/java/fr/agrometinfo/www/shared/dto/{IndicatorCategoryDTO.java => PeriodDTO.java} (60%) diff --git a/bin/start_codeserver.sh b/bin/start_codeserver.sh index 30b1c24..f48b6df 100755 --- a/bin/start_codeserver.sh +++ b/bin/start_codeserver.sh @@ -1,6 +1,7 @@ #!/bin/bash DIR=$(dirname $0) cd $DIR/.. +mvn clean install --projects=.,www-shared if [ "$1" == "" ]; then mvn gwt:codeserver -pl *-client -am else diff --git a/config/pmd-suppressions.properties b/config/pmd-suppressions.properties index 0d0eea0..fd6a1ac 100644 --- a/config/pmd-suppressions.properties +++ b/config/pmd-suppressions.properties @@ -1,11 +1,11 @@ # See https://maven.apache.org/plugins/maven-pmd-plugin/examples/violation-exclusions.html # annotations generate not clean code -fr.agrometinfo.www.shared.dto.IndicatorCategoryDTOBeanJsonDeserializerImpl=UnnecessaryImport -fr.agrometinfo.www.shared.dto.IndicatorCategoryDTOBeanJsonSerializerImpl=UnnecessaryImport -fr.agrometinfo.www.shared.dto.IndicatorCategoryDTO_MapperImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.IndicatorDTOBeanJsonDeserializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.IndicatorDTOBeanJsonSerializerImpl=UnnecessaryImport fr.agrometinfo.www.shared.dto.IndicatorDTO_MapperImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.PeriodDTOBeanJsonDeserializerImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.PeriodDTOBeanJsonSerializerImpl=UnnecessaryImport +fr.agrometinfo.www.shared.dto.PeriodDTO_MapperImpl=UnnecessaryImport fr.agrometinfo.www.shared.service.IndicatorServiceFactory=UnnecessaryImport org.geojson.FeatureBeanJsonDeserializerImpl=UnnecessaryImport org.geojson.FeatureBeanJsonSerializerImpl=UnnecessaryImport @@ -21,4 +21,4 @@ org.geojson.PolygonBeanJsonDeserializerImpl=UnnecessaryImport org.geojson.PolygonBeanJsonSerializerImpl=UnnecessaryImport org.geojson.Polygon_MapperImpl=UnnecessaryImport # wrong positive -fr.agrometinfo.www.server.dao.RegionDaoHibernate=UselessOverridingMethod \ No newline at end of file +fr.agrometinfo.www.server.dao.RegionDaoHibernate=UselessOverridingMethod diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java index a7e4255..e5c58a8 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppConstants.java @@ -51,6 +51,12 @@ public interface AppConstants extends com.google.gwt.i18n.client.ConstantsWithLo @DefaultStringValue("Choose an indicator") String chooseIndicator(); + /** + * @return translation + */ + @DefaultStringValue("Choose period") + String choosePeriod(); + /** * @return translation */ @@ -154,12 +160,6 @@ public interface AppConstants extends com.google.gwt.i18n.client.ConstantsWithLo @DefaultStringValue("HTTP status text:") String failureStatusText(); - /** - * @return translation - */ - @DefaultStringValue("Indicator categories") - String indicatorCategories(); - /** * @return translation */ @@ -178,6 +178,12 @@ public interface AppConstants extends com.google.gwt.i18n.client.ConstantsWithLo @DefaultStringValue("Log out") String logout(); + /** + * @return translation + */ + @DefaultStringValue("Metropolitan France") + String metropolitanFrance(); + /** * @return translation */ diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java index 90a3783..40f1da0 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/i18n/AppMessages.java @@ -35,10 +35,10 @@ public interface AppMessages extends Messages { * @param nb nb * @return translation */ - @DefaultMessage("{0} indicator categories.") - @AlternateMessage({"=0", "No indicator categories.", // - "=1", "1 indicator category."}) - String nbOfIndicatorCategories(@PluralCount int nb); + @DefaultMessage("{0} periods.") + @AlternateMessage({"=0", "No period.", // + "=1", "1 period."}) + String nbOfIndicatorPeriods(@PluralCount int nb); /** * @param nb nb diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java index beafb19..30f2017 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/LayoutPresenter.java @@ -1,9 +1,9 @@ package fr.agrometinfo.www.client.presenter; import java.util.List; +import java.util.Map; import java.util.Objects; -import org.dominokit.domino.ui.notifications.Notification; import org.dominokit.rest.shared.request.FailedResponseBean; import com.google.gwt.core.client.GWT; @@ -11,8 +11,9 @@ import com.google.gwt.user.client.Cookies; import fr.agrometinfo.www.client.view.BaseView; import fr.agrometinfo.www.client.view.LayoutView; +import fr.agrometinfo.www.client.view.MapView; import fr.agrometinfo.www.shared.dto.ChoiceDTO; -import fr.agrometinfo.www.shared.dto.IndicatorCategoryDTO; +import fr.agrometinfo.www.shared.dto.PeriodDTO; import fr.agrometinfo.www.shared.service.IndicatorServiceFactory; /** @@ -40,9 +41,19 @@ public final class LayoutPresenter implements Presenter { void setDevMode(boolean isDevMode); /** - * @param list indicator categories + * @param list indicator periods with indicators */ - void setIndicatorCategories(List<IndicatorCategoryDTO> list); + void setPeriods(List<PeriodDTO> list); + + /** + * @param list regions with indicators + */ + void setRegions(Map<String, String> list); + + /** + * @param list years of computed values + */ + void setYears(List<Integer> list); } /** @@ -50,6 +61,11 @@ public final class LayoutPresenter implements Presenter { */ private LayoutView view; + /** + * Presenter for {@link MapView}. + */ + private final MapPresenter mapPresenter = new MapPresenter(); + /** * @see https://github.com/gwtproject/gwt/issues/7631#issuecomment-110876116 * @return if the application is running in (Super) DevMode. @@ -70,9 +86,7 @@ public final class LayoutPresenter implements Presenter { * @param choice the user's choice */ public void onChoiceChange(final ChoiceDTO choice) { - Notification.createSuccess(choice.toString()) - .setPosition(Notification.TOP_LEFT) - .show(); + mapPresenter.loadValues(choice); } /** @@ -87,11 +101,22 @@ public final class LayoutPresenter implements Presenter { GWT.log("LayoutPresenter.start()"); view = new LayoutView(); view.setPresenter(this); + view.setMapPresenter(mapPresenter); view.init(); view.setDevMode(isDevMode()); - IndicatorServiceFactory.INSTANCE.getIndicatorCategories() // - .onSuccess(view::setIndicatorCategories) // + IndicatorServiceFactory.INSTANCE.getPeriods() // + .onSuccess(view::setPeriods) // + .onFailed(view::failureNotification) // + .send(); + + IndicatorServiceFactory.INSTANCE.getRegions() // + .onSuccess(view::setRegions) // + .onFailed(view::failureNotification) // + .send(); + + IndicatorServiceFactory.INSTANCE.getYears() // + .onSuccess(view::setYears) // .onFailed(view::failureNotification) // .send(); } diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java index 95dbb1d..18a3ba9 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/presenter/MapPresenter.java @@ -8,6 +8,7 @@ import org.dominokit.domino.ui.modals.Window; import org.dominokit.domino.ui.typography.Paragraph; import org.dominokit.domino.ui.utils.DominoElement; import org.dominokit.rest.JsRestfulRequestFactory; +import org.dominokit.rest.shared.RestfulRequest; import org.geojson.FeatureCollection; import org.pepstock.charba.client.BarChart; import org.pepstock.charba.client.colors.HtmlColor; @@ -22,6 +23,7 @@ import elemental2.dom.Node; import fr.agrometinfo.www.client.i18n.AppConstants; import fr.agrometinfo.www.client.view.BaseView; import fr.agrometinfo.www.client.view.MapView; +import fr.agrometinfo.www.shared.dto.ChoiceDTO; import fr.agrometinfo.www.shared.service.IndicatorService; /** @@ -50,6 +52,12 @@ public final class MapPresenter implements Presenter { */ private static final AppConstants CSTS = GWT.create(AppConstants.class); + /** + * URL to get indicator values. + */ + private static final String VALUES_URL = GWT.getModuleBaseURL().replace("/app/", "") + "/rs/" + + IndicatorService.PATH + "/" + IndicatorService.PATH_VALUES; + /** * Container for the map. */ @@ -61,13 +69,23 @@ public final class MapPresenter implements Presenter { private View view; /** - * Load cells from the server. + * Load indicator values on the map. + * + * @param choice user choice for the indicator values */ - public void loadCells() { + public void loadValues(final ChoiceDTO choice) { final JsRestfulRequestFactory factory = new JsRestfulRequestFactory(); - final String url = GWT.getModuleBaseURL().replace("/app/", "") + "/rs/" + IndicatorService.PATH + "/" - + IndicatorService.PATH_CELLS; - factory.get(url).onSuccess(response -> { + final RestfulRequest request = factory.get(VALUES_URL); + request.addQueryParam("indicator", choice.getIndicator()); + if (choice.getPeriod() != null) { + request.addQueryParam("period", choice.getPeriod()); + } + if (choice.getRegion() != null) { + request.addQueryParam("region", choice.getRegion()); + } + request.addQueryParam("year", String.valueOf(choice.getYear())); + request.addQueryParam("comparison", String.valueOf(choice.getComparison())); + request.onSuccess(response -> { view.setGeoJson(response.getBodyAsString()); }).send(); } @@ -110,7 +128,7 @@ public final class MapPresenter implements Presenter { .setSize(IsModalDialog.ModalSize.LARGE) // .setHeaderBackground(Color.PINK) .add(Paragraph.create("Paragraphe !" + ids)).appendChild((Node) chartElement.as()) - .appendFooterChild(Button.create(CSTS.close()).addClickListener(evt -> window.close())).open(); + .appendFooterChild(Button.create(CSTS.close()).addClickListener(evt -> window.close())).open(); } /** diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/util/DateUtils.java b/www-client/src/main/java/fr/agrometinfo/www/client/util/DateUtils.java new file mode 100644 index 0000000..92ae65b --- /dev/null +++ b/www-client/src/main/java/fr/agrometinfo/www/client/util/DateUtils.java @@ -0,0 +1,29 @@ +package fr.agrometinfo.www.client.util; + +import java.util.Date; + +/** + * Helper class for Date. + * + * Indeed, as GWT does not handle LocalDate, we still use java.util.date. + * + * @author Olivier Maury + */ +public interface DateUtils { + /** + * @return the current year. + */ + static int getCurrentYear() { + return getYear(new Date()); + } + + /** + * @param date date to handle + * @return extracted year from date + */ + @SuppressWarnings("deprecation") + private static int getYear(final Date date) { + final int offset = 1900; + return date.getYear() + offset; + } +} diff --git a/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java b/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java index ea46425..f8af4d2 100644 --- a/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java +++ b/www-client/src/main/java/fr/agrometinfo/www/client/view/LayoutView.java @@ -8,6 +8,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.StringJoiner; import org.dominokit.domino.ui.button.Button; @@ -52,8 +53,8 @@ import fr.agrometinfo.www.client.presenter.MapPresenter; import fr.agrometinfo.www.client.ui.AgroclimAppsMenu; import fr.agrometinfo.www.client.ui.HTMLSelectElementBuilder; import fr.agrometinfo.www.shared.dto.ChoiceDTO; -import fr.agrometinfo.www.shared.dto.IndicatorCategoryDTO; import fr.agrometinfo.www.shared.dto.IndicatorDTO; +import fr.agrometinfo.www.shared.dto.PeriodDTO; /** * View for the general layout. @@ -61,6 +62,10 @@ import fr.agrometinfo.www.shared.dto.IndicatorDTO; * @author Olivier Maury */ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implements LayoutPresenter.View { + /** + * Code of indicator to show by default. + */ + private static final String DEFAULT_INDICATOR = "meant"; /** * I18N constants. @@ -81,7 +86,7 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen menu.add(link); } - private static void addMenuItem(final Menu<String> menu, final String text, final MdiIcon icon, final String url) { + private static void addMenuItem(final Menu<String> menu, final String text, final MdiIcon icon, final String url) { final Runnable runnable; if (url.startsWith("http")) { runnable = () -> DomGlobal.window.open(url, "_blank"); @@ -91,11 +96,6 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen addMenuItem(menu, text, icon, runnable); } - private static HtmlContentBuilder<HTMLElement> faIcon(final String className, final String color) { - // <i class="fas fa-cloud-showers-heavy" style="color:#AAAAAA;"></i> - return Elements.i().css("fas " + className).style("color:" + color); - } - private static String getDetails(final FailedResponseBean failure) { final StringJoiner sj = new StringJoiner("<br/>"); sj.add(CSTS.failureBody()); @@ -108,11 +108,6 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen return sj.toString(); } - /** - * Container for the categories. - */ - private final HtmlContentBuilder<HTMLDivElement> categoriesElem = Elements.div().css("indicator-categories"); - /** * Choice from the user. */ @@ -138,6 +133,11 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen */ private final HtmlContentBuilder<HTMLSelectElement> indicatorSelect = select(); + /** + * Selector for indicator periods. + */ + private final HtmlContentBuilder<HTMLSelectElement> periodSelect = select(); + /** * Application layout. */ @@ -161,6 +161,16 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen */ private final Menu<String> userDropMenu = Menu.<String>create(); + /** + * Presenter for {@link MapView}. + */ + private MapPresenter mapPresenter; + + /** + * Available indicator periods with indicators. + */ + private List<PeriodDTO> periods; + /** * @param text link text * @param callback {@link EventCallbackFn<MouseEvent>} to be added to the click @@ -218,62 +228,42 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen panel.appendChild(summary); // - GWT.log("initLeftPanel() categories"); - panel.appendChild(BlockHeader.create(CSTS.indicatorCategories()).element()); - panel.appendChild(categoriesElem); + GWT.log("initLeftPanel() periods"); + panel.appendChild(BlockHeader.create(CSTS.choosePeriod()).element()); + panel.appendChild(periodSelect); + new HTMLSelectElementBuilder<PeriodDTO>() // + .setSelect(periodSelect) // + .setPrompt(CSTS.selectPrompt()) // + .addValueChangeHandler(this::onPeriodChange) // + .build(); // GWT.log("initLeftPanel() indicators"); panel.appendChild(BlockHeader.create(CSTS.chooseIndicator()).element()); panel.appendChild(indicatorSelect); + new HTMLSelectElementBuilder<IndicatorDTO>() // + .setSelect(indicatorSelect) // + .setPrompt(CSTS.selectPrompt()) // + .addValueChangeHandler(this::onIndicatorChange) // + .build(); // GWT.log("initLeftPanel() regions"); panel.appendChild(BlockHeader.create(CSTS.chooseRegion()).element()); - final Map<String, String> regionOptions = new HashMap<>(); - regionOptions.put("1", "Guadeloupe"); - regionOptions.put("2", "Martinique"); - regionOptions.put("3", "Guyane"); - regionOptions.put("4", "La Réunion"); - regionOptions.put("6", "Mayotte"); - regionOptions.put("11", "Île-de-France"); - regionOptions.put("24", "Centre-Val de Loire"); - regionOptions.put("27", "Bourgogne-Franche-Comté"); - regionOptions.put("28", "Normandie"); - regionOptions.put("32", "Hauts-de-France"); - regionOptions.put("44", "Grand Est"); - regionOptions.put("52", "Pays de la Loire"); - regionOptions.put("53", "Bretagne"); - regionOptions.put("75", "Nouvelle-Aquitaine"); - regionOptions.put("76", "Occitanie"); - regionOptions.put("84", "Auvergne-Rhône-Alpes"); - regionOptions.put("93", "Provence-Alpes-Côte d'Azur"); - regionOptions.put("94", "Corse"); new HTMLSelectElementBuilder<Entry<String, String>>() // .setSelect(regionSelect) // - .setPrompt(CSTS.selectPrompt()) // - .setTextFunction(Entry<String, String>::getValue) // - .setValueFunction(Entry<String, String>::getKey) // + .setPrompt(CSTS.metropolitanFrance()) // .addValueChangeHandler(this::onRegionChange) // - .addOptions(regionOptions.entrySet()) // .build(); panel.appendChild(regionSelect); // GWT.log("initLeftPanel() year"); panel.appendChild(BlockHeader.create(CSTS.chooseYear())); - final Map<String, String> yearOptions = new HashMap<>(); - yearOptions.put("1998", "1998"); - yearOptions.put("2001", "2001"); - yearOptions.put("2003", "2003"); - yearOptions.put("2023", "2023"); new HTMLSelectElementBuilder<Entry<String, String>>() // .setSelect(yearSelect) // .setPrompt(CSTS.selectPrompt()) // - .setTextFunction(Entry<String, String>::getValue) // - .setValueFunction(Entry<String, String>::getKey) // - .addValueChangeHandler(this::onYearChange) // - .addOptions(yearOptions.entrySet()); + .addValueChangeHandler(this::onYearChange); panel.appendChild(yearSelect); // @@ -307,10 +297,15 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen // setContentPanelHeight(); Window.addResizeHandler(e -> setContentPanelHeight()); - final MapPresenter mapPresenter = new MapPresenter(); mapPresenter.setContainer(layout.getContentPanel()); mapPresenter.start(); - mapPresenter.loadCells(); + // final ChoiceDTO defaultChoice = new ChoiceDTO(); + // defaultChoice.setComparison(false); + // defaultChoice.setIndicator("meant"); + // defaultChoice.setRegion(null); + // defaultChoice.setPeriod("year"); + // defaultChoice.setYear(DateUtils.getCurrentYear()); + // mapPresenter.loadValues(defaultChoice); } private void initTopBar() { @@ -337,8 +332,7 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen .hideOn(ScreenMedia.SMALL_AND_DOWN) // .setDropMenu(new AgroclimAppsMenu())) // .appendChild(DominoElement.of(li() // - .css(Styles.pull_right) - .add(a() // + .css(Styles.pull_right).add(a() // .add(Icons.ALL.dots_vertical_mdi().clickable()))) .showOn(ScreenMedia.SMALL_AND_DOWN) // .hideOn(ScreenMedia.MEDIUM_AND_UP) // @@ -367,25 +361,53 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen } private void onComparisonChange(final Boolean newValue) { - notification("Item selected [ " + newValue + " ]"); choice.setComparison(newValue); onChoiceChange(); } private void onIndicatorChange(final String newValue) { - notification("Item selected [ " + newValue + " ]"); choice.setIndicator(newValue); onChoiceChange(); } + private void onPeriodChange(final String newValue) { + choice.setPeriod(newValue); + choice.setIndicator(null); + + // fill indicators + // TODO clear select + List<IndicatorDTO> list = null; + for (final PeriodDTO p : this.periods) { + if (p.getCode().equals(newValue)) { + list = p.getIndicators(); + break; + } + } + if (list == null) { + return; + } + DomGlobal.console.info("Indicators : " + list); + new HTMLSelectElementBuilder<IndicatorDTO>() // + .setSelect(indicatorSelect) // + .setTextFunction(IndicatorDTO::getDescription) // + .setValueFunction(IndicatorDTO::getCode) // + .addOptions(list) // + .build(); + // select "meant" + if (list.stream().map(IndicatorDTO::getCode).anyMatch(DEFAULT_INDICATOR::equals)) { + indicatorSelect.element().value = DEFAULT_INDICATOR; + onIndicatorChange(DEFAULT_INDICATOR); + } else { + onChoiceChange(); + } + } + private void onRegionChange(final String newValue) { - notification("Item selected [ " + newValue + " ]"); choice.setRegion(newValue); onChoiceChange(); } private void onYearChange(final String newValue) { - notification("Item selected [ " + newValue + " ]"); try { choice.setYear(Integer.valueOf(newValue)); } catch (final NumberFormatException e) { @@ -421,39 +443,62 @@ public final class LayoutView extends AbstractBaseView<LayoutPresenter> implemen } } + /** + * @param presenter presenter for {@link MapView}. + */ + public void setMapPresenter(final MapPresenter presenter) { + this.mapPresenter = presenter; + } + @Override - public void setIndicatorCategories(final List<IndicatorCategoryDTO> list) { + public void setPeriods(final List<PeriodDTO> list) { + this.periods = list; // summary final StringJoiner sj = new StringJoiner(" "); - sj.add(MSGS.nbOfIndicatorCategories(list.size())); + sj.add(MSGS.nbOfIndicatorPeriods(list.size())); sj.add(MSGS.nbOfIndicators(list.stream().mapToInt(c -> c.getIndicators().size()).sum())); summary.textContent = sj.toString(); - // categories - for (final IndicatorCategoryDTO category : list) { - final Icon icon = Icons.ALL.wb_sunny(); - icon.setColor("#f3b80e"); - icon.setTooltip(category.getDescription(), PopupPosition.RIGHT); - categoriesElem.add(icon); - } - categoriesElem.addAll(// - faIcon("fa-cloud-showers-heavy", "#AAAAAA"), // - faIcon("fa-snowflake", "#3db0c8"), // - faIcon("fa-thermometer-quarter", "#87CEFA"), // - faIcon("fa-thermometer-three-quarters", "#FF0000"), // - faIcon("fa-thermometer-half", "#8B4513") // - ); - // indicators - if (!list.isEmpty()) { - DomGlobal.console.info("Indicators : " + list); - new HTMLSelectElementBuilder<IndicatorDTO>() // - .setSelect(indicatorSelect) // - .setPrompt(CSTS.selectPrompt()) // - .setTextFunction(IndicatorDTO::getUid) // - .setValueFunction(IndicatorDTO::getDescription) // - .addValueChangeHandler(this::onIndicatorChange) // - .addOptions(list.get(0).getIndicators()) // - .build(); + + if (this.periods.isEmpty()) { + return; } + // display periods + DomGlobal.console.info("Periods : " + list); + new HTMLSelectElementBuilder<PeriodDTO>() // + .setSelect(periodSelect) // + .setTextFunction(PeriodDTO::getDescription) // + .setValueFunction(PeriodDTO::getCode) // + .addOptions(list) // + .build(); + // select "year" + periodSelect.element().value = "year"; + onPeriodChange(periodSelect.element().value); + } + @Override + public void setRegions(final Map<String, String> list) { + new HTMLSelectElementBuilder<Entry<String, String>>() // + .setSelect(regionSelect) // + .setTextFunction(Entry<String, String>::getValue) // + .setValueFunction(Entry<String, String>::getKey) // + .addOptions(list.entrySet()) // + .build(); + } + + @Override + public void setYears(final List<Integer> list) { + final Map<String, String> yearOptions = new HashMap<>(); + list.forEach(y -> yearOptions.put(String.valueOf(y), String.valueOf(y))); + new HTMLSelectElementBuilder<Entry<String, String>>() // + .setSelect(yearSelect) // + .setTextFunction(Entry<String, String>::getValue) // + .setValueFunction(Entry<String, String>::getKey) // + .addOptions(yearOptions.entrySet()); + final Optional<Integer> defaultYear = list.stream().max(Integer::compare); + defaultYear.ifPresent(year -> { + yearSelect.element().value = year.toString(); + choice.setYear(year); + onChoiceChange(); + }); } } diff --git a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties index f53f276..9fca179 100644 --- a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties +++ b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppConstants_fr.properties @@ -6,6 +6,7 @@ agroclimApps = Les applications d’AgroClim applicationLoading = Chargement de l’application… cancel= Annuler chooseIndicator= Choisir un indicateur +choosePeriod= Choisir une période chooseRegion= Choisir une région chooseYear= Choisir une année close = Fermer @@ -23,10 +24,10 @@ exportData= Exporter les données failureBody = Corps : failureHeaders = Entêtes HTTP : failureStatusText = Texte d’état HTTP : -indicatorCategories= Catégories d’indicateurs login = Se connecter loginOrSignIn = ou s’inscrire avec logout = Se déconnecter +metropolitanFrance = France métropolitaine no= Non normalComparison= Comparaison à la normale normalComparisonTooltip= <b>La comparaison à la normale</b> <em>se calcule en soustrayant <b>la moyenne de l’indicateur choisi</b> pour les trente dernières années (1990-2020) de <b>l’année sélectionnée</b> diff --git a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties index b92a648..758ba39 100644 --- a/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties +++ b/www-client/src/main/resources/fr/agrometinfo/www/client/i18n/AppMessages_fr.properties @@ -1,10 +1,10 @@ # Ce fichier est encodé en UTF-8. account = Compte de {0} ({1}) failureStatusCode = Code d’état HTTP : {0} -nbOfIndicatorCategories[\=0] = Aucune catégorie d’indicateurs. -nbOfIndicatorCategories[\=1] = Une catégorie d’indicateurs. -nbOfIndicatorCategories[one] = Une catégorie d’indicateurs. -nbOfIndicatorCategories = {0} catégories d’indicateurs. +nbOfIndicatorPeriods[\=0] = Aucune catégorie d’indicateurs. +nbOfIndicatorPeriods[\=1] = Une catégorie d’indicateurs. +nbOfIndicatorPeriods[one] = Une catégorie d’indicateurs. +nbOfIndicatorPeriods = {0} catégories d’indicateurs. nbOfIndicators[\=0] = Aucun indicateur. nbOfIndicators[\=1] = Un indicateur. nbOfIndicators[one] = Un indicateur. diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java index 8ff8ce7..6d297d0 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDao.java @@ -34,11 +34,27 @@ public interface DailyValueDao { List<DailyValue> find(Indicator indicator, Region region, LocalDate date); /** - * The last {@link DailyValue#getDate()} for the indicator. + * @return the indicators (with period) related to computed values + */ + List<Indicator> findIndicators(); + + /** + * The last {@link DailyValue#getDate()} for the indicator on a year. * * @param indicator indicator to search + * @param year year * @return last date or null */ - LocalDate findLastDate(Indicator indicator); + LocalDate findLastDate(Indicator indicator, Integer year); + + /** + * @return the regions related to computed values + */ + List<Region> findRegions(); + + /** + * @return the years related to computed values + */ + List<Integer> findYears(); } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernate.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernate.java index 4c0613d..bbd3b2b 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernate.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernate.java @@ -33,16 +33,42 @@ public class DailyValueDaoHibernate extends DaoHibernate<DailyValue> implements public final List<DailyValue> find(final Indicator indicator, final Region region, final LocalDate date) { final var jpql = """ SELECT t FROM DailyValue AS t - WHERE t.indicator=:indicator AND t.date=:date AND t.cell.department.region=:region - """; + WHERE t.indicator=:indicator AND t.date=:date AND t.cell.department.region=:region"""; return super.findAllByJPQL(jpql, Map.of("indicator", indicator, "date", date, "region", region), DailyValue.class); } @Override - public final LocalDate findLastDate(final Indicator indicator) { - final var jpql = "SELECT MAX(t.date) FROM DailyValue AS t WHERE t.indicator=:indicator"; - return super.findOneByJPQL(jpql, Map.of("indicator", indicator), LocalDate.class); + public final List<Indicator> findIndicators() { + final var jpql = "SELECT DISTINCT i FROM DailyValue AS t JOIN t.indicator AS i JOIN t.indicator.period"; + return super.findAllByJPQL(jpql, null, Indicator.class); + } + + @Override + public final LocalDate findLastDate(final Indicator indicator, final Integer year) { + final var jpql = """ + SELECT MAX(t.date) + FROM DailyValue AS t + WHERE t.indicator=:indicator AND EXTRACT(YEAR FROM t.date) = :year"""; + return super.findOneByJPQL(jpql, Map.of("indicator", indicator, "year", year), LocalDate.class); + } + + @Override + public final List<Region> findRegions() { + final var jpql = """ + SELECT DISTINCT r + FROM DailyValue AS t + JOIN t.cell AS c + JOIN c.department AS d + JOIN d.region AS r + ORDER BY r.name"""; + return super.findAllByJPQL(jpql, null, Region.class); + } + + @Override + public final List<Integer> findYears() { + final var jpql = "SELECT DISTINCT EXTRACT(YEAR FROM date) AS year FROM DailyValue AS t ORDER BY year"; + return super.findAllByJPQL(jpql, null, Integer.class); } } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/dao/IndicatorDaoHibernate.java b/www-server/src/main/java/fr/agrometinfo/www/server/dao/IndicatorDaoHibernate.java index 934149c..edeec7a 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/dao/IndicatorDaoHibernate.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/dao/IndicatorDaoHibernate.java @@ -4,6 +4,7 @@ import java.util.Map; import fr.agrometinfo.www.server.model.Indicator; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.validation.constraints.NotNull; /** * Hibernate implementation of {@link IndicatorDao}. @@ -28,7 +29,7 @@ public class IndicatorDaoHibernate extends DaoHibernate<Indicator> implements In * @return found or null */ @Override - public Indicator findByCodeAndPeriod(final String code, final String periodCode) { + public Indicator findByCodeAndPeriod(@NotNull final String code, @NotNull final String periodCode) { final var jpql = "SELECT t FROM Indicator AS t WHERE t.code=:code AND t.period.code=:periodCode"; return super.findOneByJPQL(jpql, Map.of("code", code, "periodCode", periodCode), Indicator.class); } diff --git a/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java b/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java index 39a2fd4..32b1e9b 100644 --- a/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java +++ b/www-server/src/main/java/fr/agrometinfo/www/server/rs/IndicatorResource.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; import org.geojson.Feature; import org.geojson.FeatureCollection; @@ -21,8 +22,9 @@ import fr.agrometinfo.www.server.model.DailyValue; import fr.agrometinfo.www.server.model.Indicator; import fr.agrometinfo.www.server.model.Region; import fr.agrometinfo.www.server.util.LocaleUtils; -import fr.agrometinfo.www.shared.dto.IndicatorCategoryDTO; +import fr.agrometinfo.www.shared.dto.ErrorResponseDTO; import fr.agrometinfo.www.shared.dto.IndicatorDTO; +import fr.agrometinfo.www.shared.dto.PeriodDTO; import fr.agrometinfo.www.shared.service.IndicatorService; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.RequestScoped; @@ -32,8 +34,10 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import lombok.extern.log4j.Log4j2; /** @@ -135,16 +139,23 @@ public class IndicatorResource implements IndicatorService { @Inject private DailyValueDao dailyValueDao; - @GET - @Path(IndicatorService.PATH_CELLS) - @Produces("application/geo+json") - @Override - public FeatureCollection getCells() { - final FeatureCollection collection = new FeatureCollection(); - cellDao.findAll().stream() // - .map(IndicatorResource::toFeature) // - .forEach(collection::add); - return collection; + /** + * Ensure the value of query parameter is not null and not blank. + * + * @param value value of query parameter to check + * @param queryParamName name of query parameter + * @throws WebApplicationException if validation failed. + */ + private void checkRequired(final Object value, final String queryParamName) { + if ((value instanceof final String str && str.isBlank()) || value == null) { + final var status = Response.Status.BAD_REQUEST; + throw new WebApplicationException( + Response.status(status) // + .entity(ErrorResponseDTO.of(status.getStatusCode(), // + status.getReasonPhrase(), // + queryParamName + " parameter is mandatory")) // + .build()); + } } /** @@ -154,40 +165,53 @@ public class IndicatorResource implements IndicatorService { @Path(IndicatorService.PATH_LIST) @Produces(MediaType.APPLICATION_JSON) @Override - public List<IndicatorCategoryDTO> getIndicatorCategories() { + public List<PeriodDTO> getPeriods() { // TODO : ajouter un cache (CacheControl, E-Tag et WebFilter) LOGGER.traceEntry(); final var locale = LocaleUtils.getLocale(httpServletRequest); - final var indicators = indicatorDao.findAll(); - final Map<Long, IndicatorCategoryDTO> dtos = new HashMap<>(); + final var indicators = dailyValueDao.findIndicators(); + final Map<Long, PeriodDTO> dtos = new HashMap<>(); for (final Indicator indicator : indicators) { final var p = indicator.getPeriod(); final var key = Long.valueOf(p.getId()); - if (!dtos.containsKey(key)) { - final var cat = new IndicatorCategoryDTO(); - cat.setDescription(getTranslation(p.getNames(), locale)); - cat.setUid(p.getCode()); - cat.setIndicators(new ArrayList<>()); - dtos.put(key, cat); - } + dtos.computeIfAbsent(key, k -> { + final var period = new PeriodDTO(); + period.setDescription(getTranslation(p.getNames(), locale)); + period.setCode(p.getCode()); + period.setIndicators(new ArrayList<>()); + return period; + }); final var dto = new IndicatorDTO(); dto.setDescription(getTranslation(indicator.getDescriptions(), locale)); - dto.setUid(indicator.getCode()); + dto.setCode(indicator.getCode()); dtos.get(key).getIndicators().add(dto); } return new ArrayList<>(dtos.values()); } + @GET + @Path(IndicatorService.PATH_REGIONS) + @Produces(MediaType.APPLICATION_JSON) + @Override + public Map<String, String> getRegions() { + return dailyValueDao.findRegions().stream()// + .collect(Collectors.toMap(r -> String.valueOf(r.getId()), Region::getName)); + } + @GET @Path(IndicatorService.PATH_VALUES) @Produces("application/geo+json") @Override public FeatureCollection getValues(@QueryParam(value = "indicator") final String indicatorUid, @QueryParam(value = "period") final String periodCode, @QueryParam(value = "region") final Integer regionId, + @QueryParam(value = "year") final Integer year, @QueryParam(value = "comparison") final Boolean comparison) { + checkRequired(indicatorUid, "indicator"); + checkRequired(periodCode, "period"); + checkRequired(year, "year"); final FeatureCollection collection = new FeatureCollection(); final Indicator indicator = indicatorDao.findByCodeAndPeriod(indicatorUid, periodCode); - final LocalDate date = dailyValueDao.findLastDate(indicator); + final LocalDate date = dailyValueDao.findLastDate(indicator, year); final Region region; if (regionId == null) { region = null; @@ -213,6 +237,14 @@ public class IndicatorResource implements IndicatorService { return collection; } + @GET + @Path(IndicatorService.PATH_YEARS) + @Produces(MediaType.APPLICATION_JSON) + @Override + public List<Integer> getYears() { + return dailyValueDao.findYears(); + } + @PostConstruct public void init() { LOGGER.traceEntry(); diff --git a/www-server/src/test/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernateTest.java b/www-server/src/test/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernateTest.java index c66c13f..69f4eb3 100644 --- a/www-server/src/test/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernateTest.java +++ b/www-server/src/test/java/fr/agrometinfo/www/server/dao/DailyValueDaoHibernateTest.java @@ -1,5 +1,6 @@ package fr.agrometinfo.www.server.dao; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; @@ -9,7 +10,7 @@ import fr.agrometinfo.www.server.model.Indicator; /** * Test DailyValueDao Hibernate implementation. */ -public class DailyValueDaoHibernateTest { +class DailyValueDaoHibernateTest { /** * DAO to test. */ @@ -20,10 +21,34 @@ public class DailyValueDaoHibernateTest { */ private final IndicatorDao indicatorDao = new IndicatorDaoHibernate(); + @Test + void findIndicators() { + final var actual = dao.findIndicators(); + assertNotNull(actual); + assertEquals(Integer.valueOf(1), actual.size()); + assertEquals("rainsum", actual.get(0).getCode()); + assertEquals("year", actual.get(0).getPeriod().getCode()); + } + @Test void findLastDate() { final var indicator = indicatorDao.findByCodeAndPeriod("rainsum", "year"); - final var lastDate = dao.findLastDate(indicator); - assertNotNull(lastDate); + final var actual = dao.findLastDate(indicator, 2023); + assertNotNull(actual); + } + + @Test + void findRegions() { + final var actual = dao.findRegions(); + assertNotNull(actual); + assertEquals(Integer.valueOf(1), actual.size()); + } + + @Test + void findYears() { + final var actual = dao.findYears(); + assertNotNull(actual); + assertEquals(Integer.valueOf(1), actual.size()); + assertEquals(Integer.valueOf(2023), actual.get(0)); } } diff --git a/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java b/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java index 9396d87..8add6c1 100644 --- a/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java +++ b/www-server/src/test/java/fr/agrometinfo/www/server/rs/IndicatorResourceTest.java @@ -11,7 +11,6 @@ import org.junit.jupiter.api.Test; import fr.agrometinfo.www.server.dao.CellDao; import fr.agrometinfo.www.server.dao.CellDaoHibernate; -import fr.agrometinfo.www.server.dao.CellDaoHibernateTest; import fr.agrometinfo.www.server.dao.DailyValueDao; import fr.agrometinfo.www.server.dao.DailyValueDaoHibernate; import fr.agrometinfo.www.server.dao.IndicatorDao; @@ -50,24 +49,16 @@ class IndicatorResourceTest extends JerseyTest { }); } - @Test - void getCells() { - final FeatureCollection actual = target(IndicatorResource.PATH + SEP + IndicatorResource.PATH_CELLS).request() - .get(FeatureCollection.class); - assertNotNull(actual); - final Integer expected = Long.valueOf(CellDaoHibernateTest.COUNT).intValue(); - assertEquals(expected, actual.getFeatures().size()); - } - /** * Expected values from sql/dailyvalues.csv. */ @Test void getValues() { final FeatureCollection actual = target(IndicatorResource.PATH + SEP + IndicatorResource.PATH_VALUES)// - .queryParam("indicator", "rainsum")// - .queryParam("period", "year")// - .queryParam("compare", "false")// + .queryParam("indicator", "rainsum") // + .queryParam("period", "year") // + .queryParam("compare", "false") // + .queryParam("year", "2023") // .request()// .get(FeatureCollection.class); assertNotNull(actual); diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java index b041c80..62a66dd 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ChoiceDTO.java @@ -10,13 +10,18 @@ public final class ChoiceDTO { /** * The user wants to compare with normal. */ - private Boolean comparison; + private Boolean comparison = false; /** * ID of chosen indicator. */ private String indicator; + /** + * Period code of chosen indicator. + */ + private String period; + /** * Chosen region. */ @@ -41,6 +46,13 @@ public final class ChoiceDTO { return indicator; } + /** + * @return Period code of chosen indicator. + */ + public String getPeriod() { + return period; + } + /** * @return Chosen region. */ @@ -59,10 +71,9 @@ public final class ChoiceDTO { * @return the user chose all options */ public boolean isValid() { - return indicator != null && !indicator.trim().isEmpty() // - && region != null && !region.trim().isEmpty() // + return period != null && !period.trim().isEmpty() // + && indicator != null && !indicator.trim().isEmpty() // && year != null; - } /** @@ -79,6 +90,13 @@ public final class ChoiceDTO { this.indicator = value; } + /** + * @param value Period code of chosen indicator. + */ + public void setPeriod(final String value) { + this.period = value; + } + /** * @param value Chosen region. */ @@ -95,7 +113,8 @@ public final class ChoiceDTO { @Override public String toString() { - return "ChoiceDTO{" + "comparison=" + comparison + ", indicator=" + indicator + ", region=" + region + ", year=" - + year + '}'; + return "ChoiceDTO [comparison=" + comparison + ", indicator=" + indicator + ", period=" + period + ", region=" + + region + ", year=" + year + "]"; } + } diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ErrorResponseDTO.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ErrorResponseDTO.java new file mode 100644 index 0000000..4a7a6a5 --- /dev/null +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/ErrorResponseDTO.java @@ -0,0 +1,79 @@ +package fr.agrometinfo.www.shared.dto; + +/** + * JSON DTO to give error details. + * + * @author Olivier Maury + */ +public class ErrorResponseDTO { + /** + * Builder. + * + * @param statusCode HTTP status code + * @param reasonPhrase Related HTTP status message + * @param explanation Explanation + * @return instance + */ + public static ErrorResponseDTO of(final int statusCode, final String reasonPhrase, final String explanation) { + final ErrorResponseDTO dto = new ErrorResponseDTO(); + dto.setExplanation(explanation); + dto.setReasonPhrase(reasonPhrase); + dto.setStatusCode(statusCode); + return dto; + } + /** + * HTTP status code. + */ + private int statusCode; + /** + * Related HTTP status message. + */ + private String reasonPhrase; + + /** + * Explanation. + */ + private String explanation; + + /** + * @return Explanation + */ + public final String getExplanation() { + return explanation; + } + + /** + * @return Related HTTP status message. + */ + public final String getReasonPhrase() { + return reasonPhrase; + } + + /** + * @return HTTP status code. + */ + public final int getStatusCode() { + return statusCode; + } + + /** + * @param value Explanation + */ + public final void setExplanation(final String value) { + this.explanation = value; + } + + /** + * @param value Related HTTP status message. + */ + public final void setReasonPhrase(final String value) { + this.reasonPhrase = value; + } + + /** + * @param value HTTP status code + */ + public final void setStatusCode(final int value) { + this.statusCode = value; + } +} diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorDTO.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorDTO.java index fccf0bf..91105da 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorDTO.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorDTO.java @@ -18,7 +18,14 @@ public class IndicatorDTO { * * Eg.: meant for "Average temperature". */ - private String uid; + private String code; + + /** + * @return indicator UID + */ + public final String getCode() { + return code; + } /** * @return Localized description. @@ -28,10 +35,10 @@ public class IndicatorDTO { } /** - * @return the uid + * @param value Indicator UID */ - public final String getUid() { - return uid; + public final void setCode(final String value) { + this.code = value; } /** @@ -41,18 +48,11 @@ public class IndicatorDTO { this.description = value; } - /** - * @param id the uid to set - */ - public final void setUid(final String id) { - this.uid = id; - } - /** * String representation. */ @Override public String toString() { - return "IndicatorDTO{" + "uid=" + uid + ", description=" + description + '}'; + return "IndicatorDTO{" + "code=" + code + ", description=" + description + '}'; } } diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorCategoryDTO.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/PeriodDTO.java similarity index 60% rename from www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorCategoryDTO.java rename to www-shared/src/main/java/fr/agrometinfo/www/shared/dto/PeriodDTO.java index 29a028b..3f60f35 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/IndicatorCategoryDTO.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/dto/PeriodDTO.java @@ -5,26 +5,26 @@ import java.util.List; import org.dominokit.jackson.annotation.JSONMapper; /** - * Indicator category. + * Indicator period. * * @author Olivier Maury */ @JSONMapper -public final class IndicatorCategoryDTO extends IndicatorDTO { +public final class PeriodDTO extends IndicatorDTO { /** - * The indicators related to this category. + * The indicators related to this period. */ private List<IndicatorDTO> indicators; /** - * @return The indicators related to this category. + * @return The indicators related to this period. */ public List<IndicatorDTO> getIndicators() { return indicators; } /** - * @param value The indicators related to this category. + * @param value The indicators related to this period. */ public void setIndicators(final List<IndicatorDTO> value) { this.indicators = value; @@ -32,7 +32,7 @@ public final class IndicatorCategoryDTO extends IndicatorDTO { @Override public String toString() { - return "IndicatorCategoryDTO{" + "indicators=" + indicators + '}'; + return "PeriodDTO{" + "indicators=" + indicators + '}'; } } diff --git a/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java b/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java index a6eae67..b3a60ea 100644 --- a/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java +++ b/www-shared/src/main/java/fr/agrometinfo/www/shared/service/IndicatorService.java @@ -1,6 +1,7 @@ package fr.agrometinfo.www.shared.service; import java.util.List; +import java.util.Map; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -9,7 +10,7 @@ import javax.ws.rs.QueryParam; import org.dominokit.rest.shared.request.service.annotations.RequestFactory; import org.geojson.FeatureCollection; -import fr.agrometinfo.www.shared.dto.IndicatorCategoryDTO; +import fr.agrometinfo.www.shared.dto.PeriodDTO; /** * Interface for client and server resource. @@ -20,40 +21,45 @@ import fr.agrometinfo.www.shared.dto.IndicatorCategoryDTO; @Path(IndicatorService.PATH) public interface IndicatorService { /** - * Path for {@link IndicatorService#getIndicatorCategories()}. + * Service base path. */ - String PATH_LIST = "list"; + String PATH = "indicator"; /** - * Path for {@link IndicatorService#getCells()}. + * Path for {@link IndicatorService#getPeriods()}. */ - String PATH_CELLS = "cells"; + String PATH_LIST = "list"; /** * Path for {@link IndicatorService#getValues()}. */ String PATH_VALUES = "values"; /** - * Service base path. + * Path for {@link IndicatorService#getRegions()}. */ - String PATH = "indicator"; + String PATH_REGIONS = "regions"; + /** + * Path for {@link IndicatorService#getYears()}. + */ + String PATH_YEARS = "years"; /** - * @return some cells + * @return list of years of computed indicators. */ @GET - @Path(PATH_CELLS) - FeatureCollection getCells(); + @Path(PATH_LIST) + List<PeriodDTO> getPeriods(); /** - * @return list of available categories with indicators. + * @return list of regions (id : name) of computed indicators. */ @GET - @Path(PATH_LIST) - List<IndicatorCategoryDTO> getIndicatorCategories(); + @Path(PATH_REGIONS) + Map<String, String> getRegions(); /** * @param indicator indicator coe * @param period period code * @param region region ID + * @param year year * @param comparison if returned values are comparison to normal * @return indicator values */ @@ -61,5 +67,12 @@ public interface IndicatorService { @Path(PATH_VALUES) FeatureCollection getValues(@QueryParam(value = "indicator") String indicator, @QueryParam(value = "period") String period, @QueryParam(value = "region") Integer region, - @QueryParam(value = "comparison") Boolean comparison); + @QueryParam(value = "year") Integer year, @QueryParam(value = "comparison") Boolean comparison); + + /** + * @return list of computed years. + */ + @GET + @Path(PATH_YEARS) + List<Integer> getYears(); } -- GitLab