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.service.impl;
17  
18  import java.lang.reflect.InvocationTargetException;
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.Map;
22  
23  import javax.servlet.jsp.PageContext;
24  
25  import org.apache.commons.beanutils.PropertyUtils;
26  import org.kuali.ole.sys.businessobject.AccountingLine;
27  import org.kuali.ole.sys.context.SpringContext;
28  import org.kuali.ole.sys.document.AccountingDocument;
29  import org.kuali.ole.sys.document.authorization.FinancialSystemTransactionalDocumentAuthorizerBase;
30  import org.kuali.ole.sys.document.authorization.FinancialSystemTransactionalDocumentPresentationController;
31  import org.kuali.ole.sys.document.datadictionary.AccountingLineGroupDefinition;
32  import org.kuali.ole.sys.document.datadictionary.AccountingLineViewFieldDefinition;
33  import org.kuali.ole.sys.document.service.AccountingLineAuthorizationTransformer;
34  import org.kuali.ole.sys.document.service.AccountingLineFieldRenderingTransformation;
35  import org.kuali.ole.sys.document.service.AccountingLineRenderingService;
36  import org.kuali.ole.sys.document.service.AccountingLineRenderingTransformation;
37  import org.kuali.ole.sys.document.service.AccountingLineTableTransformation;
38  import org.kuali.ole.sys.document.web.AccountingLineTableRow;
39  import org.kuali.ole.sys.document.web.TableJoining;
40  import org.kuali.ole.sys.document.web.renderers.CheckboxRenderer;
41  import org.kuali.ole.sys.document.web.renderers.CurrencyRenderer;
42  import org.kuali.ole.sys.document.web.renderers.DateRenderer;
43  import org.kuali.ole.sys.document.web.renderers.DropDownRenderer;
44  import org.kuali.ole.sys.document.web.renderers.FieldRenderer;
45  import org.kuali.ole.sys.document.web.renderers.HiddenRenderer;
46  import org.kuali.ole.sys.document.web.renderers.RadioButtonGroupRenderer;
47  import org.kuali.ole.sys.document.web.renderers.ReadOnlyRenderer;
48  import org.kuali.ole.sys.document.web.renderers.TextAreaRenderer;
49  import org.kuali.ole.sys.document.web.renderers.TextRenderer;
50  import org.kuali.ole.sys.web.struts.KualiAccountingDocumentFormBase;
51  import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
52  import org.kuali.rice.kns.datadictionary.validation.fieldlevel.DateValidationPattern;
53  import org.kuali.rice.kns.service.DataDictionaryService;
54  import org.kuali.rice.kns.service.DocumentHelperService;
55  import org.kuali.rice.kns.util.KNSGlobalVariables;
56  import org.kuali.rice.kns.web.ui.Field;
57  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
58  import org.kuali.rice.krad.datadictionary.validation.ValidationPattern;
59  
60  /**
61   * The default implementation of the AccountingLineRenderingService
62   */
63  public class AccountingLineRenderingServiceImpl implements AccountingLineRenderingService {
64      protected final String KUALI_FORM_NAME = "KualiForm";
65      
66      private List<AccountingLineFieldRenderingTransformation> fieldTransformations;
67      private DataDictionaryService dataDictionaryService;
68      private AccountingLineAuthorizationTransformer accountingLineAuthorizationTransformer;
69      private List<AccountingLineRenderingTransformation> preTablificationTransformations;
70      private List<AccountingLineTableTransformation> postTablificationTransformations;
71      private DocumentHelperService documentHelperService;
72  
73      /**
74       * @see org.kuali.ole.sys.document.service.AccountingLineRenderingService#performPreTablificationTransformations(java.util.List, org.kuali.ole.sys.document.datadictionary.AccountingLineGroupDefinition, org.kuali.ole.sys.document.AccountingDocument, org.kuali.ole.sys.businessobject.AccountingLine, boolean, java.util.Map, java.lang.String)
75       */
76      public void performPreTablificationTransformations(List<TableJoining> elements, AccountingLineGroupDefinition groupDefinition, AccountingDocument accountingDocument, AccountingLine accountingLine, boolean newLine, Map unconvertedValues, String accountingLinePropertyName) {
77          performAuthorizationTransformations(elements, groupDefinition, accountingDocument, accountingLine, newLine, accountingLinePropertyName);
78          performFieldTransformations(elements, accountingDocument, accountingLine, unconvertedValues);
79          for (AccountingLineRenderingTransformation transformation : preTablificationTransformations) {
80              transformation.transformElements(elements, accountingLine);
81          }
82      }
83      
84      /**
85       * @see org.kuali.ole.sys.document.service.AccountingLineRenderingService#performPostTablificationTransformations(java.util.List, org.kuali.ole.sys.document.datadictionary.AccountingLineGroupDefinition, org.kuali.ole.sys.document.AccountingDocument, org.kuali.ole.sys.businessobject.AccountingLine, boolean)
86       */
87      public void performPostTablificationTransformations(List<AccountingLineTableRow> rows, AccountingLineGroupDefinition groupDefinition, AccountingDocument document, AccountingLine accountingLine, boolean newLine) {
88          for (AccountingLineTableTransformation transformation : postTablificationTransformations) {
89              transformation.transformRows(rows);
90          }
91      }
92  
93  
94      /**
95       * Performs the authorization transformations
96       * @param elements the layout elements which we are authorizing
97       * @param accountingLineGroupDefinition the data dictionary definition of the accounting line group
98       * @param accountingDocument the accounting line document we're rendering accounting lines for
99       * @param accountingLine the accounting line we're rendering
100      * @param newLine true if the accounting line is not yet on the form yet, false otherwise
101      */
102     protected void performAuthorizationTransformations(List<TableJoining> elements, AccountingLineGroupDefinition accountingLineGroupDefinition, AccountingDocument accountingDocument, AccountingLine accountingLine, boolean newLine, String accountingLinePropertyName) {
103         accountingLineAuthorizationTransformer.transformElements(elements, accountingLine, accountingDocument, accountingLineGroupDefinition.getAccountingLineAuthorizer(), newLine, accountingLinePropertyName);
104     }
105     
106     /**
107      * Performs field transformations for pre-rendering
108      * @param elements the layout elements that hold fields to transform
109      * @param accountingDocument the accounting document with the line we are rendering
110      * @param accountingLine the accounting line we are rendering
111      * @param unconvertedValues any unconverted values
112      */
113     protected void performFieldTransformations(List<TableJoining> elements, AccountingDocument accountingDocument, AccountingLine accountingLine, Map unconvertedValues) {
114         for (TableJoining layoutElement : elements) {
115             layoutElement.performFieldTransformations(fieldTransformations, accountingLine, unconvertedValues);
116         }
117     }
118  
119     /**
120      * Creates an accounting document authorizer for the given accounting document
121      * @param document the document to get an authorizer for
122      * @return an authorizer for the document
123      */
124     protected FinancialSystemTransactionalDocumentAuthorizerBase getDocumentAuthorizer(AccountingDocument document) {
125         final FinancialSystemTransactionalDocumentAuthorizerBase authorizer = (FinancialSystemTransactionalDocumentAuthorizerBase) getDocumentHelperService().getDocumentAuthorizer(document);
126         return authorizer;
127     }
128     
129     /**
130      * @param document the document to get the presentation controller for
131      * @return the proper presentation controller
132      */
133     protected FinancialSystemTransactionalDocumentPresentationController getPresentationController(AccountingDocument document) {
134         final FinancialSystemTransactionalDocumentPresentationController presentationController = (FinancialSystemTransactionalDocumentPresentationController) getDocumentHelperService().getDocumentPresentationController(document);
135         return presentationController;
136     }
137 
138     /**
139      * Simplify the tree so that it is made up of only table elements and fields
140      * @see org.kuali.ole.sys.document.service.AccountingLineRenderingService#tablify(java.util.List)
141      */
142     public List<AccountingLineTableRow> tablify(List<TableJoining> elements) {
143         List<AccountingLineTableRow> rows = createBlankTableRows(getMaxRowCount(elements));
144         tablifyElements(elements, rows);
145         return rows;
146     }
147     
148     /**
149      * Gets the maximum number of rows needed by any child element
150      * @param elements the elements to turn into table rows
151      * @return the maximum number of rows requested
152      */
153     protected int getMaxRowCount(List<TableJoining> elements) {
154         int maxRowCount = 0;
155         for (TableJoining element : elements) {
156             int rowCount = element.getRequestedRowCount();
157             if (rowCount > maxRowCount) {
158                 maxRowCount = rowCount;
159             }
160         }
161         return maxRowCount;
162     }
163     
164     /**
165      * This method creates a List of blank table rows, based on the requested count
166      * @param count the count of table rows
167      * @return a List of table rows ready for population
168      */
169     protected List<AccountingLineTableRow> createBlankTableRows(int count) {
170         List<AccountingLineTableRow> rows = new ArrayList<AccountingLineTableRow>();
171         for (int i = 0; i < count; i++) {
172             rows.add(new AccountingLineTableRow());
173         }
174         return rows;
175     }
176 
177     /**
178      * Requests each of the given elements to join the table
179      * @param elements the elements to join to the table
180      * @param rows the table rows to join to
181      */
182     protected void tablifyElements(List<TableJoining> elements, List<AccountingLineTableRow> rows) {
183         for (TableJoining element : elements) {
184             element.joinTable(rows);
185         }
186     }
187 
188     /**
189      * @see org.kuali.ole.sys.document.service.AccountingLineRenderingService#getFieldRendererForField(org.kuali.rice.kns.web.ui.Field, org.kuali.ole.sys.businessobject.AccountingLine)
190      * 
191      * KRAD Conversion: Performs customization of the renderer based on the properties of the fields.
192      */
193     public FieldRenderer getFieldRendererForField(Field field, AccountingLine accountingLineToRender) {
194         FieldRenderer renderer = null;
195 
196         if (field.isReadOnly() || field.getFieldType().equals(Field.READONLY)) {
197             renderer = new ReadOnlyRenderer();
198         } /* 
199         else if (field.getPropertyName().equals(OLEConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME) && !SpringContext.getBean(AccountService.class).accountsCanCrossCharts()) {
200             // the special case for rendering chart of accounts code when accounts can't cross charts
201             renderer = new DynamicReadOnlyRender();   
202         } */
203         else if (field.getFieldType().equals(Field.TEXT)) {
204             if (field.isDatePicker() || usesDateValidation(field.getPropertyName(), accountingLineToRender)) { // are we a date?
205                 renderer = new DateRenderer();
206             } else {
207                 renderer = new TextRenderer();
208             }
209         } else if (field.getFieldType().equals(Field.TEXT_AREA)) {
210             renderer = new TextAreaRenderer();
211         } else if (field.getFieldType().equals(Field.HIDDEN)) {
212             renderer = new HiddenRenderer();
213         } else if (field.getFieldType().equals(Field.CURRENCY)) {
214             renderer = new CurrencyRenderer();
215         } else if (field.getFieldType().equals(Field.DROPDOWN)) {
216             renderer = new DropDownRenderer();
217         } else if (field.getFieldType().equals(Field.RADIO)) {
218             renderer = new RadioButtonGroupRenderer();
219         } else if (field.getFieldType().equals(Field.CHECKBOX)) {
220             renderer = new CheckboxRenderer();
221         }
222         
223         return renderer;
224     }
225     
226     /**
227      * Determines if this method uses a date validation pattern, in which case, a date picker should be rendered
228      * @param propertyName the property of the field being checked from the command line
229      * @param accountingLineToRender the accounting line which is being rendered
230      * @return true if the property does use date validation, false otherwise
231      */
232     protected boolean usesDateValidation(String propertyName, Object businessObject) {
233         final org.kuali.rice.krad.datadictionary.BusinessObjectEntry entry = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getBusinessObjectEntry(businessObject.getClass().getName());
234         AttributeDefinition attributeDefinition = entry.getAttributeDefinition(propertyName);
235         
236         if (attributeDefinition == null) {
237             if (!propertyName.contains(".")) return false;
238             final int firstNestingPoint = propertyName.indexOf(".");
239             final String toNestingPoint = propertyName.substring(0, firstNestingPoint);
240             final String fromNestingPoint = propertyName.substring(firstNestingPoint+1);
241             Object childObject = null;
242             try {
243                 final Class childClass = PropertyUtils.getPropertyType(businessObject, toNestingPoint);
244                 childObject = childClass.newInstance();
245             }
246             catch (IllegalAccessException iae) {
247                 new UnsupportedOperationException(iae);
248             }
249             catch (InvocationTargetException ite) {
250                 new UnsupportedOperationException(ite);
251             }
252             catch (NoSuchMethodException nsme) {
253                 new UnsupportedOperationException(nsme);
254             }
255             catch (InstantiationException ie) {
256                 throw new UnsupportedOperationException(ie);
257             }
258             return usesDateValidation(fromNestingPoint, childObject);
259         }
260         
261         final ValidationPattern validationPattern = attributeDefinition.getValidationPattern();
262         if (validationPattern == null) return false; // no validation for sure means we ain't using date validation
263         return validationPattern instanceof DateValidationPattern;
264     }
265 
266     /**
267      * @see org.kuali.ole.sys.document.service.AccountingLineRenderingService#createGenericAccountingLineViewFieldDefinition(org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition)
268      */
269     public AccountingLineViewFieldDefinition createGenericAccountingLineViewFieldDefinition(MaintainableFieldDefinition currentDefinition) {
270         AccountingLineViewFieldDefinition fieldDefinition = new AccountingLineViewFieldDefinition();
271         
272         fieldDefinition.setRequired(currentDefinition.isRequired());
273         fieldDefinition.setUnconditionallyReadOnly(currentDefinition.isUnconditionallyReadOnly());
274         fieldDefinition.setReadOnlyAfterAdd(currentDefinition.isReadOnlyAfterAdd());
275         fieldDefinition.setNoLookup(currentDefinition.isNoLookup());
276         
277         fieldDefinition.setDefaultValue(currentDefinition.getDefaultValue());
278         fieldDefinition.setTemplate(currentDefinition.getTemplate());
279         fieldDefinition.setDefaultValueFinderClass(currentDefinition.getDefaultValueFinderClass());
280         
281         fieldDefinition.setOverrideLookupClass(currentDefinition.getOverrideLookupClass());
282         fieldDefinition.setOverrideFieldConversions(currentDefinition.getOverrideFieldConversions());
283         
284         return fieldDefinition;
285     }
286 
287     /**
288      * Gets the fieldTransformations attribute. 
289      * @return Returns the fieldTransformations.
290      */
291     public List<AccountingLineFieldRenderingTransformation> getFieldTransformations() {
292         return fieldTransformations;
293     }
294 
295     /**
296      * Sets the fieldTransformations attribute value.
297      * @param fieldTransformations The fieldTransformations to set.
298      */
299     public void setFieldTransformations(List<AccountingLineFieldRenderingTransformation> fieldTransformations) {
300         this.fieldTransformations = fieldTransformations;
301     }
302 
303     /**
304      * Gets the accountingLineAuthorizationTransformer attribute. 
305      * @return Returns the accountingLineAuthorizationTransformer.
306      */
307     public AccountingLineAuthorizationTransformer getAccountingLineAuthorizationTransformer() {
308         return accountingLineAuthorizationTransformer;
309     }
310 
311     /**
312      * Sets the accountingLineAuthorizationTransformer attribute value.
313      * @param accountingLineAuthorizationTransformer The accountingLineAuthorizationTransformer to set.
314      */
315     public void setAccountingLineAuthorizationTransformer(AccountingLineAuthorizationTransformer accountingLineAuthorizationTransformer) {
316         this.accountingLineAuthorizationTransformer = accountingLineAuthorizationTransformer;
317     }
318 
319     /**
320      * Gets the dataDictionaryService attribute. 
321      * @return Returns the dataDictionaryService.
322      */
323     public DataDictionaryService getDataDictionaryService() {
324         return dataDictionaryService;
325     }
326 
327     /**
328      * Sets the dataDictionaryService attribute value.
329      * @param dataDictionaryService The dataDictionaryService to set.
330      */
331     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
332         this.dataDictionaryService = dataDictionaryService;
333     }
334 
335     /**
336      * Gets the postTablificationTransformations attribute. 
337      * @return Returns the postTablificationTransformations.
338      */
339     public List<AccountingLineTableTransformation> getPostTablificationTransformations() {
340         return postTablificationTransformations;
341     }
342 
343     /**
344      * Sets the postTablificationTransformations attribute value.
345      * @param postTablificationTransformations The postTablificationTransformations to set.
346      */
347     public void setPostTablificationTransformations(List<AccountingLineTableTransformation> postTablificationTransformations) {
348         this.postTablificationTransformations = postTablificationTransformations;
349     }
350 
351     /**
352      * Gets the preTablificationTransformations attribute. 
353      * @return Returns the preTablificationTransformations.
354      */
355     public List<AccountingLineRenderingTransformation> getPreTablificationTransformations() {
356         return preTablificationTransformations;
357     }
358 
359     /**
360      * Sets the preTablificationTransformations attribute value.
361      * @param preTablificationTransformations The preTablificationTransformations to set.
362      */
363     public void setPreTablificationTransformations(List<AccountingLineRenderingTransformation> preTablificationTransformations) {
364         this.preTablificationTransformations = preTablificationTransformations;
365     }
366 
367     /**
368      * @see org.kuali.ole.sys.document.service.AccountingLineRenderingService#findForm(javax.servlet.jsp.PageContext)
369      */
370     public KualiAccountingDocumentFormBase findForm(PageContext pageContext) {
371         if (pageContext.getRequest().getAttribute(KUALI_FORM_NAME) != null) return (KualiAccountingDocumentFormBase)pageContext.getRequest().getAttribute(KUALI_FORM_NAME);
372         
373         if (pageContext.getSession().getAttribute(KUALI_FORM_NAME) != null) return (KualiAccountingDocumentFormBase)pageContext.getSession().getAttribute(KUALI_FORM_NAME);
374         
375         return (KualiAccountingDocumentFormBase)KNSGlobalVariables.getKualiForm();
376     }
377     
378     protected DocumentHelperService getDocumentHelperService() {
379         if (documentHelperService == null) {
380             documentHelperService = SpringContext.getBean(DocumentHelperService.class);
381         }
382         return documentHelperService;
383     }
384 }
385