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