org.kuali.rice.kim.lookup.RoleMemberLookupableHelperServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.rice.kim.lookup.RoleMemberLookupableHelperServiceImpl.java

Source

/**
 * Copyright 2005-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.rice.kim.lookup;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.kuali.rice.core.api.criteria.QueryByCriteria;
import org.kuali.rice.kim.api.KimConstants;
import org.kuali.rice.kim.api.group.Group;
import org.kuali.rice.kim.api.group.GroupQueryResults;
import org.kuali.rice.kim.api.identity.entity.Entity;
import org.kuali.rice.kim.api.identity.entity.EntityQueryResults;
import org.kuali.rice.kim.api.identity.principal.Principal;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;
import org.kuali.rice.kim.impl.role.RoleBo;
import org.kuali.rice.kim.impl.role.RoleMemberBo;
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.lookup.CollectionIncomplete;
import org.kuali.rice.krad.util.KRADPropertyConstants;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static org.kuali.rice.core.api.criteria.PredicateFactory.and;
import static org.kuali.rice.core.api.criteria.PredicateFactory.like;

public abstract class RoleMemberLookupableHelperServiceImpl extends KimLookupableHelperServiceImpl {

    protected static final String DETAIL_CRITERIA = "detailCriteria";
    protected static final String WILDCARD = "*";
    protected static final String TEMPLATE_NAMESPACE_CODE = "template."
            + KimConstants.UniqueKeyConstants.NAMESPACE_CODE;
    protected static final String TEMPLATE_NAME = "template.name";
    protected static final String TEMPLATE_ID = "template.id";
    protected static final String NAMESPACE_CODE = KimConstants.UniqueKeyConstants.NAMESPACE_CODE;
    protected static final String NAME = "name";
    protected static final String GROUP_NAME = KimConstants.UniqueKeyConstants.GROUP_NAME;
    protected static final String ASSIGNED_TO_PRINCIPAL_NAME = "assignedToPrincipal.principalName";
    protected static final String ASSIGNED_TO_GROUP_NAMESPACE_CODE = "assignedToGroupNamespaceForLookup";
    protected static final String ASSIGNED_TO_GROUP_NAME = "assignedToGroup."
            + KimConstants.UniqueKeyConstants.GROUP_NAME;
    protected static final String ASSIGNED_TO_NAMESPACE_FOR_LOOKUP = "assignedToRoleNamespaceForLookup";
    protected static final String ASSIGNED_TO_ROLE_NAME = "assignedToRole."
            + KimConstants.UniqueKeyConstants.ROLE_NAME;
    protected static final String ATTRIBUTE_NAME = "attributeName";
    protected static final String ATTRIBUTE_VALUE = "attributeValue";
    protected static final String ASSIGNED_TO_ROLE_NAMESPACE_CODE = KimConstants.UniqueKeyConstants.NAMESPACE_CODE;
    protected static final String ASSIGNED_TO_ROLE_ROLE_NAME = KimConstants.UniqueKeyConstants.ROLE_NAME;
    protected static final String ASSIGNED_TO_ROLE_MEMBER_ID = "members.memberId";
    protected static final String DETAIL_OBJECTS_ATTRIBUTE_VALUE = "attributeDetails.attributeValue";
    protected static final String DETAIL_OBJECTS_ATTRIBUTE_NAME = "attributeDetails.kimAttribute.attributeName";

    @Override
    protected List<? extends BusinessObject> getSearchResultsHelper(Map<String, String> fieldValues,
            boolean unbounded) {
        Map<String, String> searchCriteria = buildRoleSearchCriteria(fieldValues);
        if (searchCriteria == null) {
            return new ArrayList<BusinessObject>();
        }
        return getMemberSearchResults(fieldValues, unbounded);
    }

    protected abstract List<? extends BusinessObject> getMemberSearchResults(Map<String, String> searchCriteria,
            boolean unbounded);

    protected Map<String, String> buildSearchCriteria(Map<String, String> fieldValues) {
        String templateNamespaceCode = fieldValues.get(TEMPLATE_NAMESPACE_CODE);
        String templateName = fieldValues.get(TEMPLATE_NAME);
        String templateId = fieldValues.get(TEMPLATE_ID);
        String namespaceCode = fieldValues.get(NAMESPACE_CODE);
        String name = fieldValues.get(NAME);
        String attributeDetailValue = fieldValues.get(ATTRIBUTE_VALUE);
        String attributeDetailName = fieldValues.get(ATTRIBUTE_NAME);
        String detailCriteria = fieldValues.get(DETAIL_CRITERIA);
        String active = fieldValues.get(KRADPropertyConstants.ACTIVE);

        Map<String, String> searchCriteria = new HashMap<String, String>();
        if (StringUtils.isNotEmpty(templateNamespaceCode)) {
            searchCriteria.put(TEMPLATE_NAMESPACE_CODE, WILDCARD + templateNamespaceCode + WILDCARD);
        }
        if (StringUtils.isNotEmpty(templateName)) {
            searchCriteria.put(TEMPLATE_NAME, WILDCARD + templateName + WILDCARD);
        }
        if (StringUtils.isNotEmpty(templateId)) {
            searchCriteria.put(TEMPLATE_ID, templateId);
        }
        if (StringUtils.isNotEmpty(namespaceCode)) {
            searchCriteria.put(NAMESPACE_CODE, WILDCARD + namespaceCode + WILDCARD);
        }
        if (StringUtils.isNotEmpty(name)) {
            searchCriteria.put(NAME, WILDCARD + name + WILDCARD);
        }
        if (StringUtils.isNotEmpty(attributeDetailValue)) {
            searchCriteria.put(DETAIL_OBJECTS_ATTRIBUTE_VALUE, WILDCARD + attributeDetailValue + WILDCARD);
        }
        if (StringUtils.isNotEmpty(attributeDetailName)) {
            searchCriteria.put(DETAIL_OBJECTS_ATTRIBUTE_NAME, WILDCARD + attributeDetailName + WILDCARD);
        }
        if (StringUtils.isNotBlank(detailCriteria)) {
            searchCriteria.put(DETAIL_CRITERIA, detailCriteria);
        }
        if (StringUtils.isNotBlank(active)) {
            searchCriteria.put(KRADPropertyConstants.ACTIVE, active);
        }

        return searchCriteria;
    }

    protected String getQueryString(String parameter) {
        if (StringUtils.isEmpty(parameter)) {
            return WILDCARD;
        } else {
            return WILDCARD + parameter + WILDCARD;
        }
    }

    @SuppressWarnings({ "unchecked" })
    protected Map<String, String> buildRoleSearchCriteria(Map<String, String> fieldValues) {
        String assignedToPrincipalName = fieldValues.get(ASSIGNED_TO_PRINCIPAL_NAME);
        Map<String, String> searchCriteria;
        List<Principal> principals = new ArrayList<Principal>();

        if (StringUtils.isNotEmpty(assignedToPrincipalName)) { // if a principal name is specified in the search
            // KULRICE-9153: Analyze IU patch for preventing role member lookup from causing out of memory exceptions
            // Changing to exact match on principal name to prevent blowing up Rice by loading every user into memory
            if (assignedToPrincipalName.contains("*")) {
                return null; // bail out, wild cards are not allowed since
                             // IdentityServiceImpl.getPrincipalByPrincipalName has weird behavior around wildcards
            }

            Principal principal = KimApiServiceLocator.getIdentityService()
                    .getPrincipalByPrincipalName(assignedToPrincipalName);

            if (principal == null) {
                return null; // bail out, if no principal matched and a principal name was supplied, then there will be
                             // no valid matching roles.
            }

            principals.add(principal);
        }

        String assignedToGroupNamespaceCode = fieldValues.get(ASSIGNED_TO_GROUP_NAMESPACE_CODE);
        String assignedToGroupName = fieldValues.get(ASSIGNED_TO_GROUP_NAME);
        List<Group> groups = null;
        if (StringUtils.isNotEmpty(assignedToGroupNamespaceCode) && StringUtils.isEmpty(assignedToGroupName)
                || StringUtils.isEmpty(assignedToGroupNamespaceCode) && StringUtils.isNotEmpty(assignedToGroupName)
                || StringUtils.isNotEmpty(assignedToGroupNamespaceCode)
                        && StringUtils.isNotEmpty(assignedToGroupName)) {
            QueryByCriteria.Builder builder = QueryByCriteria.Builder.create();
            builder.setPredicates(and(like(NAMESPACE_CODE, getQueryString(assignedToGroupNamespaceCode)),
                    like(GROUP_NAME, getQueryString(assignedToGroupName))));
            GroupQueryResults qr = KimApiServiceLocator.getGroupService().findGroups(builder.build());
            if (qr.getResults() == null || qr.getResults().isEmpty()) {
                return null;
            }
            groups = qr.getResults();
        }

        String assignedToRoleNamespaceCode = fieldValues.get(ASSIGNED_TO_NAMESPACE_FOR_LOOKUP);
        String assignedToRoleName = fieldValues.get(ASSIGNED_TO_ROLE_NAME);

        searchCriteria = new HashMap<String, String>();
        if (StringUtils.isNotEmpty(assignedToRoleNamespaceCode)) {
            searchCriteria.put(ASSIGNED_TO_ROLE_NAMESPACE_CODE, WILDCARD + assignedToRoleNamespaceCode + WILDCARD);
        }
        if (StringUtils.isNotEmpty(assignedToRoleName)) {
            searchCriteria.put(ASSIGNED_TO_ROLE_ROLE_NAME, WILDCARD + assignedToRoleName + WILDCARD);
        }

        StringBuffer memberQueryString = null;
        if (!principals.isEmpty()) {
            memberQueryString = new StringBuffer();
            for (Principal principal : principals) {
                memberQueryString.append(principal.getPrincipalId() + KimConstants.KimUIConstants.OR_OPERATOR);
            }
            if (memberQueryString.toString().endsWith(KimConstants.KimUIConstants.OR_OPERATOR)) {
                memberQueryString.delete(
                        memberQueryString.length() - KimConstants.KimUIConstants.OR_OPERATOR.length(),
                        memberQueryString.length());
            }
        }
        if (groups != null) {
            if (memberQueryString == null) {
                memberQueryString = new StringBuffer();
            } else if (StringUtils.isNotEmpty(memberQueryString.toString())) {
                memberQueryString.append(KimConstants.KimUIConstants.OR_OPERATOR);
            }
            for (Group group : groups) {
                memberQueryString.append(group.getId() + KimConstants.KimUIConstants.OR_OPERATOR);
            }
            if (memberQueryString.toString().endsWith(KimConstants.KimUIConstants.OR_OPERATOR)) {
                memberQueryString.delete(
                        memberQueryString.length() - KimConstants.KimUIConstants.OR_OPERATOR.length(),
                        memberQueryString.length());
            }
            searchCriteria.put(ASSIGNED_TO_ROLE_MEMBER_ID, memberQueryString.toString());
        }
        if (memberQueryString != null && StringUtils.isNotEmpty(memberQueryString.toString())) {
            searchCriteria.put(ASSIGNED_TO_ROLE_MEMBER_ID, memberQueryString.toString());
        }

        return searchCriteria;
    }

    /** Checks whether the 2nd map is a subset of the first. */
    protected boolean isMapSubset(Map<String, String> mainMap, Map<String, String> subsetMap) {
        for (Map.Entry<String, String> keyValue : subsetMap.entrySet()) {
            if (!mainMap.containsKey(keyValue.getKey())
                    || !StringUtils.equals(mainMap.get(keyValue.getKey()), keyValue.getValue())) {
                //            if ( LOG.isDebugEnabled() ) {
                //               LOG.debug( "Maps did not match:\n" + mainMap + "\n" + subsetMap );
                //            }
                return false;
            }
        }
        //      if ( LOG.isDebugEnabled() ) {
        //         LOG.debug( "Maps matched:\n" + mainMap + "\n" + subsetMap );
        //      }
        return true;
    }

    /** Converts a special criteria string that is in the form key=value,key2=value2 into a map */
    protected Map<String, String> parseDetailCriteria(String detailCritiera) {
        if (StringUtils.isBlank(detailCritiera)) {
            return new HashMap<String, String>(0);
        }
        String[] keyValuePairs = StringUtils.split(detailCritiera, ',');
        if (keyValuePairs == null || keyValuePairs.length == 0) {
            return new HashMap<String, String>(0);
        }
        Map<String, String> parsedDetails = new HashMap<String, String>(keyValuePairs.length);
        for (String keyValueStr : keyValuePairs) {
            String[] keyValue = StringUtils.split(keyValueStr, '=');
            if (keyValue.length >= 2) {
                parsedDetails.put(keyValue[0], keyValue[1]);
            }
        }
        return parsedDetails;
    }

    @Override
    public List<Row> getRows() {
        List<Row> rows = super.getRows();
        Iterator<Row> i = rows.iterator();
        while (i.hasNext()) {
            Row row = i.next();
            int numFieldsRemoved = 0;
            boolean rowIsBlank = true;
            for (Iterator<Field> fieldIter = row.getFields().iterator(); fieldIter.hasNext();) {
                Field field = fieldIter.next();
                String propertyName = field.getPropertyName();
                if (propertyName.equals(DETAIL_CRITERIA)) {
                    Object val = getParameters().get(propertyName);
                    String propVal = null;
                    if (val != null) {
                        propVal = (val instanceof String) ? (String) val : ((String[]) val)[0];
                    }
                    if (StringUtils.isBlank(propVal)) {
                        fieldIter.remove();
                        numFieldsRemoved++;
                    } else {
                        field.setReadOnly(true);
                        rowIsBlank = false;
                        // leaving this in would prevent the "clear" button from resetting this value
                        //                  field.setDefaultValue( propVal );
                    }
                } else if (!Field.BLANK_SPACE.equals(field.getFieldType())) {
                    rowIsBlank = false;
                }
            }
            // Check if any fields were removed from the row.
            if (numFieldsRemoved > 0) {
                // If fields were removed, check whether or not the remainder of the row is empty or only has blank space fields.
                if (rowIsBlank) {
                    // If so, then remove the row entirely.
                    i.remove();
                } else {
                    // Otherwise, add one blank space for each field that was removed, using a technique similar to FieldUtils.createBlankSpace.
                    // It is safe to just add blank spaces as needed, since the removable field is the last of the visible ones in the list (or
                    // at least for the Permission and Responsibility lookups).
                    while (numFieldsRemoved > 0) {
                        Field blankSpace = new Field();
                        blankSpace.setFieldType(Field.BLANK_SPACE);
                        blankSpace.setPropertyName(Field.BLANK_SPACE);
                        row.getFields().add(blankSpace);
                        numFieldsRemoved--;
                    }
                }
            }
        }
        return rows;
    }

    protected Long getActualSizeIfTruncated(List result) {
        Long actualSizeIfTruncated = new Long(0);
        if (result instanceof CollectionIncomplete) {
            actualSizeIfTruncated = ((CollectionIncomplete) result).getActualSizeIfTruncated();
        }
        return actualSizeIfTruncated;
    }

    @SuppressWarnings("unchecked")
    protected List<RoleBo> searchRoles(Map<String, String> roleSearchCriteria, boolean unbounded) {
        List<RoleBo> roles = (List<RoleBo>) getLookupService().findCollectionBySearchHelper(RoleBo.class,
                roleSearchCriteria, unbounded);
        String membersCrt = roleSearchCriteria.get("members.memberId");
        List<RoleBo> roles2Remove = new ArrayList<RoleBo>();
        if (StringUtils.isNotBlank(membersCrt)) {
            List<String> memberSearchIds = new ArrayList<String>();
            List<String> memberIds = new ArrayList<String>();
            if (membersCrt.contains(KimConstants.KimUIConstants.OR_OPERATOR)) {
                memberSearchIds = new ArrayList<String>(Arrays.asList(membersCrt.split("\\|")));
            } else {
                memberSearchIds.add(membersCrt);
            }
            for (RoleBo roleBo : roles) {
                List<RoleMemberBo> roleMembers = roleBo.getMembers();
                memberIds.clear();
                CollectionUtils.filter(roleMembers, new Predicate() {
                    public boolean evaluate(Object object) {
                        RoleMemberBo member = (RoleMemberBo) object;
                        // keep active member
                        return member.isActive(new Timestamp(System.currentTimeMillis()));
                    }
                });

                if (roleMembers != null && !roleMembers.isEmpty()) {
                    for (RoleMemberBo memberImpl : roleMembers) {
                        memberIds.add(memberImpl.getMemberId());
                    }
                    if (((List<String>) CollectionUtils.intersection(memberSearchIds, memberIds)).isEmpty()) {
                        roles2Remove.add(roleBo);
                    }
                } else {
                    roles2Remove.add(roleBo);
                }
            }
        }
        if (!roles2Remove.isEmpty()) {
            roles.removeAll(roles2Remove);
        }
        return roles;
    }

}