1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krms.impl.repository;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.mo.common.Versioned;
20 import org.kuali.rice.core.api.util.tree.Node;
21 import org.kuali.rice.core.api.util.tree.Tree;
22 import org.kuali.rice.krad.data.DataObjectService;
23 import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator;
24 import org.kuali.rice.krad.data.jpa.converters.BooleanYNConverter;
25 import org.kuali.rice.krad.service.KRADServiceLocator;
26 import org.kuali.rice.krms.api.repository.LogicalOperator;
27 import org.kuali.rice.krms.api.repository.action.ActionDefinition;
28 import org.kuali.rice.krms.api.repository.proposition.PropositionType;
29 import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
30 import org.kuali.rice.krms.api.repository.rule.RuleDefinitionContract;
31 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
32 import org.kuali.rice.krms.impl.ui.CompoundOpCodeNode;
33 import org.kuali.rice.krms.impl.ui.CompoundPropositionEditNode;
34 import org.kuali.rice.krms.impl.ui.RuleTreeNode;
35 import org.kuali.rice.krms.impl.ui.SimplePropositionEditNode;
36 import org.kuali.rice.krms.impl.ui.SimplePropositionNode;
37
38 import javax.persistence.CascadeType;
39 import javax.persistence.Column;
40 import javax.persistence.Convert;
41 import javax.persistence.Entity;
42 import javax.persistence.FetchType;
43 import javax.persistence.GeneratedValue;
44 import javax.persistence.Id;
45 import javax.persistence.JoinColumn;
46 import javax.persistence.ManyToOne;
47 import javax.persistence.OneToMany;
48 import javax.persistence.Table;
49 import javax.persistence.Transient;
50 import javax.persistence.Version;
51 import java.io.IOException;
52 import java.io.ObjectOutputStream;
53 import java.io.Serializable;
54 import java.util.ArrayList;
55 import java.util.HashMap;
56 import java.util.List;
57 import java.util.Map;
58
59 @Entity
60 @Table(name = "KRMS_RULE_T")
61 public class RuleBo implements RuleDefinitionContract, Versioned, Serializable {
62
63 private static final long serialVersionUID = 1L;
64
65 public static final String RULE_SEQ_NAME = "KRMS_RULE_S";
66 static final RepositoryBoIncrementer ruleIdIncrementer = new RepositoryBoIncrementer(RULE_SEQ_NAME);
67 static final RepositoryBoIncrementer actionIdIncrementer = new RepositoryBoIncrementer("KRMS_ACTN_S");
68 static final RepositoryBoIncrementer ruleAttributeIdIncrementer = new RepositoryBoIncrementer("KRMS_RULE_ATTR_S");
69 static final RepositoryBoIncrementer actionAttributeIdIncrementer = new RepositoryBoIncrementer("KRMS_ACTN_ATTR_S");
70
71 @PortableSequenceGenerator(name = RULE_SEQ_NAME)
72 @GeneratedValue(generator = RULE_SEQ_NAME)
73 @Id
74 @Column(name = "RULE_ID")
75 private String id;
76
77 @Column(name = "NMSPC_CD")
78 private String namespace;
79
80 @Column(name = "DESC_TXT")
81 private String description;
82
83 @Column(name = "NM")
84 private String name;
85
86 @Column(name = "TYP_ID", nullable = true)
87 private String typeId;
88
89 @Column(name = "ACTV")
90 @Convert(converter = BooleanYNConverter.class)
91 private boolean active = true;
92
93 @Column(name = "VER_NBR")
94 @Version
95 private Long versionNumber;
96
97 @ManyToOne(targetEntity = PropositionBo.class, fetch = FetchType.LAZY, cascade = { CascadeType.REFRESH, CascadeType.REMOVE, CascadeType.PERSIST })
98 @JoinColumn(name = "PROP_ID", referencedColumnName = "PROP_ID", insertable = true, updatable = true)
99 private PropositionBo proposition;
100
101 @OneToMany(mappedBy = "rule",
102 cascade = { CascadeType.MERGE, CascadeType.REMOVE, CascadeType.PERSIST })
103 private List<ActionBo> actions;
104
105 @OneToMany(targetEntity = RuleAttributeBo.class, fetch = FetchType.LAZY, orphanRemoval = true, cascade = { CascadeType.REFRESH, CascadeType.REMOVE, CascadeType.PERSIST })
106 @JoinColumn(name = "RULE_ID", referencedColumnName = "RULE_ID", insertable = true, updatable = true)
107 private List<RuleAttributeBo> attributeBos;
108
109 @Transient
110 private Tree<RuleTreeNode, String> propositionTree;
111
112 @Transient
113 private String propositionSummary;
114
115 @Transient
116 private StringBuffer propositionSummaryBuffer;
117
118 @Transient
119 private String selectedPropositionId;
120
121 public RuleBo() {
122 actions = new ArrayList<ActionBo>();
123 attributeBos = new ArrayList<RuleAttributeBo>();
124 }
125
126 public PropositionBo getProposition() {
127 return proposition;
128 }
129
130 public void setProposition(PropositionBo proposition) {
131 this.proposition = proposition;
132 }
133
134
135
136
137
138
139
140 public void setTypeId(String typeId) {
141 if (StringUtils.isBlank(typeId)) {
142 this.typeId = null;
143 } else {
144 this.typeId = typeId;
145 }
146 }
147
148 public Map<String, String> getAttributes() {
149 HashMap<String, String> attributes = new HashMap<String, String>();
150
151 for (RuleAttributeBo attr : attributeBos) {
152 DataObjectService dataObjectService = KRADServiceLocator.getDataObjectService();
153 dataObjectService.wrap(attr).fetchRelationship("attributeDefinition", false, true);
154 attributes.put(attr.getAttributeDefinition().getName(), attr.getValue());
155 }
156
157 return attributes;
158 }
159
160 public void setAttributes(Map<String, String> attributes) {
161 this.attributeBos = new ArrayList<RuleAttributeBo>();
162
163 if (!StringUtils.isBlank(this.typeId)) {
164 List<KrmsAttributeDefinition> attributeDefinitions = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService().findAttributeDefinitionsByType(this.getTypeId());
165 Map<String, KrmsAttributeDefinition> attributeDefinitionsByName = new HashMap<String, KrmsAttributeDefinition>();
166
167 if (attributeDefinitions != null) {
168 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
169 attributeDefinitionsByName.put(attributeDefinition.getName(), attributeDefinition);
170 }
171 }
172
173 for (Map.Entry<String, String> attr : attributes.entrySet()) {
174 KrmsAttributeDefinition attributeDefinition = attributeDefinitionsByName.get(attr.getKey());
175 RuleAttributeBo attributeBo = new RuleAttributeBo();
176 attributeBo.setRuleId(this.getId());
177 attributeBo.setValue(attr.getValue());
178 attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attributeDefinition));
179 attributeBos.add(attributeBo);
180 }
181 }
182 }
183
184 public String getPropositionSummary() {
185 if (this.propositionTree == null) {
186 this.propositionTree = refreshPropositionTree(false);
187 }
188
189 return propositionSummaryBuffer.toString();
190 }
191
192
193
194
195
196
197 public Tree getPropositionTree() {
198 if (this.propositionTree == null) {
199 this.propositionTree = refreshPropositionTree(false);
200 }
201
202 return this.propositionTree;
203 }
204
205 public void setPropositionTree(Tree<RuleTreeNode, String> tree) {
206 this.propositionTree.equals(tree);
207 }
208
209 public Tree refreshPropositionTree(Boolean editMode) {
210 Tree myTree = new Tree<RuleTreeNode, String>();
211
212 Node<RuleTreeNode, String> rootNode = new Node<RuleTreeNode, String>();
213 myTree.setRootElement(rootNode);
214
215 propositionSummaryBuffer = new StringBuffer();
216 PropositionBo prop = this.getProposition();
217 if (prop!=null && StringUtils.isBlank(prop.getDescription())) {
218 prop.setDescription("");
219 }
220 buildPropTree(rootNode, prop, editMode);
221 this.propositionTree = myTree;
222 return myTree;
223 }
224
225
226
227
228
229
230
231
232
233
234
235 private void buildPropTree(Node sprout, PropositionBo prop, Boolean editMode) {
236
237
238
239
240 if (prop != null) {
241 if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
242
243
244 Node<RuleTreeNode, String> child = new Node<RuleTreeNode, String>();
245 child.setNodeLabel(prop.getDescription());
246
247 if (prop.getEditMode()) {
248 child.setNodeLabel("");
249 child.setNodeType(SimplePropositionEditNode.NODE_TYPE);
250 SimplePropositionEditNode pNode = new SimplePropositionEditNode(prop);
251 child.setData(pNode);
252 } else {
253 child.setNodeType(SimplePropositionNode.NODE_TYPE);
254 SimplePropositionNode pNode = new SimplePropositionNode(prop);
255 child.setData(pNode);
256 }
257
258 sprout.getChildren().add(child);
259 propositionSummaryBuffer.append(prop.getParameterDisplayString());
260 } else if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
261
262 propositionSummaryBuffer.append(" ( ");
263 Node<RuleTreeNode, String> aNode = new Node<RuleTreeNode, String>();
264 aNode.setNodeLabel(prop.getDescription());
265
266
267 if (prop.getEditMode()) {
268 aNode.setNodeLabel("");
269 aNode.setNodeType("ruleTreeNode compoundNode editNode");
270 CompoundPropositionEditNode pNode = new CompoundPropositionEditNode(prop);
271 aNode.setData(pNode);
272 } else {
273 aNode.setNodeType("ruleTreeNode compoundNode");
274 RuleTreeNode pNode = new RuleTreeNode(prop);
275 aNode.setData(pNode);
276 }
277
278 sprout.getChildren().add(aNode);
279 boolean first = true;
280 List<PropositionBo> allMyChildren = prop.getCompoundComponents();
281 int compoundSequenceNumber = 0;
282
283 for (PropositionBo child : allMyChildren) {
284 child.setCompoundSequenceNumber((compoundSequenceNumber = ++compoundSequenceNumber));
285
286
287
288 if (!first) {
289 addOpCodeNode(aNode, prop);
290 }
291
292 first = false;
293
294 buildPropTree(aNode, child, editMode);
295 }
296
297 propositionSummaryBuffer.append(" ) ");
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309 private void addOpCodeNode(Node currentNode, PropositionBo prop) {
310 String opCodeLabel = "";
311
312 if (LogicalOperator.AND.getCode().equalsIgnoreCase(prop.getCompoundOpCode())) {
313 opCodeLabel = "AND";
314 } else if (LogicalOperator.OR.getCode().equalsIgnoreCase(prop.getCompoundOpCode())) {
315 opCodeLabel = "OR";
316 }
317
318 propositionSummaryBuffer.append(" " + opCodeLabel + " ");
319 Node<RuleTreeNode, String> aNode = new Node<RuleTreeNode, String>();
320 aNode.setNodeLabel("");
321 aNode.setNodeType("ruleTreeNode compoundOpCodeNode");
322 aNode.setData(new CompoundOpCodeNode(prop));
323
324 currentNode.getChildren().add(aNode);
325 }
326
327
328
329
330
331
332
333 public static RuleDefinition to(RuleBo bo) {
334 if (bo == null) {
335 return null;
336 }
337
338 return RuleDefinition.Builder.create(bo).build();
339 }
340
341
342
343
344
345
346
347 public static RuleBo from(RuleDefinition im) {
348 if (im == null) {
349 return null;
350 }
351
352 RuleBo bo = new RuleBo();
353 bo.id = im.getId();
354 bo.namespace = im.getNamespace();
355 bo.name = im.getName();
356 bo.description = im.getDescription();
357 bo.typeId = im.getTypeId();
358 bo.active = im.isActive();
359
360 if (im.getProposition() != null) {
361 PropositionBo propositionBo = PropositionBo.from(im.getProposition());
362 bo.proposition = propositionBo;
363 propositionBo.setRuleId(im.getId());
364 }
365
366 bo.setVersionNumber(im.getVersionNumber());
367 bo.actions = new ArrayList<ActionBo>();
368
369 for (ActionDefinition action : im.getActions()) {
370 ActionBo actionBo = ActionBo.from(action);
371 bo.actions.add(actionBo);
372 actionBo.setRule(bo);
373 }
374
375
376 List<RuleAttributeBo> attrs = new ArrayList<RuleAttributeBo>();
377
378 RuleAttributeBo attributeBo;
379 for (Map.Entry<String, String> entry : im.getAttributes().entrySet()) {
380 KrmsAttributeDefinitionBo attrDefBo = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService().getKrmsAttributeBo(entry.getKey(), im.getNamespace());
381 attributeBo = new RuleAttributeBo();
382 attributeBo.setRuleId(im.getId());
383 attributeBo.setAttributeDefinition(attrDefBo);
384 attributeBo.setValue(entry.getValue());
385 attributeBo.setAttributeDefinition(attrDefBo);
386 attrs.add(attributeBo);
387 }
388
389 bo.setAttributeBos(attrs);
390
391 return bo;
392 }
393
394 public static RuleBo copyRule(RuleBo existing) {
395
396 RuleBo newRule = new RuleBo();
397
398 newRule.setId(ruleIdIncrementer.getNewId());
399 newRule.setNamespace(existing.getNamespace());
400 newRule.setDescription(existing.getDescription());
401 newRule.setTypeId(existing.getTypeId());
402 newRule.setActive(true);
403
404 PropositionBo newProp = PropositionBo.copyProposition(existing.getProposition());
405 newProp.setRuleId(newRule.getId());
406 newRule.setProposition(newProp);
407
408 newRule.setAttributeBos(copyRuleAttributes(existing));
409 newRule.setActions(copyRuleActions(existing, newRule.getId()));
410
411 return newRule;
412 }
413
414
415
416
417
418
419
420 public RuleBo copyRule(String newRuleName) {
421 RuleBo copiedRule = RuleBo.copyRule(this);
422
423
424
425
426 copiedRule.setName(newRuleName);
427
428 return copiedRule;
429 }
430
431 public static List<RuleAttributeBo> copyRuleAttributes(RuleBo existing) {
432 List<RuleAttributeBo> newAttributes = new ArrayList<RuleAttributeBo>();
433
434 for (RuleAttributeBo attr : existing.getAttributeBos()) {
435 RuleAttributeBo newAttr = new RuleAttributeBo();
436 newAttr.setId(ruleAttributeIdIncrementer.getNewId());
437 newAttr.setRuleId(attr.getRuleId());
438 newAttr.setAttributeDefinition(attr.getAttributeDefinition());
439 newAttr.setValue(attr.getValue());
440 newAttributes.add(newAttr);
441 }
442
443 return newAttributes;
444 }
445
446 public static List<ActionAttributeBo> copyActionAttributes(ActionBo existing) {
447 List<ActionAttributeBo> newAttributes = new ArrayList<ActionAttributeBo>();
448
449 for (ActionAttributeBo attr : existing.getAttributeBos()) {
450 ActionAttributeBo newAttr = new ActionAttributeBo();
451 newAttr.setId(actionAttributeIdIncrementer.getNewId());
452 newAttr.setAction(existing);
453 newAttr.setAttributeDefinition(attr.getAttributeDefinition());
454 newAttr.setValue(attr.getValue());
455 newAttributes.add(newAttr);
456 }
457
458 return newAttributes;
459 }
460
461 public static List<ActionBo> copyRuleActions(RuleBo existing, String ruleId) {
462 List<ActionBo> newActionList = new ArrayList<ActionBo>();
463
464 for (ActionBo action : existing.getActions()) {
465 ActionBo newAction = new ActionBo();
466 newAction.setId(actionIdIncrementer.getNewId());
467 newAction.setRule(existing);
468 newAction.setDescription(action.getDescription());
469 newAction.setName(action.getName());
470 newAction.setNamespace(action.getNamespace());
471 newAction.setTypeId(action.getTypeId());
472 newAction.setSequenceNumber(action.getSequenceNumber());
473 newAction.setAttributeBos(copyActionAttributes(action));
474 newActionList.add(newAction);
475 }
476
477 return newActionList;
478 }
479
480
481
482
483
484
485
486 private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException {
487 if (proposition != null) {
488 proposition.getId();
489 }
490 stream.defaultWriteObject();
491 }
492
493 public String getId() {
494 return id;
495 }
496
497 public void setId(String id) {
498 this.id = id;
499 }
500
501 public String getNamespace() {
502 return namespace;
503 }
504
505 public void setNamespace(String namespace) {
506 this.namespace = namespace;
507 }
508
509 public String getDescription() {
510 return description;
511 }
512
513 public void setDescription(String description) {
514 this.description = description;
515 }
516
517 public String getName() {
518 return name;
519 }
520
521 public void setName(String name) {
522 this.name = name;
523 }
524
525 public String getTypeId() {
526 return typeId;
527 }
528
529 public String getPropId() {
530 if (proposition != null) {
531 return proposition.getId();
532 }
533
534 return null;
535 }
536
537 public boolean getActive() {
538 return active;
539 }
540
541 public boolean isActive() {
542 return active;
543 }
544
545 public void setActive(boolean active) {
546 this.active = active;
547 }
548
549 public Long getVersionNumber() {
550 return versionNumber;
551 }
552
553 public void setVersionNumber(Long versionNumber) {
554 this.versionNumber = versionNumber;
555 }
556
557 public List<ActionBo> getActions() {
558 return actions;
559 }
560
561 public void setActions(List<ActionBo> actions) {
562 this.actions = actions;
563 }
564
565 public List<RuleAttributeBo> getAttributeBos() {
566 return attributeBos;
567 }
568
569 public void setAttributeBos(List<RuleAttributeBo> attributeBos) {
570 this.attributeBos = attributeBos;
571 }
572
573 public void setPropositionSummary(String propositionSummary) {
574 this.propositionSummary = propositionSummary;
575 }
576
577 public String getSelectedPropositionId() {
578 return selectedPropositionId;
579 }
580
581 public void setSelectedPropositionId(String selectedPropositionId) {
582 this.selectedPropositionId = selectedPropositionId;
583 }
584
585 }