org.kuali.kpme.pm.position.web.PositionMaintainableServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kpme.pm.position.web.PositionMaintainableServiceImpl.java

Source

/**
 * Copyright 2004-2014 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.kpme.pm.position.web;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.util.*;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.kuali.kpme.core.api.department.Department;
import org.kuali.kpme.core.bo.HrBusinessObject;
import org.kuali.kpme.core.bo.HrDataObjectMaintainableImpl;
import org.kuali.kpme.core.bo.derived.HrBusinessObjectDerived;
import org.kuali.kpme.core.departmentaffiliation.DepartmentAffiliationBo;
import org.kuali.kpme.core.service.HrServiceLocator;
import org.kuali.kpme.core.util.ValidationUtils;
import org.kuali.kpme.pm.position.PositionBo;
import org.kuali.kpme.pm.position.PositionDutyBo;
import org.kuali.kpme.pm.position.PositionQualificationBo;
import org.kuali.kpme.pm.position.PstnFlagBo;
import org.kuali.kpme.pm.position.funding.PositionFundingBo;
import org.kuali.kpme.pm.positiondepartment.PositionDepartmentBo;
import org.kuali.kpme.pm.positionresponsibility.PositionResponsibilityBo;
import org.kuali.kpme.pm.service.base.PmServiceLocator;
import org.kuali.rice.kew.api.document.DocumentStatus;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;
import org.kuali.rice.kns.service.KNSServiceLocator;
import org.kuali.rice.krad.bo.DocumentHeader;
import org.kuali.rice.krad.bo.Note;
import org.kuali.rice.krad.maintenance.MaintenanceDocument;
import org.kuali.rice.krad.service.KRADServiceLocator;
import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
import org.kuali.rice.krad.uif.container.CollectionGroup;
import org.kuali.rice.krad.uif.view.View;
import org.kuali.rice.krad.uif.view.ViewModel;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;

public class PositionMaintainableServiceImpl extends HrDataObjectMaintainableImpl {

    private static final long serialVersionUID = 1L;

    @Override
    public HrBusinessObject getObjectById(String id) {
        return PositionBo.from(PmServiceLocator.getPositionService().getPosition(id));
    }

    @Override
    public void customInactiveSaveLogicNewEffective(HrBusinessObject oldHrObj) {
        PositionBo bo = (PositionBo) oldHrObj;
        bo.setDepartmentList(null);
        bo.setDutyList(null);
        bo.setPositionResponsibilityList(null);
        bo.setQualificationList(null);
        bo.setFlagList(null);
        bo.setFundingList(null);
        bo.setRequiredQualList(null);
    }

    @Override
    public void customSaveLogic(HrBusinessObject hrObj) {
        PositionBo aPosition = (PositionBo) hrObj;
        for (PositionQualificationBo aQual : aPosition.getQualificationList()) {
            aQual.setHrPositionId(aPosition.getHrPositionId());
            aQual.setPmQualificationId(null);
        }
        for (PositionDutyBo aDuty : aPosition.getDutyList()) {
            aDuty.setHrPositionId(aPosition.getHrPositionId());
            aDuty.setPmDutyId(null);
        }
        for (PstnFlagBo aFlag : aPosition.getFlagList()) {
            aFlag.setHrPositionId(aPosition.getHrPositionId());
            aFlag.setPmFlagId(null);
        }
        for (PositionFundingBo aFunding : aPosition.getFundingList()) {
            aFunding.setHrPositionId(aPosition.getHrPositionId());
            aFunding.setPmPositionFunctionId(null);
        }
        for (PositionDepartmentBo aDepartment : aPosition.getDepartmentList()) {
            aDepartment.setHrPositionId(aPosition.getHrPositionId());
            aDepartment.setPmPositionDeptId(null);
        }
        for (PositionResponsibilityBo aResponsibility : aPosition.getPositionResponsibilityList()) {
            aResponsibility.setHrPositionId(aPosition.getHrPositionId());
            aResponsibility.setPositionResponsibilityId(null);
        }

        // KPME-3016 populate institution and location here
        // We should be able to do this in addNewLineToCollection, but all the components are in "pages" now with the layout change, 
        // not on the form, and addNewLineToCollection doesn't get called. 
        if (aPosition.getDepartmentList() != null) {
            for (PositionDepartmentBo aPositionDepartment : aPosition.getDepartmentList()) {
                if (aPositionDepartment != null && aPositionDepartment.getDeptAffl() != null) {
                    DepartmentAffiliationBo pda = (DepartmentAffiliationBo) aPositionDepartment.getDeptAfflObj();
                    if (pda.isPrimaryIndicator()) {
                        aPosition.setGroupKeyCode(aPositionDepartment.getGroupKeyCode());
                        break;
                    }
                }
            }
        }

    }

    @Override
    protected boolean performAddLineValidation(ViewModel viewModel, Object newLine, String collectionId,
            String collectionPath) {
        boolean isValid = super.performAddLineValidation(viewModel, newLine, collectionId, collectionPath);
        if (viewModel instanceof MaintenanceDocumentForm) {
            MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) viewModel;
            MaintenanceDocument document = maintenanceForm.getDocument();
            if (document.getNewMaintainableObject().getDataObject() instanceof PositionBo) {
                PositionBo aPosition = (PositionBo) document.getNewMaintainableObject().getDataObject();
                // Duty line validation
                if (newLine instanceof PositionDutyBo) {
                    PositionDutyBo pd = (PositionDutyBo) newLine;
                    boolean results = this.validateDutyListPercentage(pd, aPosition);
                    if (!results) {
                        return false;
                    }
                }
                // Funding line validation
                if (newLine instanceof PositionFundingBo) {
                    PositionFundingBo pf = (PositionFundingBo) newLine;
                    boolean results = this.validateAddFundingLine(pf, aPosition);
                    if (!results) {
                        return false;
                    }
                }

                // Responsibility validation
                if (newLine instanceof PositionResponsibilityBo) {
                    PositionResponsibilityBo pr = (PositionResponsibilityBo) newLine;
                    boolean results = this.validatePositionResponsibilityListPercentage(pr, aPosition);
                    if (!results) {
                        return false;
                    }
                }

                //Department validation
                if (newLine instanceof PositionDepartmentBo) {
                    PositionDepartmentBo pd = (PositionDepartmentBo) newLine;
                    boolean results = this.validateAdditionalDepartmentList(pd, aPosition);
                    if (!results) {
                        return false;
                    }
                }
            }
        }

        return isValid;
    }

    private boolean validateAdditionalDepartmentList(PositionDepartmentBo pd, PositionBo aPosition) {

        //Will only be validated if effective local date in position is not null
        if (aPosition.getEffectiveLocalDate() != null && pd != null) {
            Department department = HrServiceLocator.getDepartmentService().getDepartment(pd.getDepartment(),
                    pd.getGroupKeyCode(), aPosition.getEffectiveLocalDate());
            if (department == null) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.departmentList'].department",
                        "error.existence", "Position Department '" + pd.getDepartment() + "'");
                return false;
            }
        }

        return true;
    }

    private boolean validateDutyListPercentage(PositionDutyBo pd, PositionBo aPosition) {
        if (CollectionUtils.isNotEmpty(aPosition.getDutyList()) && pd.getPercentage() != null) {
            BigDecimal sum = pd.getPercentage();
            for (PositionDutyBo aDuty : aPosition.getDutyList()) {
                if (aDuty != null && aDuty.getPercentage() != null) {
                    sum = sum.add(aDuty.getPercentage());
                }
            }
            if (sum.compareTo(new BigDecimal(100)) > 0) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.dutyList'].percentage",
                        "duty.percentage.exceedsMaximum", sum.toString());
                return false;
            }
        }
        return true;
    }

    private boolean validatePositionResponsibilityListPercentage(PositionResponsibilityBo pd,
            PositionBo aPosition) {
        if (CollectionUtils.isNotEmpty(aPosition.getPositionResponsibilityList()) && pd.getPercentTime() != null) {
            BigDecimal sum = pd.getPercentTime();
            for (PositionResponsibilityBo aResponsibility : aPosition.getPositionResponsibilityList()) {
                if (aResponsibility != null && aResponsibility.getPercentTime() != null) {
                    sum = sum.add(aResponsibility.getPercentTime());
                }
            }
            if (sum.compareTo(new BigDecimal(100)) > 0) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.positionResponsibilityList'].percentTime",
                        "responsibility.percenttime.exceedsMaximum", sum.toString());
                return false;
            }
        }
        return true;
    }

    protected boolean validateAddFundingLine(PositionFundingBo pf, PositionBo aPosition) {
        if (StringUtils.isNotEmpty(pf.getAccount())) {
            boolean results = ValidationUtils.validateAccount(pf.getChart(), pf.getAccount());
            if (!results) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.fundingList'].account",
                        "error.existence", "Account '" + pf.getAccount() + "'");
                return results;
            }
        }
        if (StringUtils.isNotEmpty(pf.getSubAccount())) {
            boolean results = ValidationUtils.validateSubAccount(pf.getSubAccount(), pf.getAccount(),
                    pf.getChart());
            if (!results) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.fundingList'].subAccount",
                        "error.existence", "Sub Account '" + pf.getSubAccount() + "'");
                return results;
            }
        }
        if (StringUtils.isNotEmpty(pf.getObjectCode())) {
            boolean results = ValidationUtils.validateObjectCode(pf.getObjectCode(), pf.getChart(), null);
            if (!results) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.fundingList'].objectCode",
                        "error.existence", "Object Code '" + pf.getObjectCode() + "'");
                return results;
            }
        }
        if (StringUtils.isNotEmpty(pf.getSubObjectCode())) {
            boolean results = ValidationUtils.validateSubObjectCode(null, pf.getChart(), pf.getAccount(),
                    pf.getObjectCode(), pf.getSubObjectCode());
            if (!results) {
                GlobalVariables.getMessageMap().putError(
                        "newCollectionLines['document.newMaintainableObject.dataObject.fundingList'].subObjectCode",
                        "error.existence", "Sub Object Code '" + pf.getSubObjectCode() + "'");
                return results;
            }
        }
        return true;

    }

    // KPME-3016
    //set document description here so it passes validation.  It will get overriden in doRouteStatusChange method
    @Override
    public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) {
        document.getDocumentHeader().setDocumentDescription("Edit Position");
        super.processAfterEdit(document, requestParameters);
    }

    protected void setupNewPositionRecord(MaintenanceDocument document) {
        PositionBo aPosition = (PositionBo) document.getNewMaintainableObject().getDataObject();
        aPosition.setProcess("New");
        String positionNumber = KNSServiceLocator.getSequenceAccessorService()
                .getNextAvailableSequenceNumber("hr_position_s", PositionBo.class).toString();
        aPosition.setPositionNumber(positionNumber);

        document.getDocumentHeader().setDocumentDescription("New Position");
    }

    @Override
    public void processAfterNew(MaintenanceDocument document, Map<String, String[]> requestParameters) {
        setupNewPositionRecord(document);
        super.processAfterNew(document, requestParameters);
    }

    @Override
    public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> parameters) {
        setupNewPositionRecord(document);
        super.processAfterCopy(document, parameters);
    }

    @Override
    public String getDocumentTitle(MaintenanceDocument document) {
        String docTitle = document.getDocumentHeader().getDocumentDescription();
        return docTitle;
    }

    @Override
    public void doRouteStatusChange(DocumentHeader documentHeader) {

        String docDescription = null;
        PositionBo position = (PositionBo) this.getDataObject();
        DocumentStatus documentStatus = documentHeader.getWorkflowDocument().getStatus();

        //Set document description for real here
        if (StringUtils.isEmpty(position.getPositionNumber())) {
            docDescription = "Process: " + position.getProcess() + " Position Status: "
                    + position.getPositionStatus();
        } else {
            docDescription = "Process: " + position.getProcess() + " Position Number: "
                    + position.getPositionNumber() + " Position Status: " + position.getPositionStatus();
        }

        if (DocumentStatus.ENROUTE.equals(documentStatus)) {
            try {
                MaintenanceDocument md = (MaintenanceDocument) KRADServiceLocatorWeb.getDocumentService()
                        .getByDocumentHeaderId(documentHeader.getDocumentNumber());
                md.getDocumentHeader().setDocumentDescription(docDescription);
                md.getNewMaintainableObject().setDataObject(position);
                KRADServiceLocatorWeb.getDocumentService().saveDocument(md);
            } catch (WorkflowException e) {
                LOG.error(
                        "caught exception while handling doRouteStatusChange -> documentService.getByDocumentHeaderId("
                                + documentHeader.getDocumentNumber() + "). ",
                        e);
                throw new RuntimeException(
                        "caught exception while handling doRouteStatusChange -> documentService.getByDocumentHeaderId("
                                + documentHeader.getDocumentNumber() + "). ",
                        e);
            }
        }
    }

    //KPME-2624 added logic to save current logged in user to UserPrincipal id for collections
    @Override
    public void prepareForSave() {
        PositionBo position = (PositionBo) this.getDataObject();
        boolean hasPrimaryDepartment = false;
        for (PositionDepartmentBo positionDepartment : position.getDepartmentList()) {
            if (positionDepartment.getDeptAfflObj().isPrimaryIndicator()) {
                hasPrimaryDepartment = true;
                positionDepartment.setDepartment(position.getPrimaryDepartment());
                positionDepartment.setGroupKeyCode(position.getGroupKeyCode());
                //                positionDepartment.setLocation(position.getLocation());
                //                positionDepartment.setInstitution(position.getInstitution());
                positionDepartment.setDeptAffl(HrServiceLocator.getDepartmentAffiliationService()
                        .getPrimaryAffiliation().getDeptAfflType());
            }
        }

        //create primary department
        if (!hasPrimaryDepartment && StringUtils.isNotEmpty(position.getPrimaryDepartment())) {
            PositionDepartmentBo primaryDepartment = new PositionDepartmentBo();
            primaryDepartment.setDepartment(position.getPrimaryDepartment());
            primaryDepartment.setGroupKeyCode(position.getGroupKeyCode());
            // primaryDepartment.setLocation(position.getLocation());
            // primaryDepartment.setInstitution(position.getInstitution());
            primaryDepartment.setDeptAffl(
                    HrServiceLocator.getDepartmentAffiliationService().getPrimaryAffiliation().getDeptAfflType());
            position.getDepartmentList().add(primaryDepartment);
        }

        //add note if enroute change occurs
        try {
            MaintenanceDocument maintenanceDocument = (MaintenanceDocument) KRADServiceLocatorWeb
                    .getDocumentService().getByDocumentHeaderId(this.getDocumentNumber());
            if (maintenanceDocument != null
                    && maintenanceDocument.getNewMaintainableObject().getDataObject() instanceof PositionBo) {
                PositionBo previousPosition = (PositionBo) maintenanceDocument.getNewMaintainableObject()
                        .getDataObject();
                recordEnrouteChanges(previousPosition, maintenanceDocument.getNoteTarget().getObjectId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        super.prepareForSave();

    }

    private void recordEnrouteChanges(PositionBo previousPosition, String noteTarget) {
        //List of fields on the position class not to compare
        List<String> noCompareFields = new ArrayList<String>();
        noCompareFields.add("process");
        noCompareFields.add("requiredQualList");

        List<Note> noteList = new ArrayList<Note>();
        PositionBo currentPosition = (PositionBo) this.getDataObject();

        EntityNamePrincipalName approver = KimApiServiceLocator.getIdentityService()
                .getDefaultNamesForPrincipalId(currentPosition.getUserPrincipalId());

        //compare all fields on position
        try {
            for (PropertyDescriptor pd : Introspector.getBeanInfo(PositionBo.class).getPropertyDescriptors()) {

                if (pd.getReadMethod() != null && !noCompareFields.contains(pd.getName())) {
                    try {
                        Object currentObject = pd.getReadMethod().invoke(currentPosition);
                        Object previousObject = pd.getReadMethod().invoke(previousPosition);
                        if (currentObject instanceof Collection) {
                            if (!compareCollections(currentObject, previousObject)) {
                                String noteText = approver.getPrincipalName() + " changed " + pd.getDisplayName()
                                        + " from '" + previousObject.toString() + "' to '"
                                        + currentObject.toString() + "'";
                                noteList.add(
                                        createNote(noteText, noteTarget, currentPosition.getUserPrincipalId()));
                            }
                        } else {
                            if (!(currentObject == null ? previousObject == null
                                    : currentObject.equals(previousObject))) {
                                String noteText = approver.getPrincipalName() + " changed " + pd.getDisplayName()
                                        + " from '" + previousObject.toString() + "' to '"
                                        + currentObject.toString() + "'";
                                noteList.add(
                                        createNote(noteText, noteTarget, currentPosition.getUserPrincipalId()));
                            }
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }

        KRADServiceLocator.getNoteService().saveNoteList(noteList);
    }

    @SuppressWarnings("rawtypes")
    public boolean compareCollections(Object coll1, Object coll2) {
        if (coll1 == coll2)
            return true;

        if (coll1 instanceof List && coll2 instanceof List) {
            ListIterator list1 = ((List) coll1).listIterator();
            ListIterator list2 = ((List) coll2).listIterator();
            while (list1.hasNext() && list2.hasNext()) {
                Object o1 = list1.next();
                Object o2 = list2.next();

                if (o1 instanceof HrBusinessObjectDerived && o1 instanceof HrBusinessObjectDerived) {
                    HrBusinessObjectDerived hrObj1 = (HrBusinessObjectDerived) o1;
                    HrBusinessObjectDerived hrObj2 = (HrBusinessObjectDerived) o2;
                    if (!(hrObj1 == null ? hrObj2 == null : hrObj1.isEquivalentTo(hrObj2)))
                        return false;
                } else {
                    if (!(o1 == null ? o2 == null : o1.equals(o2)))
                        return false;
                }
            }

            return !(list1.hasNext() || list2.hasNext());
        } else {
            //need to add logic if other collection types are added to position
            return coll1.equals(coll2);
        }
    }

    private Note createNote(String noteText, String noteTarget, String principalId) {
        Note note = new Note();
        note.setRemoteObjectIdentifier(noteTarget);
        note.setNoteText(StringUtils.abbreviate(noteText, 800));
        note.setAuthorUniversalIdentifier(principalId);
        note.setNotePostedTimestampToCurrent();
        return note;
    }

}