001 /**
002 * Copyright 2005-2013 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("id", 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 }