org.kuali.ole.sys.document.authorization.AccountingLineAuthorizerBase.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.ole.sys.document.authorization.AccountingLineAuthorizerBase.java

Source

/*
 * Copyright 2008 The Kuali Foundation
 * 
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.opensource.org/licenses/ecl2.php
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.kuali.ole.sys.document.authorization;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.kuali.ole.sys.OLEConstants;
import org.kuali.ole.sys.OLEKeyConstants;
import org.kuali.ole.sys.businessobject.AccountingLine;
import org.kuali.ole.sys.businessobject.FinancialSystemDocumentHeader;
import org.kuali.ole.sys.context.SpringContext;
import org.kuali.ole.sys.document.AccountingDocument;
import org.kuali.ole.sys.document.Correctable;
import org.kuali.ole.sys.document.web.AccountingLineRenderingContext;
import org.kuali.ole.sys.document.web.AccountingLineViewAction;
import org.kuali.ole.sys.document.web.AccountingLineViewField;
import org.kuali.ole.sys.identity.OleKimAttributes;
import org.kuali.rice.core.api.config.property.ConfigurationService;
import org.kuali.rice.kew.api.WorkflowDocument;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kim.api.identity.Person;
import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
import org.kuali.rice.kns.service.DocumentHelperService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;

/**
 * The default implementation of AccountingLineAuthorizer
 */
public class AccountingLineAuthorizerBase implements AccountingLineAuthorizer {
    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
            .getLogger(AccountingLineAuthorizerBase.class);

    private static ConfigurationService kualiConfigurationService;
    protected static String riceImagePath;
    protected static String kfsImagePath;

    /**
     * Returns the basic actions - add for new lines, delete and balance inquiry for existing lines
     * 
     * @see org.kuali.ole.sys.document.authorization.AccountingLineAuthorizer#getActions(org.kuali.ole.sys.document.AccountingDocument,
     *      org.kuali.ole.sys.businessobject.AccountingLine, java.lang.String, java.lang.Integer, org.kuali.rice.kim.api.identity.Person,
     *      java.lang.String)
     */
    public List<AccountingLineViewAction> getActions(AccountingDocument accountingDocument,
            AccountingLineRenderingContext accountingLineRenderingContext, String accountingLinePropertyName,
            Integer accountingLineIndex, Person currentUser, String groupTitle) {
        List<AccountingLineViewAction> actions = new ArrayList<AccountingLineViewAction>();

        if (accountingLineRenderingContext.isEditableLine()
                || isMessageMapContainingErrorsOnLine(accountingLinePropertyName)) {
            Map<String, AccountingLineViewAction> actionMap = this.getActionMap(accountingLineRenderingContext,
                    accountingLinePropertyName, accountingLineIndex, groupTitle);
            actions.addAll(actionMap.values());
        }

        return actions;
    }

    /**
     * Determines if the error map contains any errors which exist on the currently rendered accounting line
     * @param accountingLinePropertyName the property name of the accounting line
     * @return true if there are errors on the line, false otherwise
     */
    protected boolean isMessageMapContainingErrorsOnLine(String accountingLinePropertyName) {
        for (Object errorKeyAsObject : GlobalVariables.getMessageMap().getPropertiesWithErrors()) {
            if (((String) errorKeyAsObject).startsWith(accountingLinePropertyName))
                return true;
        }
        return false;
    }

    /**
     * Returns a new empty HashSet
     * 
     * @see org.kuali.ole.sys.document.authorization.AccountingLineAuthorizer#getUnviewableBlocks(org.kuali.ole.sys.document.AccountingDocument,
     *      org.kuali.ole.sys.businessobject.AccountingLine, java.lang.String, boolean)
     */
    public Set<String> getUnviewableBlocks(AccountingDocument accountingDocument, AccountingLine accountingLine,
            boolean newLine, Person currentUser) {
        return new HashSet<String>();
    }

    /**
     * @see org.kuali.ole.sys.document.authorization.AccountingLineAuthorizer#renderNewLine(org.kuali.ole.sys.document.AccountingDocument,
     *      java.lang.String)
     */
    public boolean renderNewLine(AccountingDocument accountingDocument, String accountingGroupProperty) {
        return (accountingDocument.getDocumentHeader().getWorkflowDocument().isInitiated()
                || accountingDocument.getDocumentHeader().getWorkflowDocument().isSaved());
    }

    /**
     * @see org.kuali.ole.sys.document.authorization.AccountingLineAuthorizer#isGroupEditable(org.kuali.ole.sys.document.AccountingDocument,
     *      java.lang.String, org.kuali.rice.kim.api.identity.Person)
     */
    public boolean isGroupEditable(AccountingDocument accountingDocument,
            List<? extends AccountingLineRenderingContext> accountingLineRenderingContexts, Person currentUser) {
        WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
        if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
            return StringUtils.equalsIgnoreCase(workflowDocument.getInitiatorPrincipalId(),
                    currentUser.getPrincipalId());
        }

        for (AccountingLineRenderingContext renderingContext : accountingLineRenderingContexts) {
            if (renderingContext.isEditableLine())
                return true;
        }

        return false;
    }

    /**
     * collection the actions that are allowed for the given accounting line
     * 
     * @param accountingLine the given accounting line
     * @param accountingLinePropertyName the property name of the given account line, typically, the form name
     * @param accountingLineIndex the index of the given accounting line in its accounting line group
     * @param groupTitle the title of the accounting line group
     * @return the actions that are allowed for the given accounting line
     */
    protected Map<String, AccountingLineViewAction> getActionMap(
            AccountingLineRenderingContext accountingLineRenderingContext, String accountingLinePropertyName,
            Integer accountingLineIndex, String groupTitle) {
        Map<String, AccountingLineViewAction> actionMap = new HashMap<String, AccountingLineViewAction>();

        if (accountingLineIndex == null || accountingLineIndex < 0) {
            AccountingLineViewAction addAction = this.getAddAction(
                    accountingLineRenderingContext.getAccountingLine(), accountingLinePropertyName, groupTitle);
            actionMap.put(OLEConstants.INSERT_METHOD, addAction);
        } else {
            if (accountingLineRenderingContext.allowDelete()) {
                AccountingLineViewAction deleteAction = this.getDeleteAction(
                        accountingLineRenderingContext.getAccountingLine(), accountingLinePropertyName,
                        accountingLineIndex, groupTitle);
                actionMap.put(KRADConstants.DELETE_METHOD, deleteAction);
            }

            AccountingLineViewAction balanceInquiryAction = this.getBalanceInquiryAction(
                    accountingLineRenderingContext.getAccountingLine(), accountingLinePropertyName,
                    accountingLineIndex, groupTitle);
            actionMap.put(OLEConstants.PERFORMANCE_BALANCE_INQUIRY_FOR_METHOD, balanceInquiryAction);
        }

        return actionMap;
    }

    /**
     * determine whether the current user has permission to edit the given field in the given accounting line
     * 
     * @param accountingDocument the given accounting document
     * @param accountingLine the given accounting line in the document
     * @param fieldName the name of a field in the given accounting line
     * @param editableLine whether the parent line of this field is editable
     * @param editablePage whether the parent page of this field is editable
     * @param currentUser the current user
     * @return true if the the current user has permission to edit the given field in the given accounting line; otherwsie, false
     */
    public final boolean hasEditPermissionOnField(AccountingDocument accountingDocument,
            AccountingLine accountingLine, String accountingLineCollectionProperty, String fieldName,
            boolean editableLine, boolean editablePage, Person currentUser) {
        if (!determineEditPermissionOnField(accountingDocument, accountingLine, accountingLineCollectionProperty,
                fieldName, editablePage)) {
            return false;
        }

        // the fields in a new line should be always editable
        if (accountingLine.getSequenceNumber() == null) {
            return true;
        }

        // examine whether the given field can be editable
        boolean hasEditPermissionOnField = editableLine || this.determineEditPermissionByFieldName(
                accountingDocument, accountingLine,
                getKimHappyPropertyNameForField(accountingLineCollectionProperty + "." + fieldName), currentUser);
        if (hasEditPermissionOnField == false) {
            // kim check shows field should not be editable based on contents of field - check if line error message occurred on this line
            // if error message shows up, then the value must have changed recently so - we make it editable to allow user to correct it
            WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
            if (workflowDocument.isEnroute()
                    && isMessageMapContainingErrorsOnLine(accountingLineCollectionProperty))
                return true;
        }
        return hasEditPermissionOnField;
    }

    /**
     * Allows the overriding of whether a field on an accounting line is editable or not
     * @param accountingDocument the accounting document the line to test is on
     * @param accountingLine the accounting line to test
     * @param accountingLineCollectionProperty the property that the accounting line lives in
     * @param fieldName the name of the field we are testing
     * @param editableLine whether the parent line of this field is editable
     * @param editablePage whether the parent page of this field is editable
     * @return true if the field can be edited (subject to subsequence KIM check); false otherwise
     */
    public boolean determineEditPermissionOnField(AccountingDocument accountingDocument,
            AccountingLine accountingLine, String accountingLineCollectionProperty, String fieldName,
            boolean editablePage) {
        if (!editablePage)
            return false; // no edits by default on non editable pages

        final FinancialSystemDocumentHeader documentHeader = (FinancialSystemDocumentHeader) accountingDocument
                .getDocumentHeader();
        final WorkflowDocument workflowDocument = documentHeader.getWorkflowDocument();

        // if a document is cancelled or in error, all of its fields cannot be editable
        if (workflowDocument.isCanceled()
                || ObjectUtils.isNotNull(documentHeader.getFinancialDocumentInErrorNumber())) {
            return false;
        }

        return true;
    }

    /**
     * Determine whether the current user has permission to edit the given accounting line as a whole
     * 
     * @param accountingDocument the given accounting document
     * @param accountingLine the given accounting line in the document
     * @param currentUser the current user
     * @return true if the the current user has permission to edit the given accounting line; otherwsie, false
     */
    public final boolean hasEditPermissionOnAccountingLine(AccountingDocument accountingDocument,
            AccountingLine accountingLine, String accountingLineCollectionProperty, Person currentUser,
            boolean pageIsEditable) {
        if (determineEditPermissionOnLine(accountingDocument, accountingLine, accountingLineCollectionProperty,
                StringUtils.equalsIgnoreCase(
                        accountingDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(),
                        currentUser.getPrincipalId()),
                pageIsEditable)) {

            if (approvedForUnqualifiedEditing(accountingDocument, accountingLine, accountingLineCollectionProperty,
                    StringUtils.equalsIgnoreCase(
                            accountingDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(),
                            currentUser.getPrincipalId()))) {
                return true; // don't do the KIM check, we're good
            }

            // examine whether the whole line can be editable via KIM check
            final String lineFieldName = getKimHappyPropertyNameForField(accountingLineCollectionProperty);
            return this.determineEditPermissionByFieldName(accountingDocument, accountingLine, lineFieldName,
                    currentUser);
        }
        return false;
    }

    /**
     * A hook to decide, pre-KIM check, if there's an edit permission on the given accounting line
     * @param accountingDocument the accounting document the line is or wants to be associated with
     * @param accountingLine the accounting line itself
     * @param accountingLineCollectionProperty the collection the accounting line is or would be part of
     * @param currentUserIsDocumentInitiator is the current user the initiator of the document?
     * @return true if the line as a whole can be edited, false otherwise
     */
    public boolean determineEditPermissionOnLine(AccountingDocument accountingDocument,
            AccountingLine accountingLine, String accountingLineCollectionProperty,
            boolean currentUserIsDocumentInitiator, boolean pageIsEditable) {
        if (accountingDocument instanceof Correctable) {
            String errorDocumentNumber = ((FinancialSystemDocumentHeader) accountingDocument.getDocumentHeader())
                    .getFinancialDocumentInErrorNumber();
            if (StringUtils.isNotBlank(errorDocumentNumber))
                return false;
        }

        return true;
    }

    /**
     * Determines if the given line is editable, no matter what a KIM check would say about line editability.  In the default case,
     * any accounting line is editable - minus KIM check - when the document is PreRoute, or if the line is a new line
     * @param accountingDocument the accounting document the line is or wants to be associated with
     * @param accountingLine the accounting line itself
     * @param accountingLineCollectionProperty the collection the accounting line is or would be part of
     * @param currentUserIsDocumentInitiator is the current user the initiator of the document?
     * @return true if the line as a whole can be edited without the KIM check, false otherwise
     */
    protected boolean approvedForUnqualifiedEditing(AccountingDocument accountingDocument,
            AccountingLine accountingLine, String accountingLineCollectionProperty,
            boolean currentUserIsDocumentInitiator) {
        // the fields in a new line should be always editable
        if (accountingLine.getSequenceNumber() == null) {
            return true;
        }

        // check the initiation permission on the document if it is in the state of preroute
        WorkflowDocument workflowDocument = accountingDocument.getDocumentHeader().getWorkflowDocument();
        if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
            return currentUserIsDocumentInitiator;
        }
        return false;
    }

    /**
     * determine whether the current user has permission to edit the given field in the given accounting line
     * 
     * @param accountingDocument the given accounting document
     * @param accountingLine the given accounting line in the document
     * @param fieldName the name of a field in the given accounting line
     * @param currentUser the current user
     * @return true if the the current user has permission to edit the given field in the given accounting line; otherwsie, false
     */
    protected boolean determineEditPermissionByFieldName(AccountingDocument accountingDocument,
            AccountingLine accountingLine, String fieldName, Person currentUser) {
        final Map<String, String> roleQualifiers = this.getRoleQualifiers(accountingDocument, accountingLine);
        final String documentTypeName = accountingDocument.getDocumentHeader().getWorkflowDocument()
                .getDocumentTypeName();
        final Map<String, String> permissionDetail = this.getPermissionDetails(documentTypeName, fieldName);

        return this.hasEditPermission(accountingDocument, currentUser, permissionDetail, roleQualifiers);
    }

    /**
     * determine whether the current user has modification permission on an accounting line with the given qualifications. The
     * permission template and namespace have been setup in the method.
     * 
     * @param currentUser the current user
     * @param permissionDetails the given permission details
     * @param roleQualifiers the given role qualifications
     * @return true if the user has edit permission on an accounting line with the given qualifications; otherwise, false
     */
    protected boolean hasEditPermission(AccountingDocument accountingDocument, Person currentUser,
            Map<String, String> permissionDetails, Map<String, String> roleQualifiers) {
        String pricipalId = currentUser.getPrincipalId();
        DocumentAuthorizer accountingDocumentAuthorizer = this.getDocumentAuthorizer(accountingDocument);

        return accountingDocumentAuthorizer.isAuthorizedByTemplate(accountingDocument,
                OLEConstants.ParameterNamespaces.OLE, OLEConstants.PermissionTemplate.MODIFY_ACCOUNTING_LINES.name,
                pricipalId, permissionDetails, roleQualifiers);
    }

    /**
     * Gathers together all the information for a permission detail attribute set
     * 
     * @param documentTypeName the document
     * @param fieldName the given field name
     * @return all the information for a permission detail attribute set
     */
    protected Map<String, String> getPermissionDetails(String documentTypeName, String fieldName) {
        Map<String, String> permissionDetails = new HashMap<String, String>();

        if (StringUtils.isNotBlank(documentTypeName)) {
            permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
        }

        if (StringUtils.isNotBlank(fieldName)) {
            permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, fieldName);
        }

        return permissionDetails;
    }

    /**
     * Gathers together the role qualifiers for the KIM perm call
     * 
     * @param accountingLine the accounting line to get role qualifiers from
     * @return the gathered Map<String,String> of role qualifiers
     */
    protected final Map<String, String> getRoleQualifiers(AccountingDocument accountingDocument,
            AccountingLine accountingLine) {
        Map<String, String> roleQualifiers = new HashMap<String, String>();

        if (accountingLine != null) {
            roleQualifiers.put(OleKimAttributes.CHART_OF_ACCOUNTS_CODE, accountingLine.getChartOfAccountsCode());
            roleQualifiers.put(OleKimAttributes.ACCOUNT_NUMBER, accountingLine.getAccountNumber());
        }

        return roleQualifiers;
    }

    /**
     * @param field AccountingLineViewField to find KIM-happy property name for
     * @return a property name that KIM will like
     */
    protected String getKimHappyPropertyNameForField(String convertedName) {
        convertedName = stripDocumentPrefixFromName(convertedName);

        return replaceCollectionElementsWithPlurals(convertedName);
    }

    /**
     * get the full property name of the given field
     * 
     * @param field the field to get the name from
     * @return the full property name of the given field, typically, a combination of property prefix and simple property name
     */
    protected String getFieldName(AccountingLineViewField field) {
        String propertyPrefix = field.getField().getPropertyPrefix();
        String propertyName = field.getField().getPropertyName();

        return StringUtils.isNotBlank(propertyPrefix) ? (propertyPrefix + "." + propertyName) : propertyName;
    }

    /**
     * Strips "document." and everything before from the property name
     * 
     * @param name the property name to strip the document portion off of
     * @return the stripped name
     */
    protected String stripDocumentPrefixFromName(String name) {
        return name.replaceFirst("(.)*document\\.", StringUtils.EMPTY);
    }

    /**
     * Replaces references to collection elements to their respective plural names WARNING: this method is totally lame and I for
     * one wished it didn't have to exist
     * 
     * @param name the property name with perhaps collection elements in
     * @return the corrected name
     */
    protected String replaceCollectionElementsWithPlurals(String name) {
        String temp = name.replaceAll("\\[\\d+\\]", "s");
        // now - need to check if the property name ends with a double "s", which is incorrect
        if (temp.endsWith("ss")) {
            temp = StringUtils.chop(temp);
        }
        return temp;
    }

    /**
     * construct the balance inquiry action for the given accounting line
     * 
     * @param accountingLine the given accounting line
     * @param accountingLinePropertyName the property name of the given account line, typically, the form name
     * @param accountingLineIndex the index of the given accounting line in its accounting line group
     * @param groupTitle the title of the accounting line group
     * @return the balance inquiry action for the given accounting line
     */
    protected AccountingLineViewAction getBalanceInquiryAction(AccountingLine accountingLine,
            String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
        String actionMethod = this.getBalanceInquiryMethod(accountingLine, accountingLinePropertyName,
                accountingLineIndex);
        String actionLabel = this.getActionLabel(
                OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_BALANCE_INQUIRY_ACTION_LABEL,
                groupTitle, accountingLineIndex + 1);

        String actionImageName = getKFSImagePath() + "tinybutton-balinquiry.gif";

        return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
    }

    /**
     * construct the delete action for the given accounting line
     * 
     * @param accountingLine the given accounting line
     * @param accountingLinePropertyName the property name of the given account line, typically, the form name
     * @param accountingLineIndex the index of the given accounting line in its accounting line group
     * @param groupTitle the title of the accounting line group
     * @return the delete action for the given accounting line
     */
    protected AccountingLineViewAction getDeleteAction(AccountingLine accountingLine,
            String accountingLinePropertyName, Integer accountingLineIndex, String groupTitle) {
        String actionMethod = this.getDeleteLineMethod(accountingLine, accountingLinePropertyName,
                accountingLineIndex);
        String actionLabel = this.getActionLabel(
                OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_DELETE_ACTION_LABEL, groupTitle,
                accountingLineIndex + 1);

        String actionImageName = getRiceImagePath() + "tinybutton-delete1.gif";

        return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
    }

    /**
     * construct the add action for the given accounting line, typically, a new accounting line
     * 
     * @param accountingLine the given accounting line
     * @param accountingLinePropertyName the property name of the given account line, typically, the form name
     * @param accountingLineIndex the index of the given accounting line in its accounting line group
     * @param groupTitle the title of the accounting line group
     * @return the add action for the given accounting line
     */
    protected AccountingLineViewAction getAddAction(AccountingLine accountingLine,
            String accountingLinePropertyName, String groupTitle) {
        String actionMethod = this.getAddMethod(accountingLine, accountingLinePropertyName);
        String actionLabel = this.getActionLabel(
                OLEKeyConstants.AccountingLineViewRendering.ACCOUNTING_LINE_ADD_ACTION_LABEL, groupTitle);

        String actionImageName = getRiceImagePath() + "tinybutton-add1.gif";

        return new AccountingLineViewAction(actionMethod, actionLabel, actionImageName);
    }

    /**
     * get a label for an action with the specified message key and values
     * 
     * @param messageKey the given message key that points to the label
     * @param values the given values that would be displayed in label
     * @return a label for an action with the specified message key and values
     */
    protected String getActionLabel(String messageKey, Object... values) {
        String messageBody = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(messageKey);

        return MessageFormat.format(messageBody, values);
    }

    /**
     * Builds the action method name of the method that adds accounting lines for this group
     * 
     * @param accountingLine the accounting line an action is being checked for
     * @param accountingLinePropertyName the property name of the accounting line
     * @return the action method name of the method that adds accounting lines for this group
     */
    protected String getAddMethod(AccountingLine accountingLine, String accountingLineProperty) {
        final String infix = getActionInfixForNewAccountingLine(accountingLine, accountingLineProperty);
        return OLEConstants.INSERT_METHOD + infix + "Line.anchoraccounting" + infix + "Anchor";
    }

    /**
     * Builds the action method name of the method that deletes accounting lines for this group
     * 
     * @param accountingLine the accounting line an action is being checked for
     * @param accountingLinePropertyName the property name of the accounting line
     * @param accountingLineIndex the index of the given accounting line within the the group being rendered
     * @return the action method name of the method that deletes accounting lines for this group
     */
    protected String getDeleteLineMethod(AccountingLine accountingLine, String accountingLineProperty,
            Integer accountingLineIndex) {
        final String infix = getActionInfixForExtantAccountingLine(accountingLine, accountingLineProperty);
        return KRADConstants.DELETE_METHOD + infix + "Line.line" + accountingLineIndex + ".anchoraccounting" + infix
                + "Anchor";
    }

    /**
     * Builds the action method name of the method that performs a balance inquiry on accounting lines for this group
     * 
     * @param accountingLine the accounting line an action is being checked for
     * @param accountingLinePropertyName the property name of the accounting line
     * @param accountingLineIndex the index of the given accounting line within the the group being rendered
     * @return the action method name of the method that performs a balance inquiry on accounting lines for this group
     */
    protected String getBalanceInquiryMethod(AccountingLine accountingLine, String accountingLineProperty,
            Integer accountingLineIndex) {
        final String infix = getActionInfixForExtantAccountingLine(accountingLine, accountingLineProperty);
        return OLEConstants.PERFORMANCE_BALANCE_INQUIRY_FOR_METHOD + infix + "Line.line" + accountingLineIndex
                + ".anchoraccounting" + infix + "existingLineLineAnchor" + accountingLineIndex;
    }

    /**
     * Gets the "action infix" for the given accounting line, so that the action knows it is supposed to add to source vs. target
     * 
     * @param accountingLine the accounting line an action is being checked for
     * @param accountingLinePropertyName the property name of the accounting line
     * @return the name of the action infix
     */
    protected String getActionInfixForNewAccountingLine(AccountingLine accountingLine,
            String accountingLinePropertyName) {
        if (accountingLine.isSourceAccountingLine()) {
            return OLEConstants.SOURCE;
        }

        if (accountingLine.isTargetAccountingLine()) {
            return OLEConstants.TARGET;
        }

        return OLEConstants.EMPTY_STRING;
    }

    /**
     * Gets the "action infix" for the given accounting line which already exists on the document, so that the action knows it is
     * supposed to add to source vs. target
     * 
     * @param accountingLine the accounting line an action is being checked for
     * @param accountingLinePropertyName the property name of the accounting line
     * @return the name of the action infix
     */
    protected String getActionInfixForExtantAccountingLine(AccountingLine accountingLine,
            String accountingLinePropertyName) {
        if (accountingLine.isSourceAccountingLine()) {
            return OLEConstants.SOURCE;
        }

        if (accountingLine.isTargetAccountingLine()) {
            return OLEConstants.TARGET;
        }

        return OLEConstants.EMPTY_STRING;
    }

    /**
     * get the document authorizer of the given accounting document
     * 
     * @param accountingDocument the given accounting document
     * @return the document authorizer of the given accounting document
     */
    protected DocumentAuthorizer getDocumentAuthorizer(AccountingDocument accountingDocument) {
        return SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(accountingDocument);
    }

    /**
     * @return the path to rice images
     */
    protected String getRiceImagePath() {
        if (riceImagePath == null) {
            riceImagePath = getConfigurationService()
                    .getPropertyValueAsString(KRADConstants.EXTERNALIZABLE_IMAGES_URL_KEY);
        }
        return riceImagePath;
    }

    /**
     * @return the path to OLE images
     */
    protected String getKFSImagePath() {
        if (kfsImagePath == null) {
            kfsImagePath = getConfigurationService()
                    .getPropertyValueAsString(KRADConstants.APPLICATION_EXTERNALIZABLE_IMAGES_URL_KEY);
        }
        return kfsImagePath;
    }

    protected ConfigurationService getConfigurationService() {
        if (kualiConfigurationService == null) {
            kualiConfigurationService = SpringContext.getBean(ConfigurationService.class);
        }
        return kualiConfigurationService;
    }
}