View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kim.lookup;
17  
18  import static org.kuali.rice.core.api.criteria.PredicateFactory.and;
19  import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
20  import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
21  import static org.kuali.rice.core.api.criteria.PredicateFactory.like;
22  import static org.kuali.rice.core.api.criteria.PredicateFactory.likeIgnoreCase;
23  import static org.kuali.rice.core.api.criteria.PredicateFactory.or;
24  
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.Comparator;
29  import java.util.HashMap;
30  import java.util.HashSet;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  import java.util.Properties;
35  import java.util.Set;
36  
37  import org.apache.commons.collections.CollectionUtils;
38  import org.apache.commons.lang.StringUtils;
39  import org.joda.time.DateTime;
40  import org.kuali.rice.core.api.CoreApiServiceLocator;
41  import org.kuali.rice.core.api.criteria.Predicate;
42  import org.kuali.rice.core.api.criteria.QueryByCriteria;
43  import org.kuali.rice.core.api.membership.MemberType;
44  import org.kuali.rice.core.api.util.ConcreteKeyValue;
45  import org.kuali.rice.core.api.util.KeyValue;
46  import org.kuali.rice.core.api.util.Truth;
47  import org.kuali.rice.kew.api.KewApiConstants;
48  import org.kuali.rice.kim.api.KimConstants;
49  import org.kuali.rice.kim.api.identity.principal.Principal;
50  import org.kuali.rice.kim.api.permission.Permission;
51  import org.kuali.rice.kim.api.responsibility.Responsibility;
52  import org.kuali.rice.kim.api.responsibility.ResponsibilityQueryResults;
53  import org.kuali.rice.kim.api.role.Role;
54  import org.kuali.rice.kim.api.role.RoleMember;
55  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
56  import org.kuali.rice.kim.api.type.KimAttributeField;
57  import org.kuali.rice.kim.api.type.KimType;
58  import org.kuali.rice.kim.impl.KIMPropertyConstants;
59  import org.kuali.rice.kim.impl.role.RoleBo;
60  import org.kuali.rice.kim.impl.type.KimTypeBo;
61  import org.kuali.rice.kim.impl.type.KimTypeLookupableHelperServiceImpl;
62  import org.kuali.rice.kim.util.KimCommonUtilsInternal;
63  import org.kuali.rice.kim.web.struts.form.IdentityManagementRoleDocumentForm;
64  import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
65  import org.kuali.rice.kns.lookup.HtmlData;
66  import org.kuali.rice.kns.web.struts.form.KualiForm;
67  import org.kuali.rice.kns.web.struts.form.LookupForm;
68  import org.kuali.rice.kns.web.ui.Field;
69  import org.kuali.rice.kns.web.ui.Row;
70  import org.kuali.rice.krad.bo.BusinessObject;
71  import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
72  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
73  import org.kuali.rice.krad.service.ModuleService;
74  import org.kuali.rice.krad.util.BeanPropertyComparator;
75  import org.kuali.rice.krad.util.GlobalVariables;
76  import org.kuali.rice.krad.util.KRADConstants;
77  import org.kuali.rice.krad.util.UrlFactory;
78  
79  /**
80   * This is a description of what this class does - shyu don't forget to fill this in.
81   *
82   * @author Kuali Rice Team (rice.collab@kuali.org)
83   *
84   */
85  public class RoleLookupableHelperServiceImpl extends KimLookupableHelperServiceImpl {
86      private static final long serialVersionUID = 1L;
87  
88      protected static final String GROUP_CRITERIA = "group";
89      protected static final String RESPONSIBILITY_CRITERIA = "resp";
90      protected static final String PERMISSION_CRITERIA = "perm";
91      protected static final String ROLE_MEMBER_ATTRIBUTE_CRITERIA = "attr";
92      protected static final String OTHER_CRITERIA = "lookupNames";
93  
94      protected static final String LOOKUP_PARM_PERMISSION_TEMPLATE_NAMESPACE = "permTmplNamespaceCode";
95      protected static final String LOOKUP_PARM_PERMISSION_TEMPLATE_NAME = "permTmplName";
96      protected static final String LOOKUP_PARM_PERMISSION_NAMESPACE = "permNamespaceCode";
97      protected static final String LOOKUP_PARM_PERMISSION_NAME = "permName";
98  
99      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 }