DecisionFlowChartManagerImpl.java
- /*
- * Copyright 2010-2025 James Pether Sörling
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * $Id$
- * $HeadURL$
- */
- package com.hack23.cia.web.impl.ui.application.views.common.chartfactory.impl;
- import java.util.Collection;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
- import java.util.Objects;
- import java.util.Optional;
- import java.util.function.Function;
- import java.util.stream.Collectors;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenCommittee;
- import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.DecisionFlowChartManager;
- import com.hack23.cia.web.impl.ui.application.views.common.dataseriesfactory.api.DecisionDataFactory;
- import com.hack23.cia.web.impl.ui.application.views.common.dataseriesfactory.api.ProposalCommitteeeSummary;
- import com.hack23.cia.web.widgets.charts.SankeyChart;
- import com.vaadin.ui.TextArea;
- /**
- * The Class DecisionFlowChartManagerImpl.
- */
- @Service
- public final class DecisionFlowChartManagerImpl implements DecisionFlowChartManager {
- /** The decision data factory. */
- @Autowired
- private DecisionDataFactory decisionDataFactory;
- /**
- * Instantiates a new decision flow chart manager impl.
- */
- public DecisionFlowChartManagerImpl() {
- super();
- }
- /**
- * Gets the org proposal map.
- *
- * @param reportMonth the report month
- * @return the org proposal map
- */
- // Core helper methods for common operations
- private Map<String, List<ProposalCommitteeeSummary>> getOrgProposalMap(final String reportMonth) {
- return decisionDataFactory.createCommitteeSummary(reportMonth)
- .stream()
- .filter(Objects::nonNull)
- .collect(Collectors.groupingBy(
- ProposalCommitteeeSummary::org,
- Collectors.mapping(
- Function.identity(),
- Collectors.toList()
- )
- ));
- }
- /**
- * Find committee.
- *
- * @param committeeSummaryMap the committee summary map
- * @param orgKey the org key
- * @return the optional
- */
- private Optional<ViewRiksdagenCommittee> findCommittee(
- final Map<String, List<ViewRiksdagenCommittee>> committeeSummaryMap,
- final String orgKey) {
- return Optional.ofNullable(committeeSummaryMap.get(orgKey))
- .flatMap(list -> list.stream().findFirst());
- }
- /**
- * Creates the all decision flow.
- *
- * @param committeeSummaryMap the committee summary map
- * @param reportMonth the report month
- * @return the sankey chart
- */
- @Override
- public SankeyChart createAllDecisionFlow(
- final Map<String, List<ViewRiksdagenCommittee>> committeeSummaryMap,
- final String reportMonth) {
- Objects.requireNonNull(committeeSummaryMap, "Committee summary map cannot be null");
- Objects.requireNonNull(reportMonth, "Report month cannot be null");
- final SankeyChart sankeyChart = new SankeyChart();
- getOrgProposalMap(reportMonth).entrySet().stream()
- .filter(entry -> entry.getKey() != null && !entry.getValue().isEmpty())
- .forEach(entry ->
- findCommittee(committeeSummaryMap, entry.getKey())
- .ifPresent(committee ->
- addChartData(sankeyChart, entry.getValue(), committee)));
- sankeyChart.drawChart();
- return sankeyChart;
- }
- /**
- * Creates the committee decision flow.
- *
- * @param viewRiksdagenCommittee the view riksdagen committee
- * @param committeeSummaryMap the committee summary map
- * @param reportMonth the report month
- * @return the sankey chart
- */
- @Override
- public SankeyChart createCommitteeDecisionFlow(
- final ViewRiksdagenCommittee viewRiksdagenCommittee,
- final Map<String, List<ViewRiksdagenCommittee>> committeeSummaryMap,
- final String reportMonth) {
- Objects.requireNonNull(viewRiksdagenCommittee, "Committee cannot be null");
- final SankeyChart sankeyChart = new SankeyChart();
- final String targetOrg = viewRiksdagenCommittee.getEmbeddedId().getOrgCode().toUpperCase(Locale.ENGLISH);
- getOrgProposalMap(reportMonth).entrySet().stream()
- .filter(entry -> targetOrg.equals(entry.getKey().toUpperCase(Locale.ENGLISH)))
- .forEach(entry -> addDocTypeDecisionDataRows(sankeyChart, entry.getValue()));
- sankeyChart.drawChart();
- return sankeyChart;
- }
- /**
- * Creates the committeee decision summary.
- *
- * @param committeeSummaryMap the committee summary map
- * @param reportMonth the report month
- * @return the text area
- */
- @Override
- public TextArea createCommitteeeDecisionSummary(
- final Map<String, List<ViewRiksdagenCommittee>> committeeSummaryMap,
- final String reportMonth) {
- final TextArea area = new TextArea("Summary");
- final StringBuilder builder = new StringBuilder();
- final Map<String, List<ProposalCommitteeeSummary>> orgProposalMap = getOrgProposalMap(reportMonth);
- orgProposalMap.forEach((orgKey, proposals) -> {
- final String orgKeyUpper = orgKey.toUpperCase(Locale.ENGLISH);
- findCommittee(committeeSummaryMap, orgKeyUpper)
- .ifPresent(committee -> addCommiteeSummary(builder, proposals, committee));
- });
- area.setValue(builder.toString());
- return area;
- }
- /**
- * Creates the committeee decision summary.
- *
- * @param viewRiksdagenCommittee the view riksdagen committee
- * @param reportMonth the report month
- * @return the text area
- */
- @Override
- public TextArea createCommitteeeDecisionSummary(
- final ViewRiksdagenCommittee viewRiksdagenCommittee,
- final String reportMonth) {
- final TextArea area = new TextArea("Summary");
- final StringBuilder builder = new StringBuilder();
- final String targetOrg = viewRiksdagenCommittee.getEmbeddedId().getOrgCode().toUpperCase(Locale.ENGLISH);
- final List<ProposalCommitteeeSummary> proposals =
- getOrgProposalMap(reportMonth).get(targetOrg);
- addCommiteeSummary(builder, proposals, viewRiksdagenCommittee);
- area.setValue(builder.toString());
- return area;
- }
- /**
- * Adds the chart data.
- *
- * @param sankeyChart the sankey chart
- * @param proposals the proposals
- * @param committee the committee
- */
- private void addChartData(
- final SankeyChart sankeyChart,
- final List<ProposalCommitteeeSummary> proposals,
- final ViewRiksdagenCommittee committee) {
- addDocTypeDataRows(sankeyChart, proposals, committee);
- addDecisionDataRows(sankeyChart, proposals, committee);
- }
- /**
- * Adds the doc type data rows.
- *
- * @param sankeyChart the sankey chart
- * @param proposals the proposals
- * @param committee the committee
- */
- private static void addDocTypeDataRows(
- final SankeyChart sankeyChart,
- final List<ProposalCommitteeeSummary> proposals,
- final ViewRiksdagenCommittee committee) {
- final String committeeName = committee.getEmbeddedId().getDetail();
- Optional.ofNullable(proposals)
- .stream()
- .flatMap(Collection::stream)
- .filter(Objects::nonNull)
- .collect(Collectors.groupingBy(
- ProposalCommitteeeSummary::docType,
- Collectors.collectingAndThen(
- Collectors.toList(),
- docProposals -> {
- if (!docProposals.get(0).docType().isEmpty()) {
- sankeyChart.addDataRow(
- docProposals.get(0).docType(),
- committeeName,
- docProposals.size()
- );
- }
- return docProposals;
- }
- )
- ));
- }
- /**
- * Adds the decision data rows.
- *
- * @param sankeyChart the sankey chart
- * @param proposals the proposals
- * @param committee the committee
- */
- private static void addDecisionDataRows(
- final SankeyChart sankeyChart,
- final List<ProposalCommitteeeSummary> proposals,
- final ViewRiksdagenCommittee committee) {
- final String committeeName = committee.getEmbeddedId().getDetail();
- proposals.stream()
- .collect(Collectors.groupingBy(ProposalCommitteeeSummary::decision))
- .forEach((decision, decisionProposals) -> {
- if (!decision.isEmpty()) {
- sankeyChart.addDataRow(committeeName, decision, decisionProposals.size());
- }
- });
- }
- /**
- * Adds the doc type decision data rows.
- *
- * @param sankeyChart the sankey chart
- * @param proposals the proposals
- */
- private static void addDocTypeDecisionDataRows(
- final SankeyChart sankeyChart,
- final List<ProposalCommitteeeSummary> proposals) {
- Optional.ofNullable(proposals)
- .stream()
- .flatMap(Collection::stream)
- .filter(Objects::nonNull)
- .collect(Collectors.groupingBy(
- ProposalCommitteeeSummary::docType,
- Collectors.collectingAndThen(
- Collectors.toList(),
- docTypeProposals -> {
- if (!docTypeProposals.get(0).docType().isEmpty()) {
- addDecisionRowsForDocType(
- sankeyChart,
- docTypeProposals.get(0).docType(),
- docTypeProposals
- );
- }
- return docTypeProposals;
- }
- )
- ));
- }
- /**
- * Adds the decision rows for doc type.
- *
- * @param sankeyChart the sankey chart
- * @param docType the doc type
- * @param proposals the proposals
- */
- private static void addDecisionRowsForDocType(
- final SankeyChart sankeyChart,
- final String docType,
- final List<ProposalCommitteeeSummary> proposals) {
- proposals.stream()
- .collect(Collectors.groupingBy(ProposalCommitteeeSummary::decision))
- .forEach((decision, decisionProposals) -> {
- if (!decision.isEmpty()) {
- sankeyChart.addDataRow(docType, decision, decisionProposals.size());
- }
- });
- }
- /**
- * Adds the commitee summary.
- *
- * @param builder the builder
- * @param proposals the proposals
- * @param committee the committee
- */
- private static void addCommiteeSummary(
- final StringBuilder builder,
- final List<ProposalCommitteeeSummary> proposals,
- final ViewRiksdagenCommittee committee) {
- if (committee == null || proposals == null || proposals.isEmpty()) {
- return;
- }
- builder.append('\n').append(committee.getEmbeddedId().getDetail());
- proposals.stream()
- .filter(Objects::nonNull)
- .collect(Collectors.groupingBy(
- ProposalCommitteeeSummary::docType,
- Collectors.collectingAndThen(
- Collectors.toList(),
- docProposals -> {
- addSummaryEntry(builder, docProposals.get(0).docType(), docProposals);
- return docProposals;
- }
- )
- ));
- }
- /**
- * Adds the summary entry.
- *
- * @param builder the builder
- * @param docType the doc type
- * @param docTypeList the doc type list
- */
- private static void addSummaryEntry(
- final StringBuilder builder,
- final String docType,
- final List<ProposalCommitteeeSummary> docTypeList) {
- builder.append("\n ( ")
- .append(docTypeList.size())
- .append(' ')
- .append(docType)
- .append(" -> ");
- docTypeList.stream()
- .collect(Collectors.groupingBy(ProposalCommitteeeSummary::decision))
- .forEach((decision, decisionProposals) ->
- addDecisionDetails(builder, decision, decisionProposals));
- builder.append(')');
- }
- /**
- * Adds the decision details.
- *
- * @param builder the builder
- * @param decision the decision
- * @param summaries the summaries
- */
- private static void addDecisionDetails(
- final StringBuilder builder,
- final String decision,
- final List<ProposalCommitteeeSummary> summaries) {
- if (!decision.isEmpty()) {
- builder.append("\n ")
- .append(summaries.size())
- .append(' ')
- .append(decision)
- .append(' ');
- summaries.stream()
- .filter(Objects::nonNull)
- .forEach(summary ->
- builder.append("\n ")
- .append(summary.decision())
- .append(':')
- .append(summary.wording())
- .append(' ')
- .append(summary.wording2())
- .append(' '));
- }
- }
- }