View Javadoc
1   /*
2    * Copyright 2006 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.coa.document.validation.impl;
17  
18  import java.util.List;
19  
20  import org.apache.commons.lang.StringUtils;
21  import org.kuali.ole.coa.businessobject.AccountGlobalDetail;
22  import org.kuali.ole.sys.OLEKeyConstants;
23  import org.kuali.ole.sys.document.validation.impl.KfsMaintenanceDocumentRuleBase;
24  import org.kuali.rice.krad.util.GlobalVariables;
25  
26  /**
27   * This class contains common Business Rule functionality for Global Documents.
28   */
29  public class GlobalDocumentRuleBase extends KfsMaintenanceDocumentRuleBase {
30  
31      /**
32       * Constructs a GlobalDocumentRuleBase.java.
33       */
34      public GlobalDocumentRuleBase() {
35          super();
36      }
37  
38      /**
39       * This method checks whether the set of Account Change Detail records on this document all are under the same Chart of
40       * Accounts. It will set the appropriate field error if it did fail, and return the result.
41       * 
42       * @param accountGlobalDetails
43       * @return True if the test passed with no errors, False if any errors occurred.
44       */
45      protected boolean checkOnlyOneChartErrorWrapper(List<AccountGlobalDetail> accountGlobalDetails) {
46          CheckOnlyOneChartResult result = checkOnlyOneChart(accountGlobalDetails);
47          if (!result.success) {
48              putFieldError("accountGlobalDetails[" + result.firstLineNumber + "].chartOfAccountsCode", OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY);
49              putFieldError("accountGlobalDetails[" + result.failedLineNumber + "].chartOfAccountsCode", OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY);
50          }
51          return result.success;
52      }
53  
54      /**
55       * This method checks whether the set of Account Change Detail records on this document all are under the same Chart of
56       * Accounts. It will return a failed CheckOnlyOneChartResult if so. Note that this method doesnt actually set any errors, it
57       * just returns whether or not the test succeeded, and where it failed if it failed.
58       * 
59       * @param accountGlobalDetails The popualted accountGlobalDocument to test.
60       * @return A populated CheckOnlyOneChartResult object. This will contain whether the test succeeded or failed, and if failed,
61       *         what lines the failures occurred on.
62       */
63      protected CheckOnlyOneChartResult checkOnlyOneChart(List<AccountGlobalDetail> accountGlobalDetails) {
64          // if there is not enough information to do the test, then exit happily with no failure
65          if (accountGlobalDetails == null) {
66              return new CheckOnlyOneChartResult(true);
67          }
68          if (accountGlobalDetails.isEmpty()) {
69              return new CheckOnlyOneChartResult(true);
70          }
71  
72          // test to see if there is more than one chart listed, ignores blank chartcodes
73          int compareLineNumber = 0;
74          int firstChartLineNumber = 0;
75          String firstChart = "";
76          for (AccountGlobalDetail account : accountGlobalDetails) {
77              if (StringUtils.isBlank(firstChart)) {
78                  if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) {
79                      firstChart = account.getChartOfAccountsCode();
80                      firstChartLineNumber = compareLineNumber;
81                  }
82              }
83              else {
84                  if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) {
85                      if (!firstChart.equalsIgnoreCase(account.getChartOfAccountsCode())) {
86                          return new CheckOnlyOneChartResult(false, firstChartLineNumber, compareLineNumber);
87                      }
88                  }
89              }
90              compareLineNumber++;
91          }
92          return new CheckOnlyOneChartResult(true);
93      }
94  
95      /**
96       * This class is used internally to represent the result of the CheckOnlyOneChart method.
97       */
98      protected class CheckOnlyOneChartResult {
99  
100         public int firstLineNumber;
101         public int failedLineNumber;
102         public boolean success;
103 
104         /**
105          * Constructs a CheckOnlyOneChartResult
106          */
107         public CheckOnlyOneChartResult() {
108             firstLineNumber = -1;
109             failedLineNumber = -1;
110             success = true;
111         }
112 
113         /**
114          * Constructs a CheckOnlyOneChartResult
115          * 
116          * @param success
117          */
118         public CheckOnlyOneChartResult(boolean success) {
119             this();
120             this.success = success;
121         }
122 
123         /**
124          * Constructs a CheckOnlyOneChartResult
125          * 
126          * @param success
127          * @param firstLineNumber
128          * @param failedLineNumber
129          */
130         public CheckOnlyOneChartResult(boolean success, int firstLineNumber, int failedLineNumber) {
131             this.success = success;
132             this.firstLineNumber = firstLineNumber;
133             this.failedLineNumber = failedLineNumber;
134         }
135 
136     }
137 
138     /**
139      * This method tests whether the line being added has a different Chart of Accounts Code from any of the existing lines. It will
140      * set an Error and return false if this is the case.
141      * 
142      * @param newAccountLine
143      * @param accountGlobalDetails
144      * @return True if the line being added has the exact same chart as all the existing lines, False if not.
145      */
146     protected boolean checkOnlyOneChartAddLineErrorWrapper(AccountGlobalDetail newAccountLine, List<AccountGlobalDetail> accountGlobalDetails) {
147         boolean success = checkOnlyOneChartAddLine(newAccountLine, accountGlobalDetails);
148         if (!success) {
149             // putGlobalError(OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY_ADDNEW);
150             // TODO: KULCOA-1091 Need to add this error to the add line, but this doesn't work right, as the
151             // error message comes out at the bottom, and the field doesn't get highlighted.
152             // putFieldError("newAccountGlobalDetail.chartOfAccountsCode",
153             // OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY);
154 
155             // added to prevent error from showing at the top of the document, but rather in the Account Detail Edit section
156             GlobalVariables.getMessageMap().putError("chartOfAccountsCode", OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY_ADDNEW);
157         }
158         return success;
159     }
160 
161     /**
162      * This method tests whether a new line can be added, based on the rule that says all the accounts being used must belong to the
163      * same chart. If the line being added differs from any existing line's Chart code, it will return false. Note that this
164      * document does not actually set any errors, it just reports success or failure.
165      * 
166      * @param newAccountLine
167      * @param accountGlobalDetails
168      * @return True if no errors are found, False if the line being added has a different Chart code than any of the existing lines.
169      */
170     protected boolean checkOnlyOneChartAddLine(AccountGlobalDetail newAccountLine, List<AccountGlobalDetail> accountGlobalDetails) {
171         if (newAccountLine == null || accountGlobalDetails == null) {
172             return true;
173         }
174         if (accountGlobalDetails.isEmpty()) {
175             return true;
176         }
177         String newChart = newAccountLine.getChartOfAccountsCode();
178         if (StringUtils.isBlank(newChart)) {
179             return true;
180         }
181         for (AccountGlobalDetail account : accountGlobalDetails) {
182             if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) {
183                 if (!newChart.equalsIgnoreCase(account.getChartOfAccountsCode())) {
184                     return false;
185                 }
186             }
187         }
188         return true;
189     }
190 
191 }