@Before
  public void setUp() throws Exception {
    context =
        new JUnit4Mockery() {
          {
            setThreadingPolicy(new Synchroniser());
          }
        };
    service = new PropDevPropDevBudgetSubAwardServiceImpl();
    budget = new ProposalDevelopmentBudgetExt();
    budget.setBudgetId(1L + 12);
    budget.setDevelopmentProposal(new DevelopmentProposal());
    budget.getDevelopmentProposal().setSponsorCode(NIH_SPONSOR_CODE);
    subAward = new BudgetSubAwards();
    subAward.setBudgetId(budget.getBudgetId());
    subAward.setSubAwardNumber(1 + 206);
    Organization testOrg = new Organization();
    testOrg.setOrganizationName("University of Maine");
    testOrg.setOrganizationId("000040");
    subAward.setOrganization(testOrg);
    budget.getBudgetSubAwards().add(subAward);
    for (int i = 0; i < 2; i++) {
      BudgetPeriod period = new BudgetPeriod();

      period.setBudget(budget);
      period.setBudgetPeriod(i);
      period.setBudgetPeriodId(i + 1029L);
      budget.getBudgetPeriods().add(period);
      BudgetSubAwardPeriodDetail detail = new BudgetSubAwardPeriodDetail(subAward, period);
      detail.setBudgetSubAward(subAward);
      subAward.getBudgetSubAwardPeriodDetails().add(detail);
    }
    final ParameterService parmService = context.mock(ParameterService.class);
    sponsorHierarchyService = context.mock(SponsorHierarchyService.class);
    context.checking(
        new Expectations() {
          {
            one(parmService)
                .getParameterValueAsString(
                    Budget.class, Constants.SUBCONTRACTOR_DIRECT_LT_25K_PARAM);
            will(returnValue(directLt));
            one(parmService)
                .getParameterValueAsString(
                    Budget.class, Constants.SUBCONTRACTOR_DIRECT_GT_25K_PARAM);
            will(returnValue(directGt));
            one(parmService)
                .getParameterValueAsString(
                    Budget.class, Constants.SUBCONTRACTOR_F_AND_A_LT_25K_PARAM);
            will(returnValue(indirectLt));
            one(parmService)
                .getParameterValueAsString(
                    Budget.class, Constants.SUBCONTRACTOR_F_AND_A_GT_25K_PARAM);
            will(returnValue(indirectGt));
          }
        });
    service.setParameterService(parmService);
    service.setSponsorHierarchyService(sponsorHierarchyService);
    service.setBudgetService(new BudgetServiceMock());
  }
  @Test
  public void testExample1WithNonNih() throws Exception {
    context.checking(
        new Expectations() {
          {
            one(sponsorHierarchyService).isSponsorNihMultiplePi(NON_NIH_SPONSOR_CODE);
            will(returnValue(false));
          }
        });
    budget.getDevelopmentProposal().setSponsorCode(NON_NIH_SPONSOR_CODE);

    subAward.getBudgetSubAwardPeriodDetails().get(0).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(0).setIndirectCost(new ScaleTwoDecimal(75000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setIndirectCost(new ScaleTwoDecimal(75000L));

    List<Map<String, ScaleTwoDecimal>> expectedResults = new ArrayList<>();
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.get(0).put(indirectGt, ScaleTwoDecimal.ZERO);
    expectedResults.get(0).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(0).put(directGt, new ScaleTwoDecimal(200000L));
    expectedResults.get(0).put(directLt, new ScaleTwoDecimal(25000L));
    expectedResults.get(1).put(indirectGt, ScaleTwoDecimal.ZERO);
    expectedResults.get(1).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(1).put(directGt, new ScaleTwoDecimal(225000L));
    expectedResults.get(1).put(directLt, ScaleTwoDecimal.ZERO);
    service.generateSubAwardLineItems(subAward, budget);
    assertExpectedResults(expectedResults);
    assertCostShare(0);
  }
  @Test
  public void testExample1WithLineItems() throws Exception {
    context.checking(
        new Expectations() {
          {
            one(sponsorHierarchyService).isSponsorNihMultiplePi(NIH_SPONSOR_CODE);
            will(returnValue(true));
          }
        });

    subAward.getBudgetSubAwardPeriodDetails().get(0).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(0).setIndirectCost(new ScaleTwoDecimal(75000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setIndirectCost(new ScaleTwoDecimal(75000L));

    for (BudgetPeriod period : budget.getBudgetPeriods()) {
      BudgetLineItem newLineItem = new BudgetLineItem();
      newLineItem.setBudgetSubAward(subAward);
      newLineItem.setSubAwardNumber(subAward.getSubAwardNumber());
      newLineItem.setDirectCost(new ScaleTwoDecimal(100L));
      newLineItem.setCostSharingAmount(new ScaleTwoDecimal(100L));
      newLineItem.setCostElement(directLt);
      newLineItem.setLineItemNumber(1);
      period.getBudgetLineItems().add(newLineItem);
      newLineItem = (BudgetLineItem) org.kuali.rice.krad.util.ObjectUtils.deepCopy(newLineItem);
      newLineItem.setCostElement(directGt);
      newLineItem.setLineItemNumber(2);
      period.getBudgetLineItems().add(newLineItem);
      newLineItem = (BudgetLineItem) org.kuali.rice.krad.util.ObjectUtils.deepCopy(newLineItem);
      newLineItem.setCostElement(indirectLt);
      newLineItem.setLineItemNumber(3);
      period.getBudgetLineItems().add(newLineItem);
      newLineItem = (BudgetLineItem) org.kuali.rice.krad.util.ObjectUtils.deepCopy(newLineItem);
      newLineItem.setCostElement(indirectGt);
      newLineItem.setLineItemNumber(4);
      period.getBudgetLineItems().add(newLineItem);
    }

    List<Map<String, ScaleTwoDecimal>> expectedResults = new ArrayList<>();
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.get(0).put(indirectGt, new ScaleTwoDecimal(75000L));
    expectedResults.get(0).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(0).put(directGt, new ScaleTwoDecimal(125000L));
    expectedResults.get(0).put(directLt, new ScaleTwoDecimal(25000L));
    expectedResults.get(1).put(indirectGt, new ScaleTwoDecimal(75000L));
    expectedResults.get(1).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(1).put(directGt, new ScaleTwoDecimal(150000L));
    expectedResults.get(1).put(directLt, ScaleTwoDecimal.ZERO);
    service.generateSubAwardLineItems(subAward, budget);
    assertExpectedResults(expectedResults);
    assertCostShare(0);
  }
  @Test
  public void testExample1WithCostShare() throws Exception {
    context.checking(
        new Expectations() {
          {
            one(sponsorHierarchyService).isSponsorNihMultiplePi(NIH_SPONSOR_CODE);
            will(returnValue(true));
          }
        });

    subAward.getBudgetSubAwardPeriodDetails().get(0).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(0).setIndirectCost(new ScaleTwoDecimal(75000L));
    subAward.getBudgetSubAwardPeriodDetails().get(0).setCostShare(new ScaleTwoDecimal(1000L));

    subAward.getBudgetSubAwardPeriodDetails().get(1).setDirectCost(new ScaleTwoDecimal(150000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setIndirectCost(new ScaleTwoDecimal(75000L));
    subAward.getBudgetSubAwardPeriodDetails().get(1).setCostShare(new ScaleTwoDecimal(1000L));

    List<Map<String, ScaleTwoDecimal>> expectedResults = new ArrayList<>();
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.add(new HashMap<>());
    expectedResults.get(0).put(indirectGt, new ScaleTwoDecimal(75000L));
    expectedResults.get(0).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(0).put(directGt, new ScaleTwoDecimal(125000L));
    expectedResults.get(0).put(directLt, new ScaleTwoDecimal(25000L));

    expectedResults.get(1).put(indirectGt, new ScaleTwoDecimal(75000L));
    expectedResults.get(1).put(indirectLt, ScaleTwoDecimal.ZERO);
    expectedResults.get(1).put(directGt, new ScaleTwoDecimal(150000L));
    expectedResults.get(1).put(directLt, ScaleTwoDecimal.ZERO);
    service.generateSubAwardLineItems(subAward, budget);

    BudgetPeriod period = budget.getBudgetPeriods().get(0);
    Assert.assertTrue(period.getBudgetLineItems().size() == 4);
    List<BudgetLineItem> lineItemsFoundForDirectGt =
        findLineItemsByCostElement(period.getBudgetLineItems(), directGt);
    Assert.assertTrue(lineItemsFoundForDirectGt.size() == 2);
    ScaleTwoDecimal totalDirectCost =
        lineItemsFoundForDirectGt
            .get(0)
            .getLineItemCost()
            .add(lineItemsFoundForDirectGt.get(1).getLineItemCost());
    Assert.assertTrue(totalDirectCost.compareTo(new ScaleTwoDecimal(125000L)) == 0);
    ScaleTwoDecimal totalCostSharing =
        lineItemsFoundForDirectGt
            .get(0)
            .getCostSharingAmount()
            .add(lineItemsFoundForDirectGt.get(1).getCostSharingAmount());
    Assert.assertTrue(totalCostSharing.compareTo(new ScaleTwoDecimal(1000L)) == 0);
    List<BudgetLineItem> lineItemsFound =
        findLineItemsByCostElement(period.getBudgetLineItems(), directLt);
    Assert.assertTrue(
        lineItemsFound.get(0).getLineItemCost().compareTo(new ScaleTwoDecimal(25000L)) == 0);
    lineItemsFound = findLineItemsByCostElement(period.getBudgetLineItems(), indirectGt);
    Assert.assertTrue(
        lineItemsFound.get(0).getLineItemCost().compareTo(new ScaleTwoDecimal(75000L)) == 0);
    lineItemsFound = findLineItemsByCostElement(period.getBudgetLineItems(), indirectLt);
    Assert.assertTrue(lineItemsFound.size() == 0);

    period = budget.getBudgetPeriods().get(1);
    Assert.assertTrue(period.getBudgetLineItems().size() == 3);
    lineItemsFoundForDirectGt = findLineItemsByCostElement(period.getBudgetLineItems(), directGt);
    Assert.assertTrue(lineItemsFoundForDirectGt.size() == 2);
    totalDirectCost =
        lineItemsFoundForDirectGt
            .get(0)
            .getLineItemCost()
            .add(lineItemsFoundForDirectGt.get(1).getLineItemCost());
    Assert.assertTrue(totalDirectCost.compareTo(new ScaleTwoDecimal(150000L)) == 0);
    totalCostSharing =
        lineItemsFoundForDirectGt
            .get(0)
            .getCostSharingAmount()
            .add(lineItemsFoundForDirectGt.get(1).getCostSharingAmount());
    Assert.assertTrue(totalCostSharing.compareTo(new ScaleTwoDecimal(1000L)) == 0);
    lineItemsFound = findLineItemsByCostElement(period.getBudgetLineItems(), directLt);
    Assert.assertTrue(lineItemsFound.size() == 0);
    lineItemsFound = findLineItemsByCostElement(period.getBudgetLineItems(), indirectGt);
    Assert.assertTrue(
        lineItemsFound.get(0).getLineItemCost().compareTo(new ScaleTwoDecimal(75000L)) == 0);
    lineItemsFound = findLineItemsByCostElement(period.getBudgetLineItems(), indirectLt);
    Assert.assertTrue(lineItemsFound.size() == 0);
  }