001/**
002 * Copyright 2005-2017 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kim.lookup;
017
018import static org.kuali.rice.core.api.criteria.PredicateFactory.and;
019import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
020import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
021import static org.kuali.rice.core.api.criteria.PredicateFactory.like;
022import static org.kuali.rice.core.api.criteria.PredicateFactory.likeIgnoreCase;
023import static org.kuali.rice.core.api.criteria.PredicateFactory.or;
024
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.Collections;
028import java.util.Comparator;
029import java.util.HashMap;
030import java.util.HashSet;
031import java.util.List;
032import java.util.Map;
033import java.util.Map.Entry;
034import java.util.Properties;
035import java.util.Set;
036
037import org.apache.commons.collections.CollectionUtils;
038import org.apache.commons.lang.StringUtils;
039import org.joda.time.DateTime;
040import org.kuali.rice.core.api.CoreApiServiceLocator;
041import org.kuali.rice.core.api.criteria.Predicate;
042import org.kuali.rice.core.api.criteria.QueryByCriteria;
043import org.kuali.rice.core.api.membership.MemberType;
044import org.kuali.rice.core.api.util.ConcreteKeyValue;
045import org.kuali.rice.core.api.util.KeyValue;
046import org.kuali.rice.core.api.util.Truth;
047import org.kuali.rice.kew.api.KewApiConstants;
048import org.kuali.rice.kim.api.KimConstants;
049import org.kuali.rice.kim.api.identity.principal.Principal;
050import org.kuali.rice.kim.api.permission.Permission;
051import org.kuali.rice.kim.api.responsibility.Responsibility;
052import org.kuali.rice.kim.api.responsibility.ResponsibilityQueryResults;
053import org.kuali.rice.kim.api.role.Role;
054import org.kuali.rice.kim.api.role.RoleMember;
055import org.kuali.rice.kim.api.services.KimApiServiceLocator;
056import org.kuali.rice.kim.api.type.KimAttributeField;
057import org.kuali.rice.kim.api.type.KimType;
058import org.kuali.rice.kim.impl.KIMPropertyConstants;
059import org.kuali.rice.kim.impl.role.RoleBo;
060import org.kuali.rice.kim.impl.type.KimTypeBo;
061import org.kuali.rice.kim.impl.type.KimTypeLookupableHelperServiceImpl;
062import org.kuali.rice.kim.util.KimCommonUtilsInternal;
063import org.kuali.rice.kim.web.struts.form.IdentityManagementRoleDocumentForm;
064import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
065import org.kuali.rice.kns.lookup.HtmlData;
066import org.kuali.rice.kns.web.struts.form.KualiForm;
067import org.kuali.rice.kns.web.struts.form.LookupForm;
068import org.kuali.rice.kns.web.ui.Field;
069import org.kuali.rice.kns.web.ui.Row;
070import org.kuali.rice.krad.bo.BusinessObject;
071import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
072import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
073import org.kuali.rice.krad.service.ModuleService;
074import org.kuali.rice.krad.util.BeanPropertyComparator;
075import org.kuali.rice.krad.util.GlobalVariables;
076import org.kuali.rice.krad.util.KRADConstants;
077import org.kuali.rice.krad.util.UrlFactory;
078
079/**
080 * This is a description of what this class does - shyu don't forget to fill this in.
081 *
082 * @author Kuali Rice Team (rice.collab@kuali.org)
083 *
084 */
085public class RoleLookupableHelperServiceImpl extends KimLookupableHelperServiceImpl {
086    private static final long serialVersionUID = 1L;
087
088    protected static final String GROUP_CRITERIA = "group";
089    protected static final String RESPONSIBILITY_CRITERIA = "resp";
090    protected static final String PERMISSION_CRITERIA = "perm";
091    protected static final String ROLE_MEMBER_ATTRIBUTE_CRITERIA = "attr";
092    protected static final String OTHER_CRITERIA = "lookupNames";
093
094    protected static final String LOOKUP_PARM_PERMISSION_TEMPLATE_NAMESPACE = "permTmplNamespaceCode";
095    protected static final String LOOKUP_PARM_PERMISSION_TEMPLATE_NAME = "permTmplName";
096    protected static final String LOOKUP_PARM_PERMISSION_NAMESPACE = "permNamespaceCode";
097    protected static final String LOOKUP_PARM_PERMISSION_NAME = "permName";
098
099    protected static final String LOOKUP_PARM_RESP_TEMPLATE_NAMESPACE = "respTmplNamespaceCode";
100    protected static final String LOOKUP_PARM_RESP_TEMPLATE_NAME = "respTmplName";
101    protected static final String LOOKUP_PARM_RESP_NAMESPACE = "respNamespaceCode";
102    protected static final String LOOKUP_PARM_RESP_NAME = "respName";
103
104        // need this so kimtypeId value can be retained in 'rows'
105        // 1st pass populate the grprows
106        // 2nd pass for jsp, no populate, so return the existing one.
107        private List<Row> roleRows = new ArrayList<Row>();
108        private List<Row> attrRows = new ArrayList<Row>();
109        private String typeId;
110        private List<KimAttributeField> attrDefinitions;
111
112        /**
113         * This overridden method ...
114         *
115         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#allowsMaintenanceNewOrCopyAction()
116         */
117        @Override
118        public boolean allowsMaintenanceNewOrCopyAction() {
119        Map<String, String> permissionDetails = new HashMap<String, String>();
120        permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME,KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_TYPE_NAME);
121        permissionDetails.put(KRADConstants.MAINTENANCE_ACTN, KRADConstants.MAINTENANCE_NEW_ACTION);
122
123        return !KimApiServiceLocator.getPermissionService().isPermissionDefinedByTemplate(KRADConstants.KNS_NAMESPACE,
124                KimConstants.PermissionTemplateNames.CREATE_MAINTAIN_RECORDS, permissionDetails)
125                || KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(GlobalVariables.getUserSession().getPrincipalId(), KRADConstants.KNS_NAMESPACE,
126                KimConstants.PermissionTemplateNames.CREATE_MAINTAIN_RECORDS, permissionDetails,
127                new HashMap<String, String>());
128        }
129
130        /**
131         * This overridden method ...
132         *
133         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#allowsMaintenanceEditAction(org.kuali.rice.krad.bo.BusinessObject)
134         */
135        @Override
136        protected boolean allowsMaintenanceEditAction(BusinessObject businessObject) {
137        Map<String, String> permissionDetails = new HashMap<String, String>(2);
138        permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME,KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_TYPE_NAME);
139        permissionDetails.put(KRADConstants.MAINTENANCE_ACTN, KRADConstants.MAINTENANCE_EDIT_ACTION);
140
141        return !KimApiServiceLocator.getPermissionService().isPermissionDefinedByTemplate(KRADConstants.KNS_NAMESPACE,
142                KimConstants.PermissionTemplateNames.CREATE_MAINTAIN_RECORDS, permissionDetails)
143                || KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(GlobalVariables.getUserSession().getPrincipalId(), KRADConstants.KNS_NAMESPACE,
144                KimConstants.PermissionTemplateNames.CREATE_MAINTAIN_RECORDS, permissionDetails,
145                new HashMap<String, String>());
146        }
147
148    @Override
149    public List<HtmlData> getCustomActionUrls(BusinessObject bo, List pkNames) {
150        RoleBo roleBo = (RoleBo) bo;
151        List<HtmlData> anchorHtmlDataList = new ArrayList<HtmlData>();
152        if(allowsNewOrCopyAction(KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_TYPE_NAME)){
153                anchorHtmlDataList.add(getEditRoleUrl(roleBo));
154        }
155        return anchorHtmlDataList;
156    }
157
158    protected HtmlData getEditRoleUrl(RoleBo roleBo) {
159        Properties parameters = new Properties();
160        parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.DOC_HANDLER_METHOD);
161        parameters.put(KRADConstants.PARAMETER_COMMAND, KewApiConstants.INITIATE_COMMAND);
162        parameters.put(KRADConstants.DOCUMENT_TYPE_NAME, KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_TYPE_NAME);
163        parameters.put(KimConstants.PrimaryKeyConstants.SUB_ROLE_ID, roleBo.getId());
164        if (StringUtils.isNotBlank(getReturnLocation())) {
165                parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
166                }
167        String href = UrlFactory.parameterizeUrl(KimCommonUtilsInternal.getKimBasePath()+KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_ACTION, parameters);
168
169        HtmlData.AnchorHtmlData anchorHtmlData = new HtmlData.AnchorHtmlData(href,
170                        KRADConstants.DOC_HANDLER_METHOD, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL);
171        return anchorHtmlData;
172    }
173
174    @Override
175        protected HtmlData getReturnAnchorHtmlData(BusinessObject businessObject, Properties parameters, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions){
176        RoleBo roleBo = (RoleBo) businessObject;
177        HtmlData anchorHtmlData = super.getReturnAnchorHtmlData(businessObject, parameters, lookupForm, returnKeys, businessObjectRestrictions);
178
179        // prevent derived roles from being selectable (except for identityManagementRoleDocuments)
180        KualiForm myForm = (KualiForm) GlobalVariables.getUserSession().retrieveObject(getDocFormKey());
181        if (myForm == null || !(myForm instanceof IdentityManagementRoleDocumentForm)){
182                if(KimTypeLookupableHelperServiceImpl.hasDerivedRoleTypeService(KimTypeBo.to(roleBo.getKimRoleType()))){
183                        ((HtmlData.AnchorHtmlData)anchorHtmlData).setHref("");
184                }
185        }
186        return anchorHtmlData;
187    }
188
189    @Override
190    public List<? extends BusinessObject> getSearchResults(java.util.Map<String,String> fieldValues) {
191        fieldValues.remove(KRADConstants.BACK_LOCATION);
192        fieldValues.remove(KRADConstants.DOC_FORM_KEY);
193        fieldValues.remove(KRADConstants.DOC_NUM);
194
195        QueryByCriteria criteria = getRoleCriteria(fieldValues);
196
197        if(criteria == null) {
198            // The getRoleCriteria method will return null if there is a criteria which will return zero rows
199            return Collections.emptyList();
200        }
201
202        List<Role> results = KimApiServiceLocator.getRoleService().findRoles(criteria).getResults();
203        List<RoleBo> roles = new ArrayList<RoleBo>(results.size());
204        for ( Role role : results ) {
205            roles.add( RoleBo.from(role) );
206        }
207
208        return roles;
209    }
210
211        private List<KeyValue> getRoleTypeOptions() {
212                List<KeyValue> options = new ArrayList<KeyValue>();
213                options.add(new ConcreteKeyValue("", ""));
214
215                Collection<KimType> kimGroupTypes = KimApiServiceLocator.getKimTypeInfoService().findAllKimTypes();
216                // get the distinct list of type IDs from all roles in the system
217        for (KimType kimType : kimGroupTypes) {
218            if (KimTypeLookupableHelperServiceImpl.hasRoleTypeService(kimType)) {
219                String value = kimType.getNamespaceCode().trim() + KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR + kimType.getName().trim();
220                options.add(new ConcreteKeyValue(kimType.getId(), value));
221            }
222        }
223        Collections.sort(options, new Comparator<KeyValue>() {
224           @Override
225                public int compare(KeyValue k1, KeyValue k2) {
226               return k1.getValue().compareTo(k2.getValue());
227           }
228        });
229                return options;
230        }
231
232        public List<Row> getRoleRows() {
233                return this.roleRows;
234        }
235
236        public void setRoleRows(List<Row> roleRows) {
237                this.roleRows = roleRows;
238        }
239
240        public List<KimAttributeField> getAttrDefinitions() {
241                return this.attrDefinitions;
242        }
243
244        public void setAttrDefinitions(List<KimAttributeField> attrDefinitions) {
245                this.attrDefinitions = attrDefinitions;
246        }
247
248        public List<Row> getAttrRows() {
249                return this.attrRows;
250        }
251
252        public void setAttrRows(List<Row> attrRows) {
253                this.attrRows = attrRows;
254        }
255
256        public String getTypeId() {
257                return this.typeId;
258        }
259
260        public void setTypeId(String typeId) {
261                this.typeId = typeId;
262        }
263
264        @Override
265        public List<Row> getRows() {
266                new ArrayList<Row>();
267                if (getRoleRows().isEmpty()) {
268                        List<Row> rows = super.getRows();
269                        List<Row> returnRows = new ArrayList<Row>();
270                        for (Row row : rows) {
271                                for (int i = row.getFields().size() - 1; i >= 0; i--) {
272                                        Field field = row.getFields().get(i);
273                                        if (field.getPropertyName().equals("kimTypeId")) {
274                                                Field typeField = new Field();
275                                                typeField.setFieldLabel("Type");
276                                                typeField.setPropertyName("kimTypeId");
277                                                typeField.setFieldValidValues(getRoleTypeOptions());
278                                                typeField.setFieldType(Field.DROPDOWN);
279                                                typeField.setMaxLength(100);
280                                                typeField.setSize(40);
281                                                // row.getFields().set(i, new Field("Type", "", Field.DROPDOWN_REFRESH,
282                                                // false, "kimTypeId", "", getGroupTypeOptions(), null));
283                                                row.getFields().set(i, typeField);
284                                        }
285                                }
286                                returnRows.add(row);
287                        }
288                        setRoleRows(returnRows);
289                        //setAttrRows(setupAttributeRows());
290                }
291                if (getAttrRows().isEmpty()) {
292                        //setAttrDefinitions(new AttributeDefinitionMap());
293                        return getRoleRows();
294                } else {
295                        List<Row> fullRows = new ArrayList<Row>();
296                        fullRows.addAll(getRoleRows());
297                        //fullRows.addAll(getAttrRows());
298                        return fullRows;
299                }
300
301        }
302
303        @Override
304        protected List<? extends BusinessObject> getSearchResultsHelper(
305                        Map<String, String> fieldValues, boolean unbounded) {
306        List searchResults;
307        Map<String,String> nonBlankFieldValues = new HashMap<String, String>();
308        boolean includeAttr = false;
309        for (String fieldName : fieldValues.keySet()) {
310                if (StringUtils.isNotBlank(fieldValues.get(fieldName)) ) {
311                        nonBlankFieldValues.put(fieldName, fieldValues.get(fieldName));
312                        if (fieldName.contains(".")) {
313                                includeAttr = true;
314                        }
315                }
316        }
317
318        if (includeAttr) {
319                ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService( getBusinessObjectClass() );
320                BusinessObjectEntry ddEntry = eboModuleService.getExternalizableBusinessObjectDictionaryEntry(getBusinessObjectClass());
321                Map<String,String> filteredFieldValues = new HashMap<String, String>();
322                for (String fieldName : nonBlankFieldValues.keySet()) {
323                        if (ddEntry.getAttributeNames().contains(fieldName) || fieldName.contains(".")) {
324                                filteredFieldValues.put(fieldName, nonBlankFieldValues.get(fieldName));
325                        }
326                }
327                searchResults = eboModuleService.getExternalizableBusinessObjectsListForLookup(getBusinessObjectClass(), (Map)filteredFieldValues, unbounded);
328
329        } else {
330                searchResults = super.getSearchResultsHelper(fieldValues, unbounded);
331        }
332        List defaultSortColumns = getDefaultSortColumns();
333        if (defaultSortColumns.size() > 0) {
334            Collections.sort(searchResults, new BeanPropertyComparator(defaultSortColumns, true));
335        }
336        return searchResults;
337
338        }
339
340        private static final String ROLE_ID_URL_KEY = "&"+KimConstants.PrimaryKeyConstants.ROLE_ID+"=";
341
342        public static String getCustomRoleInquiryHref(String href){
343                return getCustomRoleInquiryHref("", href);
344        }
345
346        static String getCustomRoleInquiryHref(String backLocation, String href){
347        Properties parameters = new Properties();
348        String hrefPart = "";
349        String docTypeAction = "";
350        if(StringUtils.isBlank(backLocation) || backLocation.contains(KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_ACTION)
351                        || !backLocation.contains(KimConstants.KimUIConstants.KIM_GROUP_DOCUMENT_ACTION)){
352                docTypeAction = KimConstants.KimUIConstants.KIM_ROLE_INQUIRY_ACTION;
353        } else{
354                docTypeAction = KimConstants.KimUIConstants.KIM_GROUP_DOCUMENT_ACTION;
355        }
356                if (StringUtils.isNotBlank(href) && href.contains(ROLE_ID_URL_KEY)) {
357                        int idx1 = href.indexOf("&"+ KimConstants.PrimaryKeyConstants.ROLE_ID+"=");
358                    int idx2 = href.indexOf("&", idx1+1);
359                    if (idx2 < 0) {
360                        idx2 = href.length();
361                    }
362                parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.PARAM_MAINTENANCE_VIEW_MODE_INQUIRY);
363                hrefPart = href.substring(idx1, idx2);
364            }
365                return UrlFactory.parameterizeUrl(KimCommonUtilsInternal.getKimBasePath()+docTypeAction, parameters)+hrefPart;
366        }
367
368    /**
369     * This method will generate a QueryByCriteria which locates the roles
370     * matching the criteria passed into the fieldValues parameter, or null if
371     * the search would return zero results.
372     * @param fieldValues A Map of the desired criteria to use when finding roles
373     * @return A QueryByCriteria object which can be used to locate matching
374     * roles in the database or null if the search would yield zero results
375     */
376    public QueryByCriteria getRoleCriteria(Map<String, String> fieldValues) {
377        List<Predicate> criteria = new ArrayList<Predicate>();
378
379        Map<String, Map<String, String>> criteriaMap = setupCritMaps(fieldValues);
380
381        Map<String, String> lookupNames = criteriaMap.get(OTHER_CRITERIA);
382        for (Map.Entry<String, String> entry : lookupNames.entrySet()) {
383            String propertyName = entry.getKey();
384            String lookupValue = entry.getValue();
385            if (StringUtils.isNotBlank(lookupValue)) {
386                if (!propertyName.equals(KIMPropertyConstants.Principal.PRINCIPAL_NAME)) {
387                    if (propertyName.equals(KIMPropertyConstants.Principal.ACTIVE)) {
388                        criteria.add( equal( propertyName, Truth.strToBooleanIgnoreCase(lookupValue) ) );
389                    } else {
390                        criteria.add( likeIgnoreCase(propertyName, lookupValue));
391                    }
392                } else {
393                    Collection<String> roleIds = getRoleIdsForPrincipalName(lookupValue);
394
395                    if(CollectionUtils.isEmpty(roleIds)) {
396                        return null;
397                    }
398
399                    criteria.add( in(KimConstants.PrimaryKeyConstants.ID, roleIds) );
400                }
401            }
402        }
403
404//        if (!criteriaMap.get(ROLE_MEMBER_ATTRIBUTE_CRITERIA).isEmpty()) {
405//            String kimTypeId = null;
406//            for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
407//                if (entry.getKey().equals(KIMPropertyConstants.KimType.KIM_TYPE_ID)) {
408//                    kimTypeId = entry.getValue();
409//                    break;
410//                }
411//            }
412//            setupAttrCriteria(criteria, criteriaMap.get(ROLE_MEMBER_ATTRIBUTE_CRITERIA), kimTypeId);
413//        }
414        if (!criteriaMap.get(PERMISSION_CRITERIA).isEmpty()) {
415            Collection<String> permissionRoleIds = getPermissionRoleIds(criteriaMap.get(PERMISSION_CRITERIA));
416
417            if(CollectionUtils.isEmpty(permissionRoleIds)) {
418                return null;
419            }
420
421            criteria.add( in(KimConstants.PrimaryKeyConstants.ID, permissionRoleIds) );
422        }
423        if (!criteriaMap.get(RESPONSIBILITY_CRITERIA).isEmpty()) {
424            Collection<String> responsibilityRoleIds = getResponsibilityRoleIds(criteriaMap.get(RESPONSIBILITY_CRITERIA));
425
426            if(CollectionUtils.isEmpty(responsibilityRoleIds)) {
427                return null;
428            }
429
430            criteria.add( in(KimConstants.PrimaryKeyConstants.ID, responsibilityRoleIds) );
431        }
432        if (!criteriaMap.get(GROUP_CRITERIA).isEmpty()) {
433            Collection<String> groupCriteriaRoleIds = getGroupCriteriaRoleIds(criteriaMap.get(GROUP_CRITERIA));
434
435            if(CollectionUtils.isEmpty(groupCriteriaRoleIds)) {
436                return null;
437            }
438
439            criteria.add( in(KimConstants.PrimaryKeyConstants.ID, groupCriteriaRoleIds) );
440        }
441
442        return QueryByCriteria.Builder.fromPredicates(criteria);
443    }
444
445    protected Collection<String> getRoleIdsForPrincipalName(String principalName) {
446        principalName = principalName.replace('*', '%');
447
448        QueryByCriteria principalCriteria = QueryByCriteria.Builder.fromPredicates(
449                likeIgnoreCase(KIMPropertyConstants.Principal.PRINCIPAL_NAME, principalName)
450                , equal(KIMPropertyConstants.Principal.ACTIVE, Boolean.TRUE)
451                );
452        List<Principal> principals = KimApiServiceLocator.getIdentityService().findPrincipals(principalCriteria).getResults();
453
454        if (principals.isEmpty()) {
455            return Collections.singletonList("NOTFOUND");  // this forces a blank return.
456        }
457        Set<String> roleIds = new HashSet<String>();
458
459        // Get matching principal IDs
460        List<String> principalIds = new ArrayList<String>(principals.size());
461        for (Principal principal : principals) {
462            principalIds.add(principal.getPrincipalId());
463        }
464
465        // Get groups which the principals belong to
466        Set<String> groupIds = new HashSet<String>();
467        for (String principalId : principalIds) {
468            List<String> principalGroupIds = KimApiServiceLocator.getGroupService().getGroupIdsByPrincipalId(principalId);
469            if ( principalGroupIds.isEmpty() ) {
470                groupIds.add( "NOTFOUND" );
471            } else {
472                groupIds.addAll(principalGroupIds);
473            }
474        }
475
476        // Get roles to which this person has been added directly or via a group
477        QueryByCriteria roleMemberCriteria = QueryByCriteria.Builder.fromPredicates(
478                or(
479                    and(
480                            equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.PRINCIPAL.getCode())
481                            , in(KIMPropertyConstants.RoleMember.MEMBER_ID, principalIds)
482                        ),
483                    and(
484                        equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.GROUP.getCode())
485                        , in(KIMPropertyConstants.RoleMember.MEMBER_ID, groupIds)
486                        )
487                    )
488                );
489
490        List<RoleMember> roleMembers = KimApiServiceLocator.getRoleService().findRoleMembers(roleMemberCriteria).getResults();
491
492        DateTime now = new DateTime( CoreApiServiceLocator.getDateTimeService().getCurrentDate().getTime() );
493        for (RoleMember roleMbr : roleMembers ) {
494            if (roleMbr.isActive( now ) ) {
495                roleIds.add(roleMbr.getRoleId());
496            }
497        }
498
499        return roleIds;
500    }
501
502    protected static List<String> PERM_FIELD_NAMES;
503    protected static List<String> RESP_FIELD_NAMES;
504    static {
505        PERM_FIELD_NAMES = new ArrayList<String>(4);
506        PERM_FIELD_NAMES.add(LOOKUP_PARM_PERMISSION_NAME);
507        PERM_FIELD_NAMES.add(LOOKUP_PARM_PERMISSION_NAMESPACE);
508        PERM_FIELD_NAMES.add(LOOKUP_PARM_PERMISSION_TEMPLATE_NAME);
509        PERM_FIELD_NAMES.add(LOOKUP_PARM_PERMISSION_TEMPLATE_NAMESPACE);
510
511        RESP_FIELD_NAMES = new ArrayList<String>(4);
512        RESP_FIELD_NAMES.add(LOOKUP_PARM_RESP_NAME);
513        RESP_FIELD_NAMES.add(LOOKUP_PARM_RESP_NAMESPACE);
514        RESP_FIELD_NAMES.add(LOOKUP_PARM_RESP_TEMPLATE_NAME);
515        RESP_FIELD_NAMES.add(LOOKUP_PARM_RESP_TEMPLATE_NAMESPACE);
516    }
517
518    private Map<String, Map<String, String>> setupCritMaps(Map<String, String> fieldValues) {
519        Map<String, Map<String, String>> critMapMap = new HashMap<String, Map<String, String>>();
520
521        Map<String, String> permFieldMap = new HashMap<String, String>();
522        Map<String, String> respFieldMap = new HashMap<String, String>();
523//        Map<String, String> attrFieldMap = new HashMap<String, String>();
524        Map<String, String> groupFieldMap = new HashMap<String, String>();
525        Map<String, String> lookupNamesMap = new HashMap<String, String>();
526
527        for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
528            String nameValue = entry.getValue();
529            String propertyName = entry.getKey();
530            if (StringUtils.isNotBlank(nameValue)) {
531                if (PERM_FIELD_NAMES.contains(propertyName)) {
532                    permFieldMap.put(propertyName, nameValue);
533                } else if (RESP_FIELD_NAMES.contains(propertyName)) {
534                    respFieldMap.put(propertyName, nameValue);
535                } else if (propertyName.startsWith(KimConstants.AttributeConstants.GROUP_NAME)) {
536                    groupFieldMap.put(propertyName, nameValue);
537//                } else if (entry.getKey().contains(".")) {
538//                    attrFieldMap.put(entry.getKey(), nameValue).replace('*', '%');
539                } else {
540                    lookupNamesMap.put(propertyName, nameValue);
541                }
542            }
543        }
544
545        critMapMap.put(PERMISSION_CRITERIA, permFieldMap);
546        critMapMap.put(RESPONSIBILITY_CRITERIA, respFieldMap);
547        critMapMap.put(GROUP_CRITERIA, groupFieldMap);
548//        critMap.put(ROLE_MEMBER_ATTRIBUTE_CRITERIA, attrFieldMap);
549        critMapMap.put(OTHER_CRITERIA, lookupNamesMap);
550
551        return critMapMap;
552    }
553
554//    private void setupAttrCriteria(Criteria crit, Map<String, String> attrCrit, String kimTypeId) {
555//        for (Map.Entry<String, String> entry : attrCrit.entrySet()) {
556//            Criteria subCrit = new Criteria();
557//            addLikeToCriteria(subCrit, "attributes.attributeValue", entry.getValue());
558//            addEqualToCriteria(subCrit, "attributes.kimAttributeId", entry.getKey().substring(entry.getKey().indexOf(".") + 1, entry.getKey().length()));
559//            addEqualToCriteria(subCrit, "attributes.kimTypeId", kimTypeId);
560//            subCrit.addEqualToField("roleId", Criteria.PARENT_QUERY_PREFIX + "id");
561//            crit.addExists(QueryFactory.newReportQuery(RoleMemberBo.class, subCrit));
562//        }
563//    }
564
565    protected Collection<String> getPermissionRoleIds(Map<String, String> permCrit) {
566        List<Predicate> criteria = new ArrayList<Predicate>();
567
568        for (Map.Entry<String, String> entry : permCrit.entrySet()) {
569            if ( StringUtils.isNotBlank(entry.getValue()) ) {
570                String propertyName = entry.getKey();
571                String lookupValue = entry.getValue().replace('*', '%');
572                if ( propertyName.equals(LOOKUP_PARM_PERMISSION_NAME) ) {
573                    criteria.add( likeIgnoreCase(KimConstants.UniqueKeyConstants.PERMISSION_NAME, lookupValue) );
574                } else if ( propertyName.equals(LOOKUP_PARM_PERMISSION_NAMESPACE) ) {
575                    criteria.add( like(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, lookupValue) );
576                } else if ( propertyName.equals(LOOKUP_PARM_PERMISSION_TEMPLATE_NAME) ) {
577                    criteria.add( likeIgnoreCase("template." + KimConstants.UniqueKeyConstants.PERMISSION_TEMPLATE_NAME, lookupValue) );
578                } else if ( propertyName.equals(LOOKUP_PARM_PERMISSION_TEMPLATE_NAMESPACE) ){
579                    criteria.add( like("template." + KimConstants.UniqueKeyConstants.NAMESPACE_CODE, lookupValue) );
580                }
581            }
582        }
583        if(criteria.isEmpty()){
584            return Collections.singletonList("NOTFOUND");  // this forces a blank return.
585        }
586
587        List<Permission> permissions = KimApiServiceLocator.getPermissionService().findPermissions( QueryByCriteria.Builder.fromPredicates(criteria) ).getResults();
588        Set<String> roleIds = new HashSet<String>();
589
590        for ( Permission permission : permissions ) {
591            roleIds.addAll( KimApiServiceLocator.getPermissionService().getRoleIdsForPermission(permission.getNamespaceCode(), permission.getName()) );
592        }
593
594        return roleIds;
595    }
596
597    protected Collection<String> getResponsibilityRoleIds(Map<String, String> respCrit) {
598        List<Predicate> criteria = new ArrayList<Predicate>();
599
600        for (Map.Entry<String, String> entry : respCrit.entrySet()) {
601            if ( StringUtils.isNotBlank(entry.getValue()) ) {
602                String propertyName = entry.getKey();
603                String lookupValue = entry.getValue().replace('*', '%');
604                if (propertyName.equals(LOOKUP_PARM_RESP_NAME) ) {
605                    criteria.add( likeIgnoreCase(KimConstants.UniqueKeyConstants.RESPONSIBILITY_NAME, lookupValue));
606                } else if ( propertyName.equals(LOOKUP_PARM_RESP_NAMESPACE) ) {
607                    criteria.add( like(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, lookupValue));
608                } else if (propertyName.equals(LOOKUP_PARM_RESP_TEMPLATE_NAME)) {
609                    criteria.add( likeIgnoreCase("template." + KimConstants.UniqueKeyConstants.RESPONSIBILITY_TEMPLATE_NAME, lookupValue));
610                } else if ( propertyName.equals(LOOKUP_PARM_RESP_TEMPLATE_NAMESPACE) ){
611                    criteria.add( like("template." + KimConstants.UniqueKeyConstants.NAMESPACE_CODE, lookupValue));
612                }
613            }
614        }
615        if(criteria.isEmpty()){
616            return Collections.singletonList("NOTFOUND");  // this forces a blank return.
617        }
618
619        ResponsibilityQueryResults results = KimApiServiceLocator.getResponsibilityService().findResponsibilities(QueryByCriteria.Builder.fromPredicates(criteria) );
620        List<Responsibility> responsibilities = results.getResults();
621
622        Set<String> roleIds = new HashSet<String>();
623        for (Responsibility responsibility : responsibilities) {
624            roleIds.addAll(KimApiServiceLocator.getResponsibilityService().getRoleIdsForResponsibility(responsibility.getId()));
625        }
626
627        return roleIds;
628    }
629
630    protected Collection<String> getGroupCriteriaRoleIds(Map<String,String> groupCrit) {
631        List<Predicate> criteria = new ArrayList<Predicate>();
632
633        for (Entry<String, String> entry : groupCrit.entrySet()) {
634            if ( StringUtils.isNotBlank(entry.getValue()) ) {
635                String propertyName = entry.getKey();
636                String lookupValue = entry.getValue().replace('*', '%');
637                if (propertyName.equals(KimConstants.AttributeConstants.GROUP_NAME)) {
638                    criteria.add( likeIgnoreCase(KimConstants.AttributeConstants.NAME, lookupValue));
639                } else { // the namespace code for the group field is named something besides the default. Set it to the default.
640                    criteria.add( like(KimConstants.AttributeConstants.NAMESPACE_CODE, lookupValue));
641                }
642            }
643       }
644        if(criteria.isEmpty()){
645            return Collections.singletonList("NOTFOUND");  // this forces a blank return.
646        }
647
648       List<String> groupIds = KimApiServiceLocator.getGroupService().findGroupIds(QueryByCriteria.Builder.fromPredicates(criteria));
649
650       if(groupIds.isEmpty()){
651           return Collections.singletonList("NOTFOUND");  // this forces a blank return.
652       }
653
654       // Get roles to which this person has been added directly or via a group
655       QueryByCriteria roleMemberCriteria = QueryByCriteria.Builder.fromPredicates(
656               equal(KIMPropertyConstants.RoleMember.MEMBER_TYPE_CODE, MemberType.GROUP.getCode())
657               , in(KIMPropertyConstants.RoleMember.MEMBER_ID, groupIds)
658               );
659
660       List<RoleMember> roleMembers = KimApiServiceLocator.getRoleService().findRoleMembers(roleMemberCriteria).getResults();
661
662       Set<String> roleIds = new HashSet<String>();
663       DateTime now = new DateTime( CoreApiServiceLocator.getDateTimeService().getCurrentDate().getTime() );
664       for (RoleMember roleMbr : roleMembers ) {
665           if (roleMbr.isActive( now ) ) {
666               roleIds.add(roleMbr.getRoleId());
667           }
668       }
669
670       return roleIds;
671    }
672
673    /**
674     * This overridden method ...
675     *
676     * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getMaintenanceDocumentTypeName()
677     */
678    @Override
679    protected String getMaintenanceDocumentTypeName() {
680        return KimConstants.KimUIConstants.KIM_ROLE_DOCUMENT_TYPE_NAME;
681    }
682}