ParliamentDecisionFlowPageModContentFactoryImpl.java

  1. /*
  2.  * Copyright 2010-2025 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.user.parliament.pagemode;

  20. import java.time.LocalDate;
  21. import java.time.ZoneOffset;
  22. import java.util.Collections;
  23. import java.util.Comparator;
  24. import java.util.List;
  25. import java.util.Locale;
  26. import java.util.Map;
  27. import java.util.stream.Collectors;
  28. import java.util.stream.IntStream;

  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.security.access.annotation.Secured;
  31. import org.springframework.stereotype.Component;

  32. import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenCommittee;
  33. import com.hack23.cia.model.internal.application.system.impl.ApplicationEventGroup;
  34. import com.hack23.cia.web.impl.ui.application.action.ViewAction;
  35. import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.DecisionFlowChartManager;
  36. import com.hack23.cia.web.impl.ui.application.views.common.menufactory.api.pagecommands.PageCommandParliamentRankingConstants;
  37. import com.hack23.cia.web.impl.ui.application.views.common.pagemode.CardInfoRowUtil;
  38. import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
  39. import com.hack23.cia.web.impl.ui.application.views.pageclicklistener.DecisionFlowValueChangeListener;
  40. import com.hack23.cia.web.widgets.charts.SankeyChart;
  41. import com.vaadin.ui.ComboBox;
  42. import com.vaadin.ui.Layout;
  43. import com.vaadin.ui.MenuBar;
  44. import com.vaadin.ui.Panel;
  45. import com.vaadin.ui.TextArea;
  46. import com.vaadin.ui.VerticalLayout;

  47. /**
  48.  * The Class ParliamentDecisionFlowPageModContentFactoryImpl.
  49.  */
  50. @Component
  51. public final class ParliamentDecisionFlowPageModContentFactoryImpl extends AbstractParliamentPageModContentFactoryImpl {

  52.     /** The Constant DEFAULT_YEAR. */
  53.     private static final String DEFAULT_YEAR = "2023/24";

  54.     /** The Constant YEAR_SELECTOR_LABEL. */
  55.     private static final String YEAR_SELECTOR_LABEL = "Select year";

  56.     /** The decision flow chart manager. */
  57.     @Autowired
  58.     private DecisionFlowChartManager decisionFlowChartManager;

  59.     /**
  60.      * Creates the content.
  61.      *
  62.      * @param parameters the parameters
  63.      * @param menuBar the menu bar
  64.      * @param panel the panel
  65.      * @return the layout
  66.      */
  67.     @Secured({ "ROLE_ANONYMOUS", "ROLE_USER", "ROLE_ADMIN" })
  68.     @Override
  69.     public Layout createContent(final String parameters, final MenuBar menuBar, final Panel panel) {
  70.         final VerticalLayout panelContent = createPanelContent();

  71.         setupMenuAndHeader(menuBar, panel, panelContent);
  72.         final String selectedYear = extractSelectedYear(parameters);
  73.         final Map<String, List<ViewRiksdagenCommittee>> committeeMap = loadCommitteeMap();

  74.         addYearSelector(panelContent, selectedYear);
  75.         addDecisionFlowChart(panelContent, committeeMap, selectedYear);
  76.         addDecisionSummary(panelContent, committeeMap, selectedYear);

  77.         recordPageVisit(parameters, selectedYear);

  78.         return panelContent;
  79.     }

  80.     /**
  81.      * Creates list of available years for selection.
  82.      * Goes from 2010/11 up to (currentYear+1)/(currentYear+2).
  83.      *
  84.      * @return Unmodifiable list of year strings in format "YYYY/YY"
  85.      */
  86.     private static List<String> createAvailableYears() {
  87.         final int currentYear = LocalDate.now((ZoneOffset.UTC)).getYear();
  88.         return IntStream.rangeClosed(2010, currentYear + 1)
  89.             .mapToObj(year -> String.format(Locale.ENGLISH,"%d/%02d", year, (year + 1) % 100))
  90.             .sorted(Comparator.reverseOrder()) // Most recent years first
  91.             .collect(Collectors.collectingAndThen(
  92.                 Collectors.toList(),
  93.                 Collections::unmodifiableList
  94.             ));
  95.     }


  96.     /**
  97.      * Setup menu and header.
  98.      *
  99.      * @param menuBar the menu bar
  100.      * @param panel the panel
  101.      * @param panelContent the panel content
  102.      */
  103.     private void setupMenuAndHeader(final MenuBar menuBar, final Panel panel, final VerticalLayout panelContent) {
  104.         getParliamentMenuItemFactory().createParliamentTopicMenu(menuBar);
  105.         CardInfoRowUtil.createPageHeader(panel, panelContent,
  106.             ParliamentPageTitleConstants.DECISION_FLOW_TITLE,
  107.             ParliamentPageTitleConstants.DECISION_FLOW_SUBTITLE,
  108.             ParliamentPageTitleConstants.DECISION_FLOW_DESC);
  109.     }

  110.     /**
  111.      * Extract selected year.
  112.      *
  113.      * @param parameters the parameters
  114.      * @return the string
  115.      */
  116.     private String extractSelectedYear(final String parameters) {
  117.         if (parameters != null && parameters.contains("[") && parameters.contains("]")) {
  118.             return parameters.substring(
  119.                 parameters.indexOf('[') + 1,
  120.                 parameters.lastIndexOf(']')
  121.             );
  122.         }
  123.         return DEFAULT_YEAR;
  124.     }

  125.     /**
  126.      * Load committee map.
  127.      *
  128.      * @return the map
  129.      */
  130.     private Map<String, List<ViewRiksdagenCommittee>> loadCommitteeMap() {
  131.         return getApplicationManager()
  132.             .getDataContainer(ViewRiksdagenCommittee.class)
  133.             .getAll()
  134.             .stream()
  135.             .collect(Collectors.groupingBy(
  136.                 committee -> committee.getEmbeddedId().getOrgCode().toUpperCase(Locale.ENGLISH)
  137.             ));
  138.     }

  139.     /**
  140.      * Adds the year selector.
  141.      *
  142.      * @param panelContent the panel content
  143.      * @param selectedYear the selected year
  144.      */
  145.     private void addYearSelector(final VerticalLayout panelContent, final String selectedYear) {
  146.         final ComboBox<String> yearSelector = new ComboBox<>(YEAR_SELECTOR_LABEL, createAvailableYears());
  147.         yearSelector.setWidth("200px");
  148.         yearSelector.setEmptySelectionAllowed(false);
  149.         yearSelector.setSelectedItem(selectedYear);
  150.         yearSelector.addValueChangeListener(new DecisionFlowValueChangeListener(NAME, ""));

  151.         panelContent.addComponent(yearSelector);
  152.         panelContent.setExpandRatio(yearSelector, ContentRatio.SMALL);
  153.     }

  154.     /**
  155.      * Adds the decision flow chart.
  156.      *
  157.      * @param panelContent the panel content
  158.      * @param committeeMap the committee map
  159.      * @param selectedYear the selected year
  160.      */
  161.     private void addDecisionFlowChart(final VerticalLayout panelContent,
  162.             final Map<String, List<ViewRiksdagenCommittee>> committeeMap, final String selectedYear) {
  163.         final SankeyChart chart = decisionFlowChartManager.createAllDecisionFlow(committeeMap, selectedYear);
  164.         chart.setWidth("100%");

  165.         panelContent.addComponent(chart);
  166.         panelContent.setExpandRatio(chart, ContentRatio.LARGE);
  167. }

  168.     /**
  169.      * Adds the decision summary.
  170.      *
  171.      * @param panelContent the panel content
  172.      * @param committeeMap the committee map
  173.      * @param selectedYear the selected year
  174.      */
  175.     private void addDecisionSummary(final VerticalLayout panelContent,
  176.             final Map<String, List<ViewRiksdagenCommittee>> committeeMap, final String selectedYear) {
  177.         final TextArea summaryArea = decisionFlowChartManager.createCommitteeeDecisionSummary(committeeMap, selectedYear);
  178.         summaryArea.setSizeFull();
  179.         summaryArea.setReadOnly(true);

  180.         panelContent.addComponent(summaryArea);
  181.         panelContent.setExpandRatio(summaryArea, ContentRatio.SMALL_GRID);
  182.     }

  183.     /**
  184.      * Record page visit.
  185.      *
  186.      * @param parameters the parameters
  187.      * @param selectedYear the selected year
  188.      */
  189.     private void recordPageVisit(final String parameters, final String selectedYear) {
  190.         getPageActionEventHelper().createPageEvent(
  191.             ViewAction.VISIT_PARLIAMENT_RANKING_VIEW,
  192.             ApplicationEventGroup.USER,
  193.             NAME,
  194.             parameters,
  195.             selectedYear
  196.         );
  197.     }

  198.     /**
  199.      * Matches.
  200.      *
  201.      * @param page the page
  202.      * @param parameters the parameters
  203.      * @return true, if successful
  204.      */
  205.     @Override
  206.     public boolean matches(final String page, final String parameters) {
  207.         return PageCommandParliamentRankingConstants.COMMAND_CHARTS_DECISION_FLOW.matches(page, parameters);
  208.     }
  209. }