View Javadoc
1   /*
2    * Copyright 2008 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.sys.document.validation.impl;
17  
18  import java.lang.reflect.InvocationTargetException;
19  import java.util.LinkedList;
20  import java.util.Queue;
21  
22  import org.apache.commons.beanutils.PropertyUtils;
23  import org.apache.commons.lang.StringUtils;
24  import org.kuali.ole.sys.businessobject.AccountingLine;
25  import org.kuali.ole.sys.businessobject.SourceAccountingLine;
26  import org.kuali.ole.sys.context.SpringContext;
27  import org.kuali.ole.sys.document.AccountingDocument;
28  import org.kuali.ole.sys.document.validation.GenericValidation;
29  import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
30  import org.kuali.ole.sys.service.impl.OleParameterConstants;
31  import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
32  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
33  import org.kuali.rice.krad.bo.PersistableBusinessObject;
34  import org.kuali.rice.krad.util.ObjectUtils;
35  
36  /**
37   * A validation which uses parameters to determine if a value on an accounting line is valid.
38   */
39  public class AccountingLineValueAllowedValidation extends GenericValidation {
40      protected String propertyPath;
41      protected String parameterToCheckAgainst;
42      protected ParameterService parameterService;
43      protected String responsibleProperty;
44      protected AccountingDocument accountingDocumentForValidation;
45      protected AccountingLine accountingLineForValidation;
46  
47      /**
48       * Checks if a value in a given accounting line is allowed, based on system parameters.
49       * <strong>Expects an accounting document as the first parameter and accounting line as the second</strong>
50       * @see org.kuali.ole.sys.document.validation.GenericValidation#validate(java.lang.Object[])
51       */
52      public boolean validate(AttributedDocumentEvent event) {
53          
54          if (!StringUtils.isBlank(propertyPath)) {
55              refreshByPath(accountingLineForValidation);
56          }
57          
58          return isAccountingLineValueAllowed(accountingDocumentForValidation.getDocumentClassForAccountingLineValueAllowedValidation(), accountingLineForValidation, parameterToCheckAgainst, propertyPath, (responsibleProperty != null ? responsibleProperty : propertyPath));
59      }
60      
61      /**
62       * Checks that a value on an accounting line is valid, based on parameters, for a document of the given class
63       * @param documentClass the class of the document to check
64       * @param accountingLine the accounting line to check
65       * @param parameterName the name of the parameter to check
66       * @param propertyName the name of the property to check
67       * @param userEnteredPropertyName the value the user entered on the line
68       * @return true if this passes validation, false otherwise
69       */
70      protected boolean isAccountingLineValueAllowed(Class documentClass, AccountingLine accountingLine, String parameterName, String propertyName, String userEnteredPropertyName) {
71          boolean isAllowed = true;
72          String exceptionMessage = "Invalue property name provided to AccountingDocumentRuleBase isAccountingLineValueAllowed method: " + propertyName;
73          try {
74              String propertyValue = (String) PropertyUtils.getProperty(accountingLine, propertyName);
75              if (getParameterService().parameterExists(OleParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class, parameterName)) {
76                  isAllowed = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(OleParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class, parameterName, propertyValue).evaluateAndAddError(SourceAccountingLine.class, propertyName, userEnteredPropertyName);
77              }
78              if (getParameterService().parameterExists(documentClass, parameterName)) {
79                  isAllowed = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(documentClass, parameterName, propertyValue).evaluateAndAddError(SourceAccountingLine.class, propertyName, userEnteredPropertyName);
80              }
81          }
82          catch (IllegalAccessException e) {
83              throw new RuntimeException(exceptionMessage, e);
84          }
85          catch (InvocationTargetException e) {
86              throw new RuntimeException(exceptionMessage, e);
87          }
88          catch (NoSuchMethodException e) {
89              throw new RuntimeException(exceptionMessage, e);
90          }
91          return isAllowed;
92      }
93      
94      /**
95       * Refreshes a value on the accounting line, using the propertyPath to decided what to refresh
96       * @param line the accounting line to refresh a property on
97       */
98      public void refreshByPath(AccountingLine line) {
99          refreshByQueue(line, convertPathToQueue(propertyPath));
100     }
101     
102     /**
103      * Creates a Queue which represents a FIFO path of what properties to visit, based on the given property path
104      * @param path the path to convert to a Queue
105      * @return a Queue representing the path
106      */
107     protected Queue<String> convertPathToQueue(String path) {
108         Queue<String> pathQueue = new LinkedList<String>();
109         for (String property: path.split("\\.")) {
110             pathQueue.add(property);
111         }
112         return pathQueue;
113     }
114     
115     /**
116      * Recursively refreshes a property given by the queue path
117      * @param bo the business object to refresh
118      * @param path the path, in Queue form, of properties to refresh
119      */
120     protected void refreshByQueue(PersistableBusinessObject bo, Queue<String> path) {
121         if (path.size() > 1) { // we know that the last thing on our list is a code. why refresh that?
122             String currentProperty = path.remove();
123             bo.refreshReferenceObject(currentProperty);
124             PersistableBusinessObject childBO = (PersistableBusinessObject)ObjectUtils.getPropertyValue(bo, currentProperty);
125             if (!ObjectUtils.isNull(childBO)) {       
126                 refreshByQueue(childBO, path);
127             }
128         }
129     }
130 
131     /**
132      * Gets the propertyPath attribute. This is the path to the value to check, e. g. "accountNumber.subFundGroup.fundGroupCode"
133      * @return Returns the propertyPath.
134      */
135     public String getPropertyPath() {
136         return propertyPath;
137     }
138 
139     /**
140      * Sets the propertyPath attribute value. This is the path to the value to check, e. g. "accountNumber.subFundGroup.fundGroupCode"
141      * @param propertyPath The propertyPath to set.
142      */
143     public void setPropertyPath(String refreshPath) {
144         this.propertyPath = refreshPath;
145     }
146 
147     /**
148      * Gets the parameterService attribute. 
149      * @return Returns the parameterService.
150      */
151     public ParameterService getParameterService() {
152         return parameterService;
153     }
154 
155     /**
156      * Sets the parameterService attribute value.
157      * @param parameterService The parameterService to set.
158      */
159     public void setParameterService(ParameterService parameterService) {
160         this.parameterService = parameterService;
161     }
162 
163     /**
164      * Gets the parameterToCheckAgainst attribute. This is the name of the parameter which has the values to validate against.
165      * @return Returns the parameterToCheckAgainst.
166      */
167     public String getParameterToCheckAgainst() {
168         return parameterToCheckAgainst;
169     }
170 
171     /**
172      * Sets the parameterToCheckAgainst attribute value.  This is the name of the parameter which has the values to validate against.
173      * @param parameterToCheckAgainst The parameterToCheckAgainst to set.
174      */
175     public void setParameterToCheckAgainst(String parameterToCheckAgainst) {
176         this.parameterToCheckAgainst = parameterToCheckAgainst;
177     }
178 
179     /**
180      * Gets the responsibleProperty attribute. This is the property on the accounting line to show the error on.
181      * @return Returns the responsibleProperty.
182      */
183     public String getResponsibleProperty() {
184         return responsibleProperty;
185     }
186 
187     /**
188      * Sets the responsibleProperty attribute value. This is the property on the accounting line to show the error on.
189      * @param responsibleProperty The responsibleProperty to set.
190      */
191     public void setResponsibleProperty(String responsibleProperty) {
192         this.responsibleProperty = responsibleProperty;
193     }
194 
195     /**
196      * Gets the accountingDocumentForValidation attribute. 
197      * @return Returns the accountingDocumentForValidation.
198      */
199     public AccountingDocument getAccountingDocumentForValidation() {
200         return accountingDocumentForValidation;
201     }
202 
203     /**
204      * Sets the accountingDocumentForValidation attribute value.
205      * @param accountingDocumentForValidation The accountingDocumentForValidation to set.
206      */
207     public void setAccountingDocumentForValidation(AccountingDocument accountingDocumentForValidation) {
208         this.accountingDocumentForValidation = accountingDocumentForValidation;
209     }
210 
211     /**
212      * Gets the accountingLineForValidation attribute. 
213      * @return Returns the accountingLineForValidation.
214      */
215     public AccountingLine getAccountingLineForValidation() {
216         return accountingLineForValidation;
217     }
218 
219     /**
220      * Sets the accountingLineForValidation attribute value.
221      * @param accountingLineForValidation The accountingLineForValidation to set.
222      */
223     public void setAccountingLineForValidation(AccountingLine accountingLineForValidation) {
224         this.accountingLineForValidation = accountingLineForValidation;
225     }
226 }