001/** 002 * Copyright 2005-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krms.tree; 017 018import org.kuali.rice.core.api.util.tree.Node; 019import org.kuali.rice.core.api.util.tree.Tree; 020import org.kuali.rice.krad.util.ObjectUtils; 021import org.kuali.rice.krms.api.repository.proposition.PropositionType; 022import org.kuali.rice.krms.dto.PropositionEditor; 023import org.kuali.rice.krms.dto.RuleEditor; 024import org.kuali.rice.krms.tree.node.CompoundOpCodeNode; 025import org.kuali.rice.krms.tree.node.SimplePropositionEditNode; 026import org.kuali.rice.krms.tree.node.SimplePropositionNode; 027import org.kuali.rice.krms.tree.node.RuleEditorTreeNode; 028import org.kuali.rice.krms.util.KRMSConstants; 029 030/** 031 * 032 * @author Kuali Student Team 033 */ 034public class RuleEditTreeBuilder extends AbstractTreeBuilder{ 035 036 private static final long serialVersionUID = 1L; 037 038 public Tree buildTree(RuleEditor rule) { 039 040 Tree myTree = new Tree<RuleEditorTreeNode, String>(); 041 042 Node<RuleEditorTreeNode, String> rootNode = new Node<RuleEditorTreeNode, String>(); 043 rootNode.setNodeType(KRMSConstants.ROOT_TYPE); 044 045 myTree.setRootElement(rootNode); 046 047 if (rule.getPropositionEditor() != null){ 048 Node firstNode = addChildNode(rule, rootNode, rule.getPropositionEditor()); 049 firstNode.setNodeType(firstNode.getNodeType() + " " + KRMSConstants.ROOT_TYPE); 050 } 051 052 return myTree; 053 } 054 055 /** 056 * This method builds a propositionTree recursively walking through the children of the proposition. 057 * 058 * @param sprout - parent tree node 059 * @param prop - PropositionBo for which to make the tree node 060 */ 061 private Node addChildNode(RuleEditor rule, Node sprout, PropositionEditor prop) { 062 // Depending on the type of proposition (simple/compound), and the editMode, 063 // Create a treeNode of the appropriate type for the node and attach it to the 064 // sprout parameter passed in. 065 // If the prop is a compound proposition, calls itself for each of the compoundComponents 066 if (prop != null) { 067 // add a node for the description display with a child proposition node 068 Node<RuleEditorTreeNode, String> leaf = new Node<RuleEditorTreeNode, String>(); 069 if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) { 070 handleSimpleNode(rule, sprout, prop, leaf); 071 } else if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) { 072 handleCompoundNode(rule, sprout, prop, leaf); 073 } 074 075 //Set move left disabled flag if simple proposition in the root compound 076 if(sprout.getData() != null) { 077 if(((RuleEditorTreeNode) sprout.getData()).getProposition().equals(rule.getProposition())) { 078 addNodeType(leaf, KRMSConstants.DISABLE_MOVE_OUT); 079 } 080 } 081 return leaf; 082 } 083 return null; 084 } 085 086 protected void handleCompoundNode(RuleEditor rule, Node sprout, PropositionEditor prop, Node<RuleEditorTreeNode, String> leaf) { 087 //Add the proposition with alpha code in the map if it doesn't already exist. 088 if (null == prop.getKey()) { 089 prop.setKey((String) rule.getCompoundKeys().next()); 090 } 091 setupCompoundNode(rule, prop, leaf); 092 sprout.getChildren().add(leaf); 093 094 int counter = 0; 095 for (PropositionEditor child : prop.getCompoundEditors()) { 096 // add an opcode node in between each of the children. 097 if (counter > 0) { 098 addOpCodeNode(leaf, prop, counter); 099 } 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}