module.siadap.domain.util.SiadapProcessCounter.java Source code

Java tutorial

Introduction

Here is the source code for module.siadap.domain.util.SiadapProcessCounter.java

Source

/*
 * @(#)SiadapProcessCounter.java
 *
 * Copyright 2011 Instituto Superior Tecnico
 * Founding Authors: Paulo Abrantes
 * 
 *      https://fenix-ashes.ist.utl.pt/
 * 
 *   This file is part of the SIADAP Module.
 *
 *   The SIADAP Module is free software: you can
 *   redistribute it and/or modify it under the terms of the GNU Lesser General
 *   Public License as published by the Free Software Foundation, either version 
 *   3 of the License, or (at your option) any later version.
 *
 *   The SIADAP Module is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with the SIADAP Module. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package module.siadap.domain.util;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;

import javax.naming.OperationNotSupportedException;

import org.joda.time.LocalDate;

import com.google.common.base.Predicate;
import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.google.common.collect.Sets;

import module.organization.domain.Accountability;
import module.organization.domain.AccountabilityType;
import module.organization.domain.Person;
import module.organization.domain.Unit;
import module.siadap.domain.Siadap;
import module.siadap.domain.SiadapEvaluationUniverse;
import module.siadap.domain.SiadapProcessStateEnum;
import module.siadap.domain.SiadapRootModule;
import module.siadap.domain.SiadapYearConfiguration;
import module.siadap.domain.scoring.SiadapGlobalEvaluation;
import module.siadap.domain.wrappers.PersonSiadapWrapper;
import module.siadap.presentationTier.actions.UnitManagementInterfaceAction.Mode;

/**
 * 
 * @author Joo Antunes
 * @author Luis Cruz
 * 
 */
public class SiadapProcessCounter implements Serializable {

    private static final long serialVersionUID = 1L;

    private final int counts[] = new int[SiadapProcessStateEnum.values().length];

    private final HashMap<Boolean, HashMap<String, NumberAndGradeCounter>> countsByQuotaAndCategories = new HashMap<Boolean, HashMap<String, NumberAndGradeCounter>>();

    private final LocalDate dayToUse;
    private final transient SiadapYearConfiguration configuration;
    private final transient AccountabilityType unitRelations;
    //   private final transient AccountabilityType evaluationRelation;
    private final transient AccountabilityType firstKindOfWorkerRelation;
    private final transient AccountabilityType secondKindOfWorkerRelation;

    private final Multiset<Person> duplicatedPersons = ConcurrentHashMultiset.create();
    private final Multiset<Unit> duplicatedUnit = ConcurrentHashMultiset.create();
    private final boolean filteredDuplicatedPersonsSet = false;
    private final boolean filteredDuplicatedUnitSet = false;
    private final Unit topUnit;

    private boolean gatherSiadaps = true;

    private final Set<Siadap> siadaps = new HashSet<Siadap>();

    private final Set<Siadap> curricularPonderationSiadaps = new HashSet<Siadap>();

    private final Map<Integer, Set<Siadap>> notListedSiadaps = new HashMap<Integer, Set<Siadap>>();

    public SiadapProcessCounter(final Unit unit, boolean distinguishBetweenUniverses,
            SiadapYearConfiguration configuration, boolean gatherSiadaps) {
        this(unit, distinguishBetweenUniverses, configuration);
        this.gatherSiadaps = gatherSiadaps;

    }

    private SiadapProcessCounter(final Unit unit, boolean distinguishBetweenUniverses,
            SiadapYearConfiguration configuration, AccountabilityType unitAccType,
            AccountabilityType firstKindOfAccType, AccountabilityType secondKindOfAccType) {
        topUnit = unit;
        this.configuration = configuration;
        this.dayToUse = SiadapMiscUtilClass.lastDayOfYearWhereAccsAreActive(configuration.getYear());
        unitRelations = unitAccType;
        //      evaluationRelation = configuration.getEvaluationRelation();
        firstKindOfWorkerRelation = firstKindOfAccType;
        secondKindOfWorkerRelation = secondKindOfAccType;
        init(distinguishBetweenUniverses);
    }

    public SiadapProcessCounter(final Unit unit, boolean distinguishBetweenUniverses,
            SiadapYearConfiguration configuration, Mode mode) throws OperationNotSupportedException {
        this(unit, distinguishBetweenUniverses, configuration, mode.getUnitAccType(configuration),
                mode.getEmployeeAccTypes(configuration)[0], mode.getEmployeeAccTypes(configuration)[1]);
        AccountabilityType[] employeeAccTypes = mode.getEmployeeAccTypes(configuration);
        if (employeeAccTypes.length != 2) {
            throw new OperationNotSupportedException("do not support Mode: " + mode.name());
        }

    }

    public SiadapProcessCounter(final Unit unit, boolean distinguishBetweenUniverses,
            SiadapYearConfiguration configuration) {
        this(unit, distinguishBetweenUniverses, configuration, configuration.getUnitRelations(),
                configuration.getWorkingRelation(), configuration.getWorkingRelationWithNoQuota());

    }

    void init(boolean distinguishBetweenUniverses) {
        if (distinguishBetweenUniverses) {
            count(topUnit, distinguishBetweenUniverses);
            // if we are distinguishing between universes, let's also include
            // the not lister persons
            for (Siadap siadap : getOrCreateSiadapsNotListed()) {
                PersonSiadapWrapper siadapWrapper = new PersonSiadapWrapper(siadap);
                count(siadapWrapper.getPerson(), siadapWrapper.isQuotaAware());
            }
        } else {
            count(topUnit);
        }
    }

    private void count(Unit unit, boolean distinguishBetweenUniverses) {
        unit.getChildAccountabilityStream().filter(a -> a.isActive(dayToUse))
                .forEach(new Consumer<Accountability>() {
                    @Override
                    public void accept(Accountability accountability) {
                        final AccountabilityType accountabilityType = accountability.getAccountabilityType();
                        if (accountabilityType == unitRelations) {
                            final Unit child = (Unit) accountability.getChild();
                            duplicatedUnit.add(child);
                            count(child, distinguishBetweenUniverses);
                        } else if (accountabilityType == firstKindOfWorkerRelation) {
                            final Person person = (Person) accountability.getChild();
                            count(person, true);

                        } else if (accountabilityType == secondKindOfWorkerRelation) {
                            final Person person = (Person) accountability.getChild();
                            count(person, false);

                        }

                    }
                });
    }

    private void count(final Unit unit) {
        unit.getChildAccountabilityStream().filter(a -> a.isActive(dayToUse))
                .forEach(new Consumer<Accountability>() {
                    @Override
                    public void accept(Accountability accountability) {
                        final AccountabilityType accountabilityType = accountability.getAccountabilityType();
                        if (accountabilityType == unitRelations) {
                            final Unit child = (Unit) accountability.getChild();
                            duplicatedUnit.add(child);
                            count(child);
                        } else if (accountabilityType == firstKindOfWorkerRelation
                                || accountabilityType == secondKindOfWorkerRelation) {
                            final Person person = (Person) accountability.getChild();
                            count(person);
                        }
                    }
                });
    }

    private void count(final Person person) {
        final Siadap siadap = configuration.getSiadapFor(person);
        final SiadapProcessStateEnum state = siadap == null ? SiadapProcessStateEnum.NOT_CREATED
                : SiadapProcessStateEnum.getState(siadap);
        duplicatedPersons.add(person);
        counts[state.ordinal()]++;
        if (gatherSiadaps && siadap != null) {
            getSiadaps().add(siadap);
        }
    }

    public Set<Siadap> getOrCreateSiadapsNotListed() {
        final int year = configuration.getYear();
        Set<Siadap> notListedSiadapsForGivenYear = notListedSiadaps.get(year);
        if (notListedSiadapsForGivenYear == null) {
            notListedSiadapsForGivenYear = new TreeSet<Siadap>(
                    Siadap.COMPARATOR_BY_EVALUATED_PRESENTATION_NAME_FALLBACK_YEAR_THEN_OID);

            notListedSiadapsForGivenYear
                    .addAll(Sets.filter(SiadapRootModule.getInstance().getSiadapsSet(), new Predicate<Siadap>() {

                        @Override
                        public boolean apply(Siadap input) {
                            if (input == null) {
                                return false;
                            }
                            return input.getYear() == year;
                        }
                    }));

            notListedSiadapsForGivenYear.removeAll(getSiadaps());
            notListedSiadaps.put(year, notListedSiadapsForGivenYear);
            return notListedSiadapsForGivenYear;

        } else {
            return notListedSiadapsForGivenYear;
        }
    }

    public int getOrCreateSiadapsNotListedSize() {
        return getOrCreateSiadapsNotListed().size();
    }

    public static class NumberAndGradeCounter {

        public NumberAndGradeCounter(String categoryName, SiadapStatisticsSummaryBoardUniversesEnum universesEnum) {
            this.categoryName = categoryName;
            this.subCategoryTypeEnum = universesEnum;
            this.subCategoryCounter = new int[universesEnum.getNrOfSubCategories()];
            this.totalPeopleEvaluatedByCompetencesOnlyCounter = 0;
        }

        String categoryName;

        private final SiadapStatisticsSummaryBoardUniversesEnum subCategoryTypeEnum;

        int totalNumberOfCategoryPeople = 0;

        int[] subCategoryCounter;

        int totalPeopleEvaluatedByCompetencesOnlyCounter;

        final Set<Siadap> siadapsForThisCategory = new HashSet<Siadap>();

        Multiset<SiadapGlobalEvaluation> gradeCounter = HashMultiset.create();

        void addPerson(int subCategoryIndex) {
            this.subCategoryCounter[subCategoryIndex]++;
            totalNumberOfCategoryPeople++;
        }

        void addPersonEvaluatedOnlyByCompetences() {
            this.totalPeopleEvaluatedByCompetencesOnlyCounter++;
        }

        void addGrade(SiadapGlobalEvaluation evaluation) {
            gradeCounter.add(evaluation);
        }

        public boolean hasSubCategories() {
            return getNumberSubCategories() > 1;
        }

        public int getNumberSubCategories() {
            return this.subCategoryCounter.length;
        }

        public int[] getSubCategoryCounter() {
            return this.subCategoryCounter;
        }

        public void addSiadapForThisCategory(Siadap siadap) {
            this.siadapsForThisCategory.add(siadap);
        }

        public Set<Siadap> getSiadapsForThisCategory() {
            return siadapsForThisCategory;
        }

        public int getNumberOfPeopleForSubcategory(int subcategoryIndex) {
            return this.subCategoryCounter[subcategoryIndex];
        }

        public int getNumberOfPeopleEvaluatedOnlyByCompetences() {
            return this.totalPeopleEvaluatedByCompetencesOnlyCounter;
        }

        public int getTotalNumberOfCategoryPeople() {
            return totalNumberOfCategoryPeople;
        }

        public Multiset<SiadapGlobalEvaluation> getGradeCounter() {
            return gradeCounter;
        }

        public SiadapStatisticsSummaryBoardUniversesEnum getSubCategoryTypeEnum() {
            return subCategoryTypeEnum;
        }

    }

    private void count(final Person person, boolean withQuota) {
        final Siadap siadap = configuration.getSiadapFor(person);
        final SiadapProcessStateEnum state = siadap == null ? SiadapProcessStateEnum.NOT_CREATED
                : SiadapProcessStateEnum.getState(siadap);

        duplicatedPersons.add(person);

        // let's fill the complicated hashmap
        HashMap<String, NumberAndGradeCounter> categoryHashMap = getCountsByQuotaAndCategories()
                .get(Boolean.valueOf(withQuota));
        if (categoryHashMap == null)
        // if it doesn't exist for this quotaaware/noquotaaware universe, let's
        // create it
        {
            categoryHashMap = new HashMap<String, NumberAndGradeCounter>();
            getCountsByQuotaAndCategories().put(Boolean.valueOf(withQuota), categoryHashMap);
        }

        SiadapStatisticsSummaryBoardUniversesEnum universesEnum = SiadapStatisticsSummaryBoardUniversesEnum
                .getStatisticsUniverse(state);
        String categoryName = universesEnum.getCategoryString(siadap);
        NumberAndGradeCounter numberAndGradeCounter = categoryHashMap.get(categoryName);
        if (numberAndGradeCounter == null) {
            // do we already have a counter for this category?!, if not, we
            // create it
            numberAndGradeCounter = new NumberAndGradeCounter(categoryName, universesEnum);
            categoryHashMap.put(universesEnum.getCategoryString(siadap), numberAndGradeCounter);
        }

        // Registering the SIADAPS in curricular ponderation
        if (siadap != null && siadap.hasAnAssociatedCurricularPonderationEval()) {
            getCurricularPonderationSiadaps().add(siadap);
        }

        // let's register the person
        numberAndGradeCounter.addPerson(universesEnum.getSubCategoryIndex(state));

        if (siadap != null) {
            Boolean evaluatedOnlyByCompetences = siadap.getEvaluatedOnlyByCompetences();
            if (evaluatedOnlyByCompetences != null && evaluatedOnlyByCompetences) {
                numberAndGradeCounter.addPersonEvaluatedOnlyByCompetences();
            }

        }

        // let's register the person's grade
        if (siadap != null) {

            SiadapEvaluationUniverse defaultSiadapEvaluationUniverse = siadap.getDefaultSiadapEvaluationUniverse();
            if (defaultSiadapEvaluationUniverse != null
                    && defaultSiadapEvaluationUniverse.getLatestSiadapGlobalEvaluationEnum() != null) {
                numberAndGradeCounter
                        .addGrade(defaultSiadapEvaluationUniverse.getLatestSiadapGlobalEvaluationEnum());
            }
        }

        if (gatherSiadaps && siadap != null) {
            getSiadaps().add(siadap);
            numberAndGradeCounter.addSiadapForThisCategory(siadap);

        }
    }

    public Set<Person> getDuplicatePersons() {
        if (!filteredDuplicatedPersonsSet) {
            filterDuplicatedPersonsSet();
        }
        return duplicatedPersons.elementSet();

    }

    public Set<Unit> getDuplicateUnits() {
        if (!filteredDuplicatedUnitSet) {
            filterDuplicatedUnitSet();
        }
        return duplicatedUnit.elementSet();

    }

    public Multiset<Unit> getOriginalDuplicateUnits() {
        if (!filteredDuplicatedUnitSet) {
            filterDuplicatedUnitSet();
        }
        return duplicatedUnit;

    }

    private void filterDuplicatedUnitSet() {
        for (Unit unit : duplicatedUnit) {
            if (duplicatedUnit.count(unit) == 1) {
                duplicatedUnit.remove(unit);
            }
        }

    }

    private void filterDuplicatedPersonsSet() {
        for (Person person : duplicatedPersons) {
            if (duplicatedPersons.count(person) == 1) {
                duplicatedPersons.remove(person);
            }
        }
    }

    public int[] getCounts() {
        return counts;
    }

    public boolean hasAnyPendingProcesses() {
        for (int i = 0; i < counts.length; i++) {
            if (i != 6 && counts[i] > 0) {
                return true;
            }
        }
        return false;
    }

    public HashMap<Boolean, HashMap<String, NumberAndGradeCounter>> getCountsByQuotaAndCategories() {
        return countsByQuotaAndCategories;
    }

    public Set<Siadap> getSiadaps() {
        return siadaps;
    }

    public Set<Siadap> getCurricularPonderationSiadaps() {
        return curricularPonderationSiadaps;
    }

    public static Set<Siadap> getSiadapsInState(final int year, final SiadapProcessStateEnum... states) {

        HashSet<Siadap> allSiadapsInGivenStates = new HashSet<Siadap>();

        allSiadapsInGivenStates
                .addAll(Sets.filter(SiadapRootModule.getInstance().getSiadapsSet(), new Predicate<Siadap>() {

                    @Override
                    public boolean apply(Siadap siadapInstance) {
                        if (siadapInstance == null) {
                            return false;
                        }
                        if (siadapInstance.getYear() != year) {
                            return false;
                        }
                        for (SiadapProcessStateEnum state : states) {
                            if (siadapInstance.getState().equals(state)) {
                                return true;
                            }
                        }
                        return false;
                    }
                }));

        return allSiadapsInGivenStates;

    }

}