001 /* 002 * Copyright 2011 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 */ 016 package org.kuali.kfs.sys.document.web; 017 018 import java.text.MessageFormat; 019 import java.util.List; 020 import java.util.Map; 021 022 import javax.servlet.jsp.JspException; 023 import javax.servlet.jsp.PageContext; 024 import javax.servlet.jsp.tagext.Tag; 025 026 import org.apache.commons.collections.BidiMap; 027 import org.apache.commons.collections.bidimap.DualHashBidiMap; 028 import org.apache.commons.lang.StringUtils; 029 import org.kuali.kfs.coa.service.AccountService; 030 import org.kuali.kfs.sys.KFSConstants; 031 import org.kuali.kfs.sys.KFSKeyConstants; 032 import org.kuali.kfs.sys.businessobject.AccountingLine; 033 import org.kuali.kfs.sys.context.SpringContext; 034 import org.kuali.kfs.sys.document.AccountingDocument; 035 import org.kuali.kfs.sys.document.datadictionary.AccountingLineViewFieldDefinition; 036 import org.kuali.kfs.sys.document.service.AccountingLineFieldRenderingTransformation; 037 import org.kuali.kfs.sys.document.service.AccountingLineRenderingService; 038 import org.kuali.kfs.sys.document.web.renderers.DynamicNameLabelRenderer; 039 import org.kuali.kfs.sys.document.web.renderers.FieldRenderer; 040 import org.kuali.rice.kns.bo.PersistableBusinessObject; 041 import org.kuali.rice.kns.lookup.LookupUtils; 042 import org.kuali.rice.kns.service.KualiConfigurationService; 043 import org.kuali.rice.kns.service.PersistenceStructureService; 044 import org.kuali.rice.kns.util.FieldUtils; 045 import org.kuali.rice.kns.util.ObjectUtils; 046 import org.kuali.rice.kns.web.ui.Field; 047 048 /** 049 * Represents a field (plus, optionally, a dynamic name field) to be rendered as part of an accounting line. 050 */ 051 public class AccountingLineViewField extends FieldTableJoiningWithHeader implements HeaderLabelPopulating, ReadOnlyable { 052 public static final String ACCOUNTING_LINE_NAME_PREFIX_PLACE_HOLDER = "${accountingLineName}"; 053 054 private Field field; 055 private AccountingLineViewFieldDefinition definition; 056 private int arbitrarilyHighIndex; 057 private List<AccountingLineViewOverrideField> overrideFields; 058 private PersistenceStructureService persistenceStructureService; 059 060 /** 061 * Gets the definition attribute. 062 * 063 * @return Returns the definition. 064 */ 065 public AccountingLineViewFieldDefinition getDefinition() { 066 return definition; 067 } 068 069 /** 070 * Sets the definition attribute value. 071 * 072 * @param definition The definition to set. 073 */ 074 public void setDefinition(AccountingLineViewFieldDefinition definition) { 075 this.definition = definition; 076 } 077 078 /** 079 * Determines if this field should use the short label or not 080 * 081 * @return true if the short label should be used, false otherwise 082 */ 083 private boolean shouldUseShortLabel() { 084 return definition.shouldUseShortLabel(); 085 } 086 087 /** 088 * Gets the field attribute. 089 * 090 * @return Returns the field. 091 */ 092 public Field getField() { 093 return field; 094 } 095 096 /** 097 * Sets the field attribute value. 098 * 099 * @param field The field to set. 100 */ 101 public void setField(Field field) { 102 this.field = field; 103 } 104 105 /** 106 * Gets the overrideFields attribute. 107 * 108 * @return Returns the overrideFields. 109 */ 110 public List<AccountingLineViewOverrideField> getOverrideFields() { 111 return overrideFields; 112 } 113 114 /** 115 * Sets the overrideFields attribute value. 116 * 117 * @param overrideFields The overrideFields to set. 118 */ 119 public void setOverrideFields(List<AccountingLineViewOverrideField> overrideFields) { 120 this.overrideFields = overrideFields; 121 } 122 123 /** 124 * Checks the field to see if the field itself is hidden 125 * 126 * @see org.kuali.kfs.sys.document.web.AccountingLineViewRenderableElementField#isHidden() 127 */ 128 public boolean isHidden() { 129 return (field.getFieldType().equals(Field.HIDDEN) || definition.isHidden()); 130 } 131 132 /** 133 * Asks the wrapped field if it is read only (dynamic fields are, of course, always read only and therefore don't count in this 134 * determination) 135 * 136 * @see org.kuali.kfs.sys.document.web.AccountingLineViewRenderableElementField#isReadOnly() 137 */ 138 public boolean isReadOnly() { 139 return field.isReadOnly() || isHidden(); 140 } 141 142 /** 143 * @see org.kuali.kfs.sys.document.web.TableJoining#getName() 144 */ 145 public String getName() { 146 return field.getPropertyName(); 147 } 148 149 /** 150 * @see org.kuali.kfs.sys.document.web.TableJoining#readOnlyize() 151 */ 152 public void readOnlyize() { 153 if (!isHidden()) { 154 this.field.setReadOnly(true); 155 } 156 } 157 158 /** 159 * @see org.kuali.kfs.sys.document.web.TableJoiningWithHeader#getHeaderLabelProperty() 160 */ 161 public String getHeaderLabelProperty() { 162 return this.field.getPropertyName(); 163 } 164 165 /** 166 * @see org.kuali.kfs.sys.document.web.RenderableElement#renderElement(javax.servlet.jsp.PageContext, 167 * javax.servlet.jsp.tagext.Tag) 168 */ 169 public void renderElement(PageContext pageContext, Tag parentTag, AccountingLineRenderingContext renderingContext) throws JspException { 170 renderField(pageContext, parentTag, renderingContext); 171 172 if (getOverrideFields() != null && getOverrideFields().size() > 0) { 173 renderOverrideFields(pageContext, parentTag, renderingContext); 174 } 175 if (shouldRenderDynamicFeldLabel() && renderingContext.fieldsCanRenderDynamicLabels()) { 176 renderDynamicNameLabel(pageContext, parentTag, renderingContext); 177 } 178 } 179 180 /** 181 * Renders the field portion of this tag 182 * 183 * @param pageContext the page context to render to 184 * @param parentTag the tag requesting rendering 185 * @param renderingContext the rendering context of the accounting line 186 * @throws JspException thrown if something goes wrong 187 */ 188 protected void renderField(PageContext pageContext, Tag parentTag, AccountingLineRenderingContext renderingContext) throws JspException { 189 AccountingLine accountingLine = renderingContext.getAccountingLine(); 190 String accountingLineProperty = renderingContext.getAccountingLinePropertyPath(); 191 List<String> fieldNames = renderingContext.getFieldNamesForAccountingLine(); 192 List errors = renderingContext.getErrors(); 193 194 this.getField().setPropertyPrefix(accountingLineProperty); 195 boolean chartSetByAccount = getName().equals(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME) && !SpringContext.getBean(AccountService.class).accountsCanCrossCharts(); 196 //set chartOfAccountsCode readOnly if account can't cross charts 197 if (!renderingContext.isFieldModifyable(this.getName()) || chartSetByAccount) { 198 this.getField().setReadOnly(true); 199 } 200 201 FieldRenderer renderer = SpringContext.getBean(AccountingLineRenderingService.class).getFieldRendererForField(getField(), accountingLine); 202 if (renderer != null) { 203 prepareFieldRenderer(renderer, getField(), renderingContext.getAccountingDocument(), accountingLine, accountingLineProperty, fieldNames); 204 if (fieldInError(errors)) { 205 renderer.setShowError(true); 206 } 207 208 if (!isHidden()) { 209 renderer.openNoWrapSpan(pageContext, parentTag); 210 } 211 212 // dynamically set the accessible title to the current field 213 if (!this.isReadOnly()) { 214 String accessibleTitle = getField().getFieldLabel(); 215 216 if (renderingContext.isNewLine()) { 217 String format = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSKeyConstants.LABEL_NEW_ACCOUNTING_LINE_FIELD); 218 accessibleTitle = MessageFormat.format(format, accessibleTitle, renderingContext.getGroupLabel()); 219 } 220 else { 221 Integer lineNumber = renderingContext.getCurrentLineCount() + 1; 222 String format = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSKeyConstants.LABEL_ACCOUNTING_LINE_FIELD); 223 accessibleTitle = MessageFormat.format(format, accessibleTitle, renderingContext.getGroupLabel(), lineNumber); 224 } 225 226 renderer.setAccessibleTitle(accessibleTitle); 227 } 228 229 renderer.render(pageContext, parentTag); 230 if (!isHidden()) { 231 renderer.closeNoWrapSpan(pageContext, parentTag); 232 } 233 renderer.clear(); 234 } 235 } 236 237 /** 238 * Updates the field so that it can have a quickfinder and inquiry link if need be 239 * 240 * @param accountingDocument the accounting document the accounting line the field will render part of is on or will at some 241 * point be on 242 * @param accountingLine the accounting line that is being rendered 243 * @param fieldNames the list of all fields being displayed on this accounting line 244 * @param accountingLinePrefix the prefix of all field names in the accounting line 245 */ 246 protected void populateFieldForLookupAndInquiry(AccountingDocument accountingDocument, AccountingLine accountingLine, List<String> fieldNames, String accountingLinePrefix) { 247 if (!isHidden()) { 248 LookupUtils.setFieldQuickfinder(accountingLine, getField().getPropertyName(), getField(), fieldNames); 249 250 // apply the customized lookup parameters if any 251 String overrideLookupParameters = definition.getOverrideLookupParameters(); 252 if (StringUtils.isNotBlank(overrideLookupParameters)) { 253 String lookupParameters = getField().getLookupParameters(); 254 255 Map<String, String> lookupParametersMap = this.getActualParametersMap(lookupParameters, overrideLookupParameters, accountingLinePrefix); 256 257 getField().setLookupParameters(lookupParametersMap); 258 259 // if there are any any lookup parameters present, make sure the other lookup fields are populated. 260 // this can be necessary if there wouldnt natually be a lookup, via DD or OJB relationships, but one 261 // is forced. 262 if (!lookupParametersMap.isEmpty()) { 263 if (getDefinition().getOverrideLookupClass() != null) { 264 getField().setQuickFinderClassNameImpl(getDefinition().getOverrideLookupClass().getName()); 265 } 266 } 267 } 268 269 // apply the customized field conversions if any 270 String overrideFieldConversions = definition.getOverrideFieldConversions(); 271 if (StringUtils.isNotBlank(overrideFieldConversions)) { 272 String fieldConversions = getField().getFieldConversions(); 273 274 Map<String, String> fieldConversionsMap = this.getActualParametersMap(fieldConversions, overrideFieldConversions, accountingLinePrefix); 275 276 getField().setFieldConversions(fieldConversionsMap); 277 } 278 279 if (isRenderingInquiry(accountingDocument, accountingLine)) { 280 FieldUtils.setInquiryURL(getField(), accountingLine, getField().getPropertyName()); 281 } 282 } 283 } 284 285 /** 286 * Lazily retrieves the persistence structure service 287 * 288 * @return an implementation of PersistenceStructureService 289 */ 290 protected PersistenceStructureService getPersistenceStructureService() { 291 if (persistenceStructureService == null) { 292 persistenceStructureService = SpringContext.getBean(PersistenceStructureService.class); 293 } 294 return persistenceStructureService; 295 } 296 297 /** 298 * Does some initial set up on the field renderer - sets the field and the business object being rendered 299 * 300 * @param fieldRenderer the field renderer to prepare 301 * @param accountingLine the accounting line being rendered 302 * @param accountingLineProperty the property to get the accounting line from the form 303 * @param fieldNames the names of all the fields that will be rendered as part of this accounting line 304 */ 305 protected void prepareFieldRenderer(FieldRenderer fieldRenderer, Field field, AccountingDocument document, AccountingLine accountingLine, String accountingLineProperty, List<String> fieldNames) { 306 fieldRenderer.setField(field); 307 308 getField().setPropertyPrefix(accountingLineProperty); 309 populateFieldForLookupAndInquiry(document, accountingLine, fieldNames, getField().getPropertyPrefix()); 310 311 if (definition.getDynamicNameLabelGenerator() != null) { 312 fieldRenderer.overrideOnBlur(definition.getDynamicNameLabelGenerator().getDynamicNameLabelOnBlur(accountingLine, accountingLineProperty)); 313 } 314 else if (!StringUtils.isBlank(definition.getDynamicLabelProperty())) { 315 fieldRenderer.setDynamicNameLabel(accountingLineProperty + "." + definition.getDynamicLabelProperty()); 316 } 317 318 fieldRenderer.setArbitrarilyHighTabIndex(arbitrarilyHighIndex); 319 } 320 321 /** 322 * Determines if a dynamic field label should be rendered for the given field 323 * 324 * @return true if a dynamic field label should be rendered, false otherwise 325 */ 326 protected boolean shouldRenderDynamicFeldLabel() { 327 return (!getField().getFieldType().equals(Field.HIDDEN) && ((!StringUtils.isBlank(getField().getWebOnBlurHandler()) && !StringUtils.isBlank(definition.getDynamicLabelProperty())) || definition.getDynamicNameLabelGenerator() != null)); 328 } 329 330 /** 331 * @see org.kuali.kfs.sys.document.web.TableJoining#performFieldTransformation(org.kuali.kfs.sys.document.service.AccountingLineFieldRenderingTransformation, 332 * org.kuali.kfs.sys.businessobject.AccountingLine, java.util.Map, java.util.Map) 333 */ 334 @Override 335 public void performFieldTransformations(List<AccountingLineFieldRenderingTransformation> fieldTransformations, AccountingLine accountingLine, Map unconvertedValues) { 336 for (AccountingLineFieldRenderingTransformation fieldTransformation : fieldTransformations) { 337 fieldTransformation.transformField(accountingLine, getField(), getDefinition(), unconvertedValues); 338 if (getOverrideFields() != null && getOverrideFields().size() > 0) { 339 transformOverrideFields(fieldTransformation, accountingLine, unconvertedValues); 340 } 341 } 342 } 343 344 /** 345 * Runs a field transformation against all the overrides encapsulated within this field 346 * 347 * @param fieldTransformation the field transformation which will utterly change our fields 348 * @param accountingLine the accounting line being rendered 349 * @param editModes the current document edit modes 350 * @param unconvertedValues a Map of unconvertedValues 351 */ 352 protected void transformOverrideFields(AccountingLineFieldRenderingTransformation fieldTransformation, AccountingLine accountingLine, Map unconvertedValues) { 353 for (AccountingLineViewOverrideField overrideField : getOverrideFields()) { 354 overrideField.transformField(fieldTransformation, accountingLine, unconvertedValues); 355 } 356 } 357 358 /** 359 * Renders the override fields for the line 360 * 361 * @param pageContext the page context to render to 362 * @param parentTag the tag requesting all this rendering 363 * @param accountingLine the accounting line we're rendering 364 * @param accountingLinePropertyPath the path to get to that accounting 365 * @throws JspException thrown if rendering fails 366 */ 367 public void renderOverrideFields(PageContext pageContext, Tag parentTag, AccountingLineRenderingContext renderingContext) throws JspException { 368 for (AccountingLineViewOverrideField overrideField : getOverrideFields()) { 369 overrideField.setAccountingLineProperty(renderingContext.getAccountingLinePropertyPath()); 370 overrideField.renderElement(pageContext, parentTag, renderingContext); 371 } 372 } 373 374 /** 375 * Renders a dynamic field label 376 * 377 * @param pageContext the page context to render to 378 * @param parentTag the parent tag requesting this rendering 379 * @param accountingLine the line which owns the field being rendered 380 * @param accountingLinePropertyPath the path from the form to the accounting line 381 */ 382 protected void renderDynamicNameLabel(PageContext pageContext, Tag parentTag, AccountingLineRenderingContext renderingContext) throws JspException { 383 AccountingLine accountingLine = renderingContext.getAccountingLine(); 384 String accountingLinePropertyPath = renderingContext.getAccountingLinePropertyPath(); 385 386 DynamicNameLabelRenderer renderer = new DynamicNameLabelRenderer(); 387 if (definition.getDynamicNameLabelGenerator() != null) { 388 renderer.setFieldName(definition.getDynamicNameLabelGenerator().getDynamicNameLabelFieldName(accountingLine, accountingLinePropertyPath)); 389 renderer.setFieldValue(definition.getDynamicNameLabelGenerator().getDynamicNameLabelValue(accountingLine, accountingLinePropertyPath)); 390 } 391 else { 392 if (!StringUtils.isBlank(getField().getPropertyValue())) { 393 if (getField().isSecure()) { 394 renderer.setFieldValue(getField().getDisplayMask().maskValue(getField().getPropertyValue())); 395 } 396 else { 397 renderer.setFieldValue(getDynamicNameLabelDisplayedValue(accountingLine)); 398 } 399 } 400 renderer.setFieldName(accountingLinePropertyPath + "." + definition.getDynamicLabelProperty()); 401 } 402 renderer.render(pageContext, parentTag); 403 renderer.clear(); 404 } 405 406 /** 407 * Gets the value from the accounting line to display as the field value 408 * 409 * @param accountingLine the accounting line to get the value from 410 * @return the value to display for the dynamic name label 411 */ 412 protected String getDynamicNameLabelDisplayedValue(AccountingLine accountingLine) { 413 String dynamicLabelProperty = definition.getDynamicLabelProperty(); 414 Object value = accountingLine; 415 while (!ObjectUtils.isNull(value) && dynamicLabelProperty.indexOf('.') > -1) { 416 String currentProperty = StringUtils.substringBefore(dynamicLabelProperty, "."); 417 dynamicLabelProperty = StringUtils.substringAfter(dynamicLabelProperty, "."); 418 if (value instanceof PersistableBusinessObject) { 419 ((PersistableBusinessObject) value).refreshReferenceObject(currentProperty); 420 } 421 value = ObjectUtils.getPropertyValue(value, currentProperty); 422 } 423 if (!ObjectUtils.isNull(value)) { 424 value = ObjectUtils.getPropertyValue(value, dynamicLabelProperty); 425 if (value != null) 426 return value.toString(); 427 } 428 return null; 429 } 430 431 /** 432 * @see org.kuali.kfs.sys.document.web.TableJoiningWithHeader#createHeaderLabel() 433 */ 434 public HeaderLabel createHeaderLabel() { 435 return new FieldHeaderLabel(this); 436 } 437 438 /** 439 * If the field definition had an override col span greater than 1 and it doesn't seem as if the given cell had its colspan 440 * lengthened already, this method will increase the colspan of the table cell to whatever is listed 441 * 442 * @param cell the cell to possibly lengthen 443 */ 444 protected void updateTableCellWithColSpanOverride(AccountingLineTableCell cell) { 445 if (definition.getOverrideColSpan() > 1 && cell.getColSpan() == 1) { 446 cell.setColSpan(definition.getOverrideColSpan()); 447 } 448 } 449 450 /** 451 * Overridden to allow for colspan override 452 * 453 * @see org.kuali.kfs.sys.document.web.FieldTableJoiningWithHeader#createHeaderLabelTableCell() 454 */ 455 @Override 456 protected AccountingLineTableCell createHeaderLabelTableCell() { 457 AccountingLineTableCell cell = super.createHeaderLabelTableCell(); 458 updateTableCellWithColSpanOverride(cell); 459 return cell; 460 } 461 462 /** 463 * Overridden to allow for colspan override 464 * 465 * @see org.kuali.kfs.sys.document.web.FieldTableJoining#createTableCell() 466 */ 467 @Override 468 protected AccountingLineTableCell createTableCell() { 469 AccountingLineTableCell cell = super.createTableCell(); 470 updateTableCellWithColSpanOverride(cell); 471 return cell; 472 } 473 474 /** 475 * @return the colspan override of this field 476 */ 477 public int getColSpanOverride() { 478 return definition.getOverrideColSpan(); 479 } 480 481 /** 482 * @see org.kuali.kfs.sys.document.web.HeaderLabelPopulating#populateHeaderLabel(org.kuali.kfs.sys.document.web.HeaderLabel, 483 * org.kuali.kfs.sys.document.web.AccountingLineRenderingContext) 484 */ 485 public void populateHeaderLabel(HeaderLabel headerLabel, AccountingLineRenderingContext renderingContext) { 486 FieldHeaderLabel label = (FieldHeaderLabel) headerLabel; 487 label.setLabel(getField().getFieldLabel()); 488 label.setLabeledFieldEmptyOrHidden(isEmpty() || isHidden()); 489 label.setReadOnly(getField().isReadOnly()); 490 label.setRequired(getField().isFieldRequired()); 491 if (renderingContext.fieldsShouldRenderHelp()) { 492 label.setFullClassNameForHelp(renderingContext.getAccountingLine().getClass().getName()); 493 label.setAttributeEntryForHelp(getField().getPropertyName()); 494 } 495 } 496 497 /** 498 * Adds the wrapped field to the list; adds any override fields this field encapsulates as well 499 * 500 * @see org.kuali.kfs.sys.document.web.RenderableElement#appendFieldNames(java.util.List) 501 */ 502 public void appendFields(List<Field> fields) { 503 fields.add(getField()); 504 if (getOverrideFields() != null && getOverrideFields().size() > 0) { 505 for (AccountingLineViewOverrideField field : getOverrideFields()) { 506 field.appendFields(fields); 507 } 508 } 509 } 510 511 /** 512 * @see org.kuali.kfs.sys.document.web.RenderableElement#populateWithTabIndexIfRequested(int[], int) 513 */ 514 public void populateWithTabIndexIfRequested(int reallyHighIndex) { 515 this.arbitrarilyHighIndex = reallyHighIndex; 516 } 517 518 /** 519 * Determines if this field is among the fields that are in error 520 * 521 * @param errors the errors on the form 522 * @return true if this field is in error, false otherwise 523 */ 524 protected boolean fieldInError(List errors) { 525 if (errors != null) { 526 String fieldName = getField().getPropertyName(); 527 if (!StringUtils.isBlank(getField().getPropertyPrefix())) { 528 fieldName = getField().getPropertyPrefix() + "." + fieldName; 529 } 530 for (Object errorKeyAsObject : errors) { 531 final String errorKey = (String) errorKeyAsObject; 532 if (fieldName.equals(errorKey)) { 533 return true; 534 } 535 } 536 } 537 return false; 538 } 539 540 /** 541 * @see org.kuali.kfs.sys.document.web.ReadOnlyable#setEditable() 542 */ 543 public void setEditable() { 544 if (!isHidden()) { 545 this.field.setReadOnly(false); 546 } 547 } 548 549 /** 550 * Determines whether to render the inquiry for this field 551 * 552 * @param document the document which the accounting line is part of or hopefully sometime will be part of 553 * @param line the accounting line being rendered 554 * @return true if inquiry links should be rendered, false otherwise 555 */ 556 protected boolean isRenderingInquiry(AccountingDocument document, AccountingLine line) { 557 return isReadOnly(); 558 } 559 560 /** 561 * build the lookup parameter map through applying the override parameters onto the defaults 562 * 563 * @param lookupParameters the default lookup parameter string 564 * @param overrideLookupParameters the override lookup parameter string 565 * @param accountingLinePrefix the actual accounting line prefix 566 * @return the actual lookup parameter map 567 */ 568 private Map<String, String> getActualParametersMap(String parameters, String overrideParameters, String accountingLinePrefix) { 569 BidiMap parametersMap = this.buildBidirecionalMapFromParameters(parameters, accountingLinePrefix); 570 BidiMap overrideParametersMap = this.buildBidirecionalMapFromParameters(overrideParameters, accountingLinePrefix); 571 parametersMap.putAll(overrideParametersMap); 572 573 return parametersMap; 574 } 575 576 /** 577 * parse the given lookup parameter string into a bidirectinal map 578 * 579 * @param lookupParameters the lookup parameter string 580 * @param accountingLinePrefix the actual accounting line prefix 581 * @return a bidirectinal map that holds all the given lookup parameters 582 */ 583 private BidiMap buildBidirecionalMapFromParameters(String parameters, String accountingLinePrefix) { 584 BidiMap parameterMap = new DualHashBidiMap(); 585 586 // if we didnt get any incoming parameters, then just return an empty parameterMap 587 if (StringUtils.isBlank(parameters)) { 588 return parameterMap; 589 } 590 591 String[] parameterArray = StringUtils.split(parameters, KFSConstants.FIELD_CONVERSIONS_SEPERATOR); 592 593 for (String parameter : parameterArray) { 594 String[] entrySet = StringUtils.split(parameter, KFSConstants.FIELD_CONVERSION_PAIR_SEPERATOR); 595 596 if (entrySet != null) { 597 String parameterKey = escapeAccountingLineName(entrySet[0], accountingLinePrefix); 598 String parameterValue = escapeAccountingLineName(entrySet[1], accountingLinePrefix); 599 600 parameterMap.put(parameterKey, parameterValue); 601 } 602 } 603 604 return parameterMap; 605 } 606 607 /** 608 * Escapes the String ${accountingLineName} within a field and replaces it with the actual prefix of an accounting line 609 * 610 * @param propertyName the name of the property to escape the special string ${accountingLineName} out of 611 * @param accountingLinePrefix the actual accounting line prefix 612 * @return the property name with the correct accounting line prefix 613 */ 614 protected String escapeAccountingLineName(String propertyName, String accountingLinePrefix) { 615 return StringUtils.replace(propertyName, ACCOUNTING_LINE_NAME_PREFIX_PLACE_HOLDER, accountingLinePrefix + "."); 616 } 617 }