1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kim.lookup;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Properties;
23
24 import org.apache.commons.beanutils.PropertyUtils;
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.log4j.Logger;
27 import org.kuali.rice.core.util.MaxAgeSoftReference;
28 import org.kuali.rice.kew.util.KEWConstants;
29 import org.kuali.rice.kim.bo.impl.ResponsibilityImpl;
30 import org.kuali.rice.kim.bo.impl.ReviewResponsibility;
31 import org.kuali.rice.kim.bo.impl.RoleImpl;
32 import org.kuali.rice.kim.bo.role.impl.KimResponsibilityImpl;
33 import org.kuali.rice.kim.bo.role.impl.RoleResponsibilityImpl;
34 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
35 import org.kuali.rice.kim.service.KIMServiceLocator;
36 import org.kuali.rice.kim.util.KimConstants;
37 import org.kuali.rice.kns.bo.BusinessObject;
38 import org.kuali.rice.kns.lookup.CollectionIncomplete;
39 import org.kuali.rice.kns.lookup.HtmlData;
40 import org.kuali.rice.kns.service.KNSServiceLocator;
41 import org.kuali.rice.kns.service.LookupService;
42 import org.kuali.rice.kns.util.KNSConstants;
43 import org.kuali.rice.kns.util.UrlFactory;
44
45
46
47
48
49
50
51 public class ResponsibilityLookupableHelperServiceImpl extends RoleMemberLookupableHelperServiceImpl {
52
53 private static final Logger LOG = Logger.getLogger( ResponsibilityLookupableHelperServiceImpl.class );
54
55 private static final long serialVersionUID = -2882500971924192124L;
56
57 private static LookupService lookupService;
58
59 private static boolean reviewResponsibilityDocumentTypeNameLoaded = false;
60 private static String reviewResponsibilityDocumentTypeName = null;
61
62
63
64
65
66
67 @SuppressWarnings("unchecked")
68 @Override
69 public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
70 List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
71
72 if ( ((ResponsibilityImpl)businessObject).getTemplate().getName().equals( KEWConstants.DEFAULT_RESPONSIBILITY_TEMPLATE_NAME ) ) {
73 ReviewResponsibility reviewResp = new ReviewResponsibility( (ResponsibilityImpl)businessObject );
74 businessObject = reviewResp;
75 if (allowsMaintenanceEditAction(businessObject)) {
76 htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
77 }
78 if (allowsMaintenanceNewOrCopyAction()) {
79 htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
80 }
81 }
82 return htmlDataList;
83 }
84
85 @SuppressWarnings("unchecked")
86 protected String getActionUrlHref(BusinessObject businessObject, String methodToCall, List pkNames){
87 Properties parameters = new Properties();
88 parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
89
90 parameters.put(KNSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObject.getClass().getName());
91 parameters.put(KNSConstants.OVERRIDE_KEYS, KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID);
92 parameters.put(KNSConstants.COPY_KEYS, KimConstants.PrimaryKeyConstants.RESPONSIBILITY_ID);
93 if (StringUtils.isNotBlank(getReturnLocation())) {
94 parameters.put(KNSConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
95 }
96 parameters.putAll(getParametersFromPrimaryKey(businessObject, pkNames));
97 return UrlFactory.parameterizeUrl(KNSConstants.MAINTENANCE_ACTION, parameters);
98 }
99
100
101
102
103
104
105 @Override
106 protected String getMaintenanceDocumentTypeName() {
107 if ( !reviewResponsibilityDocumentTypeNameLoaded ) {
108 reviewResponsibilityDocumentTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName(ReviewResponsibility.class);
109 reviewResponsibilityDocumentTypeNameLoaded = true;
110 }
111 return reviewResponsibilityDocumentTypeName;
112 }
113
114
115
116
117 @Override
118 protected List<? extends BusinessObject> getMemberSearchResults(Map<String, String> searchCriteria, boolean unbounded) {
119 Map<String, String> responsibilitySearchCriteria = buildSearchCriteria(searchCriteria);
120 Map<String, String> roleSearchCriteria = buildRoleSearchCriteria(searchCriteria);
121 boolean responsibilityCriteriaEmpty = responsibilitySearchCriteria==null || responsibilitySearchCriteria.isEmpty();
122 boolean roleCriteriaEmpty = roleSearchCriteria==null || roleSearchCriteria.isEmpty();
123
124 List<ResponsibilityImpl> responsibilitySearchResultsCopy = new CollectionIncomplete<ResponsibilityImpl>(new ArrayList<ResponsibilityImpl>(), new Long(0));
125 if(!responsibilityCriteriaEmpty && !roleCriteriaEmpty){
126 responsibilitySearchResultsCopy = getCombinedSearchResults(responsibilitySearchCriteria, roleSearchCriteria, unbounded);
127 } else if(responsibilityCriteriaEmpty && !roleCriteriaEmpty){
128 responsibilitySearchResultsCopy = getResponsibilitiesWithRoleSearchCriteria(roleSearchCriteria, unbounded);
129 } else if(!responsibilityCriteriaEmpty && roleCriteriaEmpty){
130 responsibilitySearchResultsCopy = getResponsibilitiesWithResponsibilitySearchCriteria(responsibilitySearchCriteria, unbounded);
131 } else if(responsibilityCriteriaEmpty && roleCriteriaEmpty){
132 return getAllResponsibilities(unbounded);
133 }
134 return responsibilitySearchResultsCopy;
135 }
136
137 private List<ResponsibilityImpl> getAllResponsibilities(boolean unbounded){
138 List<ResponsibilityImpl> responsibilities = searchResponsibilities(new HashMap<String, String>(), unbounded);
139 for(ResponsibilityImpl responsibility: responsibilities)
140 populateAssignedToRoles(responsibility);
141 return responsibilities;
142 }
143
144 private List<ResponsibilityImpl> getCombinedSearchResults(
145 Map<String, String> responsibilitySearchCriteria, Map<String, String> roleSearchCriteria, boolean unbounded){
146 List<ResponsibilityImpl> responsibilitySearchResults = searchResponsibilities(responsibilitySearchCriteria, unbounded);
147 List<RoleImpl> roleSearchResults = searchRoles(roleSearchCriteria, unbounded);
148 List<ResponsibilityImpl> responsibilitiesForRoleSearchResults = getResponsibilitiesForRoleSearchResults(roleSearchResults, unbounded);
149 List<ResponsibilityImpl> matchedResponsibilities = new CollectionIncomplete<ResponsibilityImpl>(
150 new ArrayList<ResponsibilityImpl>(), getActualSizeIfTruncated(responsibilitiesForRoleSearchResults));
151 if((responsibilitySearchResults!=null && !responsibilitySearchResults.isEmpty()) &&
152 (responsibilitiesForRoleSearchResults!=null && !responsibilitiesForRoleSearchResults.isEmpty())){
153 for(ResponsibilityImpl responsibility: responsibilitySearchResults){
154 for(ResponsibilityImpl responsibilityFromRoleSearch: responsibilitiesForRoleSearchResults){
155 if(responsibilityFromRoleSearch.getResponsibilityId().equals(responsibility.getResponsibilityId()))
156 matchedResponsibilities.add(responsibilityFromRoleSearch);
157 }
158 }
159 }
160
161
162
163
164
165
166
167
168
169
170 return matchedResponsibilities;
171 }
172
173 @SuppressWarnings("unchecked")
174 private List<ResponsibilityImpl> searchResponsibilities(Map<String, String> responsibilitySearchCriteria, boolean unbounded){
175 return getResponsibilitiesSearchResultsCopy((List<KimResponsibilityImpl>)
176 getLookupService().findCollectionBySearchHelper(
177 KimResponsibilityImpl.class, responsibilitySearchCriteria, unbounded));
178 }
179
180 private List<ResponsibilityImpl> getResponsibilitiesWithRoleSearchCriteria(Map<String, String> roleSearchCriteria, boolean unbounded){
181 List<RoleImpl> roleSearchResults = searchRoles(roleSearchCriteria, unbounded);
182 return getResponsibilitiesForRoleSearchResults(roleSearchResults, unbounded);
183 }
184
185 private List<ResponsibilityImpl> getResponsibilitiesForRoleSearchResults(List<RoleImpl> roleSearchResults, boolean unbounded){
186 Long actualSizeIfTruncated = getActualSizeIfTruncated(roleSearchResults);
187 List<ResponsibilityImpl> responsibilities = new ArrayList<ResponsibilityImpl>();
188 List<ResponsibilityImpl> tempResponsibilities;
189 List<String> collectedResponsibilityIds = new ArrayList<String>();
190 Map<String, String> responsibilityCriteria;
191
192 for(RoleImpl roleImpl: roleSearchResults){
193 responsibilityCriteria = new HashMap<String, String>();
194 responsibilityCriteria.put("roleResponsibilities.roleId", roleImpl.getRoleId());
195 tempResponsibilities = searchResponsibilities(responsibilityCriteria, unbounded);
196 actualSizeIfTruncated += getActualSizeIfTruncated(tempResponsibilities);
197 for(ResponsibilityImpl responsibility: tempResponsibilities){
198 if(!collectedResponsibilityIds.contains(responsibility.getResponsibilityId())){
199 populateAssignedToRoles(responsibility);
200 collectedResponsibilityIds.add(responsibility.getResponsibilityId());
201 responsibilities.add(responsibility);
202 }
203
204 List<String> parentRoleIds = KIMServiceLocator.getRoleService().getMemberParentRoleIds(KimConstants.KimUIConstants.MEMBER_TYPE_ROLE_CODE, roleImpl.getRoleId());
205 for (String parentRoleId : parentRoleIds) {
206 Map<String, String> roleSearchCriteria = new HashMap<String, String>();
207 roleSearchCriteria.put("roleId", parentRoleId);
208
209 responsibilities = mergeResponsibilityLists(responsibilities, getResponsibilitiesWithRoleSearchCriteria(roleSearchCriteria, unbounded));
210 }
211 }
212 }
213 return new CollectionIncomplete<ResponsibilityImpl>(responsibilities, actualSizeIfTruncated);
214 }
215
216 private void populateAssignedToRoles(ResponsibilityImpl responsibility){
217 AttributeSet criteria = new AttributeSet();
218 if ( responsibility.getAssignedToRoles().isEmpty() ) {
219 for(RoleResponsibilityImpl roleResponsibility: responsibility.getRoleResponsibilities()){
220 criteria.put(KimConstants.PrimaryKeyConstants.ROLE_ID, roleResponsibility.getRoleId());
221 responsibility.getAssignedToRoles().add((RoleImpl)getBusinessObjectService().findByPrimaryKey(RoleImpl.class, criteria));
222 }
223 }
224 }
225
226
227
228
229 private static final Map<Map<String,String>,MaxAgeSoftReference<List<ResponsibilityImpl>>> respResultCache = new HashMap<Map<String,String>, MaxAgeSoftReference<List<ResponsibilityImpl>>>();
230 private static final long RESP_CACHE_EXPIRE_SECONDS = 30L;
231
232 private List<ResponsibilityImpl> getResponsibilitiesWithResponsibilitySearchCriteria(Map<String, String> responsibilitySearchCriteria, boolean unbounded){
233 String detailCriteriaStr = responsibilitySearchCriteria.remove( DETAIL_CRITERIA );
234 AttributeSet detailCriteria = parseDetailCriteria(detailCriteriaStr);
235 MaxAgeSoftReference<List<ResponsibilityImpl>> cachedResult = respResultCache.get(responsibilitySearchCriteria);
236 List<ResponsibilityImpl> responsibilities = null;
237 if ( cachedResult == null || cachedResult.get() == null ) {
238 responsibilities = searchResponsibilities(responsibilitySearchCriteria, unbounded);
239 synchronized( respResultCache ) {
240 respResultCache.put(responsibilitySearchCriteria, new MaxAgeSoftReference<List<ResponsibilityImpl>>( RESP_CACHE_EXPIRE_SECONDS, responsibilities ) );
241 }
242 } else {
243 responsibilities = cachedResult.get();
244 }
245 List<ResponsibilityImpl> filteredResponsibilities = new CollectionIncomplete<ResponsibilityImpl>(
246 new ArrayList<ResponsibilityImpl>(), getActualSizeIfTruncated(responsibilities));
247 for(ResponsibilityImpl responsibility: responsibilities){
248 if ( detailCriteria.isEmpty() ) {
249 filteredResponsibilities.add(responsibility);
250 populateAssignedToRoles(responsibility);
251 } else {
252 if ( isMapSubset( responsibility.getDetails(), detailCriteria ) ) {
253 filteredResponsibilities.add(responsibility);
254 populateAssignedToRoles(responsibility);
255 }
256 }
257 }
258 return filteredResponsibilities;
259 }
260
261 private List<ResponsibilityImpl> getResponsibilitiesSearchResultsCopy(List<KimResponsibilityImpl> responsibilitySearchResults){
262 List<ResponsibilityImpl> responsibilitySearchResultsCopy = new CollectionIncomplete<ResponsibilityImpl>(
263 new ArrayList<ResponsibilityImpl>(), getActualSizeIfTruncated(responsibilitySearchResults));
264 for(KimResponsibilityImpl responsibilityImpl: responsibilitySearchResults){
265 ResponsibilityImpl responsibilityCopy = new ResponsibilityImpl();
266 try{
267 PropertyUtils.copyProperties(responsibilityCopy, responsibilityImpl);
268 } catch(Exception ex){
269 LOG.error( "Unable to copy properties from KimResponsibilityImpl to ResponsibilityImpl, skipping.", ex );
270 continue;
271 }
272 responsibilitySearchResultsCopy.add(responsibilityCopy);
273 }
274 return responsibilitySearchResultsCopy;
275 }
276
277
278
279
280
281 public LookupService getLookupService() {
282 if ( lookupService == null ) {
283 lookupService = KNSServiceLocator.getLookupService();
284 }
285 return lookupService;
286 }
287
288 private List<ResponsibilityImpl> mergeResponsibilityLists(List<ResponsibilityImpl> perm1, List<ResponsibilityImpl> perm2) {
289 List<ResponsibilityImpl> returnList = new ArrayList<ResponsibilityImpl>(perm1);
290 List<String> responsibilityIds = new ArrayList<String>(perm1.size());
291 for (ResponsibilityImpl perm : returnList) {
292 responsibilityIds.add(perm.getResponsibilityId());
293 }
294 for (int i=0; i<perm2.size(); i++) {
295 if (!responsibilityIds.contains(perm2.get(i).getResponsibilityId())) {
296 returnList.add(perm2.get(i));
297 }
298 }
299 return returnList;
300 }
301 }