1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.rule.web;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.apache.struts.action.ActionForm;
21 import org.apache.struts.action.ActionForward;
22 import org.apache.struts.action.ActionMapping;
23 import org.apache.struts.action.ActionMessages;
24 import org.kuali.rice.core.api.config.property.ConfigContext;
25 import org.kuali.rice.core.api.criteria.Predicate;
26 import org.kuali.rice.core.api.criteria.QueryByCriteria;
27 import org.kuali.rice.kew.doctype.bo.DocumentType;
28 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
29 import org.kuali.rice.kew.engine.node.BranchPrototype;
30 import org.kuali.rice.kew.engine.node.RouteNode;
31 import org.kuali.rice.kew.engine.node.RouteNodeConfigParam;
32 import org.kuali.rice.kew.rule.RuleBaseValues;
33 import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
34 import org.kuali.rice.kew.rule.service.RuleServiceInternal;
35 import org.kuali.rice.kew.service.KEWServiceLocator;
36 import org.kuali.rice.kew.api.KewApiConstants;
37 import org.kuali.rice.kew.web.KewKualiAction;
38 import org.kuali.rice.kim.api.KimConstants;
39 import org.kuali.rice.kim.api.group.Group;
40 import org.kuali.rice.kim.api.permission.Permission;
41 import org.kuali.rice.kim.api.responsibility.Responsibility;
42 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
43 import org.kuali.rice.kns.service.DocumentHelperService;
44 import org.kuali.rice.kns.service.KNSServiceLocator;
45 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
46 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
47 import org.kuali.rice.krad.util.GlobalVariables;
48 import org.kuali.rice.krad.util.KRADConstants;
49
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52 import java.util.ArrayList;
53 import java.util.Collections;
54 import java.util.Comparator;
55 import java.util.HashMap;
56 import java.util.Iterator;
57 import java.util.List;
58
59 import static org.kuali.rice.core.api.criteria.PredicateFactory.and;
60 import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
61
62
63
64
65
66
67
68 public class RuleQuickLinksAction extends KewKualiAction {
69
70 private static final Logger LOG = Logger.getLogger(RuleQuickLinksAction.class);
71
72 private MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
73 private DocumentHelperService documentHelperService;
74
75 public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
76 makeLookupPathParam(mapping, request);
77 establishRequiredState(request, form);
78 return mapping.findForward("basic");
79 }
80
81 @SuppressWarnings("unchecked")
82 public ActionMessages establishRequiredState(HttpServletRequest request, ActionForm form) throws Exception {
83 RuleQuickLinksForm qlForm = (RuleQuickLinksForm) form;
84 List<DocumentType> documentTypes;
85 if (qlForm.getRootDocTypeName() != null) {
86 documentTypes = new ArrayList<DocumentType>();
87 DocumentType docType = getDocumentTypeService().findByName(qlForm.getRootDocTypeName());
88 documentTypes.add(docType);
89 request.setAttribute("renderOpened", Boolean.TRUE);
90 } else {
91 documentTypes = getDocumentTypeService().findAllCurrentRootDocuments();
92 }
93 qlForm.setDocumentTypeQuickLinksStructures(getDocumentTypeDataStructure(documentTypes));
94 int shouldDisplayCount = 0;
95 for ( DocumentTypeQuickLinksStructure dt : qlForm.getDocumentTypeQuickLinksStructures() ) {
96 if ( dt.isShouldDisplay() ) {
97 shouldDisplayCount++;
98 }
99 }
100 if ( shouldDisplayCount == 1 ) {
101 request.setAttribute("renderOpened", Boolean.TRUE);
102 }
103 String documentTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName(DocumentType.class);
104 try {
105 if ((documentTypeName != null) && getDocumentHelperService().getDocumentAuthorizer(documentTypeName).canInitiate(documentTypeName, GlobalVariables.getUserSession().getPerson())) {
106 qlForm.setCanInitiateDocumentTypeDocument( true );
107 }
108 } catch (Exception ex) {
109
110 LOG.error( "Unable to check initiation permission for "+ documentTypeName, ex );
111 }
112
113 return null;
114 }
115
116 public ActionForward addDelegationRule(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
117 ActionForward result = null;
118
119 String ruleTemplateId = request.getParameter("delegationRule.ruleTemplate.id");
120 String docTypeName = request.getParameter("delegationRule.documentType.name");
121 List rules = getRuleService().search(docTypeName, null, ruleTemplateId, "", null, null, Boolean.FALSE, Boolean.TRUE, new HashMap(), null);
122
123 if (rules.size() == 1) {
124 RuleBaseValues rule = (RuleBaseValues)rules.get(0);
125 String url = ConfigContext.getCurrentContextConfig().getKEWBaseURL() +
126 "/DelegateRule.do?methodToCall=start" +
127 "&parentRuleId=" + rule.getId();
128 result = new ActionForward(url, true);
129 } else {
130 makeLookupPathParam(mapping, request);
131 result = new ActionForward(ConfigContext.getCurrentContextConfig().getKRBaseURL() +
132 "/lookup.do?methodToCall=start&"+ stripMethodToCall(request.getQueryString()), true);
133 }
134
135 return result;
136 }
137
138 private List getDocumentTypeDataStructure(List rootDocuments) {
139 List documentTypeQuickLinksStructures = new ArrayList();
140 for (Iterator iter = rootDocuments.iterator(); iter.hasNext();) {
141 DocumentTypeQuickLinksStructure quickLinkStruct =new DocumentTypeQuickLinksStructure((DocumentType) iter.next());
142 if (! quickLinkStruct.getFlattenedNodes().isEmpty() || ! quickLinkStruct.getChildrenDocumentTypes().isEmpty()) {
143 documentTypeQuickLinksStructures.add(quickLinkStruct);
144 }
145
146 }
147
148 return documentTypeQuickLinksStructures;
149 }
150
151
152
153
154
155
156
157
158 public static class DocumentTypeQuickLinksStructure {
159 private DocumentType documentType;
160 private List<RouteNode> flattenedNodes = new ArrayList<RouteNode>();
161 private List<DocumentTypeQuickLinksStructure> childrenDocumentTypes = new ArrayList<DocumentTypeQuickLinksStructure>();
162 private List<Permission> permissions = null;
163
164 private DocumentTypeQuickLinksStructure(DocumentType documentType) {
165 this.documentType = documentType;
166 if ( documentType != null ) {
167 List<RouteNode> tempFlattenedNodes = KEWServiceLocator.getRouteNodeService()
168 .getFlattenedNodes( documentType, true );
169 for ( RouteNode routeNode : tempFlattenedNodes ) {
170 if ( routeNode.isFlexRM() || routeNode.isRoleNode() ) {
171 flattenedNodes.add( new RouteNodeForDisplay( routeNode ) );
172 }
173 }
174
175
176
177
178
179
180 for ( Iterator<DocumentType> iter = documentType.getChildrenDocTypes().iterator(); iter.hasNext(); ) {
181 childrenDocumentTypes.add( new DocumentTypeQuickLinksStructure( iter.next() ) );
182 }
183 Collections.sort(childrenDocumentTypes,new Comparator() {
184 public int compare(Object o1, Object o2) {
185 return ( ((DocumentTypeQuickLinksStructure)o1).documentType.getLabel().compareTo(((DocumentTypeQuickLinksStructure)o2).documentType.getLabel()));
186 }
187 });
188 }
189 }
190
191 public List getChildrenDocumentTypes() {
192 return childrenDocumentTypes;
193 }
194 public void setChildrenDocumentTypes(List<DocumentTypeQuickLinksStructure> childrenDocumentTypes) {
195 this.childrenDocumentTypes = childrenDocumentTypes;
196 }
197 public DocumentType getDocumentType() {
198 return documentType;
199 }
200 public void setDocumentType(DocumentType documentType) {
201 this.documentType = documentType;
202 }
203 public List getFlattenedNodes() {
204 return flattenedNodes;
205 }
206 public void setFlattenedNodes(List<RouteNode> flattenedNodes) {
207 this.flattenedNodes = flattenedNodes;
208 }
209 public boolean isShouldDisplay() {
210
211
212
213
214
215
216
217
218 return true;
219 }
220
221 public List<Permission> getPermissions() {
222 if ( permissions == null ) {
223 Predicate p = and(
224 equal("attributeName", "documentTypeName"),
225 equal("active", Boolean.TRUE),
226 equal("detailCriteria",
227 KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME+"="+getDocumentType().getName()));
228 permissions = KimApiServiceLocator.getPermissionService().findPermissions( QueryByCriteria.Builder.fromPredicates(p)).getResults();
229
230 }
231 return permissions;
232 }
233
234 public boolean isHasRelatedPermissions() {
235 return !getPermissions().isEmpty();
236 }
237
238 public int getRelatedPermissionCount() {
239 return getPermissions().size();
240 }
241 }
242
243 public static class RouteNodeForDisplay extends RouteNode {
244 private static final long serialVersionUID = 1L;
245 private RouteNode baseNode;
246
247 public RouteNodeForDisplay( RouteNode baseNode ) {
248 this.baseNode = baseNode;
249 }
250
251 public boolean equals(Object obj) {
252 return this.baseNode.equals(obj);
253 }
254
255 public String getActivationType() {
256 return this.baseNode.getActivationType();
257 }
258
259 public BranchPrototype getBranch() {
260 return this.baseNode.getBranch();
261 }
262
263 public List<RouteNodeConfigParam> getConfigParams() {
264 return this.baseNode.getConfigParams();
265 }
266
267 public String getContentFragment() {
268 return this.baseNode.getContentFragment();
269 }
270
271 public DocumentType getDocumentType() {
272 return this.baseNode.getDocumentType();
273 }
274
275 public String getDocumentTypeId() {
276 return this.baseNode.getDocumentTypeId();
277 }
278 public Group getExceptionWorkgroup() {
279 return this.baseNode.getExceptionWorkgroup();
280 }
281 public String getExceptionWorkgroupId() {
282 return this.baseNode.getExceptionWorkgroupId();
283 }
284 public String getExceptionWorkgroupName() {
285 return this.baseNode.getExceptionWorkgroupName();
286 }
287 public Boolean getFinalApprovalInd() {
288 return this.baseNode.getFinalApprovalInd();
289 }
290 public Integer getLockVerNbr() {
291 return this.baseNode.getLockVerNbr();
292 }
293 public Boolean getMandatoryRouteInd() {
294 return this.baseNode.getMandatoryRouteInd();
295 }
296 public List<RouteNode> getNextNodes() {
297 return this.baseNode.getNextNodes();
298 }
299 public String getNodeType() {
300 return this.baseNode.getNodeType();
301 }
302 public List<RouteNode> getPreviousNodes() {
303 return this.baseNode.getPreviousNodes();
304 }
305 public String getRouteMethodCode() {
306 return this.baseNode.getRouteMethodCode();
307 }
308 public String getRouteMethodName() {
309 return this.baseNode.getRouteMethodName();
310 }
311 public String getRouteNodeId() {
312 return this.baseNode.getRouteNodeId();
313 }
314 public String getRouteNodeName() {
315 return this.baseNode.getRouteNodeName();
316 }
317 public RuleTemplateBo getRuleTemplate() {
318 return this.baseNode.getRuleTemplate();
319 }
320 public int hashCode() {
321 return this.baseNode.hashCode();
322 }
323 public boolean isExceptionGroupDefined() {
324 return this.baseNode.isExceptionGroupDefined();
325 }
326 public boolean isFlexRM() {
327 return this.baseNode.isFlexRM();
328 }
329 public boolean isRoleNode() {
330 return this.baseNode.isRoleNode();
331 }
332 public String toString() {
333 return this.baseNode.toString();
334 }
335
336 private List<Responsibility> responsibilities = null;
337
338 public List<Responsibility> getResponsibilities() {
339 if ( responsibilities == null ) {
340 QueryByCriteria.Builder builder = QueryByCriteria.Builder.create();
341 Predicate p = and(
342 equal("template.namespaceCode", KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE),
343 equal("template.name", KewApiConstants.DEFAULT_RESPONSIBILITY_TEMPLATE_NAME),
344 equal("active", Boolean.TRUE),
345 equal("attributes[documentTypeName]", getDocumentType().getName())
346
347
348
349 );
350
351
352 builder.setPredicates(p);
353
354 List<Responsibility> possibleResponsibilities =
355 KimApiServiceLocator.getResponsibilityService().findResponsibilities(builder.build()).getResults();
356
357 if ( !possibleResponsibilities.isEmpty() ) {
358 for ( Responsibility resp : possibleResponsibilities ) {
359 String routeNodeName = resp.getAttributes().get( KimConstants.AttributeConstants.ROUTE_NODE_NAME);
360 if (StringUtils.isNotEmpty(routeNodeName) && StringUtils.equals(routeNodeName, getRouteNodeName())){
361 responsibilities.add(resp);
362 }
363 }
364 } else {
365 responsibilities = possibleResponsibilities;
366 }
367 }
368 return responsibilities;
369 }
370
371 public int getResponsibilityCount() {
372 return getResponsibilities().size();
373 }
374
375 public boolean isHasResponsibility() {
376 return !getResponsibilities().isEmpty();
377 }
378 }
379
380 private void makeLookupPathParam(ActionMapping mapping, HttpServletRequest request) {
381 String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + mapping.getModuleConfig().getPrefix();
382 request.setAttribute("basePath", basePath);
383 }
384
385 private String stripMethodToCall(String queryString) {
386 return queryString.replaceAll("methodToCall=addDelegationRule&", "");
387 }
388
389 private DocumentTypeService getDocumentTypeService() {
390 return KEWServiceLocator.getDocumentTypeService();
391 }
392
393 private RuleServiceInternal getRuleService() {
394 return KEWServiceLocator.getRuleService();
395 }
396
397 public DocumentHelperService getDocumentHelperService() {
398 if(documentHelperService == null){
399 documentHelperService = KNSServiceLocator.getDocumentHelperService();
400 }
401 return documentHelperService;
402 }
403
404 public MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
405 if(maintenanceDocumentDictionaryService == null){
406 maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
407 }
408 return maintenanceDocumentDictionaryService;
409 }
410
411 @Override
412 public ActionForward toggleTab(ActionMapping mapping, ActionForm form,
413 HttpServletRequest request, HttpServletResponse response)
414 throws Exception {
415
416 establishRequiredState(request, form);
417 return super.toggleTab(mapping, form, request, response);
418 }
419
420 }