001/* 002 * Copyright 2008 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.sys.document.service.impl; 017 018import java.lang.reflect.InvocationTargetException; 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Map; 022 023import javax.servlet.jsp.PageContext; 024 025import org.apache.commons.beanutils.PropertyUtils; 026import org.kuali.ole.sys.businessobject.AccountingLine; 027import org.kuali.ole.sys.context.SpringContext; 028import org.kuali.ole.sys.document.AccountingDocument; 029import org.kuali.ole.sys.document.authorization.FinancialSystemTransactionalDocumentAuthorizerBase; 030import org.kuali.ole.sys.document.authorization.FinancialSystemTransactionalDocumentPresentationController; 031import org.kuali.ole.sys.document.datadictionary.AccountingLineGroupDefinition; 032import org.kuali.ole.sys.document.datadictionary.AccountingLineViewFieldDefinition; 033import org.kuali.ole.sys.document.service.AccountingLineAuthorizationTransformer; 034import org.kuali.ole.sys.document.service.AccountingLineFieldRenderingTransformation; 035import org.kuali.ole.sys.document.service.AccountingLineRenderingService; 036import org.kuali.ole.sys.document.service.AccountingLineRenderingTransformation; 037import org.kuali.ole.sys.document.service.AccountingLineTableTransformation; 038import org.kuali.ole.sys.document.web.AccountingLineTableRow; 039import org.kuali.ole.sys.document.web.TableJoining; 040import org.kuali.ole.sys.document.web.renderers.CheckboxRenderer; 041import org.kuali.ole.sys.document.web.renderers.CurrencyRenderer; 042import org.kuali.ole.sys.document.web.renderers.DateRenderer; 043import org.kuali.ole.sys.document.web.renderers.DropDownRenderer; 044import org.kuali.ole.sys.document.web.renderers.FieldRenderer; 045import org.kuali.ole.sys.document.web.renderers.HiddenRenderer; 046import org.kuali.ole.sys.document.web.renderers.RadioButtonGroupRenderer; 047import org.kuali.ole.sys.document.web.renderers.ReadOnlyRenderer; 048import org.kuali.ole.sys.document.web.renderers.TextAreaRenderer; 049import org.kuali.ole.sys.document.web.renderers.TextRenderer; 050import org.kuali.ole.sys.web.struts.KualiAccountingDocumentFormBase; 051import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition; 052import org.kuali.rice.kns.datadictionary.validation.fieldlevel.DateValidationPattern; 053import org.kuali.rice.kns.service.DataDictionaryService; 054import org.kuali.rice.kns.service.DocumentHelperService; 055import org.kuali.rice.kns.util.KNSGlobalVariables; 056import org.kuali.rice.kns.web.ui.Field; 057import org.kuali.rice.krad.datadictionary.AttributeDefinition; 058import org.kuali.rice.krad.datadictionary.validation.ValidationPattern; 059 060/** 061 * The default implementation of the AccountingLineRenderingService 062 */ 063public class AccountingLineRenderingServiceImpl implements AccountingLineRenderingService { 064 protected final String KUALI_FORM_NAME = "KualiForm"; 065 066 private List<AccountingLineFieldRenderingTransformation> fieldTransformations; 067 private DataDictionaryService dataDictionaryService; 068 private AccountingLineAuthorizationTransformer accountingLineAuthorizationTransformer; 069 private List<AccountingLineRenderingTransformation> preTablificationTransformations; 070 private List<AccountingLineTableTransformation> postTablificationTransformations; 071 private DocumentHelperService documentHelperService; 072 073 /** 074 * @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) 075 */ 076 public void performPreTablificationTransformations(List<TableJoining> elements, AccountingLineGroupDefinition groupDefinition, AccountingDocument accountingDocument, AccountingLine accountingLine, boolean newLine, Map unconvertedValues, String accountingLinePropertyName) { 077 performAuthorizationTransformations(elements, groupDefinition, accountingDocument, accountingLine, newLine, accountingLinePropertyName); 078 performFieldTransformations(elements, accountingDocument, accountingLine, unconvertedValues); 079 for (AccountingLineRenderingTransformation transformation : preTablificationTransformations) { 080 transformation.transformElements(elements, accountingLine); 081 } 082 } 083 084 /** 085 * @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) 086 */ 087 public void performPostTablificationTransformations(List<AccountingLineTableRow> rows, AccountingLineGroupDefinition groupDefinition, AccountingDocument document, AccountingLine accountingLine, boolean newLine) { 088 for (AccountingLineTableTransformation transformation : postTablificationTransformations) { 089 transformation.transformRows(rows); 090 } 091 } 092 093 094 /** 095 * Performs the authorization transformations 096 * @param elements the layout elements which we are authorizing 097 * @param accountingLineGroupDefinition the data dictionary definition of the accounting line group 098 * @param accountingDocument the accounting line document we're rendering accounting lines for 099 * @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