citizen-intelligence-agency/src/main/java/com/hack23/cia/web/impl/ui/application/views/common/chartfactory/impl/AbstractGhantChartManagerImpl.java

Summary

Maintainability
A
1 hr
Test Coverage
/*
 * Copyright 2010-2021 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.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.joda.time.DateTime;
import org.tltv.gantt.Gantt;
import org.tltv.gantt.client.shared.AbstractStep.CaptionMode;
import org.tltv.gantt.client.shared.Resolution;
import org.tltv.gantt.client.shared.Step;
import org.tltv.gantt.client.shared.SubStep;

import com.hack23.cia.web.impl.ui.application.views.common.sizing.ContentRatio;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.AbstractOrderedLayout;

/**
 * The Class AbstractGhantChartManagerImpl.
 *
 * @param <T>
 *            the generic type
 */
public abstract class AbstractGhantChartManagerImpl<T extends Object> {

    /** The Constant CONTENT_SEPARATOR. */
    private static final char CONTENT_SEPARATOR = ' ';

    /** The Constant FILTER_DATA_BEFORE_YEAR. */
    private static final int FILTER_DATA_BEFORE_YEAR = 2000;

    /** The Constant PARTY_END_TAG. */
    private static final char PARTY_END_TAG = ')';

    /** The Constant PARTY_START_TAG. */
    private static final String PARTY_START_TAG = " (";

    /**
     * Instantiates a new abstract ghant chart manager impl.
     */
    public AbstractGhantChartManagerImpl() {
        super();
    }

    /**
     * Creates the gantt.
     *
     * @return the gantt
     */
    private static final Gantt createGantt() {
        final Gantt gantt = new Gantt();
        gantt.setSizeFull();
        gantt.setWidth(100, Unit.PERCENTAGE);
        gantt.setHeight(100, Unit.PERCENTAGE);
        gantt.setResizableSteps(false);
        gantt.setMovableSteps(false);
        gantt.setResolution(Resolution.Week);
        return gantt;
    }

    /**
     * Strip dates after current date.
     *
     * @param toDate
     *            the to date
     * @return the date
     */
    private static final Date stripDatesAfterCurrentDate(final Date toDate) {
        final DateTime currentTime = new DateTime();

        if (currentTime.isBefore(toDate.getTime())) {
            return currentTime.plusDays(1).toDate();
        } else {
            return toDate;
        }
    }

    /**
     * Adds the view generic role member to step.
     *
     * @param stepName
     *            the step name
     * @param step
     *            the step
     * @param assignments
     *            the assignments
     * @param stepMapping
     *            the step mapping
     */
    private void addViewGenericRoleMemberToStep(final String stepName, final Step step, final List<T> assignments,
            final StepMapping<T> stepMapping) {

        for (final T assignmentData : assignments) {

            String subStepName = "";

            if (stepMapping.getRoleCode(assignmentData) != null) {
                subStepName = new StringBuilder().append(stepMapping.getFirstName(assignmentData))
                        .append(CONTENT_SEPARATOR).append(stepMapping.getLastName(assignmentData))
                        .append(PARTY_START_TAG).append(stepMapping.getParty(assignmentData)).append(PARTY_END_TAG)
                        .toString();
            }

            final SubStep sameRoleSubStep = new SubStep(stepName + '.' + subStepName,CaptionMode.HTML);
            sameRoleSubStep.setDescription(stepName + '.' + subStepName);
            sameRoleSubStep.setBackgroundColor(stepMapping.getBackgroundColor(assignmentData));

            sameRoleSubStep.setStartDate(stepMapping.getFromDate(assignmentData).getTime());
            sameRoleSubStep.setEndDate(stripDatesAfterCurrentDate(stepMapping.getToDate(assignmentData)).getTime());

            step.addSubStep(sameRoleSubStep);
        }
    }

    /**
     * Creates the generic gantt.
     *
     * @param assignmentList
     *            the assignment list
     * @param roleMapping
     *            the role mapping
     * @param stepMapping
     *            the step mapping
     * @return the gantt
     */
    private Gantt createGenericGantt(final List<T> assignmentList, final Function<T, String> roleMapping,
            final StepMapping<T> stepMapping) {

        final Map<String, List<T>> assignmentListMap = assignmentList.stream()
                .collect(Collectors.groupingBy(roleMapping, TreeMap::new, Collectors.toList()));

        final Gantt gantt = createGantt();

        if (!assignmentList.isEmpty()) {

            gantt.setStartDate(stepMapping.getFromDate(assignmentList.get(0)));
            gantt.setEndDate(
                    stripDatesAfterCurrentDate(stepMapping.getToDate(assignmentList.get(assignmentList.size() - 1))));

            for (final Entry<String, List<T>> entry : entriesSortedByValues(assignmentListMap, stepMapping)) {

                final String stepName = entry.getKey();

                final Step step = new Step(stepName,CaptionMode.HTML);
                step.setDescription(stepName);

                final List<T> assignments = entry.getValue();

                Collections.sort(assignments, getComparator());

                addViewGenericRoleMemberToStep(stepName, step, assignments, stepMapping);

                gantt.addStep(step);
            }
        }

        return gantt;
    }


    /**
     * Creates the role ghant.
     *
     * @param roleSummaryLayoutTabsheet the role summary layout tabsheet
     * @param assignmentList            the assignment list
     */
    public final void createRoleGhant(final AbstractOrderedLayout roleSummaryLayoutTabsheet, final Collection<T> assignmentList) {

        final Comparator<T> compare = getComparator();

        final List<T> list = assignmentList.stream().filter(
                (final T x) -> new DateTime(getStepMapping().getFromDate(x).getTime()).getYear() > FILTER_DATA_BEFORE_YEAR)
                .collect(Collectors.toList());

        Collections.sort(list, compare);

        final Gantt createGantt = createGenericGantt(list, getRoleMapping(), getStepMapping());
        roleSummaryLayoutTabsheet.addComponent(createGantt);
        roleSummaryLayoutTabsheet.setExpandRatio(createGantt, ContentRatio.GRID);

    }

    /**
     * Entries sorted by values.
     *
     * @param map
     *            the map
     * @param stepMapping
     *            the step mapping
     * @return the sorted set
     */
    private SortedSet<Map.Entry<String, List<T>>> entriesSortedByValues(final Map<String, List<T>> map,
            final StepMapping<T> stepMapping) {
        final Comparator<? super Entry<String, List<T>>> compare = (o1, o2) -> {

            final Comparator<T> compare1 = (o11, o21) -> {
                final int compareDate = stepMapping.getFromDate(o11).compareTo(stepMapping.getFromDate(o21));
                if (compareDate == 0) {
                    final int compareType = stepMapping.getRoleCode(o11).compareTo(stepMapping.getRoleCode(o21));
                    if (compareType == 0) {
                        return stepMapping.getOrg(o11).compareTo(stepMapping.getOrg(o21));
                    } else {
                        return compareType;
                    }
                }

                return compareDate;
            };

            Collections.sort(o1.getValue(), compare1);
            Collections.sort(o2.getValue(), compare1);

            return compare1.compare(o1.getValue().get(0), o2.getValue().get(0));
        };

        final SortedSet<Map.Entry<String, List<T>>> sortedEntries = new TreeSet<>(compare);
        sortedEntries.addAll(map.entrySet());
        return sortedEntries;
    }

    /**
     * Gets the comparator.
     *
     * @return the comparator
     */
    protected abstract Comparator<T> getComparator();

    /**
     * Gets the role mapping.
     *
     * @return the role mapping
     */
    protected abstract Function<T, String> getRoleMapping();

    /**
     * Gets the step mapping.
     *
     * @return the step mapping
     */
    protected abstract StepMapping<T> getStepMapping();

    /**
     * The Interface StepMapping.
     *
     * @param <T>
     *            the generic type
     */
    public interface StepMapping<T> {

        /**
         * Gets the background color.
         *
         * @param t
         *            the t
         * @return the background color
         */
        String getBackgroundColor(T t);

        /**
         * Gets the first name.
         *
         * @param assignmentData
         *            the assignment data
         * @return the first name
         */
        Object getFirstName(T assignmentData);

        /**
         * Gets the from date.
         *
         * @param t
         *            the t
         * @return the from date
         */
        Date getFromDate(T t);

        /**
         * Gets the last name.
         *
         * @param assignmentData
         *            the assignment data
         * @return the last name
         */
        Object getLastName(T assignmentData);

        /**
         * Gets the org.
         *
         * @param t
         *            the t
         * @return the org
         */
        String getOrg(T t);

        /**
         * Gets the party.
         *
         * @param t
         *            the t
         * @return the party
         */
        String getParty(T t);

        /**
         * Gets the role code.
         *
         * @param t
         *            the t
         * @return the role code
         */
        String getRoleCode(T t);

        /**
         * Gets the to date.
         *
         * @param t
         *            the t
         * @return the to date
         */
        Date getToDate(T t);

    }

}