001/* 002 * Copyright 2006 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.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/ecl2.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 */ 016package org.kuali.ole.coa.document.validation.impl; 017 018import java.util.List; 019 020import org.apache.commons.lang.StringUtils; 021import org.kuali.ole.coa.businessobject.AccountGlobalDetail; 022import org.kuali.ole.sys.OLEKeyConstants; 023import org.kuali.ole.sys.document.validation.impl.KfsMaintenanceDocumentRuleBase; 024import org.kuali.rice.krad.util.GlobalVariables; 025 026/** 027 * This class contains common Business Rule functionality for Global Documents. 028 */ 029public class GlobalDocumentRuleBase extends KfsMaintenanceDocumentRuleBase { 030 031 /** 032 * Constructs a GlobalDocumentRuleBase.java. 033 */ 034 public GlobalDocumentRuleBase() { 035 super(); 036 } 037 038 /** 039 * This method checks whether the set of Account Change Detail records on this document all are under the same Chart of 040 * Accounts. It will set the appropriate field error if it did fail, and return the result. 041 * 042 * @param accountGlobalDetails 043 * @return True if the test passed with no errors, False if any errors occurred. 044 */ 045 protected boolean checkOnlyOneChartErrorWrapper(List<AccountGlobalDetail> accountGlobalDetails) { 046 CheckOnlyOneChartResult result = checkOnlyOneChart(accountGlobalDetails); 047 if (!result.success) { 048 putFieldError("accountGlobalDetails[" + result.firstLineNumber + "].chartOfAccountsCode", OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY); 049 putFieldError("accountGlobalDetails[" + result.failedLineNumber + "].chartOfAccountsCode", OLEKeyConstants.ERROR_DOCUMENT_GLOBAL_ACCOUNT_ONE_CHART_ONLY); 050 } 051 return result.success; 052 } 053 054 /** 055 * This method checks whether the set of Account Change Detail records on this document all are under the same Chart of 056 * Accounts. It will return a failed CheckOnlyOneChartResult if so. Note that this method doesnt actually set any errors, it 057 * just returns whether or not the test succeeded, and where it failed if it failed. 058 * 059 * @param accountGlobalDetails The popualted accountGlobalDocument to test. 060 * @return A populated CheckOnlyOneChartResult object. This will contain whether the test succeeded or failed, and if failed, 061 * what lines the failures occurred on. 062 */ 063 protected CheckOnlyOneChartResult checkOnlyOneChart(List<AccountGlobalDetail> accountGlobalDetails) { 064 // if there is not enough information to do the test, then exit happily with no failure 065 if (accountGlobalDetails == null) { 066 return new CheckOnlyOneChartResult(true); 067 } 068 if (accountGlobalDetails.isEmpty()) { 069 return new CheckOnlyOneChartResult(true); 070 } 071 072 // test to see if there is more than one chart listed, ignores blank chartcodes 073 int compareLineNumber = 0; 074 int firstChartLineNumber = 0; 075 String firstChart = ""; 076 for (AccountGlobalDetail account : accountGlobalDetails) { 077 if (StringUtils.isBlank(firstChart)) { 078 if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) { 079 firstChart = account.getChartOfAccountsCode(); 080 firstChartLineNumber = compareLineNumber; 081 } 082 } 083 else { 084 if (StringUtils.isNotBlank(account.getChartOfAccountsCode())) { 085 if (!firstChart.equalsIgnoreCase(account.getChartOfAccountsCode())) { 086 return new CheckOnlyOneChartResult(false, firstChartLineNumber, compareLineNumber); 087 } 088 } 089 } 090 compareLineNumber++; 091 } 092 return new CheckOnlyOneChartResult(true); 093 } 094 095 /** 096 * This class is used internally to represent the result of the CheckOnlyOneChart method. 097 */ 098 protected class CheckOnlyOneChartResult { 099 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}