View Javadoc

1   /**
2    * Copyright 2005-2014 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.impl.responsibility;
17  
18  import org.apache.commons.beanutils.PropertyUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.log4j.Logger;
21  import org.kuali.rice.core.api.membership.MemberType;
22  import org.kuali.rice.kew.api.KewApiConstants;
23  import org.kuali.rice.kim.api.KimConstants;
24  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
25  import org.kuali.rice.kim.impl.role.RoleBo;
26  import org.kuali.rice.kim.impl.role.RoleResponsibilityBo;
27  import org.kuali.rice.kim.lookup.RoleMemberLookupableHelperServiceImpl;
28  import org.kuali.rice.kns.lookup.HtmlData;
29  import org.kuali.rice.krad.bo.BusinessObject;
30  import org.kuali.rice.krad.lookup.CollectionIncomplete;
31  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
32  import org.kuali.rice.krad.service.LookupService;
33  import org.kuali.rice.krad.util.KRADConstants;
34  import org.kuali.rice.krad.util.UrlFactory;
35  
36  import java.lang.reflect.InvocationTargetException;
37  import java.util.ArrayList;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.Properties;
42  
43  public class ResponsibilityLookupableHelperServiceImpl extends RoleMemberLookupableHelperServiceImpl {
44  
45  	private static final Logger LOG = Logger.getLogger( ResponsibilityLookupableHelperServiceImpl.class );
46  	
47  	private static final long serialVersionUID = -2882500971924192124L;
48  	
49  	private static LookupService lookupService;
50  
51  	private static boolean reviewResponsibilityDocumentTypeNameLoaded = false;
52  	private static String reviewResponsibilityDocumentTypeName = null;
53  	
54  	@SuppressWarnings("unchecked")
55  	@Override
56  	public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
57      	List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
58      	// convert the UberResponsibilityBo class into a ReviewResponsibility object
59          if ( (((UberResponsibilityBo)businessObject).getTemplate() != null)
60                  && ((UberResponsibilityBo)businessObject).getTemplate().getName().equals( KewApiConstants.DEFAULT_RESPONSIBILITY_TEMPLATE_NAME ) ) {
61          	ReviewResponsibilityBo reviewResp = new ReviewResponsibilityBo( (UberResponsibilityBo)businessObject );
62          	businessObject = reviewResp;
63  	        if (allowsMaintenanceEditAction(businessObject)) {
64  	        	htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
65  	        }
66  	        if (allowsMaintenanceNewOrCopyAction()) {
67  	        	htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
68  	        }
69          }
70          return htmlDataList;
71  	}
72  
73      @SuppressWarnings("unchecked")
74  	protected String getActionUrlHref(BusinessObject businessObject, String methodToCall, List pkNames){
75          Properties parameters = new Properties();
76          parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
77          // TODO: why is this not using the businessObject parmeter's class?
78          parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObject.getClass().getName());
79          parameters.put(KRADConstants.OVERRIDE_KEYS, KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID);
80          parameters.put(KRADConstants.COPY_KEYS, KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID);
81          if (StringUtils.isNotBlank(getReturnLocation())) {
82          	parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
83  		}
84          parameters.putAll(getParametersFromPrimaryKey(businessObject, pkNames));
85          return UrlFactory.parameterizeUrl(KRADConstants.MAINTENANCE_ACTION, parameters);
86      }
87  	
88  	@Override
89  	protected String getMaintenanceDocumentTypeName() {
90  		if ( !reviewResponsibilityDocumentTypeNameLoaded ) {
91  			reviewResponsibilityDocumentTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName(ReviewResponsibilityBo.class);
92  			reviewResponsibilityDocumentTypeNameLoaded = true;
93  		}
94  		return reviewResponsibilityDocumentTypeName;
95  	}
96  	
97  	@Override
98  	protected List<? extends BusinessObject> getMemberSearchResults(Map<String, String> searchCriteria, boolean unbounded) {
99  		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 }