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 }