1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krms.impl.ui;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.criteria.QueryByCriteria;
21 import org.kuali.rice.core.api.criteria.QueryResults;
22 import org.kuali.rice.core.api.uif.RemotableAttributeError;
23 import org.kuali.rice.core.api.util.KeyValue;
24 import org.kuali.rice.core.api.util.io.SerializationUtils;
25 import org.kuali.rice.core.api.util.tree.Node;
26 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
27 import org.kuali.rice.krad.service.KRADServiceLocator;
28 import org.kuali.rice.krad.uif.UifParameters;
29 import org.kuali.rice.krad.util.GlobalVariables;
30 import org.kuali.rice.krad.util.KRADUtils;
31 import org.kuali.rice.krad.web.controller.MaintenanceDocumentController;
32 import org.kuali.rice.krad.web.controller.MethodAccessible;
33 import org.kuali.rice.krad.web.form.DocumentFormBase;
34 import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
35 import org.kuali.rice.krad.web.form.UifFormBase;
36 import org.kuali.rice.krms.api.KrmsApiServiceLocator;
37 import org.kuali.rice.krms.api.engine.expression.ComparisonOperatorService;
38 import org.kuali.rice.krms.api.repository.LogicalOperator;
39 import org.kuali.rice.krms.api.repository.operator.CustomOperator;
40 import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
41 import org.kuali.rice.krms.api.repository.proposition.PropositionType;
42 import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
43 import org.kuali.rice.krms.api.repository.term.TermDefinition;
44 import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
45 import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
46 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
47 import org.kuali.rice.krms.impl.repository.ActionBo;
48 import org.kuali.rice.krms.impl.repository.AgendaBo;
49 import org.kuali.rice.krms.impl.repository.AgendaItemBo;
50 import org.kuali.rice.krms.impl.repository.ContextBoService;
51 import org.kuali.rice.krms.impl.repository.FunctionBoService;
52 import org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService;
53 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
54 import org.kuali.rice.krms.impl.repository.PropositionBo;
55 import org.kuali.rice.krms.impl.repository.PropositionParameterBo;
56 import org.kuali.rice.krms.impl.repository.RepositoryBoIncrementer;
57 import org.kuali.rice.krms.impl.repository.RuleBo;
58 import org.kuali.rice.krms.impl.repository.RuleBoService;
59 import org.kuali.rice.krms.impl.repository.TermBo;
60 import org.kuali.rice.krms.impl.rule.AgendaEditorBusRule;
61 import org.kuali.rice.krms.impl.util.KRMSPropertyConstants;
62 import org.kuali.rice.krms.impl.util.KrmsImplConstants;
63 import org.kuali.rice.krms.impl.util.KrmsServiceLocatorInternal;
64 import org.springframework.stereotype.Controller;
65 import org.springframework.validation.BindingResult;
66 import org.springframework.web.bind.annotation.ModelAttribute;
67 import org.springframework.web.bind.annotation.RequestMapping;
68 import org.springframework.web.bind.annotation.RequestMethod;
69 import org.springframework.web.bind.annotation.RequestParam;
70 import org.springframework.web.bind.annotation.ResponseBody;
71 import org.springframework.web.servlet.ModelAndView;
72
73 import javax.servlet.http.HttpServletRequest;
74 import javax.servlet.http.HttpServletResponse;
75 import java.util.ArrayList;
76 import java.util.Collections;
77 import java.util.HashMap;
78 import java.util.List;
79 import java.util.Map;
80
81
82
83
84
85 @Controller
86 @RequestMapping(value = org.kuali.rice.krms.impl.util.KrmsImplConstants.WebPaths.AGENDA_EDITOR_PATH)
87 public class AgendaEditorController extends MaintenanceDocumentController {
88
89 private static final RepositoryBoIncrementer agendaIdIncrementer = new RepositoryBoIncrementer(AgendaBo.AGENDA_SEQ_NAME);
90 private static final RepositoryBoIncrementer agendaItemIdIncrementer = new RepositoryBoIncrementer(AgendaItemBo.AGENDA_ITEM_SEQ_NAME);
91 private static final RepositoryBoIncrementer ruleIdIncrementer = new RepositoryBoIncrementer(RuleBo.RULE_SEQ_NAME);
92
93
94
95
96
97
98
99 @Override
100 @RequestMapping(params = "methodToCall=route")
101 public ModelAndView route(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
102 HttpServletRequest request, HttpServletResponse response) {
103
104 ModelAndView modelAndView;
105 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) form;
106 AgendaEditor agendaEditor = ((AgendaEditor) maintenanceForm.getDocument().getNewMaintainableObject().getDataObject());
107 agendaEditor.setSelectedAgendaItemId("");
108 agendaEditor.setDisableButtons(true);
109 modelAndView = super.route(form, result, request, response);
110
111 return modelAndView;
112 }
113
114
115
116
117
118
119 @RequestMapping(params = "methodToCall=" + "refresh")
120 @Override
121 public ModelAndView refresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
122 HttpServletRequest request, HttpServletResponse response) throws Exception {
123 ModelAndView modelAndView = super.refresh(form, result, request, response);
124
125
126 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) form;
127 AgendaEditor agendaEditor = ((AgendaEditor) maintenanceForm.getDocument().getNewMaintainableObject().getDataObject());
128 AgendaEditorBusRule rule = new AgendaEditorBusRule();
129 if (rule.validContext(agendaEditor) && rule.validAgendaName(agendaEditor)) {
130
131 if (!StringUtils.equals(agendaEditor.getOldContextId(), agendaEditor.getAgenda().getContextId())) {
132 agendaEditor.setOldContextId(agendaEditor.getAgenda().getContextId());
133
134 String namespace = "";
135 if (!StringUtils.isBlank(agendaEditor.getAgenda().getContextId())) {
136 namespace = getContextBoService().getContextByContextId(agendaEditor.getAgenda().getContextId()).getNamespace();
137 }
138
139 for (AgendaItemBo agendaItem : agendaEditor.getAgenda().getItems()) {
140 agendaItem.getRule().setNamespace(namespace);
141 for (ActionBo action : agendaItem.getRule().getActions()) {
142 action.setNamespace(namespace);
143 }
144 }
145 }
146 }
147 return modelAndView;
148 }
149
150 @Override
151 @MethodAccessible
152 public ModelAndView maintenanceEdit(@ModelAttribute("KualiForm") MaintenanceDocumentForm form, BindingResult result,
153 HttpServletRequest request, HttpServletResponse response) throws Exception {
154
155
156 form.setPageId(null);
157 return super.maintenanceEdit(form,result,request,response);
158 }
159
160
161
162
163 @RequestMapping(params = "methodToCall=" + "goToAddRule")
164 public ModelAndView goToAddRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
165 HttpServletRequest request, HttpServletResponse response) throws Exception {
166 AgendaEditor agendaEditorForBusRuleChecks = getAgendaEditor(form);
167 AgendaEditorBusRule rule = new AgendaEditorBusRule();
168 if (rule.validContext(agendaEditorForBusRuleChecks) && rule.validAgendaName(agendaEditorForBusRuleChecks)) {
169 setAgendaItemLine(form, null);
170 AgendaEditor agendaEditor = getAgendaEditor(form);
171 agendaEditor.setAddRuleInProgress(true);
172 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-AddRule-Page");
173
174 return super.navigate(form, result, request, response);
175 }
176
177 return super.navigate(form, result, request, response);
178 }
179
180
181
182
183
184
185
186
187
188 private void setAgendaItemLine(UifFormBase form, AgendaItemBo agendaItem) {
189 AgendaEditor agendaEditor = getAgendaEditor(form);
190 if (agendaItem == null) {
191 RuleBo rule = new RuleBo();
192 rule.setId(ruleIdIncrementer.getNewId());
193 if (StringUtils.isBlank(agendaEditor.getAgenda().getContextId())) {
194 rule.setNamespace("");
195 } else {
196 rule.setNamespace(getContextBoService().getContextByContextId(agendaEditor.getAgenda().getContextId()).getNamespace());
197 }
198 agendaItem = new AgendaItemBo();
199 agendaItem.setRule(rule);
200 agendaEditor.setAgendaItemLine(agendaItem);
201 } else {
202
203 agendaEditor.setAgendaItemLine((AgendaItemBo) SerializationUtils.deepCopy(agendaItem));
204 }
205
206
207 if (agendaItem.getRule().getActions().isEmpty()) {
208 ActionBo actionBo = new ActionBo();
209 actionBo.setTypeId("");
210 actionBo.setNamespace(agendaItem.getRule().getNamespace());
211 actionBo.setRule(agendaItem.getRule());
212 actionBo.setSequenceNumber(1);
213 agendaEditor.setAgendaItemLineRuleAction(actionBo);
214 } else {
215 agendaEditor.setAgendaItemLineRuleAction(agendaItem.getRule().getActions().get(0));
216 }
217
218 agendaEditor.setCustomRuleActionAttributesMap(agendaEditor.getAgendaItemLineRuleAction().getAttributes());
219 agendaEditor.setCustomRuleAttributesMap(agendaEditor.getAgendaItemLine().getRule().getAttributes());
220 }
221
222
223
224
225
226
227
228 private String getSelectedAgendaItemId(UifFormBase form) {
229 AgendaEditor agendaEditor = getAgendaEditor(form);
230 return agendaEditor.getSelectedAgendaItemId();
231 }
232
233
234
235
236
237
238
239 private void setCutAgendaItemId(UifFormBase form, String cutAgendaItemId) {
240 AgendaEditor agendaEditor = getAgendaEditor(form);
241 agendaEditor.setCutAgendaItemId(cutAgendaItemId);
242 }
243
244
245
246
247
248
249
250 private String getCutAgendaItemId(UifFormBase form) {
251 AgendaEditor agendaEditor = getAgendaEditor(form);
252 return agendaEditor.getCutAgendaItemId();
253 }
254
255
256
257
258 @RequestMapping(params = "methodToCall=" + "goToEditRule")
259 public ModelAndView goToEditRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
260 HttpServletRequest request, HttpServletResponse response) throws Exception {
261
262 AgendaEditor agendaEditor = getAgendaEditor(form);
263 AgendaEditorBusRule rule = new AgendaEditorBusRule();
264
265 if (rule.validContext(agendaEditor) && rule.validAgendaName(agendaEditor)) {
266 agendaEditor.setAddRuleInProgress(false);
267
268 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
269 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
270 AgendaItemBo node = getAgendaItemById(firstItem, selectedItemId);
271
272 preprocessCustomOperators(node.getRule().getProposition(), getCustomOperatorValueMap(form));
273
274 setAgendaItemLine(form, node);
275
276 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-EditRule-Page");
277
278 return super.navigate(form, result, request, response);
279 }
280
281 return super.navigate(form, result, request, response);
282 }
283
284
285
286
287
288
289
290
291
292 protected Map<String,String> getCustomOperatorValueMap(UifFormBase form) {
293 List<KeyValue> allPropositionOpCodes = new PropositionOpCodeValuesFinder().getKeyValues(form);
294
295
296 Map<String, String> functionIdToCustomOpCodeMap = new HashMap<String, String>();
297 for (KeyValue opCode : allPropositionOpCodes) {
298 if (opCode.getKey().startsWith(KrmsImplConstants.CUSTOM_OPERATOR_PREFIX)) {
299 CustomOperator customOperator = getCustomOperatorUiTranslator().getCustomOperator(opCode.getKey());
300 functionIdToCustomOpCodeMap.put(customOperator.getOperatorFunctionDefinition().getId(), opCode.getKey());
301 }
302 }
303
304 return functionIdToCustomOpCodeMap;
305 }
306
307
308
309
310
311
312
313
314 protected void preprocessCustomOperators(PropositionBo proposition, Map<String, String> customOperatorValuesMap) {
315 if (proposition == null) { return; }
316
317 if (proposition.getParameters() != null && proposition.getParameters().size() > 0) {
318 for (PropositionParameterBo param : proposition.getParameters()) {
319 if (PropositionParameterType.FUNCTION.getCode().equals(param.getParameterType())) {
320
321 String convertedValue = customOperatorValuesMap.get(param.getValue());
322 if (!StringUtils.isEmpty(convertedValue)) {
323 param.setValue(convertedValue);
324 }
325 }
326 }
327 } else if (proposition.getCompoundComponents() != null && proposition.getCompoundComponents().size() > 0) {
328 for (PropositionBo childProposition : proposition.getCompoundComponents()) {
329
330 preprocessCustomOperators(childProposition, customOperatorValuesMap);
331 }
332 }
333 }
334
335
336
337
338 @RequestMapping(params = "methodToCall=" + "addRule")
339 public ModelAndView addRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
340 HttpServletRequest request, HttpServletResponse response) throws Exception {
341
342 AgendaEditor agendaEditor = getAgendaEditor(form);
343 AgendaBo agenda = agendaEditor.getAgenda();
344 AgendaItemBo newAgendaItem = agendaEditor.getAgendaItemLine();
345
346 if (!validateProposition(newAgendaItem.getRule().getProposition(), newAgendaItem.getRule().getNamespace())) {
347 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-AddRule-Page");
348
349 return super.navigate(form, result, request, response);
350 }
351
352 newAgendaItem.getRule().setAttributes(agendaEditor.getCustomRuleAttributesMap());
353 updateRuleAction(agendaEditor);
354
355 if (agenda.getItems() == null) {
356 agenda.setItems(new ArrayList<AgendaItemBo>());
357 }
358
359 AgendaEditorBusRule rule = new AgendaEditorBusRule();
360 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) form;
361 MaintenanceDocument document = maintenanceForm.getDocument();
362
363 if (rule.processAgendaItemBusinessRules(document)) {
364 newAgendaItem.setId(agendaItemIdIncrementer.getNewId());
365 newAgendaItem.setAgendaId(getCreateAgendaId(agenda));
366
367 if (agenda.getFirstItemId() == null) {
368 agenda.setFirstItemId(newAgendaItem.getId());
369 } else {
370
371 String selectedAgendaItemId = getSelectedAgendaItemId(form);
372
373 if (StringUtils.isBlank(selectedAgendaItemId)) {
374
375 AgendaItemBo node = getFirstAgendaItem(agenda);
376 while (node.getAlways() != null) {
377 node = node.getAlways();
378 }
379 node.setAlwaysId(newAgendaItem.getId());
380 node.setAlways(newAgendaItem);
381 } else {
382
383 AgendaItemBo firstItem = getFirstAgendaItem(agenda);
384 AgendaItemBo node = getAgendaItemById(firstItem, selectedAgendaItemId);
385 newAgendaItem.setAlwaysId(node.getAlwaysId());
386 newAgendaItem.setAlways(node.getAlways());
387 node.setAlwaysId(newAgendaItem.getId());
388 node.setAlways(newAgendaItem);
389 }
390 }
391
392 agenda.getItems().add(newAgendaItem);
393 agendaEditor.setAddRuleInProgress(false);
394 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-Agenda-Page");
395 } else {
396 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-AddRule-Page");
397 }
398
399 return super.navigate(form, result, request, response);
400 }
401
402
403
404
405
406
407
408
409
410 private boolean validateProposition(PropositionBo proposition, String namespace) {
411 boolean result = true;
412
413 if (proposition != null) {
414
415 if (StringUtils.isBlank(proposition.getDescription())) {
416 GlobalVariables.getMessageMap().putError(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
417 "error.rule.proposition.missingDescription");
418 result &= false;
419 }
420
421 if (StringUtils.isBlank(proposition.getCompoundOpCode())) {
422
423
424 result &= validateSimpleProposition(proposition, namespace);
425
426 } else {
427
428 List<PropositionBo> compoundComponents = proposition.getCompoundComponents();
429
430 if (!CollectionUtils.isEmpty(proposition.getParameters())) {
431 GlobalVariables.getMessageMap().putError(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
432 "error.rule.proposition.compound.invalidParameter", proposition.getDescription());
433 result &= false;
434 }
435
436
437 if (!CollectionUtils.isEmpty(compoundComponents)) for (PropositionBo childProp : compoundComponents) {
438 result &= validateProposition(childProp, namespace);
439 }
440 }
441 }
442
443 return result;
444 }
445
446
447
448
449
450
451
452
453 private boolean validateSimpleProposition(PropositionBo proposition, String namespace) {
454 boolean result = true;
455
456 String propConstant = null;
457 if (proposition.getParameters().get(1) != null) {
458 propConstant = proposition.getParameters().get(1).getValue();
459 }
460 String operatorCode = null;
461 if (proposition.getParameters().get(2) != null) {
462 operatorCode = proposition.getParameters().get(2).getValue();
463 }
464
465 String termId = null;
466 if (proposition.getParameters().get(0) != null) {
467 termId = proposition.getParameters().get(0).getValue();
468 }
469
470
471 if (StringUtils.isBlank(termId)) {
472 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
473 "error.rule.proposition.simple.blankField", proposition.getDescription(), "Term");
474 result &= false;
475 } else {
476 result = validateTerm(proposition, namespace);
477 }
478
479 if (StringUtils.isBlank(operatorCode)) {
480 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
481 "error.rule.proposition.simple.blankField", proposition.getDescription(), "Operator");
482 result &= false;
483 }
484
485 if (StringUtils.isBlank(propConstant) && !operatorCode.endsWith("null")) {
486 GlobalVariables.getMessageMap().putErrorForSectionId(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
487 "error.rule.proposition.simple.blankField", proposition.getDescription(), "Value");
488 result &= false;
489 } else if (operatorCode.endsWith("null")) {
490 if (propConstant != null) {
491 proposition.getParameters().get(1).setValue(null);
492 }
493 } else if (!StringUtils.isBlank(termId)) {
494
495 String termType = lookupTermType(termId);
496
497 if (operatorCode.startsWith(KrmsImplConstants.CUSTOM_OPERATOR_PREFIX)) {
498 CustomOperator customOperator = getCustomOperatorUiTranslator().getCustomOperator(operatorCode);
499 List<RemotableAttributeError> errors = customOperator.validateOperandClasses(termType, String.class.getName());
500
501 if (!CollectionUtils.isEmpty(errors)) {
502 for (RemotableAttributeError error : errors) {
503 GlobalVariables.getMessageMap().putError(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
504 error.getMessage(), proposition.getDescription(), termType);
505 }
506
507 result &= false;
508 }
509 } else {
510 ComparisonOperatorService comparisonOperatorService = KrmsApiServiceLocator.getComparisonOperatorService();
511 if (comparisonOperatorService.canCoerce(termType, propConstant)) {
512 if (comparisonOperatorService.coerce(termType, propConstant) == null) {
513 GlobalVariables.getMessageMap().putError(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
514 "error.rule.proposition.simple.invalidValue", proposition.getDescription(), propConstant);
515 result &= false;
516 }
517 }
518 }
519 }
520
521 if (!CollectionUtils.isEmpty(proposition.getCompoundComponents())) {
522 GlobalVariables.getMessageMap().putError(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
523 "error.rule.proposition.simple.hasChildren", proposition.getDescription());
524 result &= false;
525 }
526
527 return result;
528 }
529
530
531
532
533
534
535
536
537 private boolean validateTerm(PropositionBo proposition, String namespace) {
538 boolean result = true;
539
540 String termId = proposition.getParameters().get(0).getValue();
541 if (termId.startsWith(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX)) {
542
543
544
545 if (StringUtils.isBlank(proposition.getNewTermDescription())) {
546 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
547 "error.rule.proposition.simple.emptyTermName", proposition.getDescription());
548 result &= false;
549 } else {
550
551 Map<String, String> critMap = new HashMap<String, String>();
552
553 critMap.put("description", proposition.getNewTermDescription());
554 critMap.put("specification.namespace", namespace);
555 QueryByCriteria criteria = QueryByCriteria.Builder.andAttributes(critMap).build();
556
557 QueryResults<TermBo> matchingTerms =
558 KRADServiceLocator.getDataObjectService().findMatching(TermBo.class, criteria);
559
560 if (!CollectionUtils.isEmpty(matchingTerms.getResults())) {
561
562 GlobalVariables.getMessageMap().putWarningWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
563 "warning.rule.proposition.simple.duplicateTermName", proposition.getDescription());
564 }
565 }
566
567 String termSpecificationId = termId.substring(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX.length());
568
569 TermResolverDefinition termResolverDefinition =
570 AgendaEditorMaintainable.getSimplestTermResolver(termSpecificationId, namespace);
571
572 if (termResolverDefinition == null) {
573 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
574 "error.rule.proposition.simple.invalidTerm", proposition.getDescription());
575 result &= false;
576 } else {
577 List<String> parameterNames = new ArrayList<String>(termResolverDefinition.getParameterNames());
578 Collections.sort(parameterNames);
579 for (String parameterName : parameterNames) {
580 if (!proposition.getTermParameters().containsKey(parameterName) ||
581 StringUtils.isBlank(proposition.getTermParameters().get(parameterName))) {
582 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
583 "error.rule.proposition.simple.missingTermParameter", proposition.getDescription());
584 result &= false;
585 break;
586 }
587 }
588 }
589
590 } else {
591
592 TermDefinition termDefinition = KrmsRepositoryServiceLocator.getTermBoService().getTerm(termId);
593 if (termDefinition == null) {
594 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
595 "error.rule.proposition.simple.invalidTerm", proposition.getDescription());
596 } else if (!namespace.equals(termDefinition.getSpecification().getNamespace())) {
597 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
598 "error.rule.proposition.simple.invalidTerm", proposition.getDescription());
599 }
600 }
601 return result;
602 }
603
604
605
606
607
608
609 private String lookupTermType(String key) {
610 TermSpecificationDefinition termSpec = null;
611 if (key.startsWith(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX)) {
612 String termSpecificationId = key.substring(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX.length());
613 termSpec = KrmsRepositoryServiceLocator.getTermBoService().getTermSpecificationById(termSpecificationId);
614 } else {
615 TermDefinition term = KrmsRepositoryServiceLocator.getTermBoService().getTerm(key);
616 if (term != null) {
617 termSpec = term.getSpecification();
618 }
619 }
620 if (termSpec != null) {
621 return termSpec.getType();
622 } else {
623 return null;
624 }
625 }
626
627
628
629
630
631 private String getCreateAgendaId(AgendaBo agenda) {
632 if (agenda.getId() == null) {
633 agenda.setId(agendaIdIncrementer.getNewId());
634 }
635
636 return agenda.getId();
637 }
638
639 private void updateRuleAction(AgendaEditor agendaEditor) {
640 agendaEditor.getAgendaItemLine().getRule().setActions(new ArrayList<ActionBo>());
641 if (StringUtils.isNotBlank(agendaEditor.getAgendaItemLineRuleAction().getTypeId())) {
642 agendaEditor.getAgendaItemLineRuleAction().setAttributes(agendaEditor.getCustomRuleActionAttributesMap());
643 agendaEditor.getAgendaItemLine().getRule().getActions().add(agendaEditor.getAgendaItemLineRuleAction());
644 }
645 }
646
647
648
649
650
651
652
653 private Map<String, KrmsAttributeDefinition> buildAttributeDefinitionMap(String actionTypeId) {
654 KrmsAttributeDefinitionService attributeDefinitionService =
655 KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
656
657
658 Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
659
660 List<KrmsAttributeDefinition> attributeDefinitions =
661 attributeDefinitionService.findAttributeDefinitionsByType(actionTypeId);
662
663 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
664 attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
665 }
666 return attributeDefinitionMap;
667 }
668
669
670
671
672 @RequestMapping(params = "methodToCall=" + "editRule")
673 public ModelAndView editRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
674 HttpServletRequest request, HttpServletResponse response) throws Exception {
675 AgendaEditor agendaEditor = getAgendaEditor(form);
676
677 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
678 AgendaItemBo node = getAgendaItemById(firstItem, getSelectedAgendaItemId(form));
679 AgendaItemBo agendaItemLine = agendaEditor.getAgendaItemLine();
680
681 if (!validateProposition(agendaItemLine.getRule().getProposition(), agendaItemLine.getRule().getNamespace())) {
682 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-EditRule-Page");
683
684 return super.navigate(form, result, request, response);
685 }
686
687 agendaItemLine.getRule().setAttributes(agendaEditor.getCustomRuleAttributesMap());
688 updateRuleAction(agendaEditor);
689
690 AgendaEditorBusRule rule = new AgendaEditorBusRule();
691 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) form;
692 MaintenanceDocument document = maintenanceForm.getDocument();
693 if (rule.processAgendaItemBusinessRules(document)) {
694 node.setRule(agendaItemLine.getRule());
695 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-Agenda-Page");
696 } else {
697 form.getActionParameters().put(UifParameters.NAVIGATE_TO_PAGE_ID, "AgendaEditorView-EditRule-Page");
698 }
699 return super.navigate(form, result, request, response);
700 }
701
702
703
704
705
706
707 private AgendaItemInstanceChildAccessor getLastChildsAlwaysAccessor(AgendaItemInstanceChildAccessor instanceAccessor) {
708 AgendaItemBo next = instanceAccessor.getChild();
709 if (next == null) return instanceAccessor;
710 while (next.getAlways() != null) { next = next.getAlways(); };
711 return new AgendaItemInstanceChildAccessor(AgendaItemChildAccessor.always, next);
712 }
713
714
715
716
717
718
719 private AgendaItemInstanceChildAccessor getInstanceAccessorToChild(AgendaItemBo parent, String agendaItemId) {
720
721
722 for (AgendaItemChildAccessor levelOrderChildAccessor : AgendaItemChildAccessor.children) {
723
724 AgendaItemBo next = levelOrderChildAccessor.getChild(parent);
725
726
727 if (next != null && agendaItemId.equals(next.getId())) return new AgendaItemInstanceChildAccessor(levelOrderChildAccessor, parent);
728
729
730 while (next != null && next.getAlwaysId() != null) {
731 if (next.getAlwaysId().equals(agendaItemId)) return new AgendaItemInstanceChildAccessor(AgendaItemChildAccessor.always, next);
732
733 next = next.getAlways();
734 }
735 }
736
737 return null;
738 }
739
740 @MethodAccessible
741 @RequestMapping(params = "methodToCall=" + "ajaxRefresh")
742 public ModelAndView ajaxRefresh(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
743 HttpServletRequest request, HttpServletResponse response)
744 throws Exception {
745
746 return getUIFModelAndView(form);
747 }
748
749 @MethodAccessible
750 @RequestMapping(params = "methodToCall=" + "ajaxMoveUp")
751 public ModelAndView ajaxMoveUp(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
752 HttpServletRequest request, HttpServletResponse response)
753 throws Exception {
754 moveSelectedSubtreeUp(form);
755
756
757 return getUIFModelAndView(form);
758 }
759
760
761
762
763
764
765
766 @MethodAccessible
767 @RequestMapping(params = "methodToCall=" + "ajaxValidRuleName", method=RequestMethod.GET)
768 public @ResponseBody boolean ajaxValidRuleName(@RequestParam String name, @RequestParam String namespace) {
769 return (getRuleBoService().getRuleByNameAndNamespace(name, namespace) != null);
770 }
771
772
773
774
775
776
777 private void moveSelectedSubtreeUp(UifFormBase form) {
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798 AgendaEditor agendaEditor = getAgendaEditor(form);
799
800 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
801
802 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
803 AgendaItemBo node = getAgendaItemById(firstItem, selectedItemId);
804 AgendaItemBo parent = getParent(firstItem, selectedItemId);
805 AgendaItemBo parentsOlderCousin = (parent == null) ? null : getNextOldestOfSameGeneration(firstItem, parent);
806
807 StringBuilder ruleEditorMessage = new StringBuilder();
808 AgendaItemChildAccessor childAccessor = getOldestChildAccessor(node, parent);
809 if (childAccessor != null) {
810 if (childAccessor == AgendaItemChildAccessor.whenFalse) {
811
812 AgendaItemInstanceChildAccessor youngestWhenTrueSiblingInsertionPoint =
813 getLastChildsAlwaysAccessor(new AgendaItemInstanceChildAccessor(AgendaItemChildAccessor.whenTrue, parent));
814 youngestWhenTrueSiblingInsertionPoint.setChild(node);
815 AgendaItemChildAccessor.whenFalse.setChild(parent, node.getAlways());
816 AgendaItemChildAccessor.always.setChild(node, null);
817
818 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" up ");
819 ruleEditorMessage.append("to last position in When TRUE group of ").append(parent.getRule().getName());
820 } else if (parentsOlderCousin != null) {
821
822 AgendaItemInstanceChildAccessor youngestWhenFalseSiblingInsertionPoint =
823 getLastChildsAlwaysAccessor(new AgendaItemInstanceChildAccessor(AgendaItemChildAccessor.whenFalse, parentsOlderCousin));
824 youngestWhenFalseSiblingInsertionPoint.setChild(node);
825 AgendaItemChildAccessor.whenTrue.setChild(parent, node.getAlways());
826 AgendaItemChildAccessor.always.setChild(node, null);
827 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" up ");
828 ruleEditorMessage.append("to When FALSE group of ").append(parentsOlderCousin.getRule().getName());
829 }
830 } else if (!selectedItemId.equals(firstItem.getId())) {
831
832 AgendaItemBo bogusRootNode = null;
833 if (parent == null) {
834
835 bogusRootNode = new AgendaItemBo();
836 AgendaItemChildAccessor.whenTrue.setChild(bogusRootNode, firstItem);
837 parent = bogusRootNode;
838 }
839
840
841 AgendaItemInstanceChildAccessor accessorToSelectedNode = getInstanceAccessorToChild(parent, node.getId());
842 AgendaItemBo olderSibling = accessorToSelectedNode.getInstance();
843 AgendaItemInstanceChildAccessor accessorToOlderSibling = getInstanceAccessorToChild(parent, olderSibling.getId());
844
845 accessorToOlderSibling.setChild(node);
846 accessorToSelectedNode.setChild(node.getAlways());
847 AgendaItemChildAccessor.always.setChild(node, olderSibling);
848
849 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" up ");
850
851 if (bogusRootNode != null) {
852
853 agendaEditor.getAgenda().setFirstItemId(bogusRootNode.getWhenTrueId());
854 ruleEditorMessage.append(" to ").append(getFirstAgendaItem(agendaEditor.getAgenda()).getRule().getName()).append(" When TRUE group");
855 } else {
856 ruleEditorMessage.append(" within its sibling group, above " + olderSibling.getRule().getName());
857 }
858 }
859 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
860 }
861
862 @MethodAccessible
863 @RequestMapping(params = "methodToCall=" + "ajaxMoveDown")
864 public ModelAndView ajaxMoveDown(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
865 HttpServletRequest request, HttpServletResponse response)
866 throws Exception {
867 moveSelectedSubtreeDown(form);
868
869
870 return getUIFModelAndView(form);
871 }
872
873
874
875
876
877
878 private void moveSelectedSubtreeDown(UifFormBase form) {
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899 AgendaEditor agendaEditor = getAgendaEditor(form);
900
901 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
902
903 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
904 AgendaItemBo node = getAgendaItemById(firstItem, selectedItemId);
905 AgendaItemBo parent = getParent(firstItem, selectedItemId);
906 AgendaItemBo parentsYoungerCousin = (parent == null) ? null : getNextYoungestOfSameGeneration(firstItem, parent);
907
908 StringBuilder ruleEditorMessage = new StringBuilder();
909 if (node.getAlways() == null && parent != null) {
910
911 if (parent.getWhenTrue() != null && isSiblings(parent.getWhenTrue(), node)) {
912
913 AgendaItemInstanceChildAccessor accessorToSelectedNode = getInstanceAccessorToChild(parent, node.getId());
914 accessorToSelectedNode.setChild(null);
915
916 AgendaItemBo parentsFirstChild = parent.getWhenFalse();
917 AgendaItemChildAccessor.whenFalse.setChild(parent, node);
918 AgendaItemChildAccessor.always.setChild(node, parentsFirstChild);
919
920 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" down ");
921 ruleEditorMessage.append("to first child under When FALSE group of ").append(parent.getRule().getName());
922 } else if (parentsYoungerCousin != null) {
923
924 AgendaItemInstanceChildAccessor accessorToSelectedNode = getInstanceAccessorToChild(parent, node.getId());
925 accessorToSelectedNode.setChild(null);
926
927 AgendaItemBo parentsYoungerCousinsFirstChild = parentsYoungerCousin.getWhenTrue();
928 AgendaItemChildAccessor.whenTrue.setChild(parentsYoungerCousin, node);
929 AgendaItemChildAccessor.always.setChild(node, parentsYoungerCousinsFirstChild);
930
931 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" down ");
932 ruleEditorMessage.append("to first child under When TRUE group of ").append(parentsYoungerCousin.getRule().getName());
933 }
934 } else if (node.getAlways() != null) {
935
936 AgendaItemBo bogusRootNode = null;
937 if (parent == null) {
938
939
940 bogusRootNode = new AgendaItemBo();
941 AgendaItemChildAccessor.whenFalse.setChild(bogusRootNode, firstItem);
942 parent = bogusRootNode;
943 }
944
945
946 AgendaItemInstanceChildAccessor accessorToSelectedNode = getInstanceAccessorToChild(parent, node.getId());
947 AgendaItemBo youngerSibling = node.getAlways();
948 accessorToSelectedNode.setChild(youngerSibling);
949 AgendaItemChildAccessor.always.setChild(node, youngerSibling.getAlways());
950 AgendaItemChildAccessor.always.setChild(youngerSibling, node);
951
952 if (bogusRootNode != null) {
953
954 agendaEditor.getAgenda().setFirstItemId(bogusRootNode.getWhenFalseId());
955 }
956 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" down ");
957 ruleEditorMessage.append(" within its sibling group, below ").append(youngerSibling.getRule().getName());
958 }
959 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
960 }
961
962 @MethodAccessible
963 @RequestMapping(params = "methodToCall=" + "ajaxMoveLeft")
964 public ModelAndView ajaxMoveLeft(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
965 HttpServletRequest request, HttpServletResponse response)
966 throws Exception {
967
968 moveSelectedSubtreeLeft(form);
969
970
971 return getUIFModelAndView(form);
972 }
973
974
975
976
977
978
979 private void moveSelectedSubtreeLeft(UifFormBase form) {
980
981
982
983
984
985 AgendaEditor agendaEditor = getAgendaEditor(form);
986
987 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
988
989 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
990 AgendaItemBo node = getAgendaItemById(firstItem, selectedItemId);
991 AgendaItemBo parent = getParent(firstItem, selectedItemId);
992
993 if (parent != null) {
994 AgendaItemInstanceChildAccessor accessorToSelectedNode = getInstanceAccessorToChild(parent, node.getId());
995 accessorToSelectedNode.setChild(node.getAlways());
996 AgendaItemChildAccessor.always.setChild(node, parent.getAlways());
997 AgendaItemChildAccessor.always.setChild(parent, node);
998
999 StringBuilder ruleEditorMessage = new StringBuilder();
1000 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" left to be a sibling of its parent ").append(parent.getRule().getName());
1001 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
1002 }
1003 }
1004
1005 @MethodAccessible
1006 @RequestMapping(params = "methodToCall=" + "ajaxMoveRight")
1007 public ModelAndView ajaxMoveRight(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1008 HttpServletRequest request, HttpServletResponse response)
1009 throws Exception {
1010
1011 moveSelectedSubtreeRight(form);
1012
1013
1014 return getUIFModelAndView(form);
1015 }
1016
1017
1018
1019
1020
1021
1022 private void moveSelectedSubtreeRight(UifFormBase form) {
1023
1024
1025
1026
1027
1028
1029
1030 AgendaEditor agendaEditor = getAgendaEditor(form);
1031
1032 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
1033
1034 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
1035 AgendaItemBo node = getAgendaItemById(firstItem, selectedItemId);
1036 AgendaItemBo parent = getParent(firstItem, selectedItemId);
1037
1038 AgendaItemBo bogusRootNode = null;
1039 if (parent == null) {
1040
1041 bogusRootNode = new AgendaItemBo();
1042 AgendaItemChildAccessor.whenFalse.setChild(bogusRootNode, firstItem);
1043 parent = bogusRootNode;
1044 }
1045
1046 AgendaItemInstanceChildAccessor accessorToSelectedNode = getInstanceAccessorToChild(parent, node.getId());
1047 AgendaItemBo olderSibling = (accessorToSelectedNode.getInstance() == parent) ? null : accessorToSelectedNode.getInstance();
1048
1049 StringBuilder ruleEditorMessage = new StringBuilder();
1050 if (olderSibling != null) {
1051 accessorToSelectedNode.setChild(node.getAlways());
1052 AgendaItemInstanceChildAccessor yougestWhenFalseSiblingInsertionPoint =
1053 getLastChildsAlwaysAccessor(new AgendaItemInstanceChildAccessor(AgendaItemChildAccessor.whenFalse, olderSibling));
1054 yougestWhenFalseSiblingInsertionPoint.setChild(node);
1055 AgendaItemChildAccessor.always.setChild(node, null);
1056
1057 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" right to ");
1058 ruleEditorMessage.append(olderSibling.getRule().getName()).append(" When FALSE group.");
1059 } else if (node.getAlways() != null) {
1060 accessorToSelectedNode.setChild(node.getAlways());
1061 AgendaItemBo childsWhenTrue = node.getAlways().getWhenTrue();
1062 AgendaItemChildAccessor.whenTrue.setChild(node.getAlways(), node);
1063 AgendaItemChildAccessor.always.setChild(node, childsWhenTrue);
1064
1065 ruleEditorMessage.append("Moved ").append(node.getRule().getName()).append(" right to ");
1066 if (childsWhenTrue != null) {
1067 ruleEditorMessage.append(childsWhenTrue.getRule().getName()).append(" When TRUE group");
1068 }
1069 }
1070
1071 if (bogusRootNode != null) {
1072
1073 agendaEditor.getAgenda().setFirstItemId(bogusRootNode.getWhenFalseId());
1074 ruleEditorMessage.append(getFirstAgendaItem(agendaEditor.getAgenda()).getRule().getName()).append(" When TRUE group");
1075 }
1076 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
1077 }
1078
1079
1080
1081
1082
1083
1084
1085
1086 private boolean isSiblings(AgendaItemBo cousin1, AgendaItemBo cousin2) {
1087 if (cousin1.equals(cousin2)) return true;
1088
1089
1090 AgendaItemBo candidate = cousin2;
1091 while (null != (candidate = candidate.getAlways())) {
1092 if (candidate.equals(cousin1)) return true;
1093 }
1094
1095 candidate = cousin1;
1096 while (null != (candidate = candidate.getAlways())) {
1097 if (candidate.equals(cousin2)) return true;
1098 }
1099 return false;
1100 }
1101
1102
1103
1104
1105
1106
1107
1108 private AgendaItemChildAccessor getOldestChildAccessor(
1109 AgendaItemBo child, AgendaItemBo parent) {
1110 AgendaItemChildAccessor levelOrderChildAccessor = null;
1111
1112 if (parent != null) {
1113 for (AgendaItemChildAccessor childAccessor : AgendaItemChildAccessor.children) {
1114 if (child.equals(childAccessor.getChild(parent))) {
1115 levelOrderChildAccessor = childAccessor;
1116 break;
1117 }
1118 }
1119 }
1120 return levelOrderChildAccessor;
1121 }
1122
1123
1124
1125
1126
1127
1128
1129 private AgendaItemBo getFirstAgendaItem(AgendaBo agenda) {
1130 AgendaItemBo firstItem = null;
1131 if (agenda != null && agenda.getItems() != null) for (AgendaItemBo agendaItem : agenda.getItems()) {
1132 if (agenda.getFirstItemId().equals(agendaItem.getId())) {
1133 firstItem = agendaItem;
1134 break;
1135 }
1136 }
1137 return firstItem;
1138 }
1139
1140
1141
1142
1143
1144
1145 private AgendaItemBo getNextYoungestOfSameGeneration(AgendaItemBo root, AgendaItemBo agendaItem) {
1146
1147 int genNumber = getAgendaItemGenerationNumber(0, root, agendaItem.getId());
1148 List<AgendaItemBo> genList = new ArrayList<AgendaItemBo>();
1149 buildAgendaItemGenerationList(genList, root, 0, genNumber);
1150
1151 int itemIndex = genList.indexOf(agendaItem);
1152 if (genList.size() > itemIndex + 1) return genList.get(itemIndex + 1);
1153
1154 return null;
1155 }
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165 private int getAgendaItemGenerationNumber(int currentLevel, AgendaItemBo node, String agendaItemId) {
1166 int result = -1;
1167 if (agendaItemId.equals(node.getId())) {
1168 result = currentLevel;
1169 } else {
1170 for (AgendaItemChildAccessor childAccessor : AgendaItemChildAccessor.linkedNodes) {
1171 AgendaItemBo child = childAccessor.getChild(node);
1172 if (child != null) {
1173 int nextLevel = currentLevel;
1174
1175 if (childAccessor != AgendaItemChildAccessor.always) {
1176 nextLevel = currentLevel +1;
1177 }
1178 result = getAgendaItemGenerationNumber(nextLevel, child, agendaItemId);
1179 if (result != -1) break;
1180 }
1181 }
1182 }
1183 return result;
1184 }
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 private void buildAgendaItemGenerationList(List<AgendaItemBo> genList, AgendaItemBo node, int currentLevel, int generation) {
1195 if (currentLevel == generation) {
1196 genList.add(node);
1197 }
1198
1199 if (currentLevel > generation) return;
1200
1201 for (AgendaItemChildAccessor childAccessor : AgendaItemChildAccessor.linkedNodes) {
1202 AgendaItemBo child = childAccessor.getChild(node);
1203 if (child != null) {
1204 int nextLevel = currentLevel;
1205
1206 if (childAccessor != AgendaItemChildAccessor.always) {
1207 nextLevel = currentLevel +1;
1208 }
1209 buildAgendaItemGenerationList(genList, child, nextLevel, generation);
1210 }
1211 }
1212 }
1213
1214
1215
1216
1217
1218
1219 private AgendaItemBo getNextOldestOfSameGeneration(AgendaItemBo root, AgendaItemBo agendaItem) {
1220
1221 int genNumber = getAgendaItemGenerationNumber(0, root, agendaItem.getId());
1222 List<AgendaItemBo> genList = new ArrayList<AgendaItemBo>();
1223 buildAgendaItemGenerationList(genList, root, 0, genNumber);
1224
1225 int itemIndex = genList.indexOf(agendaItem);
1226 if (itemIndex >= 1) return genList.get(itemIndex - 1);
1227
1228 return null;
1229 }
1230
1231
1232
1233
1234
1235
1236 private AgendaItemBo getParent(AgendaItemBo root, String agendaItemId) {
1237 return getParentHelper(root, null, agendaItemId);
1238 }
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248 private AgendaItemBo getParentHelper(AgendaItemBo node, AgendaItemBo levelOrderParent, String agendaItemId) {
1249 AgendaItemBo result = null;
1250 if (agendaItemId.equals(node.getId())) {
1251 result = levelOrderParent;
1252 } else {
1253 for (AgendaItemChildAccessor childAccessor : AgendaItemChildAccessor.linkedNodes) {
1254 AgendaItemBo child = childAccessor.getChild(node);
1255 if (child != null) {
1256
1257 AgendaItemBo lop = (childAccessor == AgendaItemChildAccessor.always) ? levelOrderParent : node;
1258 result = getParentHelper(child, lop, agendaItemId);
1259 if (result != null) break;
1260 }
1261 }
1262 }
1263 return result;
1264 }
1265
1266
1267
1268
1269 private AgendaItemBo getAgendaItemById(AgendaItemBo node, String agendaItemId) {
1270 if (node == null) throw new IllegalArgumentException("node must be non-null");
1271
1272 AgendaItemBo result = null;
1273
1274 if (agendaItemId.equals(node.getId())) {
1275 result = node;
1276 } else {
1277 for (AgendaItemChildAccessor childAccessor : AgendaItemChildAccessor.linkedNodes) {
1278 AgendaItemBo child = childAccessor.getChild(node);
1279 if (child != null) {
1280 result = getAgendaItemById(child, agendaItemId);
1281 if (result != null) break;
1282 }
1283 }
1284 }
1285 return result;
1286 }
1287
1288
1289
1290
1291
1292 private AgendaEditor getAgendaEditor(UifFormBase form) {
1293 MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm) form;
1294 return ((AgendaEditor)maintenanceForm.getDocument().getDocumentDataObject());
1295 }
1296
1297 @MethodAccessible
1298 @RequestMapping(params = "methodToCall=" + "ajaxDelete")
1299 public ModelAndView ajaxDelete(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1300 HttpServletRequest request, HttpServletResponse response)
1301 throws Exception {
1302
1303 deleteSelectedSubtree(form);
1304
1305
1306 return getUIFModelAndView(form);
1307 }
1308
1309 private void deleteSelectedSubtree(UifFormBase form) {
1310 AgendaEditor agendaEditor = getAgendaEditor(form);
1311 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
1312
1313 if (firstItem != null) {
1314 String agendaItemSelected = agendaEditor.getSelectedAgendaItemId();
1315 AgendaItemBo selectedItem = getAgendaItemById(firstItem, agendaItemSelected);
1316
1317
1318 if (agendaItemSelected.equals(firstItem.getId())) {
1319 agendaEditor.getAgenda().setFirstItemId(firstItem.getAlwaysId());
1320 } else {
1321 deleteAgendaItem(firstItem, agendaItemSelected);
1322 }
1323
1324 StringBuilder ruleEditorMessage = new StringBuilder();
1325 ruleEditorMessage.append("Deleted ").append(selectedItem.getRule().getName());
1326
1327 if (selectedItem.getWhenTrue() != null) {
1328 removeAgendaItem(agendaEditor.getAgenda().getItems(), selectedItem.getWhenTrue());
1329 ruleEditorMessage.append(" and its When TRUE ").append(selectedItem.getWhenTrue().getRule().getName());
1330 }
1331 if (selectedItem.getWhenFalse() != null) {
1332 removeAgendaItem(agendaEditor.getAgenda().getItems(), selectedItem.getWhenFalse());
1333 ruleEditorMessage.append(" and its When FALSE ").append(selectedItem.getWhenFalse().getRule().getName());
1334 }
1335 agendaEditor.getAgenda().getItems().remove(selectedItem);
1336 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
1337 }
1338 }
1339
1340 private void deleteAgendaItem(AgendaItemBo root, String agendaItemIdToDelete) {
1341 if (deleteAgendaItem(root, AgendaItemChildAccessor.whenTrue, agendaItemIdToDelete) ||
1342 deleteAgendaItem(root, AgendaItemChildAccessor.whenFalse, agendaItemIdToDelete) ||
1343 deleteAgendaItem(root, AgendaItemChildAccessor.always, agendaItemIdToDelete));
1344 }
1345
1346 private boolean deleteAgendaItem(AgendaItemBo agendaItem, AgendaItemChildAccessor childAccessor, String agendaItemIdToDelete) {
1347 if (agendaItem == null || childAccessor.getChild(agendaItem) == null) return false;
1348 if (agendaItemIdToDelete.equals(childAccessor.getChild(agendaItem).getId())) {
1349
1350 AgendaItemBo grandchildToKeep = childAccessor.getChild(agendaItem).getAlways();
1351 childAccessor.setChild(agendaItem, grandchildToKeep);
1352 return true;
1353 } else {
1354 AgendaItemBo child = childAccessor.getChild(agendaItem);
1355
1356 for (AgendaItemChildAccessor nextChildAccessor : AgendaItemChildAccessor.linkedNodes) {
1357 if (deleteAgendaItem(child, nextChildAccessor, agendaItemIdToDelete)) return true;
1358 }
1359 }
1360 return false;
1361 }
1362
1363
1364
1365
1366
1367
1368 private void removeAgendaItem(List<AgendaItemBo> items, AgendaItemBo removeAgendaItem) {
1369 if (removeAgendaItem.getWhenTrue() != null) {
1370 removeAgendaItem(items, removeAgendaItem.getWhenTrue());
1371 }
1372 if (removeAgendaItem.getWhenFalse() != null) {
1373 removeAgendaItem(items, removeAgendaItem.getWhenFalse());
1374 }
1375 if (removeAgendaItem.getAlways() != null) {
1376 removeAgendaItem(items, removeAgendaItem.getAlways());
1377 }
1378 items.remove(removeAgendaItem);
1379 }
1380
1381 @MethodAccessible
1382 @RequestMapping(params = "methodToCall=" + "ajaxCut")
1383 public ModelAndView ajaxCut(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1384 HttpServletRequest request, HttpServletResponse response) throws Exception {
1385
1386 AgendaEditor agendaEditor = getAgendaEditor(form);
1387
1388 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
1389 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
1390
1391 AgendaItemBo selectedAgendaItem = getAgendaItemById(firstItem, selectedItemId);
1392 setCutAgendaItemId(form, selectedItemId);
1393
1394 StringBuilder ruleEditorMessage = new StringBuilder();
1395 ruleEditorMessage.append("Marked ").append(selectedAgendaItem.getRule().getName()).append(" for cutting.");
1396 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
1397
1398 return getUIFModelAndView(form);
1399 }
1400
1401 @MethodAccessible
1402 @RequestMapping(params = "methodToCall=" + "ajaxPaste")
1403 public ModelAndView ajaxPaste(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1404 HttpServletRequest request, HttpServletResponse response) throws Exception {
1405
1406 AgendaEditor agendaEditor = getAgendaEditor(form);
1407
1408 AgendaItemBo firstItem = getFirstAgendaItem(agendaEditor.getAgenda());
1409 String selectedItemId = agendaEditor.getSelectedAgendaItemId();
1410
1411 String agendaItemId = getCutAgendaItemId(form);
1412 if (StringUtils.isNotBlank(selectedItemId) && StringUtils.isNotBlank(agendaItemId)) {
1413 StringBuilder ruleEditorMessage = new StringBuilder();
1414 AgendaItemBo node = getAgendaItemById(firstItem, agendaItemId);
1415 AgendaItemBo orgRefNode = getReferringNode(firstItem, agendaItemId);
1416 AgendaItemBo newRefNode = getAgendaItemById(firstItem, selectedItemId);
1417
1418 if (isSameOrChildNode(node, newRefNode)) {
1419
1420
1421 ruleEditorMessage.append("Cannot paste ").append(node.getRule().getName()).append(" to itself.");
1422 } else {
1423
1424 if (orgRefNode == null) {
1425 agendaEditor.getAgenda().setFirstItemId(node.getAlwaysId());
1426 } else {
1427
1428
1429 if (node.getId().equals(orgRefNode.getWhenTrueId())) {
1430 orgRefNode.setWhenTrueId(node.getAlwaysId());
1431 orgRefNode.setWhenTrue(node.getAlways());
1432 } else if(node.getId().equals(orgRefNode.getWhenFalseId())) {
1433 orgRefNode.setWhenFalseId(node.getAlwaysId());
1434 orgRefNode.setWhenFalse(node.getAlways());
1435 } else {
1436 orgRefNode.setAlwaysId(node.getAlwaysId());
1437 orgRefNode.setAlways(node.getAlways());
1438 }
1439 }
1440
1441
1442 node.setAlwaysId(newRefNode.getAlwaysId());
1443 node.setAlways(newRefNode.getAlways());
1444 newRefNode.setAlwaysId(node.getId());
1445 newRefNode.setAlways(node);
1446
1447 ruleEditorMessage.append(" Pasted ").append(node.getRule().getName());
1448 ruleEditorMessage.append(" to ").append(newRefNode.getRule().getName());
1449 agendaEditor.setRuleEditorMessage(ruleEditorMessage.toString());
1450
1451 }
1452 setCutAgendaItemId(form, null);
1453 }
1454
1455
1456
1457 return getUIFModelAndView(form);
1458 }
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469 private boolean isSameOrChildNode(AgendaItemBo node, AgendaItemBo newParent) {
1470 return isSameOrChildNodeHelper(node, newParent, AgendaItemChildAccessor.children);
1471 }
1472
1473 private boolean isSameOrChildNodeHelper(AgendaItemBo node, AgendaItemBo newParent, AgendaItemChildAccessor[] childAccessors) {
1474 boolean result = false;
1475 if (newParent == null || node == null) {
1476 return false;
1477 }
1478 if (StringUtils.equals(node.getId(), newParent.getId())) {
1479 result = true;
1480 } else {
1481 for (AgendaItemChildAccessor childAccessor : childAccessors) {
1482 AgendaItemBo child = childAccessor.getChild(node);
1483 if (child != null) {
1484 result = isSameOrChildNodeHelper(child, newParent, AgendaItemChildAccessor.linkedNodes);
1485 if (result == true) break;
1486 }
1487 }
1488 }
1489 return result;
1490 }
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501 private AgendaItemBo getReferringNode(AgendaItemBo root, String agendaItemId) {
1502 return getReferringNodeHelper(root, null, agendaItemId);
1503 }
1504
1505 private AgendaItemBo getReferringNodeHelper(AgendaItemBo node, AgendaItemBo referringNode, String agendaItemId) {
1506 AgendaItemBo result = null;
1507 if (agendaItemId.equals(node.getId())) {
1508 result = referringNode;
1509 } else {
1510 for (AgendaItemChildAccessor childAccessor : AgendaItemChildAccessor.linkedNodes) {
1511 AgendaItemBo child = childAccessor.getChild(node);
1512 if (child != null) {
1513 result = getReferringNodeHelper(child, node, agendaItemId);
1514 if (result != null) break;
1515 }
1516 }
1517 }
1518 return result;
1519 }
1520
1521 private FunctionBoService getFunctionBoService() {
1522 return KrmsRepositoryServiceLocator.getFunctionBoService();
1523 }
1524
1525
1526
1527
1528 private ContextBoService getContextBoService() {
1529 return KrmsRepositoryServiceLocator.getContextBoService();
1530 }
1531
1532
1533
1534
1535 private RuleBoService getRuleBoService() {
1536 return KrmsRepositoryServiceLocator.getRuleBoService();
1537 }
1538
1539 private CustomOperatorUiTranslator getCustomOperatorUiTranslator() {
1540 return KrmsServiceLocatorInternal.getCustomOperatorUiTranslator();
1541 }
1542
1543
1544
1545
1546
1547 private static class AgendaItemInstanceChildAccessor {
1548
1549 private final AgendaItemChildAccessor accessor;
1550 private final AgendaItemBo instance;
1551
1552 public AgendaItemInstanceChildAccessor(AgendaItemChildAccessor accessor, AgendaItemBo instance) {
1553 this.accessor = accessor;
1554 this.instance = instance;
1555 }
1556
1557 public void setChild(AgendaItemBo child) {
1558 accessor.setChild(instance, child);
1559 }
1560
1561 public AgendaItemBo getChild() {
1562 return accessor.getChild(instance);
1563 }
1564
1565 public AgendaItemBo getInstance() { return instance; }
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596 protected static class AgendaItemChildAccessor {
1597
1598 private enum Child { WHEN_TRUE, WHEN_FALSE, ALWAYS };
1599
1600 private static final AgendaItemChildAccessor whenTrue = new AgendaItemChildAccessor(Child.WHEN_TRUE);
1601 private static final AgendaItemChildAccessor whenFalse = new AgendaItemChildAccessor(Child.WHEN_FALSE);
1602 private static final AgendaItemChildAccessor always = new AgendaItemChildAccessor(Child.ALWAYS);
1603
1604
1605
1606
1607 private static final AgendaItemChildAccessor [] linkedNodes = { whenTrue, whenFalse, always };
1608
1609
1610
1611
1612 private static final AgendaItemChildAccessor [] children = { whenTrue, whenFalse };
1613
1614 private final Child whichChild;
1615
1616 private AgendaItemChildAccessor(Child whichChild) {
1617 if (whichChild == null) throw new IllegalArgumentException("whichChild must be non-null");
1618 this.whichChild = whichChild;
1619 }
1620
1621
1622
1623
1624 public AgendaItemBo getChild(AgendaItemBo parent) {
1625 switch (whichChild) {
1626 case WHEN_TRUE: return parent.getWhenTrue();
1627 case WHEN_FALSE: return parent.getWhenFalse();
1628 case ALWAYS: return parent.getAlways();
1629 default: throw new IllegalStateException();
1630 }
1631 }
1632
1633
1634
1635
1636 public void setChild(AgendaItemBo parent, AgendaItemBo child) {
1637 switch (whichChild) {
1638 case WHEN_TRUE:
1639 parent.setWhenTrue(child);
1640 parent.setWhenTrueId(child == null ? null : child.getId());
1641 break;
1642 case WHEN_FALSE:
1643 parent.setWhenFalse(child);
1644 parent.setWhenFalseId(child == null ? null : child.getId());
1645 break;
1646 case ALWAYS:
1647 parent.setAlways(child);
1648 parent.setAlwaysId(child == null ? null : child.getId());
1649 break;
1650 default: throw new IllegalStateException();
1651 }
1652 }
1653 }
1654
1655
1656
1657 @RequestMapping(params = "methodToCall=" + "copyRule")
1658 public ModelAndView copyRule(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1659 HttpServletRequest request, HttpServletResponse response) throws Exception {
1660
1661 AgendaEditor agendaEditor = getAgendaEditor(form);
1662 String name = agendaEditor.getCopyRuleName();
1663 String namespace = agendaEditor.getNamespace();
1664
1665
1666 final String copyRuleNameErrorPropertyName = "AgendaEditorView-AddRule-Page";
1667 if (StringUtils.isBlank(name)) {
1668 GlobalVariables.getMessageMap().putError(copyRuleNameErrorPropertyName, "error.rule.missingCopyRuleName");
1669 return super.refresh(form, result, request, response);
1670 }
1671
1672 RuleDefinition oldRuleDefinition = getRuleBoService().getRuleByNameAndNamespace(name, namespace);
1673
1674 if (oldRuleDefinition == null) {
1675 GlobalVariables.getMessageMap().putError(copyRuleNameErrorPropertyName, "error.rule.invalidCopyRuleName", namespace + ":" + name);
1676 return super.refresh(form, result, request, response);
1677 }
1678
1679 RuleBo oldRule = RuleBo.from(oldRuleDefinition);
1680 RuleBo newRule = RuleBo.copyRule(oldRule);
1681 agendaEditor.getAgendaItemLine().setRule( newRule );
1682
1683 if (!newRule.getActions().isEmpty()) {
1684 agendaEditor.setAgendaItemLineRuleAction( newRule.getActions().get(0));
1685 }
1686 return super.refresh(form, result, request, response);
1687 }
1688
1689
1690
1691
1692
1693 @MethodAccessible
1694 @RequestMapping(params = "methodToCall=" + "goToEditProposition")
1695 public ModelAndView goToEditProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1696 HttpServletRequest request, HttpServletResponse response) throws Exception {
1697
1698
1699 AgendaEditor agendaEditor = getAgendaEditor(form);
1700 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
1701 String selectedPropId = agendaEditor.getSelectedPropositionId();
1702
1703 Node<RuleTreeNode,String> root = rule.getPropositionTree().getRootElement();
1704 PropositionBo propositionToToggleEdit = null;
1705 boolean newEditMode = true;
1706
1707
1708 Node<RuleTreeNode,String> parent = findParentPropositionNode( root, selectedPropId);
1709 if (parent != null){
1710 List<Node<RuleTreeNode,String>> children = parent.getChildren();
1711 for( int index=0; index< children.size(); index++){
1712 Node<RuleTreeNode,String> child = children.get(index);
1713 if (propIdMatches(child, selectedPropId)){
1714 PropositionBo prop = child.getData().getProposition();
1715 propositionToToggleEdit = prop;
1716 newEditMode = !prop.getEditMode();
1717 break;
1718 } else {
1719 child.getData().getProposition().setEditMode(false);
1720 }
1721 }
1722 }
1723
1724 resetEditModeOnPropositionTree(root);
1725 if (propositionToToggleEdit != null) {
1726 propositionToToggleEdit.setEditMode(newEditMode);
1727
1728 rule.refreshPropositionTree(null);
1729 }
1730
1731 return getUIFModelAndView(form);
1732 }
1733
1734
1735
1736
1737
1738
1739 protected Node<RuleTreeNode,String> getLastSimpleNode(List<Node<RuleTreeNode,String>> grandChildren) {
1740 int lastIndex = grandChildren.size() - 1;
1741 Node<RuleTreeNode,String> lastSimpleNode = grandChildren.get(lastIndex);
1742
1743
1744 while (!(SimplePropositionNode.NODE_TYPE.equalsIgnoreCase(lastSimpleNode.getNodeType())
1745 || SimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(lastSimpleNode.getNodeType())
1746 ) && lastIndex >= 0) {
1747 lastSimpleNode = grandChildren.get(lastIndex);
1748 lastIndex--;
1749 }
1750
1751 return lastSimpleNode;
1752 }
1753
1754
1755
1756
1757
1758
1759
1760
1761 protected String getDefaultAddLocationPropositionId(Node<RuleTreeNode, String> root) {
1762 List<Node<RuleTreeNode,String>> children = root.getChildren();
1763 String selectedId = "";
1764
1765
1766
1767
1768 if (children.size() != 0) {
1769 Node<RuleTreeNode,String> child = children.get(0);
1770 List<Node<RuleTreeNode,String>> grandChildren = child.getChildren();
1771
1772
1773 if (grandChildren.size() != 0) {
1774 Node<RuleTreeNode,String> lastSimpleNode = getLastSimpleNode(grandChildren);
1775 selectedId = lastSimpleNode.getData().getProposition().getId();
1776 } else {
1777
1778
1779 selectedId = child.getData().getProposition().getId();
1780 }
1781 }
1782
1783 return selectedId;
1784 }
1785
1786 @MethodAccessible
1787 @RequestMapping(params = "methodToCall=" + "addProposition")
1788 public ModelAndView addProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1789 HttpServletRequest request, HttpServletResponse response) throws Exception {
1790
1791 AgendaEditor agendaEditor = getAgendaEditor(form);
1792 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
1793 String selectedPropId = agendaEditor.getSelectedPropositionId();
1794
1795
1796 Node<RuleTreeNode,String> root = agendaEditor.getAgendaItemLine().getRule().getPropositionTree().getRootElement();
1797
1798
1799
1800 if (StringUtils.isEmpty(selectedPropId)) {
1801 selectedPropId = getDefaultAddLocationPropositionId(root);
1802 }
1803
1804
1805 Node<RuleTreeNode,String> parent = findParentPropositionNode( root, selectedPropId);
1806
1807 resetEditModeOnPropositionTree(root);
1808
1809
1810 if (parent != null){
1811 List<Node<RuleTreeNode,String>> children = parent.getChildren();
1812 for( int index=0; index< children.size(); index++){
1813 Node<RuleTreeNode,String> child = children.get(index);
1814
1815
1816 if (propIdMatches(child, selectedPropId)){
1817
1818
1819
1820
1821 if (parent == root &&
1822 (SimplePropositionNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType()) ||
1823 SimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType()))){
1824
1825
1826 PropositionBo compound = PropositionBo.createCompoundPropositionBoStub(child.getData().getProposition(), true);
1827 compound.setDescription("New Compound Proposition");
1828
1829 rule.setProposition(compound);
1830 rule.refreshPropositionTree(null);
1831 }
1832
1833 else if(SimplePropositionNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType()) ||
1834 SimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType())){
1835
1836
1837 PropositionBo blank = PropositionBo.createSimplePropositionBoStub(child.getData().getProposition(),PropositionType.SIMPLE.getCode());
1838
1839 PropositionBo parentProp = parent.getData().getProposition();
1840 parentProp.getCompoundComponents().add(((index/2)+1), blank);
1841
1842 rule.refreshPropositionTree(true);
1843 }
1844
1845 break;
1846 }
1847 }
1848 } else {
1849
1850
1851 if (root.getChildren().isEmpty()){
1852 PropositionBo blank = PropositionBo.createSimplePropositionBoStub(null,PropositionType.SIMPLE.getCode());
1853 blank.setRuleId(rule.getId());
1854 rule.setProposition(blank);
1855 rule.setProposition(blank);
1856 rule.refreshPropositionTree(true);
1857 }
1858 }
1859 return getUIFModelAndView(form);
1860 }
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870 private void addOpCodeNode(Node currentNode, PropositionBo prop, int index){
1871 String opCodeLabel = "";
1872
1873 if (LogicalOperator.AND.getCode().equalsIgnoreCase(prop.getCompoundOpCode())){
1874 opCodeLabel = "AND";
1875 } else if (LogicalOperator.OR.getCode().equalsIgnoreCase(prop.getCompoundOpCode())){
1876 opCodeLabel = "OR";
1877 }
1878 Node<RuleTreeNode, String> aNode = new Node<RuleTreeNode, String>();
1879 aNode.setNodeLabel("");
1880 aNode.setNodeType("ruleTreeNode compoundOpCodeNode");
1881 aNode.setData(new CompoundOpCodeNode(prop));
1882 currentNode.insertChildAt(index, aNode);
1883 }
1884
1885
1886 private boolean propIdMatches(Node<RuleTreeNode, String> node, String propId){
1887 if (propId!=null && node != null && node.getData() != null && propId.equalsIgnoreCase(node.getData().getProposition().getId())) {
1888 return true;
1889 }
1890 return false;
1891 }
1892
1893
1894
1895
1896
1897 private void resetEditModeOnPropositionTree(Node<RuleTreeNode, String> currentNode){
1898 if (currentNode.getData() != null){
1899 RuleTreeNode dataNode = currentNode.getData();
1900 dataNode.getProposition().setEditMode(false);
1901 }
1902 List<Node<RuleTreeNode,String>> children = currentNode.getChildren();
1903 for( Node<RuleTreeNode,String> child : children){
1904 resetEditModeOnPropositionTree(child);
1905 }
1906 }
1907
1908 private Node<RuleTreeNode, String> findPropositionTreeNode(Node<RuleTreeNode, String> currentNode, String selectedPropId){
1909 Node<RuleTreeNode,String> bingo = null;
1910 if (currentNode.getData() != null){
1911 RuleTreeNode dataNode = currentNode.getData();
1912 if (selectedPropId.equalsIgnoreCase(dataNode.getProposition().getId())){
1913 return currentNode;
1914 }
1915 }
1916 List<Node<RuleTreeNode,String>> children = currentNode.getChildren();
1917 for( Node<RuleTreeNode,String> child : children){
1918 bingo = findPropositionTreeNode(child, selectedPropId);
1919 if (bingo != null) break;
1920 }
1921 return bingo;
1922 }
1923
1924 private Node<RuleTreeNode, String> findParentPropositionNode(Node<RuleTreeNode, String> currentNode, String selectedPropId){
1925 Node<RuleTreeNode,String> bingo = null;
1926 if (selectedPropId != null) {
1927
1928 List<Node<RuleTreeNode,String>> children = currentNode.getChildren();
1929 for( Node<RuleTreeNode,String> child : children){
1930 RuleTreeNode dataNode = child.getData();
1931 if (selectedPropId.equalsIgnoreCase(dataNode.getProposition().getId()))
1932 return currentNode;
1933 }
1934
1935
1936 for( Node<RuleTreeNode,String> kid : children){
1937 bingo = findParentPropositionNode(kid, selectedPropId);
1938 if (bingo != null) break;
1939 }
1940 }
1941 return bingo;
1942 }
1943
1944
1945
1946
1947
1948
1949
1950 private int findChildIndex(Node<RuleTreeNode,String> parent, String propId){
1951 int index;
1952 List<Node<RuleTreeNode,String>> children = parent.getChildren();
1953 for(index=0; index< children.size(); index++){
1954 Node<RuleTreeNode,String> child = children.get(index);
1955
1956 if (propIdMatches(child, propId)){
1957 return index;
1958 }
1959 }
1960 return -1;
1961 }
1962
1963 @MethodAccessible
1964 @RequestMapping(params = "methodToCall=" + "movePropositionUp")
1965 public ModelAndView movePropositionUp(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1966 HttpServletRequest request, HttpServletResponse response)
1967 throws Exception {
1968 moveSelectedProposition(form, true);
1969
1970 return getUIFModelAndView(form);
1971 }
1972
1973 @MethodAccessible
1974 @RequestMapping(params = "methodToCall=" + "movePropositionDown")
1975 public ModelAndView movePropositionDown(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1976 HttpServletRequest request, HttpServletResponse response)
1977 throws Exception {
1978 moveSelectedProposition(form, false);
1979
1980 return getUIFModelAndView(form);
1981 }
1982
1983 private void moveSelectedProposition(UifFormBase form, boolean up) {
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993 AgendaEditor agendaEditor = getAgendaEditor(form);
1994 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
1995 String selectedPropId = agendaEditor.getSelectedPropositionId();
1996
1997
1998 Node<RuleTreeNode,String> parent = findParentPropositionNode(rule.getPropositionTree().getRootElement(), selectedPropId);
1999
2000
2001 if (parent != null){
2002 List<Node<RuleTreeNode,String>> children = parent.getChildren();
2003 for( int index=0; index< children.size(); index++){
2004 Node<RuleTreeNode,String> child = children.get(index);
2005
2006 if (propIdMatches(child, selectedPropId)){
2007 if(SimplePropositionNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType()) ||
2008 SimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType()) ||
2009 RuleTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(child.getNodeType()) ){
2010
2011 if (((index > 0) && up) || ((index <(children.size() - 1)&& !up))){
2012
2013 PropositionBo parentProp = parent.getData().getProposition();
2014 PropositionBo workingProp = parentProp.getCompoundComponents().remove(index/2);
2015 if (up){
2016 parentProp.getCompoundComponents().add((index/2)-1, workingProp);
2017 }else{
2018 parentProp.getCompoundComponents().add((index/2)+1, workingProp);
2019 }
2020
2021
2022
2023 boolean editMode = (SimplePropositionEditNode.NODE_TYPE.equalsIgnoreCase(child.getNodeType()));
2024 rule.refreshPropositionTree(editMode);
2025 }
2026 }
2027
2028 break;
2029 }
2030 }
2031 }
2032 }
2033
2034 @MethodAccessible
2035 @RequestMapping(params = "methodToCall=" + "movePropositionLeft")
2036 public ModelAndView movePropositionLeft(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2037 HttpServletRequest request, HttpServletResponse response)
2038 throws Exception {
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048 AgendaEditor agendaEditor = getAgendaEditor(form);
2049 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
2050 String selectedPropId = agendaEditor.getSelectedPropositionId();
2051
2052
2053 Node<RuleTreeNode,String> root = rule.getPropositionTree().getRootElement();
2054 Node<RuleTreeNode,String> parent = findParentPropositionNode(root, selectedPropId);
2055 if ((parent != null) && (RuleTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(parent.getNodeType()))){
2056 Node<RuleTreeNode,String> granny = findParentPropositionNode(root,parent.getData().getProposition().getId());
2057 if (granny != root){
2058 int oldIndex = findChildIndex(parent, selectedPropId);
2059 int newIndex = findChildIndex(granny, parent.getData().getProposition().getId());
2060 if (oldIndex >= 0 && newIndex >= 0){
2061 PropositionBo prop = parent.getData().getProposition().getCompoundComponents().remove(oldIndex/2);
2062 granny.getData().getProposition().getCompoundComponents().add((newIndex/2)+1, prop);
2063 rule.refreshPropositionTree(false);
2064 }
2065 } else {
2066
2067
2068
2069 }
2070 }
2071 return getUIFModelAndView(form);
2072 }
2073
2074 @MethodAccessible
2075 @RequestMapping(params = "methodToCall=" + "movePropositionRight")
2076 public ModelAndView movePropositionRight(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2077 HttpServletRequest request, HttpServletResponse response)
2078 throws Exception {
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088 AgendaEditor agendaEditor = getAgendaEditor(form);
2089 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
2090 String selectedPropId = agendaEditor.getSelectedPropositionId();
2091
2092
2093 Node<RuleTreeNode,String> parent = findParentPropositionNode(
2094 rule.getPropositionTree().getRootElement(), selectedPropId);
2095 if (parent != null){
2096 int index = findChildIndex(parent, selectedPropId);
2097
2098 if (index >= 0 && index+1 < parent.getChildren().size()){
2099 Node<RuleTreeNode,String> child = parent.getChildren().get(index);
2100 Node<RuleTreeNode,String> nextSibling = parent.getChildren().get(index+2);
2101
2102 if(RuleTreeNode.COMPOUND_NODE_TYPE.equalsIgnoreCase(nextSibling.getNodeType()) ){
2103
2104 PropositionBo prop = parent.getData().getProposition().getCompoundComponents().remove(index/2);
2105
2106 nextSibling.getData().getProposition().getCompoundComponents().add(0, prop);
2107 rule.refreshPropositionTree(false);
2108 }
2109 }
2110 }
2111 return getUIFModelAndView(form);
2112 }
2113
2114
2115
2116
2117
2118
2119 @MethodAccessible
2120 @RequestMapping(params = "methodToCall=" + "togglePropositionSimpleCompound")
2121 public ModelAndView togglePropositionSimpleCompound(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2122 HttpServletRequest request, HttpServletResponse response)
2123 throws Exception {
2124
2125 AgendaEditor agendaEditor = getAgendaEditor(form);
2126 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
2127 String selectedPropId = agendaEditor.getSelectedPropositionId();
2128
2129 resetEditModeOnPropositionTree(rule.getPropositionTree().getRootElement());
2130
2131 if (!StringUtils.isBlank(selectedPropId)) {
2132
2133 Node<RuleTreeNode,String> parent = findParentPropositionNode(
2134 rule.getPropositionTree().getRootElement(), selectedPropId);
2135 if (parent != null){
2136
2137 int index = findChildIndex(parent, selectedPropId);
2138
2139 PropositionBo propBo = parent.getChildren().get(index).getData().getProposition();
2140
2141
2142 PropositionBo compound = PropositionBo.createCompoundPropositionBoStub(propBo, true);
2143 compound.setDescription("New Compound Proposition");
2144 compound.setEditMode(false);
2145
2146 if (parent.getData() == null) {
2147 rule.setProposition(compound);
2148 } else {
2149 PropositionBo parentBo = parent.getData().getProposition();
2150 List<PropositionBo> siblings = parentBo.getCompoundComponents();
2151
2152 int propIndex = -1;
2153 for (int i=0; i<siblings.size(); i++) {
2154 if (propBo.getId().equals(siblings.get(i).getId())) {
2155 propIndex = i;
2156 break;
2157 }
2158 }
2159
2160 parentBo.getCompoundComponents().set(propIndex, compound);
2161 }
2162 }
2163 }
2164
2165 agendaEditor.getAgendaItemLine().getRule().refreshPropositionTree(true);
2166 return getUIFModelAndView(form);
2167 }
2168
2169 @MethodAccessible
2170 @RequestMapping(params = "methodToCall=" + "cutProposition")
2171 public ModelAndView cutProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2172 HttpServletRequest request, HttpServletResponse response)
2173 throws Exception {
2174
2175 AgendaEditor agendaEditor = getAgendaEditor(form);
2176 String selectedPropId = agendaEditor.getSelectedPropositionId();
2177 agendaEditor.setCutPropositionId(selectedPropId);
2178
2179 return getUIFModelAndView(form);
2180 }
2181
2182 @MethodAccessible
2183 @RequestMapping(params = "methodToCall=" + "pasteProposition")
2184 public ModelAndView pasteProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2185 HttpServletRequest request, HttpServletResponse response)
2186 throws Exception {
2187
2188 AgendaEditor agendaEditor = getAgendaEditor(form);
2189 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
2190
2191
2192 String cutPropId = agendaEditor.getCutPropositionId();
2193 String selectedPropId = agendaEditor.getSelectedPropositionId();
2194
2195 if (StringUtils.isNotBlank(selectedPropId) && selectedPropId.equals(cutPropId)) {
2196
2197 } else {
2198
2199
2200 Node<RuleTreeNode, String> root = rule.getPropositionTree().getRootElement();
2201
2202 if (StringUtils.isNotBlank(selectedPropId) && StringUtils.isNotBlank(cutPropId)) {
2203 Node<RuleTreeNode,String> parentNode = findParentPropositionNode(root, selectedPropId);
2204 PropositionBo newParent;
2205 if (parentNode == root){
2206
2207
2208
2209
2210 newParent = PropositionBo.createCompoundPropositionBoStub2(
2211 root.getChildren().get(0).getData().getProposition());
2212 newParent.setEditMode(true);
2213 rule.setProposition(newParent);
2214 } else {
2215 newParent = parentNode.getData().getProposition();
2216 }
2217 PropositionBo oldParent = findParentPropositionNode(root, cutPropId).getData().getProposition();
2218
2219 PropositionBo workingProp = null;
2220
2221 if (oldParent != null){
2222 List <PropositionBo> children = oldParent.getCompoundComponents();
2223 for( int index=0; index< children.size(); index++){
2224 if (cutPropId.equalsIgnoreCase(children.get(index).getId())){
2225 workingProp = oldParent.getCompoundComponents().remove(index);
2226 break;
2227 }
2228 }
2229 }
2230
2231
2232 if (newParent != null && workingProp != null){
2233 List <PropositionBo> children = newParent.getCompoundComponents();
2234 for( int index=0; index< children.size(); index++){
2235 if (selectedPropId.equalsIgnoreCase(children.get(index).getId())){
2236 children.add(index+1, workingProp);
2237 break;
2238 }
2239 }
2240 }
2241
2242
2243 rule.refreshPropositionTree(false);
2244 }
2245 }
2246 agendaEditor.setCutPropositionId(null);
2247
2248 return getUIFModelAndView(form);
2249 }
2250
2251 @MethodAccessible
2252 @RequestMapping(params = "methodToCall=" + "deleteProposition")
2253 public ModelAndView deleteProposition(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2254 HttpServletRequest request, HttpServletResponse response)
2255 throws Exception {
2256 AgendaEditor agendaEditor = getAgendaEditor(form);
2257 String selectedPropId = agendaEditor.getSelectedPropositionId();
2258 Node<RuleTreeNode, String> root = agendaEditor.getAgendaItemLine().getRule().getPropositionTree().getRootElement();
2259
2260 Node<RuleTreeNode, String> parentNode = findParentPropositionNode(root, selectedPropId);
2261
2262
2263 if (parentNode != null && parentNode.getData() != null) {
2264 PropositionBo parent = parentNode.getData().getProposition();
2265 if (parent != null){
2266 List <PropositionBo> children = parent.getCompoundComponents();
2267 for( int index=0; index< children.size(); index++){
2268 if (selectedPropId.equalsIgnoreCase(children.get(index).getId())){
2269 parent.getCompoundComponents().remove(index);
2270 break;
2271 }
2272 }
2273 }
2274 } else {
2275 if (KRADUtils.isNotNull(parentNode)) {
2276 parentNode.getChildren().clear();
2277 agendaEditor.getAgendaItemLine().getRule().getPropositionTree().setRootElement(null);
2278 agendaEditor.getAgendaItemLine().getRule().setProposition(null);
2279 } else {
2280 GlobalVariables.getMessageMap().putError(KRMSPropertyConstants.Rule.PROPOSITION_TREE_GROUP_ID,
2281 "error.rule.proposition.noneHighlighted");
2282 }
2283 }
2284
2285 agendaEditor.getAgendaItemLine().getRule().refreshPropositionTree(false);
2286 return getUIFModelAndView(form);
2287 }
2288
2289 @MethodAccessible
2290 @RequestMapping(params = "methodToCall=" + "updateCompoundOperator")
2291 public ModelAndView updateCompoundOperator(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
2292 HttpServletRequest request, HttpServletResponse response)
2293 throws Exception {
2294
2295 AgendaEditor agendaEditor = getAgendaEditor(form);
2296 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
2297 rule.refreshPropositionTree(false);
2298
2299 return getUIFModelAndView(form);
2300 }
2301
2302 }