org.kuali.kra.common.committee.lookup.CommitteeLookupableHelperServiceImplBase.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kra.common.committee.lookup.CommitteeLookupableHelperServiceImplBase.java

Source

/*
 * Copyright 2005-2013 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/ecl1.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.kra.common.committee.lookup;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.kuali.kra.common.committee.bo.CommitteeBase;
import org.kuali.kra.common.committee.bo.CommitteeMembershipBase;
import org.kuali.kra.common.committee.bo.CommitteeMembershipRole;
import org.kuali.kra.common.committee.bo.CommitteeResearchAreaBase;
import org.kuali.kra.common.committee.document.CommitteeDocumentBase;
import org.kuali.kra.infrastructure.KraServiceLocator;
import org.kuali.kra.lookup.KraLookupableHelperServiceImpl;
import org.kuali.kra.questionnaire.question.Question;
import org.kuali.kra.service.KraAuthorizationService;
import org.kuali.rice.kew.api.KewApiConstants;
import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
import org.kuali.rice.kns.lookup.HtmlData;
import org.kuali.rice.kns.lookup.LookupUtils;
import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
import org.kuali.rice.kns.web.ui.Field;
import org.kuali.rice.kns.web.ui.Row;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.bo.PersistableBusinessObject;
import org.kuali.rice.krad.lookup.CollectionIncomplete;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.service.KRADServiceLocator;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;

/**
 * 
 * This class is for committee lookup.
 */
@SuppressWarnings({ "serial", "deprecation" })
public abstract class CommitteeLookupableHelperServiceImplBase<CMT extends CommitteeBase<CMT, CD, ?>, CD extends CommitteeDocumentBase<CD, CMT, ?>>

        extends KraLookupableHelperServiceImpl {

    private static final String COMMITTEE_TYPE_CODE_FIELD_NAME = "committeeTypeCode";
    private static final String PERSON_NAME = "personName";
    private static final String RESEARCH_AREA_CODE = "researchAreaCode";

    // TODO *********commented the code below during IACUC refactoring*********     
    //    private static final Log LOG = LogFactory.getLog(CommitteeLookupableHelperServiceImplBase.class);

    private static final String DOCHANDLER_LINK = "%s/DocHandler.do?command=displayDocSearchView&docId=%s";

    @Override
    public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
        // we set the lookup to only list committees of type chosen
        fieldValues.put(COMMITTEE_TYPE_CODE_FIELD_NAME, getCommitteeTypeCodeHook());

        // TODO *********commented the code below during IACUC refactoring********* 
        //        fieldValues.put(COMMITTEE_TYPE_CODE_FIELD_NAME, CommitteeType.IACUC_TYPE_CODE);

        List<CMT> activeCommittees = (List<CMT>) getUniqueList(super.getSearchResultsUnbounded(fieldValues),
                fieldValues);
        Long matchingResultsCount = new Long(activeCommittees.size());
        // TODO should the Question.class be replaced by a committee class below?
        Integer searchResultsLimit = LookupUtils.getSearchResultsLimit(Question.class);

        if ((matchingResultsCount == null) || (matchingResultsCount.intValue() <= searchResultsLimit.intValue())) {
            return new CollectionIncomplete(activeCommittees, new Long(0));
        } else {
            return new CollectionIncomplete(trimResult(activeCommittees, searchResultsLimit), matchingResultsCount);
        }
    }

    protected abstract String getCommitteeTypeCodeHook();

    /**
     * Specifically, for drop down.
     * @see org.kuali.core.lookup.AbstractLookupableHelperServiceImpl#getRows()
     */
    @Override
    public List<Row> getRows() {
        List<Row> rows = super.getRows();
        for (Row row : rows) {
            for (Field field : row.getFields()) {
                if (field.getPropertyName().equals("committeeResearchAreas.researchAreaCode")) {
                    super.updateLookupField(field, RESEARCH_AREA_CODE, "org.kuali.kra.bo.ResearchArea");
                } else if (field.getPropertyName().equals("committeeMemberships.personName")) {
                    super.updateLookupField(field, PERSON_NAME,
                            getCommitteeMembershipFullyQualifiedClassNameHook());
                    // TODO *********commented the code below during IACUC refactoring********* 
                    //                    super.updateLookupField(field,PERSON_NAME,"org.kuali.kra.common.committee.bo.CommitteeMembershipBase");
                }
            }
        }
        return rows;
    }

    protected abstract String getCommitteeMembershipFullyQualifiedClassNameHook();

    /*
     * remove duplicates and get only the one with the highest sequence number from the search results
     */
    @SuppressWarnings("unchecked")
    protected List<? extends BusinessObject> getUniqueList(List<? extends BusinessObject> searchResults,
            Map<String, String> fieldValues) {

        List<CMT> uniqueResults = new ArrayList<CMT>();
        List<String> committeeIds = new ArrayList<String>();
        ((List<CMT>) searchResults).addAll(getUnapprovedCommittees(fieldValues));
        if (CollectionUtils.isNotEmpty(searchResults)) {
            Collections.sort((List<CMT>) searchResults, Collections.reverseOrder());
            for (CMT committee : (List<CMT>) searchResults) {
                if (!committeeIds.contains(committee.getCommitteeId())) {
                    committee.getCommitteeChair();
                    uniqueResults.add(committee);
                    committeeIds.add(committee.getCommitteeId());
                }
            }
        }
        return uniqueResults;
    }

    protected abstract String getHtmlAction();

    // TODO *********commented the code below during IACUC refactoring*********     
    //    protected String getHtmlAction() {
    //        return "commonCommitteeCommittee.do";
    //    }

    protected abstract String getDocumentTypeName();

    // TODO *********commented the code below during IACUC refactoring********* 
    //    protected String getDocumentTypeName() {
    //        return "CommonCommitteeDocument";
    //    }

    protected String getKeyFieldName() {
        return "committeeId";
    }

    @Override
    public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
        List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
        String editCommitteeDocId = getEditedCommitteeDocId((CMT) businessObject);
        boolean isUnappprovedCommittee = false;
        if (KewApiConstants.ROUTE_HEADER_SAVED_CD
                .equals((((CMT) businessObject).getCommitteeDocument().getDocStatusCode()))
                && ((CMT) businessObject).getSequenceNumber() == 1) {
            isUnappprovedCommittee = true;
            editCommitteeDocId = ((CMT) businessObject).getCommitteeDocument().getDocumentNumber();
        }
        //        if (getKraAuthorizationService().hasPermission(getUserIdentifier(), (CMT) businessObject,
        //                PermissionConstants.MODIFY_IACUC_COMMITTEE)) {
        if (getKraAuthorizationService().hasPermission(getUserIdentifier(), (CMT) businessObject,
                getModifyCommitteePermissionNameHook())) {
            htmlDataList = super.getCustomActionUrls(businessObject, pkNames);
            if (StringUtils.isNotBlank(editCommitteeDocId)) {
                AnchorHtmlData htmlData = (AnchorHtmlData) htmlDataList.get(0);
                CD document = ((CMT) businessObject).getCommitteeDocument();
                String workflowUrl = getKualiConfigurationService()
                        .getPropertyValueAsString(KRADConstants.WORKFLOW_URL_KEY);
                htmlData.setHref(String.format(DOCHANDLER_LINK, workflowUrl, editCommitteeDocId));
                htmlData.setDisplayText("resume edit");
            }
        }
        //        if (!isUnappprovedCommittee && getKraAuthorizationService().hasPermission(getUserIdentifier(), (CommonCommittee) businessObject,
        //                PermissionConstants.VIEW_IACUC_COMMITTEE)) {
        if (!isUnappprovedCommittee && getKraAuthorizationService().hasPermission(getUserIdentifier(),
                (CMT) businessObject, getViewCommitteePermissionNameHook())) {
            AnchorHtmlData htmlData = getViewLink(((CMT) businessObject).getCommitteeDocument());
            htmlData.setDisplayText("view active");
            htmlDataList.add(htmlData);
        }
        return htmlDataList;
    }

    protected abstract String getViewCommitteePermissionNameHook();

    protected abstract String getModifyCommitteePermissionNameHook();

    /*
     * get the document number of the committee that is being edited.
     */
    protected String getEditedCommitteeDocId(CMT committee) {
        String docId = null;
        List<CD> documents = getCommitteeDocuments(committee.getCommitteeId());
        if (CollectionUtils.isNotEmpty(documents)) {
            docId = documents.get(0).getDocumentNumber();
        }
        return docId;
    }

    /*
     * get saved committee documents of the committeeId specified.
     * should only have one if exists
     */
    protected List<CD> getCommitteeDocuments(String committeeId) {
        Map<String, String> fieldValues = new HashMap<String, String>();
        fieldValues.put("committeeId", committeeId);
        // TODO *********commented the code below during IACUC refactoring*********         
        //        List<CommonCommitteeDocument> documents = (List<CommonCommitteeDocument>) getBusinessObjectService()
        //                .findMatching(CommonCommitteeDocument.class, fieldValues);
        List<CD> documents = (List<CD>) getBusinessObjectService().findMatching(getCommitteeDocumentBOClassHook(),
                fieldValues);
        List<CD> result = new ArrayList<CD>();
        for (CD commDoc : documents) {
            if (KewApiConstants.ROUTE_HEADER_SAVED_CD.equals(commDoc.getDocStatusCode())) {
                result.add(commDoc);
            }
        }
        return result;

    }

    protected abstract Class<CD> getCommitteeDocumentBOClassHook();

    /*
     * Get the committee that is saved, but not approved yet.  basically this is sequence = 1
     */
    protected List<CMT> getUnapprovedCommittees(Map<String, String> criterias) {

        Map<String, String> fieldValues = new HashMap<String, String>();
        fieldValues.put("docStatusCode", "S");

        // TODO *********commented the code below during IACUC refactoring*********         
        //        List<CommonCommitteeDocument> documents = (List<CommonCommitteeDocument>) getBusinessObjectService().findMatching(
        //                CommonCommitteeDocument.class, fieldValues);

        List<CD> documents = (List<CD>) getBusinessObjectService().findMatching(getCommitteeDocumentBOClassHook(),
                fieldValues);
        List<CMT> result = new ArrayList<CMT>();
        List<String> committeeIds = getCommitteeIds();
        for (CD commDoc : documents) {
            if (!committeeIds.contains(commDoc.getCommitteeId())) {
                try {
                    CD workflowCommitteeDoc = (CD) KraServiceLocator.getService(DocumentService.class)
                            .getByDocumentHeaderId(commDoc.getDocumentNumber());
                    // Get XML of workflow document
                    String content = KraServiceLocator.getService(RouteHeaderService.class)
                            .getContent(
                                    workflowCommitteeDoc.getDocumentHeader().getWorkflowDocument().getDocumentId())
                            .getDocumentContent();

                    // Create committee from XML and add to the document

                    commDoc.getCommitteeList().add(populateCommitteeFromXmlDocumentContents(content));
                    if (isCriteriaMatched(commDoc.getCommittee(), criterias)) {
                        commDoc.getCommittee().setCommitteeDocument(commDoc);
                        result.add(commDoc.getCommittee());
                    }
                } catch (Exception e) {
                    LOG.info("CommitteeBase Doc " + commDoc.getDocumentNumber() + " parsing error");
                }
            }
        }
        return result;

    }

    /*
     * This is to check the committee, which is not approved yet, matches the search criteria specified.
     * This is a new committee and not persisted to DB yet.  So, this tedious criteria check is needed.
     */
    protected boolean isCriteriaMatched(CMT committee, Map<String, String> criterias) {
        boolean isMatch = isMatching(criterias.get("committeeId"), committee.getCommitteeId())
                && isMatching(criterias.get("committeeName"), committee.getCommitteeName())
                && isMatching(criterias.get("homeUnitNumber"), committee.getHomeUnitNumber())
                && isMatching(criterias.get("committeeDescription"), committee.getCommitteeDescription())
                && isMatchingCode(criterias.get("committeeTypeCode"), committee.getCommitteeTypeCode())
                && isMatchingCode(criterias.get("reviewTypeCode"), committee.getReviewTypeCode());

        // membership check
        if (isMatch && (StringUtils.isNotBlank(criterias.get("committeeMemberships.personName")) || StringUtils
                .isNotBlank(criterias.get("committeeMemberships.membershipRoles.membershipRoleCode")))) {
            if (CollectionUtils.isNotEmpty(committee.getCommitteeMemberships())) {
                if (StringUtils.isNotBlank(criterias.get("committeeMemberships.personName"))) {
                    isMatch = isMemberNameMatch(criterias.get("committeeMemberships.personName"),
                            committee.getCommitteeMemberships());

                }
                if (isMatch && StringUtils
                        .isNotBlank(criterias.get("committeeMemberships.membershipRoles.membershipRoleCode"))) {
                    isMatch = isMemberRoleMatch(
                            criterias.get("committeeMemberships.membershipRoles.membershipRoleCode"),
                            committee.getCommitteeMemberships());
                }
            } else {
                isMatch = false;
            }
        }

        // researchareacode check
        if (isMatch && (StringUtils.isNotBlank(criterias.get("committeeResearchAreas.researchAreaCode")))) {
            if (CollectionUtils.isNotEmpty(committee.getCommitteeResearchAreas())) {
                isMatch = isAreaResearchMatch(criterias.get("committeeResearchAreas.researchAreaCode"),
                        committee.getCommitteeResearchAreas());
            } else {
                isMatch = false;
            }
        }
        if (isMatch) {
            committee.refreshReferenceObject("homeUnit");
        }
        return isMatch;
    }

    /*
     * check if any member name matched the criteria
     */
    protected boolean isMemberNameMatch(String matchmember, List<CommitteeMembershipBase> members) {
        boolean isMatch = false;
        for (CommitteeMembershipBase member : members) {
            if (isMatching(matchmember, member.getPersonName())) {
                isMatch = true;
                break;
            }
        }
        return isMatch;
    }

    /*
     * check if any member role code matched the selected role code
     */
    protected boolean isMemberRoleMatch(String matchRoleCode, List<CommitteeMembershipBase> members) {
        boolean isMatch = false;
        for (CommitteeMembershipBase member : members) {
            for (CommitteeMembershipRole role : member.getMembershipRoles()) {
                if (isMatchingCode(matchRoleCode, role.getMembershipRoleCode())) {
                    isMatch = true;
                    break;
                }
            }
        }
        return isMatch;
    }

    /*
     * check if any committee research area code matched search criteria
     */
    protected boolean isAreaResearchMatch(String matchArea, List<CommitteeResearchAreaBase> researchAreas) {
        boolean isMatch = false;
        for (CommitteeResearchAreaBase researchArea : researchAreas) {
            if (isMatching(matchArea, researchArea.getResearchAreaCode())) {
                isMatch = true;
                break;
            }
        }
        return isMatch;
    }

    /*
     * using reg expression to check if pattern matched
     */
    protected boolean isMatching(String patternString, String value) {
        boolean isMatch = false;
        if (StringUtils.isBlank(patternString)) {
            isMatch = true;
        } else {
            patternString = patternString.replaceAll("\\?", "\\\\?");
            patternString = patternString.replaceAll("\\.", "\\\\.");
            if (patternString.indexOf("*") == 0) {
                patternString = patternString.replaceFirst("\\*", "^*");
            }
            if (!patternString.endsWith("*")) {
                patternString = patternString + "$";
            }
            Pattern p = Pattern.compile(patternString.toUpperCase());
            Matcher m = p.matcher(value.toUpperCase());
            isMatch = m.find();
        }
        return isMatch;

    }

    /*
     * check if the selected code matched
     */
    protected boolean isMatchingCode(String selectedCode, String value) {
        boolean isMatch = false;
        if (StringUtils.isBlank(selectedCode)) {
            isMatch = true;
        } else {
            isMatch = selectedCode.equals(value);
        }
        return isMatch;

    }

    /*
     * Create a CommitteeBase object and populate it from the xml.
     */
    protected CMT populateCommitteeFromXmlDocumentContents(String xmlDocumentContents) {
        CMT committee = null;
        if (!StringUtils.isEmpty(xmlDocumentContents)) {

            // TODO *********commented the code below during IACUC refactoring*********             
            //                committee = (CommonCommittee) getBusinessObjectFromXML(xmlDocumentContents, CommonCommittee.class.getName());

            committee = (CMT) getBusinessObjectFromXML(xmlDocumentContents, getCommitteeBOClassHook().getName());
        }
        return committee;
    }

    protected abstract Class<CMT> getCommitteeBOClassHook();

    /*
     * Retrieves substring of document contents from maintainable tag name. Then use xml service to translate xml into a business
     * object.
     */
    protected PersistableBusinessObject getBusinessObjectFromXML(String xmlDocumentContents, String objectTagName) {
        String objXml = StringUtils.substringBetween(xmlDocumentContents, "<" + objectTagName + ">",
                "</" + objectTagName + ">");
        objXml = "<" + objectTagName + ">" + objXml + "</" + objectTagName + ">";
        if (objXml.contains("itemDesctiption")) {
            objXml = objXml.replaceAll("itemDesctiption", "itemDescription");
        }
        PersistableBusinessObject businessObject = (PersistableBusinessObject) KRADServiceLocator
                .getXmlObjectSerializerService().fromXml(objXml);
        return businessObject;
    }

    protected KraAuthorizationService getKraAuthorizationService() {
        return KraServiceLocator.getService(KraAuthorizationService.class);
    }

    /*
     * get the existing approved committee id
     */
    protected List<String> getCommitteeIds() {
        List<CMT> committees = (List<CMT>) getBusinessObjectService().findAll(getCommitteeBOClassHook());
        List<String> result = new ArrayList<String>();
        for (CMT committee : committees) {
            if (!result.contains(committee.getCommitteeId())) {
                result.add(committee.getCommitteeId());
            }
        }
        return result;
    }

    protected String getUserIdentifier() {
        return GlobalVariables.getUserSession().getPrincipalId();
    }

    /**
     * This method trims the search result.
     * @param result, the result set to be trimmed
     * @param trimSize, the maximum size of the trimmed result set
     * @return the trimmed result set
     */
    protected List<CMT> trimResult(List<CMT> result, Integer trimSize) {
        List<CMT> trimedResult = new ArrayList<CMT>();
        for (CMT committee : result) {
            if (trimedResult.size() < trimSize) {
                trimedResult.add(committee);
            }
        }
        return trimedResult;
    }

}