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.kuali.rice.core.api.util.tree.Node;
19  import org.kuali.rice.core.api.util.tree.Tree;
20  import org.kuali.rice.krad.util.ObjectUtils;
21  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
22  import org.kuali.rice.krms.dto.PropositionEditor;
23  import org.kuali.rice.krms.dto.RuleEditor;
24  import org.kuali.rice.krms.tree.node.CompoundOpCodeNode;
25  import org.kuali.rice.krms.tree.node.SimplePropositionEditNode;
26  import org.kuali.rice.krms.tree.node.SimplePropositionNode;
27  import org.kuali.rice.krms.tree.node.RuleEditorTreeNode;
28  import org.kuali.rice.krms.util.KRMSConstants;
29  
30  /**
31   *
32   * @author Kuali Student Team
33   */
34  public class RuleEditTreeBuilder extends AbstractTreeBuilder{
35  
36      private static final long serialVersionUID = 1L;
37  
38      public Tree buildTree(RuleEditor rule) {
39  
40          Tree myTree = new Tree<RuleEditorTreeNode, String>();
41  
42          Node<RuleEditorTreeNode, String> rootNode = new Node<RuleEditorTreeNode, String>();
43          rootNode.setNodeType(KRMSConstants.ROOT_TYPE);
44  
45          myTree.setRootElement(rootNode);
46  
47          if (rule.getPropositionEditor() != null){
48              Node firstNode = addChildNode(rule, rootNode, rule.getPropositionEditor());
49              firstNode.setNodeType(firstNode.getNodeType() + " " + KRMSConstants.ROOT_TYPE);
50          }
51  
52          return myTree;
53      }
54  
55      /**
56       * This method builds a propositionTree recursively walking through the children of the proposition.
57       *
58       * @param sprout - parent tree node
59       * @param prop   - PropositionBo for which to make the tree node
60       */
61      private Node addChildNode(RuleEditor rule, Node sprout, PropositionEditor prop) {
62          // Depending on the type of proposition (simple/compound), and the editMode,
63          // Create a treeNode of the appropriate type for the node and attach it to the
64          // sprout parameter passed in.
65          // If the prop is a compound proposition, calls itself for each of the compoundComponents
66          if (prop != null) {
67              // add a node for the description display with a child proposition node
68              Node<RuleEditorTreeNode, String> leaf = new Node<RuleEditorTreeNode, String>();
69              if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
70                  handleSimpleNode(rule, sprout, prop, leaf);
71              } else if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) {
72                  handleCompoundNode(rule, sprout, prop, leaf);
73              }
74  
75              //Set move left disabled flag if simple proposition in the root compound
76              if(sprout.getData() != null) {
77                  if(((RuleEditorTreeNode) sprout.getData()).getProposition().equals(rule.getProposition())) {
78                      addNodeType(leaf, KRMSConstants.DISABLE_MOVE_OUT);
79                  }
80              }
81              return leaf;
82          }
83          return null;
84      }
85  
86      protected void handleCompoundNode(RuleEditor rule, Node sprout, PropositionEditor prop, Node<RuleEditorTreeNode, String> leaf) {
87          //Add the proposition with alpha code in the map if it doesn't already exist.
88          if (null == prop.getKey()) {
89              prop.setKey((String) rule.getCompoundKeys().next());
90          }
91          setupCompoundNode(rule, prop, leaf);
92          sprout.getChildren().add(leaf);
93  
94          int counter = 0;
95          for (PropositionEditor child : prop.getCompoundEditors()) {
96              // add an opcode node in between each of the children.
97              if (counter > 0) {
98                  addOpCodeNode(leaf, prop, counter);
99              }
100             // call to build the childs node
101             Node childNode = addChildNode(rule, leaf, child);
102             if (counter==0){
103                 addNodeType(childNode, KRMSConstants.FIRST_IN_GROUP);
104             }
105             if (counter==prop.getCompoundEditors().size()-1){
106                 addNodeType(childNode, KRMSConstants.LAST_IN_GROUP);
107             }
108             //Add flag to identify if child can move right, if child has sibling after it
109             if((leaf.getData().getProposition().getCompoundEditors().size() - 1) != counter) {
110                 if(!leaf.getData().getProposition().getCompoundEditors().get(leaf.getData().getProposition().getCompoundEditors().indexOf(child) + 1).getPropositionTypeCode().equals("C")) {
111                     addNodeType(childNode, KRMSConstants.DISABLE_MOVE_IN);
112                 }
113             } //Set flag for last child in leaf
114             else {
115                 addNodeType(childNode, KRMSConstants.DISABLE_MOVE_IN);
116             }
117             counter++;
118         }
119     }
120 
121     protected void setupCompoundNode(RuleEditor rule, PropositionEditor prop, Node<RuleEditorTreeNode, String> leaf) {
122         // Compound Proposition: editMode has description as an editable field
123         leaf.setNodeLabel(this.getDescription(prop));
124         leaf.setNodeType(KRMSConstants.COMPOUND_NODE_TYPE);
125         leaf.setData(new SimplePropositionNode(prop));
126     }
127 
128     protected void handleSimpleNode(RuleEditor rule, Node sprout, PropositionEditor prop, Node<RuleEditorTreeNode, String> leaf) {
129         //Add the proposition with alpha code in the map if it doesn't already exist.
130         if (null == prop.getKey()) {
131             prop.setKey((String) rule.getSimpleKeys().next());
132         }
133         // Simple Proposition: add a node for the description display with a child proposition node
134         if (prop.isEditMode()) {
135             setupEditNode(rule, prop, leaf);
136         } else {
137             setupSimpleNode(rule, prop, leaf);
138         }
139 
140         sprout.getChildren().add(leaf);
141     }
142 
143     protected void setupEditNode(RuleEditor rule, PropositionEditor prop, Node<RuleEditorTreeNode, String> leaf) {
144         leaf.setNodeType(KRMSConstants.EDIT_NODE_TYPE);
145         PropositionEditor copy = (PropositionEditor) ObjectUtils.deepCopy(prop);
146         leaf.setData(new SimplePropositionEditNode(copy));
147     }
148 
149     protected void setupSimpleNode(RuleEditor rule, PropositionEditor prop, Node<RuleEditorTreeNode, String> leaf) {
150         leaf.setNodeLabel(this.buildNodeLabel(rule, prop));
151         leaf.setNodeType(KRMSConstants.SIMPLE_NODE_TYPE);
152         addNodeType(leaf, KRMSConstants.NODE_TYPE_SUBRULEELEMENT);
153         leaf.setData(new SimplePropositionNode(prop));
154     }
155 
156     protected String buildNodeLabel(RuleEditor rule, PropositionEditor prop) {
157         //Build the node label.
158         String prefix = this.getPropositionPrefix(prop);
159         return prefix + this.getDescription(prop);
160     }
161 
162     /**
163      * This method adds an opCode Node to separate components in a compound proposition.
164      *
165      * @param currentNode
166      * @param prop
167      * @return
168      */
169     protected void addOpCodeNode(Node currentNode, PropositionEditor prop, int counter) {
170         //Create the node.
171         Node<CompoundOpCodeNode, String> aNode = new Node<CompoundOpCodeNode, String>();
172         aNode.setNodeType(KRMSConstants.COMPOUND_OP_NODE_TYPE);
173 
174         //Add a dummy editor.
175         PropositionEditor editor = new PropositionEditor();
176         editor.setKey(prop.getKey() + counter);
177         editor.setCompoundOpCode(prop.getCompoundOpCode());
178 
179         aNode.setData(new CompoundOpCodeNode(editor));
180         currentNode.getChildren().add(aNode);
181     }
182 
183     public String getNaturalLanguageUsageKey(){
184         return null;
185     }
186 
187 }