View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krms.tree;
17  
18  import org.apache.commons.lang.StringEscapeUtils;
19  import org.kuali.rice.core.api.util.tree.Node;
20  import org.kuali.rice.core.api.util.tree.Tree;
21  import org.kuali.rice.krad.util.ObjectUtils;
22  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
23  import org.kuali.rice.krms.dto.PropositionEditor;
24  import org.kuali.rice.krms.dto.RuleEditor;
25  import org.kuali.rice.krms.tree.node.CompoundOpCodeNode;
26  import org.kuali.rice.krms.tree.node.SimplePropositionEditNode;
27  import org.kuali.rice.krms.tree.node.SimplePropositionNode;
28  import org.kuali.rice.krms.tree.node.RuleEditorTreeNode;
29  import org.kuali.rice.krms.util.KRMSConstants;
30  
31  /**
32   *
33   * @author Kuali Student Team
34   */
35  public class RuleEditTreeBuilder extends AbstractTreeBuilder{
36  
37      private static final long serialVersionUID = 1L;
38  
39      public Tree buildTree(RuleEditor rule) {
40  
41          Tree myTree = new Tree<RuleEditorTreeNode, String>();
42  
43          Node<RuleEditorTreeNode, String> rootNode = new Node<RuleEditorTreeNode, String>();
44          rootNode.setNodeType(RuleEditorTreeNode.ROOT_TYPE);
45  
46          myTree.setRootElement(rootNode);
47  
48          if (rule.getPropositionEditor() != null){
49              Node firstNode = addChildNode(rule, rootNode, rule.getPropositionEditor());
50              firstNode.setNodeType(firstNode.getNodeType() + " " + RuleEditorTreeNode.ROOT_TYPE);
51          }
52  
53          return myTree;
54      }
55  
56      /**
57       * This method builds a propositionTree recursively walking through the children of the proposition.
58       *
59       * @param sprout - parent tree node
60       * @param prop   - PropositionBo for which to make the tree node
61       */
62      private Node addChildNode(RuleEditor rule, Node sprout, PropositionEditor prop) {
63          // Depending on the type of proposition (simple/compound), and the editMode,
64          // Create a treeNode of the appropriate type for the node and attach it to the
65          // sprout parameter passed in.
66          // If the prop is a compound proposition, calls itself for each of the compoundComponents
67          if (prop != null) {
68              // add a node for the description display with a child proposition node
69              Node<RuleEditorTreeNode, String> leaf = new Node<RuleEditorTreeNode, String>();
70              if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
71                  //Add the proposition with alpha code in the map if it doesn't already exist.
72                  if (null == prop.getKey()) {
73                      prop.setKey((String) rule.getSimpleKeys().next());
74                  }
75                  // Simple Proposition: add a node for the description display with a child proposition node
76                  if (prop.isEditMode()) {
77                      leaf.setNodeType(SimplePropositionEditNode.NODE_TYPE);
78                      PropositionEditor copy = (PropositionEditor) ObjectUtils.deepCopy(prop);
79                      leaf.setData(new SimplePropositionEditNode(copy));
80                  } else {
81                      leaf.setNodeLabel(this.buildNodeLabel(rule, prop));
82                      leaf.setNodeType(SimplePropositionNode.NODE_TYPE);
83                      addNodeType(leaf, KRMSConstants.NODE_TYPE_SUBRULEELEMENT);
84                      leaf.setData(new SimplePropositionNode(prop));
85                  }
86  
87                  sprout.getChildren().add(leaf);
88              } else if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
89                  //Add the proposition with alpha code in the map if it doesn't already exist.
90                  if (null == prop.getKey()) {
91                      prop.setKey((String) rule.getCompoundKeys().next());
92                  }
93                  // Compound Proposition: editMode has description as an editable field
94                  leaf.setNodeLabel(StringEscapeUtils.escapeHtml(this.getDescription(prop)));
95                  leaf.setNodeType(RuleEditorTreeNode.COMPOUND_NODE_TYPE);
96                  leaf.setData(new RuleEditorTreeNode(prop));
97  
98                  sprout.getChildren().add(leaf);
99  
100                 int counter = 0;
101                 for (PropositionEditor child : prop.getCompoundEditors()) {
102                     // add an opcode node in between each of the children.
103                     if (counter > 0) {
104                         addOpCodeNode(leaf, prop, counter);
105                     }
106                     // call to build the childs node
107                     Node childNode = addChildNode(rule, leaf, child);
108                     if (counter==0){
109                         addNodeType(childNode, RuleEditorTreeNode.FIRST_IN_GROUP);
110                     }
111                     if (counter==prop.getCompoundEditors().size()-1){
112                         addNodeType(childNode, RuleEditorTreeNode.LAST_IN_GROUP);
113                     }
114                     //Add flag to identify if child can move right, if child has sibling after it
115                     if((leaf.getData().getProposition().getCompoundEditors().size() - 1) != counter) {
116                         if(!leaf.getData().getProposition().getCompoundEditors().get(leaf.getData().getProposition().getCompoundEditors().indexOf(child) + 1).getPropositionTypeCode().equals("C")) {
117                             addNodeType(childNode, RuleEditorTreeNode.DISABLE_MOVE_IN);
118                         }
119                     } //Set flag for last child in leaf
120                     else {
121                         addNodeType(childNode, RuleEditorTreeNode.DISABLE_MOVE_IN);
122                     }
123                     counter++;
124                 }
125             }
126             //Set move left disabled flag if simple proposition in the root compound
127             if(sprout.getData() != null) {
128                 if(((RuleEditorTreeNode) sprout.getData()).getProposition().equals(rule.getProposition())) {
129                     addNodeType(leaf, RuleEditorTreeNode.DISABLE_MOVE_OUT);
130                 }
131             }
132             return leaf;
133         }
134         return null;
135     }
136 
137     private String buildNodeLabel(RuleEditor rule, PropositionEditor prop) {
138         //Build the node label.
139         String prefix = this.getPropositionPrefix(prop);
140         return prefix + StringEscapeUtils.escapeHtml(this.getDescription(prop));
141     }
142 
143     /**
144      * This method adds an opCode Node to separate components in a compound proposition.
145      *
146      * @param currentNode
147      * @param prop
148      * @return
149      */
150     private void addOpCodeNode(Node currentNode, PropositionEditor prop, int counter) {
151         //Create the node.
152         Node<CompoundOpCodeNode, String> aNode = new Node<CompoundOpCodeNode, String>();
153         aNode.setNodeType(RuleEditorTreeNode.COMPOUND_OP_NODE_TYPE);
154 
155         //Add a dummy editor.
156         PropositionEditor editor = new PropositionEditor();
157         editor.setKey(prop.getKey() + counter);
158         editor.setCompoundOpCode(prop.getCompoundOpCode());
159 
160         aNode.setData(new CompoundOpCodeNode(editor));
161         currentNode.getChildren().add(aNode);
162     }
163 
164     public String getNaturalLanguageUsageKey(){
165         return null;
166     }
167 
168 }