001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.module.kra.budget.web.struts.form;
017:
018: import java.util.ArrayList;
019: import java.util.Arrays;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.kuali.core.util.KualiDecimal;
028: import org.kuali.kfs.context.SpringContext;
029: import org.kuali.module.kra.budget.bo.BudgetNonpersonnel;
030: import org.kuali.module.kra.budget.bo.NonpersonnelCategory;
031: import org.kuali.module.kra.budget.document.BudgetDocument;
032: import org.kuali.module.kra.budget.service.BudgetNonpersonnelService;
033: import org.kuali.module.kra.budget.service.BudgetPeriodService;
034:
035: /**
036: * This is used by the UI to get totals, counts, and other things needed to render nonpersonnel copy over properly.
037: */
038: public class BudgetNonpersonnelCopyOverFormHelper {
039:
040: // This map holds the individual NonpersonnelCopyOverCategoryHelper objects.
041: // The Key is the nonpersonnel category code, the value is the NonpersonnelCopyOverCategoryHelper.
042: Map nonpersonnelCopyOverCategoryHelpers;
043:
044: /**
045: * Constructs a BudgetNonpersonnelFormHelper. Default, no arg constructor
046: */
047: public BudgetNonpersonnelCopyOverFormHelper() {
048: nonpersonnelCopyOverCategoryHelpers = new HashMap();
049: }
050:
051: /**
052: * Constructs a BudgetNonpersonnelCopyOverFormHelper based on data extracted from a BudgetForm.
053: *
054: * @param budgetForm which is used to take the categories and nonpersonnel objects from
055: */
056: public BudgetNonpersonnelCopyOverFormHelper(BudgetForm budgetForm) {
057: nonpersonnelCopyOverCategoryHelpers = new HashMap();
058: List nonpersonnelCategories = budgetForm
059: .getNonpersonnelCategories();
060: List nonpersonnelItems = budgetForm.getBudgetDocument()
061: .getBudget().getNonpersonnelItems();
062:
063: // Build NonpersonnelCopyOverCategoryHelper for each category.
064: for (Iterator nonpersonnelCategoryIter = nonpersonnelCategories
065: .iterator(); nonpersonnelCategoryIter.hasNext();) {
066: NonpersonnelCategory nonpersonnelCategory = (NonpersonnelCategory) nonpersonnelCategoryIter
067: .next();
068:
069: nonpersonnelCopyOverCategoryHelpers
070: .put(
071: nonpersonnelCategory.getCode(),
072: new NonpersonnelCopyOverCategoryHelper(
073: nonpersonnelCategory,
074: budgetForm.getCurrentTaskNumber(),
075: budgetForm.getBudgetDocument()
076: .getBudget().getPeriods(),
077: budgetForm
078: .getBudgetDocument()
079: .getBudget()
080: .getBudgetNonpersonnelInflationRate(),
081: nonpersonnelItems));
082: }
083:
084: // Calculate totals
085: this .refresh(budgetForm.getBudgetDocument().getBudget()
086: .getPeriods().size());
087: }
088:
089: /**
090: * Copies the nonpersonnel objects contained in this object back into the nonpersonnel list in BudgetForm. The data duplication
091: * is present in order to simplify display on the copy over page and most importantly to facilitate saving at the right time.
092: *
093: * @param budgetForm which is used to copy the nonpersonnel objects into
094: */
095: public void deconstruct(BudgetForm budgetForm) {
096: List nonpersonnelCategories = budgetForm
097: .getNonpersonnelCategories();
098:
099: // iterate over each category
100: for (Iterator nonpersonnelCategoryIter = nonpersonnelCategories
101: .iterator(); nonpersonnelCategoryIter.hasNext();) {
102: NonpersonnelCategory nonpersonnelCategory = (NonpersonnelCategory) nonpersonnelCategoryIter
103: .next();
104:
105: NonpersonnelCopyOverCategoryHelper nonpersonnelCopyOverCategoryHelper = (NonpersonnelCopyOverCategoryHelper) nonpersonnelCopyOverCategoryHelpers
106: .get(nonpersonnelCategory.getCode());
107: if (nonpersonnelCopyOverCategoryHelper != null) {
108: nonpersonnelCopyOverCategoryHelper
109: .deconstruct((BudgetDocument) budgetForm
110: .getDocument());
111: }
112: }
113: }
114:
115: /**
116: * Updates the datastructure with new values based on a page refresh or prior to a return. Specifically this involves ensuring
117: * origin item checkboxes are correctly checked (checked for items that have been copied over) and totals are calculated.
118: *
119: * @param periodsSize number of periods
120: */
121: public void refresh(int periodsSize) {
122: Collection nprsHelpers = nonpersonnelCopyOverCategoryHelpers
123: .values();
124:
125: // iterate over each category
126: for (Iterator nprsHelpersIter = nprsHelpers.iterator(); nprsHelpersIter
127: .hasNext();) {
128: NonpersonnelCopyOverCategoryHelper nonpersonnelCopyOverCategoryHelper = (NonpersonnelCopyOverCategoryHelper) nprsHelpersIter
129: .next();
130:
131: nonpersonnelCopyOverCategoryHelper.refresh(periodsSize);
132: }
133: }
134:
135: /**
136: * Gets the nonpersonnelCopyOverCategoryHelpers attribute.
137: *
138: * @return Returns the nonpersonnelCopyOverCategoryHelpers.
139: */
140: public Map getNonpersonnelCopyOverCategoryHelpers() {
141: return nonpersonnelCopyOverCategoryHelpers;
142: }
143:
144: /**
145: * Sets the nonpersonnelCopyOverCategoryHelpers attribute value.
146: *
147: * @param nonpersonnelCopyOverCategoryHelpers The nonpersonnelCopyOverCategoryHelpers to set.
148: */
149: public void setNonpersonnelCopyOverCategoryHelpers(
150: Map budgetNonpersonnelHelperMap) {
151: this .nonpersonnelCopyOverCategoryHelpers = budgetNonpersonnelHelperMap;
152: }
153:
154: /**
155: * Gets a NonpersonnelCopyOverCategoryHelper from nonpersonnelCopyOverCategoryHelpers. Creates it if it doesn't exist yet. This
156: * is useful because the hidden variables on the copy over page need a place to be put.
157: *
158: * @param key Key for the NonpersonnelCopyOverCategoryHelper to get
159: * @return Returns a NonpersonnelCopyOverCategoryHelper.
160: */
161: public NonpersonnelCopyOverCategoryHelper getNonpersonnelCopyOverCategoryHelper(
162: String key) {
163: NonpersonnelCopyOverCategoryHelper nonpersonnelCopyOverCategoryHelper = (NonpersonnelCopyOverCategoryHelper) nonpersonnelCopyOverCategoryHelpers
164: .get(key);
165:
166: if (nonpersonnelCopyOverCategoryHelper == null) {
167: nonpersonnelCopyOverCategoryHelper = new NonpersonnelCopyOverCategoryHelper();
168:
169: nonpersonnelCopyOverCategoryHelpers.put(key,
170: nonpersonnelCopyOverCategoryHelper);
171: }
172:
173: return nonpersonnelCopyOverCategoryHelper;
174: }
175:
176: /**
177: * Class that stores the nonpersonnel items. From the copy over page seen this is a category with each having the line items for
178: * all tasks.
179: */
180: public class NonpersonnelCopyOverCategoryHelper {
181: private String nonpersonnelCategoryCode; // this field isn't critical, but it is helpful
182: private List agencyRequestAmountTotal;
183: private List budgetInstitutionCostShareAmountTotal;
184: private List budgetThirdPartyCostShareAmountTotal;
185: private List nprsItems;
186:
187: /**
188: * Constructs a NonpersonnelCopyOverCategoryHelper. Default, no arg constructor
189: */
190: public NonpersonnelCopyOverCategoryHelper() {
191: this .nprsItems = new ArrayList();
192: }
193:
194: /**
195: * Constructor for NonpersonnelCopyOverCategoryHelper that represents a current period, task summary. It will pick out all
196: * the appropriate nonpersonnel items meeting those criteria and place their amounts into
197: * NonpersonnelCopyOverLineItemHelper.
198: *
199: * @param nonpersonnelCategory category that this NonpersonnelCopyOverCategoryHelper represents
200: * @param currentTaskNumber current task that this NonpersonnelCopyOverCategoryHelper represents ("task summar" basically)
201: * @param periods Budget.periods
202: * @param budgetNonpersonnelInflationRate inflation rate of this budget
203: * @param nonpersonnelItems all nonpersonnel items, this method will pick the appropriate ones out, this needs to be ordered
204: * by sequence number.
205: */
206: public NonpersonnelCopyOverCategoryHelper(
207: NonpersonnelCategory nonpersonnelCategory,
208: Integer currentTaskNumber, List periods,
209: KualiDecimal budgetNonpersonnelInflationRate,
210: List nonpersonnelItems) {
211: this ();
212: this .setNonpersonnelCategoryCode(nonpersonnelCategory
213: .getCode());
214:
215: this .addBudgetNonpersonnelItem(currentTaskNumber, periods,
216: budgetNonpersonnelInflationRate, nonpersonnelItems);
217: }
218:
219: /**
220: * @see org.kuali.module.kra.budget.web.struts.form.BudgetNonpersonnelCopyOverFormHelper#deconstruct(BudgetForm budgetForm)
221: * @param budgetDocument Budget.document
222: */
223: public void deconstruct(BudgetDocument budgetDocument) {
224: // iterate over each line item
225: for (Iterator nprsItemsIter = nprsItems.iterator(); nprsItemsIter
226: .hasNext();) {
227: NonpersonnelCopyOverLineItemHelper nonpersonnelCopyOverLineItemHelper = (NonpersonnelCopyOverLineItemHelper) nprsItemsIter
228: .next();
229:
230: nonpersonnelCopyOverLineItemHelper
231: .deconstruct(budgetDocument);
232: }
233: }
234:
235: /**
236: * @see org.kuali.module.kra.budget.web.struts.form.BudgetNonpersonnelCopyOverFormHelper#refresh()
237: * @param periodsSize number of periods
238: */
239: public void refresh(int periodsSize) {
240: KualiDecimal agencyRequestAmountTotalArr[] = new KualiDecimal[periodsSize];
241: KualiDecimal budgetInstitutionCostShareAmountTotalArr[] = new KualiDecimal[periodsSize];
242: KualiDecimal budgetThirdPartyCostShareAmountTotalArr[] = new KualiDecimal[periodsSize];
243:
244: // initialize the arrays with 0 values
245: for (int i = 0; i < periodsSize; i++) {
246: agencyRequestAmountTotalArr[i] = new KualiDecimal(0);
247: budgetInstitutionCostShareAmountTotalArr[i] = new KualiDecimal(
248: 0);
249: budgetThirdPartyCostShareAmountTotalArr[i] = new KualiDecimal(
250: 0);
251: }
252:
253: // iterate over each line item
254: for (Iterator nprsItemsIter = nprsItems.iterator(); nprsItemsIter
255: .hasNext();) {
256: NonpersonnelCopyOverLineItemHelper nonpersonnelCopyOverLineItemHelper = (NonpersonnelCopyOverLineItemHelper) nprsItemsIter
257: .next();
258:
259: // handles checking appropriate checkboxes, note this is unrelated to calculating amount totals.
260: nonpersonnelCopyOverLineItemHelper.refresh();
261:
262: for (int i = 0; i < periodsSize; i++) { // for each period
263: // add value to the total
264: BudgetNonpersonnelCopyOverBoHelper periodAmount = nonpersonnelCopyOverLineItemHelper
265: .getPeriodAmount(i);
266: agencyRequestAmountTotalArr[i] = agencyRequestAmountTotalArr[i]
267: .add(periodAmount
268: .getDisplayAgencyRequestAmount());
269: budgetInstitutionCostShareAmountTotalArr[i] = budgetInstitutionCostShareAmountTotalArr[i]
270: .add(periodAmount
271: .getDisplayBudgetInstitutionCostShareAmount());
272: budgetThirdPartyCostShareAmountTotalArr[i] = budgetThirdPartyCostShareAmountTotalArr[i]
273: .add(periodAmount
274: .getDisplayBudgetThirdPartyCostShareAmount());
275: }
276: }
277:
278: // convert array to the list
279: agencyRequestAmountTotal = Arrays
280: .asList(agencyRequestAmountTotalArr);
281: budgetInstitutionCostShareAmountTotal = Arrays
282: .asList(budgetInstitutionCostShareAmountTotalArr);
283: budgetThirdPartyCostShareAmountTotal = Arrays
284: .asList(budgetThirdPartyCostShareAmountTotalArr);
285: }
286:
287: /**
288: * Helper method that removes business logic from constructor to properly place each item of budgetNonpersonnel.
289: *
290: * @param currentTaskNumber current task that this NonpersonnelCopyOverCategoryHelper represents ("task summar" basically)
291: * @param periods Budget.periods
292: * @param budgetNonpersonnelInflationRate inflation rate of this budget
293: * @param nonpersonnelItems all nonpersonnel items, this method will pick the appropriate ones out, this needs to be ordered
294: * by sequence number.
295: */
296: private void addBudgetNonpersonnelItem(
297: Integer currentTaskNumber, List periods,
298: KualiDecimal budgetNonpersonnelInflationRate,
299: List nonpersonnelItems) {
300: HashMap nprsCopyOverLineItemHelpers = new HashMap();
301:
302: // Loop and check below assumes origin items are always found before copy over items. Sort to make sure.
303: Collections.sort(nonpersonnelItems);
304:
305: // loop over all nonpersonnelItems for this budget
306: for (Iterator nonpersonnelItemsIter = nonpersonnelItems
307: .iterator(); nonpersonnelItemsIter.hasNext();) {
308: BudgetNonpersonnel budgetNonpersonnel = (BudgetNonpersonnel) nonpersonnelItemsIter
309: .next();
310:
311: // check if this nonpersonnelItem is part of this task and category, otherwise skip
312: if (budgetNonpersonnel.getBudgetTaskSequenceNumber()
313: .equals(currentTaskNumber)
314: && budgetNonpersonnel
315: .getBudgetNonpersonnelCategoryCode()
316: .equals(
317: this
318: .getNonpersonnelCategoryCode())) {
319:
320: if (budgetNonpersonnel.isOriginItem()) { // it is an origin item
321: // Create a new BudgetNonpersonnelCopyOverBoHelper, without inflation (so rate = 0)
322: BudgetNonpersonnelCopyOverBoHelper nonpersonnelCopyOverBoHelper = new BudgetNonpersonnelCopyOverBoHelper(
323: budgetNonpersonnel);
324: // Create a new NonpersonnelCopyOverLineItemHelper and initilize it with list of length of periods
325: NonpersonnelCopyOverLineItemHelper nprsCopyOverLineItemHelper = new NonpersonnelCopyOverLineItemHelper(
326: nonpersonnelCopyOverBoHelper, periods,
327: budgetNonpersonnelInflationRate);
328:
329: // Add it to the local class list and to a local method HashMap. The local method
330: // HashMap is so that it's easily found by possible already existing copy over
331: // items (see else clause below).
332: this .nprsItems.add(nprsCopyOverLineItemHelper);
333: nprsCopyOverLineItemHelpers
334: .put(
335: nonpersonnelCopyOverBoHelper
336: .getBudgetNonpersonnelSequenceNumber(),
337: nprsCopyOverLineItemHelper);
338: } else { // it is a copied over item
339: // find this items' origin item
340: NonpersonnelCopyOverLineItemHelper nprsCopyOverLineItemHelper = (NonpersonnelCopyOverLineItemHelper) nprsCopyOverLineItemHelpers
341: .get(budgetNonpersonnel
342: .getBudgetOriginSequenceNumber());
343:
344: // new item with inflation rate, and add it to list (appropriate spot of period number)
345: int inflationLength = SpringContext
346: .getBean(BudgetPeriodService.class)
347: .getPeriodsRange(
348: nprsCopyOverLineItemHelper
349: .getOriginBudgetPeriodSequenceNumber(),
350: budgetNonpersonnel
351: .getBudgetPeriodSequenceNumber(),
352: periods);
353: BudgetNonpersonnelCopyOverBoHelper nonpersonnelCopyOverBoHelper = new BudgetNonpersonnelCopyOverBoHelper(
354: budgetNonpersonnel, inflationLength,
355: budgetNonpersonnelInflationRate);
356: nprsCopyOverLineItemHelper.add(
357: nonpersonnelCopyOverBoHelper, periods);
358: }
359:
360: }
361: }
362: }
363:
364: /**
365: * Gets the nonpersonnelCategoryCode attribute.
366: *
367: * @return Returns the nonpersonnelCategoryCode.
368: */
369: public String getNonpersonnelCategoryCode() {
370: return nonpersonnelCategoryCode;
371: }
372:
373: /**
374: * Sets the nonpersonnelCategoryCode attribute value.
375: *
376: * @param nonpersonnelCategoryCode The nonpersonnelCategoryCode to set.
377: */
378: public void setNonpersonnelCategoryCode(
379: String nonpersonnelCategoryCode) {
380: this .nonpersonnelCategoryCode = nonpersonnelCategoryCode;
381: }
382:
383: /**
384: * Gets the agencyRequestAmountTotal attribute.
385: *
386: * @return Returns the agencyRequestAmountTotal.
387: */
388: public List getAgencyRequestAmountTotal() {
389: return agencyRequestAmountTotal;
390: }
391:
392: /**
393: * Sets the agencyRequestAmountTotal attribute value.
394: *
395: * @param agencyRequestAmountTotal The agencyRequestAmountTotal to set.
396: */
397: public void setAgencyRequestAmountTotal(
398: List agencyRequestAmountTotal) {
399: this .agencyRequestAmountTotal = agencyRequestAmountTotal;
400: }
401:
402: /**
403: * Gets the budgetThirdPartyCostShareAmountTotal attribute.
404: *
405: * @return Returns the budgetThirdPartyCostShareAmountTotal.
406: */
407: public List getBudgetThirdPartyCostShareAmountTotal() {
408: return budgetThirdPartyCostShareAmountTotal;
409: }
410:
411: /**
412: * Sets the budgetThirdPartyCostShareAmountTotal attribute value.
413: *
414: * @param budgetThirdPartyCostShareAmountTotal The budgetThirdPartyCostShareAmountTotal to set.
415: */
416: public void setBudgetThirdPartyCostShareAmountTotal(
417: List budgetThirdPartyCostShareAmountTotal) {
418: this .budgetThirdPartyCostShareAmountTotal = budgetThirdPartyCostShareAmountTotal;
419: }
420:
421: /**
422: * Gets the budgetInstitutionCostShareAmountTotal attribute.
423: *
424: * @return Returns the budgetInstitutionCostShareAmountTotal.
425: */
426: public List getBudgetInstitutionCostShareAmountTotal() {
427: return budgetInstitutionCostShareAmountTotal;
428: }
429:
430: /**
431: * Sets the budgetInstitutionCostShareAmountTotal attribute value.
432: *
433: * @param budgetInstitutionCostShareAmountTotal The budgetInstitutionCostShareAmountTotal to set.
434: */
435: public void setBudgetInstitutionCostShareAmountTotal(
436: List budgetInstitutionCostShareAmountTotal) {
437: this .budgetInstitutionCostShareAmountTotal = budgetInstitutionCostShareAmountTotal;
438: }
439:
440: /**
441: * Gets the nprsItems attribute.
442: *
443: * @return Returns the nprsItems.
444: */
445: public List getNprsItems() {
446: return nprsItems;
447: }
448:
449: /**
450: * Sets the nprsItems attribute value.
451: *
452: * @param nprsItems The nprsItems to set.
453: */
454: public void setNprsItems(List nprsItems) {
455: this .nprsItems = nprsItems;
456: }
457:
458: /**
459: * Gets the newNonpersonnel attribute.
460: *
461: * @return Returns the newNonpersonnel.
462: */
463: public NonpersonnelCopyOverLineItemHelper getNprsItem(int index) {
464: while (getNprsItems().size() <= index) {
465: getNprsItems().add(
466: new NonpersonnelCopyOverLineItemHelper());
467: }
468: return (NonpersonnelCopyOverLineItemHelper) getNprsItems()
469: .get(index);
470: }
471:
472: /**
473: * For each item NonpersonnelCopyOverCategoryHelper we have this object to essentially represent each nonpersonnel item per
474: * period (it helps to look at the nonpersonnel copy over page -- periods go out horizontally, that is what this object with
475: * its list represents).
476: */
477: public class NonpersonnelCopyOverLineItemHelper {
478: // these two are the same for each item in the periodAmounts list. It is in this object
479: // for display convenience.
480: private String nonpersonnelSubCategoryName;
481: private String budgetNonpersonnelDescription;
482:
483: private Integer originBudgetPeriodSequenceNumber; // for ease of determining where the boss is
484: private List periodAmounts; // mostly static in size (would have preferred []), but ArrayList will make implementation
485:
486: // of getPeriodAmount easier which is needed by struts for hidden variables
487:
488: /**
489: * Constructs a NonpersonnelCopyOverCategoryHelper. Default, no arg constructor
490: */
491: public NonpersonnelCopyOverLineItemHelper() {
492: periodAmounts = new ArrayList();
493: }
494:
495: /**
496: * Constructor for this object. This object does not do too much other then tracking pertinent information for easy
497: * retrieval on the copy over page and then (finally!) holding each BudgetNonpersonnelCopyOverBoHelper object in an
498: * array.
499: *
500: * @param budgetNonpersonnelCopyOverBoHelper the row that this objects represents
501: * @param periods Budget.periods
502: * @param budgetNonpersonnelInflationRate inflation rate of this budget
503: */
504: public NonpersonnelCopyOverLineItemHelper(
505: BudgetNonpersonnelCopyOverBoHelper budgetNonpersonnelCopyOverBoHelper,
506: List periods,
507: KualiDecimal budgetNonpersonnelInflationRate) {
508: this .nonpersonnelSubCategoryName = budgetNonpersonnelCopyOverBoHelper
509: .getNonpersonnelObjectCode()
510: .getNonpersonnelSubCategory().getName();
511: this .budgetNonpersonnelDescription = budgetNonpersonnelCopyOverBoHelper
512: .getBudgetNonpersonnelDescription();
513: this .originBudgetPeriodSequenceNumber = budgetNonpersonnelCopyOverBoHelper
514: .getBudgetPeriodSequenceNumber();
515:
516: // We do this with an array because otherwise we have to fill the list with empty items
517: // upto the location of the origin item. The code gets a bit dirty then.
518: BudgetNonpersonnelCopyOverBoHelper[] periodAmountsArr = new BudgetNonpersonnelCopyOverBoHelper[periods
519: .size()];
520:
521: // Place the origin item
522: int originItemIndex = SpringContext.getBean(
523: BudgetPeriodService.class).getPeriodIndex(
524: budgetNonpersonnelCopyOverBoHelper
525: .getBudgetPeriodSequenceNumber(),
526: periods);
527: periodAmountsArr[originItemIndex] = budgetNonpersonnelCopyOverBoHelper;
528:
529: // Fill the items before the origin item.
530: this .backwardFillPeriodAmounts(periodAmountsArr,
531: originItemIndex);
532:
533: // Next we check if this item has been copied forward, if it hasn't then we have to
534: // forward fill it with copy over items that have inflation rate.
535: if (!budgetNonpersonnelCopyOverBoHelper
536: .isCopiedOverItem()) {
537: this .forwardFillPeriodAmounts(periodAmountsArr,
538: originItemIndex,
539: budgetNonpersonnelCopyOverBoHelper,
540: periods, budgetNonpersonnelInflationRate);
541: }
542:
543: periodAmounts = Arrays.asList(periodAmountsArr);
544: }
545:
546: /**
547: * @see org.kuali.module.kra.budget.web.struts.form.BudgetNonpersonnelCopyOverFormHelper#deconstruct(BudgetForm
548: * budgetForm)
549: * @param budgetDocument Budget.document
550: */
551: public void deconstruct(BudgetDocument budgetDocument) {
552: // check if any of the indicators are set, if not, we can skip this item
553: if (this .isCopyIndicatorSet()) {
554: // item gets copied from & to every period, starting from the location of the origin item
555: for (int i = this .findOriginItemIndex(); i < periodAmounts
556: .size(); i++) {
557: BudgetNonpersonnelCopyOverBoHelper budgetNonpersonnelCopyOverBoHelper = (BudgetNonpersonnelCopyOverBoHelper) periodAmounts
558: .get(i);
559:
560: if (budgetNonpersonnelCopyOverBoHelper
561: .getBudgetNonpersonnelSequenceNumber() == null) {
562: // item didn't exist as nonpersonnel item yet.
563:
564: // add it to the Budget Document per the standard methods provided, addNonpersonnel will set sequence
565: // number
566: BudgetNonpersonnel newNonpersonnel = budgetNonpersonnelCopyOverBoHelper
567: .getBudgetNonpersonnel();
568: budgetDocument
569: .addNonpersonnel(newNonpersonnel);
570: } else {
571: // item existed before, could be an origin item
572:
573: // find nonpersonnelItem that is to be updated
574: List nonpersonnelItems = budgetDocument
575: .getBudget().getNonpersonnelItems();
576: BudgetNonpersonnel budgetNonpersonnel = SpringContext
577: .getBean(
578: BudgetNonpersonnelService.class)
579: .findBudgetNonpersonnel(
580: budgetNonpersonnelCopyOverBoHelper
581: .getBudgetNonpersonnelSequenceNumber(),
582: nonpersonnelItems);
583:
584: // update indicators
585: budgetNonpersonnel
586: .setAgencyCopyIndicator(budgetNonpersonnelCopyOverBoHelper
587: .getAgencyCopyIndicator());
588: budgetNonpersonnel
589: .setBudgetInstitutionCostShareCopyIndicator(budgetNonpersonnelCopyOverBoHelper
590: .getBudgetInstitutionCostShareCopyIndicator());
591: budgetNonpersonnel
592: .setBudgetThirdPartyCostShareCopyIndicator(budgetNonpersonnelCopyOverBoHelper
593: .getBudgetThirdPartyCostShareCopyIndicator());
594:
595: budgetNonpersonnel
596: .setCopyToFuturePeriods(false); // nothing to do with copy over, just make sure the
597: // checkbox is unchecked if "save" is used to copy
598: // over items on NPRS page
599:
600: // update amounts. If indicator set, use inflated amounts, otherwise use original amounts. Need to
601: // check both cases because we don't know if user checked or unchecked field.
602: if (budgetNonpersonnelCopyOverBoHelper
603: .getAgencyCopyIndicator()) {
604: budgetNonpersonnel
605: .setAgencyRequestAmount(budgetNonpersonnelCopyOverBoHelper
606: .getBudgetInflatedAgencyAmount());
607: } else {
608: budgetNonpersonnel
609: .setAgencyRequestAmount(budgetNonpersonnelCopyOverBoHelper
610: .getAgencyRequestAmount());
611: }
612: if (budgetNonpersonnelCopyOverBoHelper
613: .getBudgetInstitutionCostShareCopyIndicator()) {
614: budgetNonpersonnel
615: .setBudgetInstitutionCostShareAmount(budgetNonpersonnelCopyOverBoHelper
616: .getBudgetInflatedInstitutionCostShareAmount());
617: } else {
618: budgetNonpersonnel
619: .setBudgetInstitutionCostShareAmount(budgetNonpersonnelCopyOverBoHelper
620: .getBudgetInstitutionCostShareAmount());
621: }
622: if (budgetNonpersonnelCopyOverBoHelper
623: .getBudgetThirdPartyCostShareCopyIndicator()) {
624: budgetNonpersonnel
625: .setBudgetThirdPartyCostShareAmount(budgetNonpersonnelCopyOverBoHelper
626: .getBudgetInflatedThirdPartyCostShareAmount());
627: } else {
628: budgetNonpersonnel
629: .setBudgetThirdPartyCostShareAmount(budgetNonpersonnelCopyOverBoHelper
630: .getBudgetThirdPartyCostShareAmount());
631: }
632:
633: if (budgetNonpersonnelCopyOverBoHelper
634: .isOriginItem()) {
635: // update budgetOriginSequenceNumber. This is important if it was an origin item
636: // so that the interface can easily tell if an item has been copied over. This
637: // isn't done in the BudgetNonpersonnelCopyOverBoHelper constructors because we
638: // want to make sure it's only done for items that are copied over.
639: budgetNonpersonnel
640: .setBudgetOriginSequenceNumber(budgetNonpersonnelCopyOverBoHelper
641: .getBudgetNonpersonnelSequenceNumber());
642: }
643: }
644: }
645: }
646: }
647:
648: /**
649: * @see org.kuali.module.kra.budget.web.struts.form.BudgetNonpersonnelCopyOverFormHelper#refresh()
650: */
651: public void refresh() {
652: BudgetNonpersonnelCopyOverBoHelper originItem = (BudgetNonpersonnelCopyOverBoHelper) periodAmounts
653: .get(this .findOriginItemIndex());
654:
655: for (int i = 0; i < periodAmounts.size(); i++) {
656: BudgetNonpersonnelCopyOverBoHelper budgetNonpersonnelCopyOverBoHelper = (BudgetNonpersonnelCopyOverBoHelper) periodAmounts
657: .get(i);
658:
659: if (budgetNonpersonnelCopyOverBoHelper
660: .getAgencyCopyIndicator()) {
661: originItem.setAgencyCopyIndicator(true);
662: }
663: if (budgetNonpersonnelCopyOverBoHelper
664: .getBudgetInstitutionCostShareCopyIndicator()) {
665: originItem
666: .setBudgetInstitutionCostShareCopyIndicator(true);
667: }
668: if (budgetNonpersonnelCopyOverBoHelper
669: .getBudgetThirdPartyCostShareCopyIndicator()) {
670: originItem
671: .setBudgetThirdPartyCostShareCopyIndicator(true);
672: }
673: }
674: }
675:
676: /**
677: * Fills items before the origin item with dummy Nonpersonnel objects. This is so that the interface displays 0 amounts
678: * for those. This could be handled via the tag but since struts does the same thing when evaluating hidden variables,
679: * we might as well do the same via the constructor.
680: *
681: * @see org.kuali.module.kra.budget.web.struts.form.BudgetNonpersonnelCopyOverFormHelper.NonpersonnelCopyOverCategoryHelper.NonpersonnelCopyOverLineItemHelper#getPeriodAmount(int
682: * index)
683: * @param periodAmountsArr array passed from constructor so that it's avoided to asList / toArray unnecessarily
684: * @param originItemIndex index of the originItem in the array (note: originItemIndex !=
685: * originItem.budgetPeriodSequenceNumberOverride)
686: */
687: protected void backwardFillPeriodAmounts(
688: BudgetNonpersonnelCopyOverBoHelper[] periodAmountsArr,
689: int originItemIndex) {
690: for (int i = 0; i < originItemIndex; i++) {
691: BudgetNonpersonnelCopyOverBoHelper nonpersonnelCopyOverBoHelper = new BudgetNonpersonnelCopyOverBoHelper();
692: periodAmountsArr[i] = nonpersonnelCopyOverBoHelper;
693: }
694: }
695:
696: /**
697: * Used for Nonpersonnel items that have not been copied forward. For those we need to forward fill the list with items
698: * that contain inflation rates. This will enable displaying those rates (and checkboxes) propertly on the interface. It
699: * also makes returning to nonpersonnel easier.
700: *
701: * @param periodAmountsArr array passed from constructor so that it's avoided to asList / toArray unnecessarily
702: * @param originItemIndex index of the originItem in the array (note: originItemIndex !=
703: * originItem.budgetPeriodSequenceNumberOverride)
704: * @param originItem originItem itself
705: * @param budgetNonpersonnelInflationRate inflation rate of this budget
706: */
707: protected void forwardFillPeriodAmounts(
708: BudgetNonpersonnelCopyOverBoHelper[] periodAmountsArr,
709: int originItemIndex,
710: BudgetNonpersonnelCopyOverBoHelper originItem,
711: List periods,
712: KualiDecimal budgetNonpersonnelInflationRate) {
713: // Loop over the array starting after the origin item (hence: forwardFill)
714: for (int i = originItemIndex + 1; i < periodAmountsArr.length; i++) {
715:
716: // Retrieve a few variables that we need to create the new forward filling object
717: BudgetPeriodService budgetPeriodService = SpringContext
718: .getBean(BudgetPeriodService.class);
719: Integer budgetPeriodSequenceNumberOverride = budgetPeriodService
720: .getPeriodAfterOffset(
721: originItem
722: .getBudgetPeriodSequenceNumber(),
723: i - originItemIndex, periods)
724: .getBudgetPeriodSequenceNumber();
725: int inflationLength = budgetPeriodService
726: .getPeriodsRange(originItem
727: .getBudgetPeriodSequenceNumber(),
728: budgetPeriodSequenceNumberOverride,
729: periods);
730:
731: // Create the new object and put it in the list
732: BudgetNonpersonnelCopyOverBoHelper nonpersonnelCopyOverBoHelper = new BudgetNonpersonnelCopyOverBoHelper(
733: originItem,
734: budgetPeriodSequenceNumberOverride,
735: inflationLength,
736: budgetNonpersonnelInflationRate);
737: periodAmountsArr[i] = nonpersonnelCopyOverBoHelper;
738: }
739: }
740:
741: /**
742: * Adds a BudgetNonpersonnelCopyOverBoHelper object to periodAmounts in this object.
743: *
744: * @param budgetNonpersonnelCopyOverBoHelper to be added.
745: * @param periods Budget.periods. This is important so that
746: * budgetNonpersonnelCopyOverBoHelper.getBudgetPeriodSequenceNumber() can be used to figure out the spot it
747: * belongs in.
748: */
749: public void add(
750: BudgetNonpersonnelCopyOverBoHelper budgetNonpersonnelCopyOverBoHelper,
751: List periods) {
752: // Since this List was created with Arrays.asList, using List.add is unsupported per
753: // JavaDoc. That is why it's put into Array format, added and put back into List. This
754: // might seem a bit complicated but as part of a code walkthrough this seemed the cleanest
755: // solution.
756: BudgetNonpersonnelCopyOverBoHelper[] periodAmountsArr = (BudgetNonpersonnelCopyOverBoHelper[]) periodAmounts
757: .toArray();
758:
759: int targetIndex = SpringContext.getBean(
760: BudgetPeriodService.class).getPeriodIndex(
761: budgetNonpersonnelCopyOverBoHelper
762: .getBudgetPeriodSequenceNumber(),
763: periods);
764:
765: periodAmountsArr[targetIndex] = budgetNonpersonnelCopyOverBoHelper;
766: periodAmounts = Arrays.asList(periodAmountsArr);
767: }
768:
769: /**
770: * Checks if any of the get*CopyIndicator's are set for any of this objects elements.
771: *
772: * @return indicating if any of the get*CopyIndicator indicators are set for its elements.
773: */
774: public boolean isCopyIndicatorSet() {
775: for (int i = 0; i < periodAmounts.size(); i++) {
776: BudgetNonpersonnelCopyOverBoHelper budgetNonpersonnelCopyOverBoHelper = (BudgetNonpersonnelCopyOverBoHelper) periodAmounts
777: .get(i);
778:
779: if (budgetNonpersonnelCopyOverBoHelper
780: .getAgencyCopyIndicator()
781: || budgetNonpersonnelCopyOverBoHelper
782: .getBudgetInstitutionCostShareCopyIndicator()
783: || budgetNonpersonnelCopyOverBoHelper
784: .getBudgetThirdPartyCostShareCopyIndicator()) {
785: return true;
786: }
787: }
788:
789: return false;
790: }
791:
792: /**
793: * Finds the origin item index in periodAmounts. Returns -1 if it could not be found (although that should never happen
794: * except if this object does not have any periodAmounts yet).
795: *
796: * @return origin item index
797: */
798: public int findOriginItemIndex() {
799: int originItemIndex = -1;
800:
801: // Looks for the origin item (first item that != null) and breaks loop
802: // as soon as it is found.
803: for (int i = 0; i < periodAmounts.size()
804: && originItemIndex == -1; i++) {
805: if (periodAmounts.get(i) != null
806: && ((BudgetNonpersonnelCopyOverBoHelper) periodAmounts
807: .get(i)).isOriginItem()) {
808: originItemIndex = i;
809: }
810: }
811:
812: return originItemIndex;
813: }
814:
815: /**
816: * Gets the budgetNonpersonnelDescription attribute.
817: *
818: * @return Returns the budgetNonpersonnelDescription.
819: */
820: public String getBudgetNonpersonnelDescription() {
821: return budgetNonpersonnelDescription;
822: }
823:
824: /**
825: * Sets the budgetNonpersonnelDescription attribute value.
826: *
827: * @param budgetNonpersonnelDescription The budgetNonpersonnelDescription to set.
828: */
829: public void setBudgetNonpersonnelDescription(
830: String budgetNonpersonnelDescription) {
831: this .budgetNonpersonnelDescription = budgetNonpersonnelDescription;
832: }
833:
834: /**
835: * Gets the nonpersonnelSubCategoryName attribute.
836: *
837: * @return Returns the nonpersonnelSubCategoryName.
838: */
839: public String getNonpersonnelSubCategoryName() {
840: return nonpersonnelSubCategoryName;
841: }
842:
843: /**
844: * Sets the nonpersonnelSubCategoryName attribute value.
845: *
846: * @param nonpersonnelSubCategoryName The nonpersonnelSubCategoryName to set.
847: */
848: public void setNonpersonnelSubCategoryName(
849: String nonpersonnelSubCategoryName) {
850: this .nonpersonnelSubCategoryName = nonpersonnelSubCategoryName;
851: }
852:
853: /**
854: * Gets the originBudgetPeriodSequenceNumber attribute.
855: *
856: * @return Returns the originBudgetPeriodSequenceNumber.
857: */
858: public Integer getOriginBudgetPeriodSequenceNumber() {
859: return originBudgetPeriodSequenceNumber;
860: }
861:
862: /**
863: * Sets the originBudgetPeriodSequenceNumber attribute value.
864: *
865: * @param originBudgetPeriodSequenceNumber The originBudgetPeriodSequenceNumber to set.
866: */
867: public void setOriginBudgetPeriodSequenceNumber(
868: Integer originBudgetPeriodSequenceNumber) {
869: this .originBudgetPeriodSequenceNumber = originBudgetPeriodSequenceNumber;
870: }
871:
872: /**
873: * Gets the periodAmounts attribute.
874: *
875: * @return Returns the periodAmounts.
876: */
877: public List getPeriodAmounts() {
878: return periodAmounts;
879: }
880:
881: /**
882: * Sets the periodAmounts attribute value.
883: *
884: * @param periodAmounts The periodAmounts to set.
885: */
886: public void setPeriodAmounts(List periods) {
887: this .periodAmounts = periods;
888: }
889:
890: /**
891: * Gets the newNonpersonnel attribute.
892: *
893: * @return Returns the newNonpersonnel.
894: */
895: public BudgetNonpersonnelCopyOverBoHelper getPeriodAmount(
896: int index) {
897: while (getPeriodAmounts().size() <= index) {
898: getPeriodAmounts().add(
899: new BudgetNonpersonnelCopyOverBoHelper());
900: }
901: return (BudgetNonpersonnelCopyOverBoHelper) getPeriodAmounts()
902: .get(index);
903: }
904: }
905: }
906: }
|