DashboardViewOverviewPageModContentFactoryImpl.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.common.pagemode;

  20. import java.util.Collections;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.Map.Entry;
  24. import java.util.Set;
  25. import java.util.stream.Collectors;

  26. import org.springframework.beans.factory.annotation.Autowired;
  27. import org.springframework.security.access.annotation.Secured;
  28. import org.springframework.stereotype.Component;

  29. import com.github.markash.ui.component.card.CounterStatisticModel;
  30. import com.github.markash.ui.component.card.CounterStatisticsCard;
  31. import com.github.markash.ui.component.card.StatisticShow;
  32. import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenCommittee;
  33. import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenCommittee_;
  34. import com.hack23.cia.model.internal.application.data.ministry.impl.ViewRiksdagenGovermentRoleMember;
  35. import com.hack23.cia.model.internal.application.data.ministry.impl.ViewRiksdagenGovermentRoleMember_;
  36. import com.hack23.cia.model.internal.application.data.ministry.impl.ViewRiksdagenMinistry;
  37. import com.hack23.cia.model.internal.application.data.ministry.impl.ViewRiksdagenMinistry_;
  38. import com.hack23.cia.model.internal.application.data.party.impl.ViewRiksdagenPartySummary;
  39. import com.hack23.cia.model.internal.application.data.party.impl.ViewRiksdagenPartySummary_;
  40. import com.hack23.cia.model.internal.application.data.politician.impl.ViewRiksdagenPolitician;
  41. import com.hack23.cia.model.internal.application.data.politician.impl.ViewRiksdagenPolitician_;
  42. import com.hack23.cia.model.internal.application.data.rules.impl.ResourceType;
  43. import com.hack23.cia.model.internal.application.data.rules.impl.RuleViolation;
  44. import com.hack23.cia.model.internal.application.data.rules.impl.Status;
  45. import com.hack23.cia.model.internal.application.system.impl.ApplicationEventGroup;
  46. import com.hack23.cia.service.api.DataContainer;
  47. import com.hack23.cia.service.external.esv.api.EsvApi;
  48. import com.hack23.cia.service.external.esv.api.GovernmentBodyAnnualSummary;
  49. import com.hack23.cia.web.impl.ui.application.action.ViewAction;
  50. import com.hack23.cia.web.impl.ui.application.views.common.menufactory.api.pagecommands.PageCommandMainViewConstants;
  51. import com.hack23.cia.web.impl.ui.application.views.common.rows.RowUtil;
  52. import com.hack23.cia.web.impl.ui.application.views.common.viewnames.CommonsViews;
  53. import com.hack23.cia.web.impl.ui.application.views.common.viewnames.UserViews;
  54. import com.jarektoro.responsivelayout.ResponsiveRow;
  55. import com.vaadin.icons.VaadinIcons;
  56. import com.vaadin.server.ExternalResource;
  57. import com.vaadin.server.Responsive;
  58. import com.vaadin.server.Sizeable.Unit;
  59. import com.vaadin.ui.HorizontalLayout;
  60. import com.vaadin.ui.Label;
  61. import com.vaadin.ui.Layout;
  62. import com.vaadin.ui.Link;
  63. import com.vaadin.ui.MenuBar;
  64. import com.vaadin.ui.Panel;
  65. import com.vaadin.ui.VerticalLayout;

  66. /**
  67.  * The DashboardViewOverviewPageModContentFactoryImpl creates a high-level dashboard
  68.  * overview for the Citizen Intelligence Agency. It displays various metrics and
  69.  * statistics about the monarch, government, parliament, and related financial and
  70.  * risk data.
  71.  */
  72. @Component
  73. public final class DashboardViewOverviewPageModContentFactoryImpl extends AbstractBasicPageModContentFactoryImpl {

  74.     /** The Constant ORG_CODE_GOV_OFFICES. */
  75.     private static final String ORG_CODE_GOV_OFFICES = "202100-3831";

  76.     /** The Constant ORG_CODE_RIKSDAG. */
  77.     private static final String ORG_CODE_RIKSDAG = "202100-2627";

  78.     /** The Constant ORG_CODE_MONARCH. */
  79.     private static final String ORG_CODE_MONARCH = "202100-3484";

  80.     /** The Constant FINANCIAL. */
  81.     private static final String FINANCIAL = "Financial";

  82.     /** The Constant PAGE_PREFIX. */
  83.     private static final String PAGE_PREFIX = "#!";

  84.     /** The Constant PAGE_SEPARATOR. */
  85.     private static final char PAGE_SEPARATOR = '/';

  86.     /** The Constant DISPLAY_SIZE_LG_DEVICE. */
  87.     private static final int DISPLAY_SIZE_LG_DEVICE = 4;

  88.     /** The Constant DISPLAY_SIZE_MD_DEVICE. */
  89.     private static final int DISPLAY_SIZE_MD_DEVICE = 4;

  90.     /** The Constant DISPLAY_SIZE_XS_DEVICE. */
  91.     private static final int DISPLAY_SIZE_XS_DEVICE = 12;

  92.     /** The Constant DISPLAYS_SIZE_XM_DEVICE. */
  93.     private static final int DISPLAYS_SIZE_XM_DEVICE = 6;

  94.     /** The esv api. */
  95.     @Autowired
  96.     private EsvApi esvApi;

  97.     /**
  98.      * Instantiates a new dashboard view overview page mod content factory.
  99.      */
  100.     public DashboardViewOverviewPageModContentFactoryImpl() {
  101.         super();
  102.     }

  103.     /**
  104.      * Create content for the dashboard overview page. Displays KPIs, statistics,
  105.      * and financial info for monarch, government, parliament, and related entities.
  106.      *
  107.      * @param parameters the navigation parameters
  108.      * @param menuBar    the main menu bar
  109.      * @param panel      the main panel holding the content
  110.      * @return a Layout containing the dashboard overview
  111.      */
  112.     @Secured({ "ROLE_ANONYMOUS", "ROLE_USER", "ROLE_ADMIN" })
  113.     @Override
  114.     public Layout createContent(final String parameters, final MenuBar menuBar, final Panel panel) {
  115.         final VerticalLayout panelContent = createPanelContent();
  116.         final String pageId = getPageId(parameters);

  117.         getMenuItemFactory().createMainPageMenuBar(menuBar);
  118.         CardInfoRowUtil.createPageHeader(panel, panelContent,
  119.                 CommonViewConstants.DASHBOARD_TITLE,
  120.                 CommonViewConstants.DASHBOARD_HEADER,
  121.                 CommonViewConstants.DASHBOARD_DESCRIPTION);

  122.         final ResponsiveRow row = RowUtil.createGridLayout(panelContent);

  123.         createDashboardMonarch(row);
  124.         createDashboardGovernment(row);
  125.         createDashboardParliament(row);
  126.         createDashboardPartRiskByType(row);
  127.         createDashboardPartRiskBySeverity(row);

  128.         getPageActionEventHelper().createPageEvent(ViewAction.VISIT_DASHBOARD_VIEW, ApplicationEventGroup.USER,
  129.                 CommonsViews.DASHBOARD_VIEW_NAME, parameters, pageId);

  130.         return panelContent;
  131.     }

  132.     /**
  133.      * Create a section for Monarch info.
  134.      *
  135.      * @param row the row
  136.      */
  137.     private void createDashboardMonarch(final ResponsiveRow row) {
  138.         final VerticalLayout monarchLayout = createLayoutWithTitle("Monarch");

  139.         // Basic Monarch info
  140.         addFullWidthLabel(monarchLayout, "Head of state(King): Carl Gustaf Folke Hubertus since 15 September 1973");
  141.         addFullWidthLabel(monarchLayout, "Future head of state(Queen): Victoria Ingrid Alice Désirée");

  142.         addMonarchIncomeSpending(monarchLayout);

  143.         row.addColumn()
  144.                 .withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE, DISPLAY_SIZE_LG_DEVICE)
  145.                 .withComponent(monarchLayout);
  146.     }

  147.     /**
  148.      * Create a section for Government info.
  149.      *
  150.      * @param row the row
  151.      */
  152.     @SuppressWarnings("unchecked")
  153.     private void createDashboardGovernment(final ResponsiveRow row) {
  154.         final VerticalLayout govLayout = createLayoutWithTitle("Government");
  155.         final HorizontalLayout statsLayout = new HorizontalLayout();
  156.         Responsive.makeResponsive(statsLayout);

  157.         final DataContainer<ViewRiksdagenGovermentRoleMember, String> govermentRoleMemberData = getApplicationManager()
  158.                 .getDataContainer(ViewRiksdagenGovermentRoleMember.class);

  159.         final List<ViewRiksdagenGovermentRoleMember> ministryMembers = govermentRoleMemberData
  160.                 .findListByProperty(new Object[] { Boolean.TRUE }, ViewRiksdagenGovermentRoleMember_.active);

  161.         statsLayout.addComponent(createStatisticCard("Members", ministryMembers.size()));

  162.         final DataContainer<ViewRiksdagenMinistry, String> ministryData = getApplicationManager()
  163.                 .getDataContainer(ViewRiksdagenMinistry.class);

  164.         final List<ViewRiksdagenMinistry> ministries = ministryData
  165.                 .findListByProperty(new Object[] { Boolean.TRUE }, ViewRiksdagenMinistry_.active);

  166.         statsLayout.addComponent(createStatisticCard("Ministries", ministries.size()));

  167.         final DataContainer<ViewRiksdagenPartySummary, String> partyData = getApplicationManager()
  168.                 .getDataContainer(ViewRiksdagenPartySummary.class);

  169.         final List<ViewRiksdagenPartySummary> partiesInGov = partyData.findListByProperty(new Object[] { Boolean.TRUE },
  170.                 ViewRiksdagenPartySummary_.activeGovernment);

  171.         statsLayout.addComponent(createStatisticCard("Parties", partiesInGov.size()));

  172.         final List<GovernmentBodyAnnualSummary> governmentBodies = esvApi.getData().get(2024);
  173.         statsLayout.addComponent(createStatisticCard("Government bodies", governmentBodies.size()));

  174.         final int totalGovHeadcount = governmentBodies.stream().mapToInt(GovernmentBodyAnnualSummary::getAnnualWorkHeadCount).sum();
  175.         statsLayout.addComponent(createStatisticCard("Headcount", totalGovHeadcount));

  176.         govLayout.addComponent(statsLayout);
  177.         addIncomeSpending(govLayout, ORG_CODE_GOV_OFFICES, "Regeringskansliet(Government Offices)", 1191, 1216, -70);

  178.         row.addColumn()
  179.                 .withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE, DISPLAY_SIZE_LG_DEVICE)
  180.                 .withComponent(govLayout);
  181.     }

  182.     /**
  183.      * Create a section for Parliament info.
  184.      *
  185.      * @param row the row
  186.      */
  187.     @SuppressWarnings("unchecked")
  188.     private void createDashboardParliament(final ResponsiveRow row) {
  189.         final VerticalLayout parliamentLayout = createLayoutWithTitle("Parliament");
  190.         final HorizontalLayout statsLayout = new HorizontalLayout();
  191.         Responsive.makeResponsive(statsLayout);

  192.         final DataContainer<ViewRiksdagenPolitician, String> parliamentData = getApplicationManager()
  193.                 .getDataContainer(ViewRiksdagenPolitician.class);
  194.         final List<ViewRiksdagenPolitician> parliamentMembers = parliamentData
  195.                 .findListByProperty(new Object[] { Boolean.TRUE }, ViewRiksdagenPolitician_.activeParliament);

  196.         statsLayout.addComponent(createStatisticCard("Members", parliamentMembers.size()));

  197.         final DataContainer<ViewRiksdagenPartySummary, String> partyData = getApplicationManager()
  198.                 .getDataContainer(ViewRiksdagenPartySummary.class);
  199.         final List<ViewRiksdagenPartySummary> parliamentParties = partyData.findListByProperty(new Object[] { Boolean.TRUE },
  200.                 ViewRiksdagenPartySummary_.activeParliament);
  201.         statsLayout.addComponent(createStatisticCard("Parties", parliamentParties.size()));

  202.         final DataContainer<ViewRiksdagenCommittee, String> committeeData = getApplicationManager()
  203.                 .getDataContainer(ViewRiksdagenCommittee.class);
  204.         final List<ViewRiksdagenCommittee> committees = committeeData
  205.                 .findListByProperty(new Object[] { Boolean.TRUE }, ViewRiksdagenCommittee_.active);
  206.         statsLayout.addComponent(createStatisticCard("Committees", committees.size()));

  207.         parliamentLayout.addComponent(statsLayout);
  208.         addParliamentIncomeSpending(parliamentLayout, ORG_CODE_RIKSDAG, "Riksdagsförvaltningen(the Riksdag administration)", 1719);

  209.         // Additional panel or content (if needed)
  210.         final VerticalLayout layoutPanel = createPanelContent();
  211.         parliamentLayout.addComponent(layoutPanel);

  212.         row.addColumn()
  213.                 .withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE, DISPLAY_SIZE_LG_DEVICE)
  214.                 .withComponent(parliamentLayout);
  215.     }

  216.     /**
  217.      * Create a section listing the number of risks by type.
  218.      *
  219.      * @param row the row
  220.      */
  221.     private void createDashboardPartRiskByType(final ResponsiveRow row) {
  222.         final VerticalLayout layout = createLayoutWithTitle(CommonViewConstants.RISK_BY_TYPE_TITLE);
  223.         final HorizontalLayout horizontalLayout = new HorizontalLayout();
  224.         Responsive.makeResponsive(horizontalLayout);

  225.         final DataContainer<RuleViolation, String> violationData = getApplicationManager()
  226.                 .getDataContainer(RuleViolation.class);
  227.         final List<RuleViolation> ruleViolations = violationData.getAll();

  228.         // Group by ResourceType and show counts
  229.         final Map<ResourceType, List<RuleViolation>> groupedByType = ruleViolations.stream()
  230.                 .collect(Collectors.groupingBy(RuleViolation::getResourceType));

  231.         for (final Entry<ResourceType, List<RuleViolation>> entry : groupedByType.entrySet()) {
  232.             horizontalLayout.addComponent(createStatisticCard(entry.getKey().toString(), entry.getValue().size()));
  233.         }

  234.         layout.addComponent(horizontalLayout);

  235.         row.addColumn()
  236.                 .withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE, DISPLAY_SIZE_LG_DEVICE)
  237.                 .withComponent(layout);
  238.     }

  239.     /**
  240.      * Create a section listing the number of risks by severity.
  241.      *
  242.      * @param row the row
  243.      */
  244.     private void createDashboardPartRiskBySeverity(final ResponsiveRow row) {
  245.         final VerticalLayout layout = createLayoutWithTitle("Number of risk by severity");
  246.         final HorizontalLayout horizontalLayout = new HorizontalLayout();
  247.         Responsive.makeResponsive(horizontalLayout);

  248.         final DataContainer<RuleViolation, String> violationData = getApplicationManager()
  249.                 .getDataContainer(RuleViolation.class);
  250.         final List<RuleViolation> ruleViolations = violationData.getAll();

  251.         // Group by Status and show counts
  252.         final Map<Status, List<RuleViolation>> groupedByStatus = ruleViolations.stream()
  253.                 .collect(Collectors.groupingBy(RuleViolation::getStatus));

  254.         for (final Entry<Status, List<RuleViolation>> entry : groupedByStatus.entrySet()) {
  255.             horizontalLayout.addComponent(createStatisticCard(entry.getKey().toString(), entry.getValue().size()));
  256.         }

  257.         layout.addComponent(horizontalLayout);

  258.         row.addColumn()
  259.                 .withDisplayRules(DISPLAY_SIZE_XS_DEVICE, DISPLAYS_SIZE_XM_DEVICE, DISPLAY_SIZE_MD_DEVICE, DISPLAY_SIZE_LG_DEVICE)
  260.                 .withComponent(layout);
  261.     }

  262.     /**
  263.      * Add income/spending overview for a given orgId.
  264.      *
  265.      * @param layout the layout
  266.      * @param orgId the org id
  267.      * @param linkTitle the link title
  268.      * @param incomeBillionSek the income billion sek
  269.      * @param spendingBillionSek the spending billion sek
  270.      * @param resultBillionSek the result billion sek
  271.      */
  272.     private void addIncomeSpending(final VerticalLayout layout, final String orgId, final String linkTitle,
  273.             final int incomeBillionSek, final int spendingBillionSek, final int resultBillionSek) {

  274.         addGovernmentBodyLink(layout, orgId, linkTitle);

  275.         final Label titleLabel = new Label(FINANCIAL);
  276.         Responsive.makeResponsive(titleLabel);
  277.         titleLabel.setWidth(100, Unit.PERCENTAGE);
  278.         layout.addComponent(titleLabel);

  279.         final HorizontalLayout financialLayout = new HorizontalLayout();
  280.         Responsive.makeResponsive(financialLayout);

  281.         createHeadCountCard(financialLayout, orgId);

  282.         financialLayout.addComponent(createStatisticCard("Income(B SEK)", incomeBillionSek));
  283.         financialLayout.addComponent(createStatisticCard("Spending(B SEK)", spendingBillionSek));
  284.         financialLayout.addComponent(createStatisticCard("Result(B SEK)", resultBillionSek));

  285.         layout.addComponent(financialLayout);
  286.     }

  287.     /**
  288.      * Add Parliament income and spending info.
  289.      *
  290.      * @param layout the layout
  291.      * @param orgId the org id
  292.      * @param linkTitle the link title
  293.      * @param spendingMSek the spending M sek
  294.      */
  295.     private void addParliamentIncomeSpending(final VerticalLayout layout, final String orgId, final String linkTitle,
  296.             final int spendingMSek) {

  297.         addGovernmentBodyLink(layout, orgId, linkTitle);

  298.         final Label titleLabel = new Label(FINANCIAL);
  299.         Responsive.makeResponsive(titleLabel);
  300.         titleLabel.setWidth(100, Unit.PERCENTAGE);
  301.         layout.addComponent(titleLabel);

  302.         final HorizontalLayout financialLayout = new HorizontalLayout();
  303.         Responsive.makeResponsive(financialLayout);

  304.         createHeadCountCard(financialLayout, orgId);

  305.         financialLayout.addComponent(createStatisticCard("Spending(M SEK)", spendingMSek));

  306.         layout.addComponent(financialLayout);
  307.     }

  308.     /**
  309.      * Add Monarch income and spending info.
  310.      *
  311.      * @param layout the layout
  312.      */
  313.     private void addMonarchIncomeSpending(final VerticalLayout layout) {
  314.         addGovernmentBodyLink(layout, ORG_CODE_MONARCH, "Kungliga hov- och slottsstaten(The Royal Court)");

  315.         final Label titleLabel = new Label(FINANCIAL);
  316.         Responsive.makeResponsive(titleLabel);
  317.         titleLabel.setWidth(100, Unit.PERCENTAGE);
  318.         layout.addComponent(titleLabel);

  319.         final HorizontalLayout financialLayout = new HorizontalLayout();
  320.         Responsive.makeResponsive(financialLayout);

  321.         createHeadCountCard(financialLayout, ORG_CODE_MONARCH);

  322.         // Example: Just Spending info
  323.         financialLayout.addComponent(createStatisticCard("Spending(M SEK)", 148));

  324.         layout.addComponent(financialLayout);
  325.     }

  326.     /**
  327.      * Create a statistic card with a given title and value.
  328.      *
  329.      * @param title the title
  330.      * @param value the value
  331.      * @return the counter statistics card
  332.      */
  333.     private CounterStatisticsCard createStatisticCard(final String title, final int value) {
  334.         return new CounterStatisticsCard(
  335.                 VaadinIcons.WARNING,
  336.                 new CounterStatisticModel(title, value).withShow(StatisticShow.Sum).withIconHidden().withShowOnlyStatistic(true),
  337.                 title);
  338.     }

  339.     /**
  340.      * Create a vertical layout with a title label.
  341.      *
  342.      * @param title the title
  343.      * @return the vertical layout
  344.      */
  345.     private static VerticalLayout createLayoutWithTitle(final String title) {
  346.         final VerticalLayout layout = new VerticalLayout();
  347.         layout.addStyleName("leader-baseball-card");
  348.         Responsive.makeResponsive(layout);
  349.         layout.setSizeUndefined();

  350.         final Label titleLabel = new Label(title);
  351.         Responsive.makeResponsive(titleLabel);
  352.         titleLabel.addStyleName("title");
  353.         titleLabel.setWidth(100, Unit.PERCENTAGE);
  354.         layout.addComponent(titleLabel);

  355.         return layout;
  356.     }

  357.     /**
  358.      * Add a full-width label to a layout.
  359.      *
  360.      * @param layout the layout
  361.      * @param text the text
  362.      */
  363.     private static void addFullWidthLabel(final VerticalLayout layout, final String text) {
  364.         final Label label = new Label(text);
  365.         Responsive.makeResponsive(label);
  366.         label.setWidth(100, Unit.PERCENTAGE);
  367.         layout.addComponent(label);
  368.     }

  369.     /**
  370.      * Add a link to a government body page.
  371.      *
  372.      * @param layout the layout
  373.      * @param orgId the org id
  374.      * @param linkTitle the link title
  375.      */
  376.     private void addGovernmentBodyLink(final VerticalLayout layout, final String orgId, final String linkTitle) {
  377.         final Link pageLink = new Link(linkTitle,
  378.                 new ExternalResource(PAGE_PREFIX + UserViews.GOVERNMENT_BODY_VIEW_NAME + PAGE_SEPARATOR + orgId));
  379.         pageLink.setId(ViewAction.VISIT_GOVERNMENT_BODY_VIEW.name() + PAGE_SEPARATOR + orgId);
  380.         pageLink.setIcon(VaadinIcons.GROUP);
  381.         Responsive.makeResponsive(pageLink);
  382.         pageLink.setWidth(100, Unit.PERCENTAGE);
  383.         layout.addComponent(pageLink);
  384.     }

  385.     /**
  386.      * Create a card showing headcount for a given orgId.
  387.      *
  388.      * @param panelContent the panel content
  389.      * @param orgId the org id
  390.      */
  391.     private void createHeadCountCard(final Layout panelContent, final String orgId) {
  392.         final Map<String, List<GovernmentBodyAnnualSummary>> yearlyData = esvApi.getData().get(2024).stream()
  393.                 .collect(Collectors.groupingBy(GovernmentBodyAnnualSummary::getOrgNumber));

  394.         final List<GovernmentBodyAnnualSummary> summaries = yearlyData.get(getPageId(orgId));

  395.         if (summaries != null && !summaries.isEmpty()) {
  396.             final GovernmentBodyAnnualSummary bodySummary = summaries.get(0);
  397.             if (bodySummary != null) {
  398.                 final Map<Integer,GovernmentBodyAnnualSummary> dataPerBody = esvApi.getDataPerGovernmentBody(bodySummary.getName());
  399.                 final Set<Integer> yearKeys = dataPerBody.keySet();
  400.                 final GovernmentBodyAnnualSummary latestSummary = dataPerBody.get(Collections.max(yearKeys));

  401.                 panelContent.addComponent(
  402.                         new CounterStatisticsCard(
  403.                                 VaadinIcons.WARNING,
  404.                                 new CounterStatisticModel("Headcount", latestSummary.getHeadCount())
  405.                                         .withShow(StatisticShow.Sum).withIconHidden().withShowOnlyStatistic(true),
  406.                                 "Headcount"));
  407.             }
  408.         }
  409.     }

  410.     /**
  411.      * Checks if this factory matches the given page and parameters.
  412.      */
  413.     @Override
  414.     public boolean matches(final String page, final String parameters) {
  415.         return PageCommandMainViewConstants.COMMAND_DASHBOARDVIEW_OVERVIEW.matches(page, parameters);
  416.     }

  417. }