/**
   * Validates credit splits of all investigators in a <code>{@link ProposalDevelopmentDocument}
   * </code>. Takes a <code>{@link Collection}</code> of investigators for a given credit type, and
   * validates credit splits for each investigator as well as iterating and validating credit splits
   * for each unit belonging to an investigator.
   *
   * @param investigators
   * @param creditTypeCode
   * @return true if the investigator collection is valid for the credit type, and false if it's
   *     invalid
   */
  public boolean validate(
      Collection<ProposalPerson> investigators, InvestigatorCreditType creditType) {
    boolean retval = true;

    DecimalHolder investigatorCreditTotal = new DecimalHolder(KualiDecimal.ZERO);

    if (!validateCreditSplitable(investigators.iterator(), creditType, investigatorCreditTotal)) {
      addAuditError(ERROR_TOTAL_CREDIT_SPLIT_UPBOUND, creditType.getDescription());
      retval = false;
    }

    info(INV_VALIDATION_MESSAGE, retval);

    for (ProposalPerson investigator : investigators) {
      DecimalHolder unitCreditTotal = new DecimalHolder(KualiDecimal.ZERO);

      if (!validateCreditSplitable(
          investigator.getUnits().iterator(), creditType, unitCreditTotal)) {
        addAuditError(
            ERROR_CREDIT_SPLIT_UPBOUND,
            creditType.getDescription(),
            getCreditSplitableName(investigator));
        retval = false;
      }

      info(UNIT_VALIDATION_MESSAGE, retval);
    }

    return retval;
  }
 /**
  * It populates the Active credit type in the proposalpersoncreditsplit and unitcreditsplit
  *
  * @param document
  * @return true or false
  */
 public void populateActiveCredittypesPerson(ProposalDevelopmentDocument document) {
   Collection<InvestigatorCreditType> invcrdttype = getInvestigatorCreditTypes();
   for (ProposalPerson person : document.getDevelopmentProposal().getInvestigators()) {
     for (InvestigatorCreditType invcredtype : invcrdttype) {
       boolean creditTypeFound = false;
       for (ProposalPersonCreditSplit proposalpersoncrdt : person.getCreditSplits()) {
         if ((invcredtype.getCode().equals(proposalpersoncrdt.getInvCreditTypeCode()))) {
           creditTypeFound = true;
           break;
         }
       }
       if (!creditTypeFound) {
         ProposalPersonCreditSplit creditSplit = new ProposalPersonCreditSplit();
         creditSplit.setProposalPerson(person);
         creditSplit.setInvCreditTypeCode(invcredtype.getCode());
         creditSplit.setCredit(new ScaleTwoDecimal(0));
         person.getCreditSplits().add(creditSplit);
       }
     }
     for (ProposalPersonUnit unitsplit : person.getUnits()) {
       for (InvestigatorCreditType invcrdtype : invcrdttype) {
         boolean creditTypeFound = false;
         for (ProposalUnitCreditSplit unitcreditsplit : unitsplit.getCreditSplits()) {
           if ((invcrdtype.getCode().equals(unitcreditsplit.getInvCreditTypeCode()))) {
             creditTypeFound = true;
             break;
           }
         }
         if (!creditTypeFound) {
           ProposalUnitCreditSplit creditSplit = new ProposalUnitCreditSplit();
           creditSplit.setProposalPersonUnit(unitsplit);
           creditSplit.setInvCreditTypeCode(invcrdtype.getCode());
           creditSplit.setCredit(new ScaleTwoDecimal(0));
           unitsplit.getCreditSplits().add(creditSplit);
         }
       }
     }
   }
 }
  @Override
  public List<ProposalCreditSplitListDto> createCreditSplitListItems(
      List<ProposalPerson> investigators) {
    List<ProposalCreditSplitListDto> creditSplitListItems =
        new ArrayList<ProposalCreditSplitListDto>();
    Map<String, ProposalPersonCreditSplit> totalInvestigatorSplits =
        new HashMap<String, ProposalPersonCreditSplit>();
    for (ProposalPerson investigator : investigators) {
      ProposalCreditSplitListDto investigatorLine = new ProposalCreditSplitListDto();
      investigatorLine.setDescription(investigator.getFullName());
      investigatorLine.setLineType("investigator");
      investigatorLine.getCreditSplits().addAll(investigator.getCreditSplits());
      creditSplitListItems.add(investigatorLine);
      for (ProposalPersonCreditSplit invesitgatorCreditSplit : investigator.getCreditSplits()) {
        if (totalInvestigatorSplits.containsKey(invesitgatorCreditSplit.getInvCreditTypeCode())) {
          ProposalPersonCreditSplit creditSplit =
              totalInvestigatorSplits.get(invesitgatorCreditSplit.getInvCreditTypeCode());
          creditSplit.setCredit(creditSplit.getCredit().add(invesitgatorCreditSplit.getCredit()));
        } else {
          ProposalPersonCreditSplit creditSplit = new ProposalPersonCreditSplit();
          creditSplit.setCredit(invesitgatorCreditSplit.getCredit());
          totalInvestigatorSplits.put(invesitgatorCreditSplit.getInvCreditTypeCode(), creditSplit);
        }
      }

      Map<String, ProposalUnitCreditSplit> totalUnitSplits =
          new HashMap<String, ProposalUnitCreditSplit>();
      for (ProposalPersonUnit unit : investigator.getUnits()) {
        ProposalCreditSplitListDto unitLine = new ProposalCreditSplitListDto();
        unitLine.setDescription(unit.getUnitNumber() + " - " + unit.getUnit().getUnitName());
        unitLine.getCreditSplits().addAll(unit.getCreditSplits());
        unitLine.setLineType("unit");
        creditSplitListItems.add(unitLine);
        for (ProposalUnitCreditSplit unitCreditSplit : unit.getCreditSplits()) {
          if (totalUnitSplits.containsKey(unitCreditSplit.getInvCreditTypeCode())) {
            ProposalUnitCreditSplit creditSplit =
                totalUnitSplits.get(unitCreditSplit.getInvCreditTypeCode());
            creditSplit.setCredit(creditSplit.getCredit().add(unitCreditSplit.getCredit()));
          } else {
            ProposalUnitCreditSplit creditSplit = new ProposalUnitCreditSplit();
            creditSplit.setCredit(unitCreditSplit.getCredit());
            totalUnitSplits.put(unitCreditSplit.getInvCreditTypeCode(), creditSplit);
          }
        }
      }

      ProposalCreditSplitListDto unitTotalLine = new ProposalCreditSplitListDto();
      unitTotalLine.setDescription("Unit Total:");
      unitTotalLine.setLineType("unit-total");
      for (Map.Entry<String, ProposalUnitCreditSplit> entry : totalUnitSplits.entrySet()) {
        unitTotalLine.getCreditSplits().add(0, entry.getValue());
      }
      creditSplitListItems.add(unitTotalLine);
    }

    ProposalCreditSplitListDto investigatorTotalLine = new ProposalCreditSplitListDto();
    investigatorTotalLine.setDescription("Investigator Total:");
    investigatorTotalLine.setLineType("investigator-total");
    for (Map.Entry<String, ProposalPersonCreditSplit> entry : totalInvestigatorSplits.entrySet()) {
      investigatorTotalLine.getCreditSplits().add(0, entry.getValue());
    }
    creditSplitListItems.add(investigatorTotalLine);

    return creditSplitListItems;
  }
  /**
   * Everytime something changes that will effect credit split values, this gets called to generate
   * a graph of the new data.
   *
   * @param document
   * @return Map
   */
  public Map calculateCreditSplitTotals(ProposalDevelopmentDocument document) {
    Map<String, Map<String, ScaleTwoDecimal>> retval =
        new HashMap<String, Map<String, ScaleTwoDecimal>>();

    // Initialize investigator credit types if there aren't any
    if (document.getDevelopmentProposal().getInvestigatorCreditTypes() == null
        || document.getDevelopmentProposal().getInvestigatorCreditTypes().size() == 0) {
      document.getDevelopmentProposal().setInvestigatorCreditTypes(getInvestigatorCreditTypes());
    }

    Collection<InvestigatorCreditType> creditTypes =
        document.getDevelopmentProposal().getInvestigatorCreditTypes();

    for (ProposalPerson investigator : document.getDevelopmentProposal().getInvestigators()) {
      Map<String, ScaleTwoDecimal> creditTypeTotals =
          retval.get(investigator.getProposalPersonNumber().toString());
      Map<String, ScaleTwoDecimal> investigatorCreditTypeTotals =
          retval.get(PROPOSAL_PERSON_INVESTIGATOR);

      if (creditTypeTotals == null) {
        creditTypeTotals = new HashMap<String, ScaleTwoDecimal>();
        retval.put(investigator.getProposalPersonNumber().toString(), creditTypeTotals);
      }
      if (investigatorCreditTypeTotals == null) {
        investigatorCreditTypeTotals = new HashMap<String, ScaleTwoDecimal>();
        retval.put(PROPOSAL_PERSON_INVESTIGATOR, investigatorCreditTypeTotals);
      }

      // Initialize everything to zero
      for (InvestigatorCreditType creditType : creditTypes) {
        ScaleTwoDecimal totalCredit = creditTypeTotals.get(creditType.getCode());

        if (totalCredit == null) {
          totalCredit = new ScaleTwoDecimal(0);
          creditTypeTotals.put(creditType.getCode(), totalCredit);
        }
        ScaleTwoDecimal investigatorTotalCredit =
            investigatorCreditTypeTotals.get(creditType.getCode());

        if (investigatorTotalCredit == null) {
          investigatorTotalCredit = new ScaleTwoDecimal(0);
          investigatorCreditTypeTotals.put(creditType.getCode(), investigatorTotalCredit);
        }
        // set investigator credit total
        for (CreditSplit creditSplit : investigator.getCreditSplits()) {
          if (creditSplit.getInvCreditTypeCode().equals(creditType.getCode())) {
            investigatorCreditTypeTotals.put(
                creditType.getCode(), investigatorTotalCredit.add(creditSplit.getCredit()));
          }
        }
      }

      for (ProposalPersonUnit unit : investigator.getUnits()) {
        for (CreditSplit creditSplit : unit.getCreditSplits()) {
          ScaleTwoDecimal totalCredit = creditTypeTotals.get(creditSplit.getInvCreditTypeCode());

          if (totalCredit == null) {
            totalCredit = new ScaleTwoDecimal(0);
            creditTypeTotals.put(creditSplit.getInvCreditTypeCode(), totalCredit);
          }
          creditTypeTotals.put(
              creditSplit.getInvCreditTypeCode(), totalCredit.add(creditSplit.getCredit()));
        }
      }
    }

    return retval;
  }