001 /** 002 * Copyright 2005-2012 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 */ 016 package org.kuali.rice.kim.impl.responsibility; 017 018 import org.apache.commons.beanutils.PropertyUtils; 019 import org.apache.commons.lang.StringUtils; 020 import org.apache.log4j.Logger; 021 import org.kuali.rice.core.api.membership.MemberType; 022 import org.kuali.rice.kew.api.KewApiConstants; 023 import org.kuali.rice.kim.api.KimConstants; 024 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 025 import org.kuali.rice.kim.impl.role.RoleBo; 026 import org.kuali.rice.kim.impl.role.RoleResponsibilityBo; 027 import org.kuali.rice.kim.lookup.RoleMemberLookupableHelperServiceImpl; 028 import org.kuali.rice.kns.lookup.HtmlData; 029 import org.kuali.rice.krad.bo.BusinessObject; 030 import org.kuali.rice.krad.lookup.CollectionIncomplete; 031 import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 032 import org.kuali.rice.krad.service.LookupService; 033 import org.kuali.rice.krad.util.KRADConstants; 034 import org.kuali.rice.krad.util.UrlFactory; 035 036 import java.lang.reflect.InvocationTargetException; 037 import java.util.ArrayList; 038 import java.util.HashMap; 039 import java.util.List; 040 import java.util.Map; 041 import java.util.Properties; 042 043 public class ResponsibilityLookupableHelperServiceImpl extends RoleMemberLookupableHelperServiceImpl { 044 045 private static final Logger LOG = Logger.getLogger( ResponsibilityLookupableHelperServiceImpl.class ); 046 047 private static final long serialVersionUID = -2882500971924192124L; 048 049 private static LookupService lookupService; 050 051 private static boolean reviewResponsibilityDocumentTypeNameLoaded = false; 052 private static String reviewResponsibilityDocumentTypeName = null; 053 054 @SuppressWarnings("unchecked") 055 @Override 056 public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) { 057 List<HtmlData> htmlDataList = new ArrayList<HtmlData>(); 058 // convert the UberResponsibilityBo class into a ReviewResponsibility object 059 if ( (((UberResponsibilityBo)businessObject).getTemplate() != null) 060 && ((UberResponsibilityBo)businessObject).getTemplate().getName().equals( KewApiConstants.DEFAULT_RESPONSIBILITY_TEMPLATE_NAME ) ) { 061 ReviewResponsibilityBo reviewResp = new ReviewResponsibilityBo( (UberResponsibilityBo)businessObject ); 062 businessObject = reviewResp; 063 if (allowsMaintenanceEditAction(businessObject)) { 064 htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames)); 065 } 066 if (allowsMaintenanceNewOrCopyAction()) { 067 htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames)); 068 } 069 } 070 return htmlDataList; 071 } 072 073 @SuppressWarnings("unchecked") 074 protected String getActionUrlHref(BusinessObject businessObject, String methodToCall, List pkNames){ 075 Properties parameters = new Properties(); 076 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall); 077 // TODO: why is this not using the businessObject parmeter's class? 078 parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObject.getClass().getName()); 079 parameters.put(KRADConstants.OVERRIDE_KEYS, KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID); 080 parameters.put(KRADConstants.COPY_KEYS, KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID); 081 if (StringUtils.isNotBlank(getReturnLocation())) { 082 parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation()); 083 } 084 parameters.putAll(getParametersFromPrimaryKey(businessObject, pkNames)); 085 return UrlFactory.parameterizeUrl(KRADConstants.MAINTENANCE_ACTION, parameters); 086 } 087 088 @Override 089 protected String getMaintenanceDocumentTypeName() { 090 if ( !reviewResponsibilityDocumentTypeNameLoaded ) { 091 reviewResponsibilityDocumentTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName(ReviewResponsibilityBo.class); 092 reviewResponsibilityDocumentTypeNameLoaded = true; 093 } 094 return reviewResponsibilityDocumentTypeName; 095 } 096 097 @Override 098 protected List<? extends BusinessObject> getMemberSearchResults(Map<String, String> searchCriteria, boolean unbounded) { 099 Map<String, String> responsibilitySearchCriteria = buildSearchCriteria(searchCriteria); 100 Map<String, String> roleSearchCriteria = buildRoleSearchCriteria(searchCriteria); 101 boolean responsibilityCriteriaEmpty = responsibilitySearchCriteria==null || responsibilitySearchCriteria.isEmpty(); 102 boolean roleCriteriaEmpty = roleSearchCriteria==null || roleSearchCriteria.isEmpty(); 103 104 List<UberResponsibilityBo> responsibilitySearchResultsCopy = new CollectionIncomplete<UberResponsibilityBo>(new ArrayList<UberResponsibilityBo>(), new Long(0)); 105 if(!responsibilityCriteriaEmpty && !roleCriteriaEmpty){ 106 responsibilitySearchResultsCopy = getCombinedSearchResults(responsibilitySearchCriteria, roleSearchCriteria, unbounded); 107 } else if(responsibilityCriteriaEmpty && !roleCriteriaEmpty){ 108 responsibilitySearchResultsCopy = getResponsibilitiesWithRoleSearchCriteria(roleSearchCriteria, unbounded); 109 } else if(!responsibilityCriteriaEmpty && roleCriteriaEmpty){ 110 responsibilitySearchResultsCopy = getResponsibilitiesWithResponsibilitySearchCriteria(responsibilitySearchCriteria, unbounded); 111 } else if(responsibilityCriteriaEmpty && roleCriteriaEmpty){ 112 return getAllResponsibilities(unbounded); 113 } 114 return responsibilitySearchResultsCopy; 115 } 116 117 private List<UberResponsibilityBo> getAllResponsibilities(boolean unbounded){ 118 List<UberResponsibilityBo> responsibilities = searchResponsibilities(new HashMap<String, String>(), unbounded); 119 for(UberResponsibilityBo responsibility: responsibilities) { 120 populateAssignedToRoles(responsibility); 121 } 122 return responsibilities; 123 } 124 125 private List<UberResponsibilityBo> getCombinedSearchResults( 126 Map<String, String> responsibilitySearchCriteria, Map<String, String> roleSearchCriteria, boolean unbounded){ 127 List<UberResponsibilityBo> responsibilitySearchResults = searchResponsibilities(responsibilitySearchCriteria, unbounded); 128 List<RoleBo> roleSearchResults = searchRoles(roleSearchCriteria, unbounded); 129 List<UberResponsibilityBo> responsibilitiesForRoleSearchResults = getResponsibilitiesForRoleSearchResults(roleSearchResults, unbounded); 130 List<UberResponsibilityBo> matchedResponsibilities = new CollectionIncomplete<UberResponsibilityBo>( 131 new ArrayList<UberResponsibilityBo>(), getActualSizeIfTruncated(responsibilitiesForRoleSearchResults)); 132 if((responsibilitySearchResults!=null && !responsibilitySearchResults.isEmpty()) && 133 (responsibilitiesForRoleSearchResults!=null && !responsibilitiesForRoleSearchResults.isEmpty())){ 134 for(UberResponsibilityBo responsibility: responsibilitySearchResults){ 135 for(UberResponsibilityBo responsibilityFromRoleSearch: responsibilitiesForRoleSearchResults){ 136 if(responsibilityFromRoleSearch.getId().equals(responsibility.getId())) { 137 matchedResponsibilities.add(responsibilityFromRoleSearch); 138 } 139 } 140 } 141 } 142 143 return matchedResponsibilities; 144 } 145 146 @SuppressWarnings("unchecked") 147 private List<UberResponsibilityBo> searchResponsibilities(Map<String, String> responsibilitySearchCriteria, boolean unbounded){ 148 return getResponsibilitiesSearchResultsCopy((List<ResponsibilityBo>) 149 getLookupService().findCollectionBySearchHelper( 150 ResponsibilityBo.class, responsibilitySearchCriteria, unbounded)); 151 } 152 153 private List<UberResponsibilityBo> getResponsibilitiesWithRoleSearchCriteria(Map<String, String> roleSearchCriteria, boolean unbounded){ 154 List<RoleBo> roleSearchResults = searchRoles(roleSearchCriteria, unbounded); 155 return getResponsibilitiesForRoleSearchResults(roleSearchResults, unbounded); 156 } 157 158 private List<UberResponsibilityBo> getResponsibilitiesForRoleSearchResults(List<RoleBo> roleSearchResults, boolean unbounded){ 159 Long actualSizeIfTruncated = getActualSizeIfTruncated(roleSearchResults); 160 List<UberResponsibilityBo> responsibilities = new ArrayList<UberResponsibilityBo>(); 161 List<UberResponsibilityBo> tempResponsibilities; 162 List<String> collectedResponsibilityIds = new ArrayList<String>(); 163 Map<String, String> responsibilityCriteria; 164 165 for(RoleBo roleImpl: roleSearchResults){ 166 responsibilityCriteria = new HashMap<String, String>(); 167 responsibilityCriteria.put("roleResponsibilities.roleId", roleImpl.getId()); 168 tempResponsibilities = searchResponsibilities(responsibilityCriteria, unbounded); 169 actualSizeIfTruncated += getActualSizeIfTruncated(tempResponsibilities); 170 for(UberResponsibilityBo responsibility: tempResponsibilities){ 171 if(!collectedResponsibilityIds.contains(responsibility.getId())){ 172 populateAssignedToRoles(responsibility); 173 collectedResponsibilityIds.add(responsibility.getId()); 174 responsibilities.add(responsibility); 175 } 176 //need to find roles that current role is a member of and build search string 177 List<String> parentRoleIds = KimApiServiceLocator.getRoleService().getMemberParentRoleIds(MemberType.ROLE.getCode(), roleImpl.getId()); 178 for (String parentRoleId : parentRoleIds) { 179 Map<String, String> roleSearchCriteria = new HashMap<String, String>(); 180 roleSearchCriteria.put("roleId", parentRoleId); 181 //get all parent role permissions and merge them with current permissions 182 responsibilities = mergeResponsibilityLists(responsibilities, getResponsibilitiesWithRoleSearchCriteria(roleSearchCriteria, unbounded)); 183 } 184 } 185 } 186 return new CollectionIncomplete<UberResponsibilityBo>(responsibilities, actualSizeIfTruncated); 187 } 188 189 private void populateAssignedToRoles(UberResponsibilityBo responsibility){ 190 Map<String, String> criteria = new HashMap<String, String>(); 191 if ( responsibility.getAssignedToRoles().isEmpty() ) { 192 for(RoleResponsibilityBo roleResponsibility: responsibility.getRoleResponsibilities()){ 193 criteria.put(KimConstants.PrimaryKeyConstants.ID, roleResponsibility.getRoleId()); 194 responsibility.getAssignedToRoles().add(getBusinessObjectService().findByPrimaryKey(RoleBo.class, criteria)); 195 } 196 } 197 } 198 199 private List<UberResponsibilityBo> getResponsibilitiesWithResponsibilitySearchCriteria(Map<String, String> responsibilitySearchCriteria, boolean unbounded){ 200 String detailCriteriaStr = responsibilitySearchCriteria.remove( DETAIL_CRITERIA ); 201 Map<String, String> detailCriteria = parseDetailCriteria(detailCriteriaStr); 202 final List<UberResponsibilityBo> responsibilities = searchResponsibilities(responsibilitySearchCriteria, unbounded); 203 List<UberResponsibilityBo> filteredResponsibilities = new CollectionIncomplete<UberResponsibilityBo>( 204 new ArrayList<UberResponsibilityBo>(), getActualSizeIfTruncated(responsibilities)); 205 for(UberResponsibilityBo responsibility: responsibilities){ 206 if ( detailCriteria.isEmpty() ) { 207 filteredResponsibilities.add(responsibility); 208 populateAssignedToRoles(responsibility); 209 } else { 210 if ( isMapSubset( new HashMap<String, String>(responsibility.getAttributes()), detailCriteria ) ) { 211 filteredResponsibilities.add(responsibility); 212 populateAssignedToRoles(responsibility); 213 } 214 } 215 } 216 return filteredResponsibilities; 217 } 218 219 private List<UberResponsibilityBo> getResponsibilitiesSearchResultsCopy(List<ResponsibilityBo> responsibilitySearchResults){ 220 List<UberResponsibilityBo> responsibilitySearchResultsCopy = new CollectionIncomplete<UberResponsibilityBo>( 221 new ArrayList<UberResponsibilityBo>(), getActualSizeIfTruncated(responsibilitySearchResults)); 222 for(ResponsibilityBo responsibilityImpl: responsibilitySearchResults){ 223 UberResponsibilityBo responsibilityCopy = new UberResponsibilityBo(); 224 225 try { 226 PropertyUtils.copyProperties(responsibilityCopy, responsibilityImpl); 227 //Hack for tomcat 7 KULRICE:5927 228 responsibilityCopy.setTemplate(responsibilityImpl.getTemplate()); 229 } catch (IllegalAccessException e) { 230 throw new RuntimeException("unable to copy properties"); 231 } catch (InvocationTargetException e) { 232 throw new RuntimeException("unable to copy properties"); 233 } catch (NoSuchMethodException e) { 234 throw new RuntimeException("unable to copy properties"); 235 } 236 237 responsibilitySearchResultsCopy.add(responsibilityCopy); 238 } 239 return responsibilitySearchResultsCopy; 240 } 241 242 243 /** 244 * @return the lookupService 245 */ 246 public LookupService getLookupService() { 247 if ( lookupService == null ) { 248 lookupService = KRADServiceLocatorWeb.getLookupService(); 249 } 250 return lookupService; 251 } 252 253 private List<UberResponsibilityBo> mergeResponsibilityLists(List<UberResponsibilityBo> perm1, List<UberResponsibilityBo> perm2) { 254 List<UberResponsibilityBo> returnList = new ArrayList<UberResponsibilityBo>(perm1); 255 List<String> responsibilityIds = new ArrayList<String>(perm1.size()); 256 for (UberResponsibilityBo perm : returnList) { 257 responsibilityIds.add(perm.getId()); 258 } 259 for (int i=0; i<perm2.size(); i++) { 260 if (!responsibilityIds.contains(perm2.get(i).getId())) { 261 returnList.add(perm2.get(i)); 262 } 263 } 264 return returnList; 265 } 266 }