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.apache.commons.lang.StringEscapeUtils; 019import org.kuali.rice.core.api.util.tree.Node; 020import org.kuali.rice.core.api.util.tree.Tree; 021import org.kuali.rice.krad.util.ObjectUtils; 022import org.kuali.rice.krms.api.repository.proposition.PropositionType; 023import org.kuali.rice.krms.dto.PropositionEditor; 024import org.kuali.rice.krms.dto.RuleEditor; 025import org.kuali.rice.krms.tree.node.CompoundOpCodeNode; 026import org.kuali.rice.krms.tree.node.SimplePropositionEditNode; 027import org.kuali.rice.krms.tree.node.SimplePropositionNode; 028import org.kuali.rice.krms.tree.node.RuleEditorTreeNode; 029import org.kuali.rice.krms.util.KRMSConstants; 030 031/** 032 * 033 * @author Kuali Student Team 034 */ 035public class RuleEditTreeBuilder extends AbstractTreeBuilder{ 036 037 private static final long serialVersionUID = 1L; 038 039 public Tree buildTree(RuleEditor rule) { 040 041 Tree myTree = new Tree<RuleEditorTreeNode, String>(); 042 043 Node<RuleEditorTreeNode, String> rootNode = new Node<RuleEditorTreeNode, String>(); 044 rootNode.setNodeType(RuleEditorTreeNode.ROOT_TYPE); 045 046 myTree.setRootElement(rootNode); 047 048 if (rule.getPropositionEditor() != null){ 049 Node firstNode = addChildNode(rule, rootNode, rule.getPropositionEditor()); 050 firstNode.setNodeType(firstNode.getNodeType() + " " + RuleEditorTreeNode.ROOT_TYPE); 051 } 052 053 return myTree; 054 } 055 056 /** 057 * This method builds a propositionTree recursively walking through the children of the proposition. 058 * 059 * @param sprout - parent tree node 060 * @param prop - PropositionBo for which to make the tree node 061 */ 062 private Node addChildNode(RuleEditor rule, Node sprout, PropositionEditor prop) { 063 // Depending on the type of proposition (simple/compound), and the editMode, 064 // Create a treeNode of the appropriate type for the node and attach it to the 065 // sprout parameter passed in. 066 // If the prop is a compound proposition, calls itself for each of the compoundComponents 067 if (prop != null) { 068 // add a node for the description display with a child proposition node 069 Node<RuleEditorTreeNode, String> leaf = new Node<RuleEditorTreeNode, String>(); 070 if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) { 071 //Add the proposition with alpha code in the map if it doesn't already exist. 072 if (null == prop.getKey()) { 073 prop.setKey((String) rule.getSimpleKeys().next()); 074 } 075 // Simple Proposition: add a node for the description display with a child proposition node 076 if (prop.isEditMode()) { 077 leaf.setNodeType(SimplePropositionEditNode.NODE_TYPE); 078 PropositionEditor copy = (PropositionEditor) ObjectUtils.deepCopy(prop); 079 leaf.setData(new SimplePropositionEditNode(copy)); 080 } else { 081 leaf.setNodeLabel(this.buildNodeLabel(rule, prop)); 082 leaf.setNodeType(SimplePropositionNode.NODE_TYPE); 083 addNodeType(leaf, KRMSConstants.NODE_TYPE_SUBRULEELEMENT); 084 leaf.setData(new SimplePropositionNode(prop)); 085 } 086 087 sprout.getChildren().add(leaf); 088 } else if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(prop.getPropositionTypeCode())) { 089 //Add the proposition with alpha code in the map if it doesn't already exist. 090 if (null == prop.getKey()) { 091 prop.setKey((String) rule.getCompoundKeys().next()); 092 } 093 // Compound Proposition: editMode has description as an editable field 094 leaf.setNodeLabel(StringEscapeUtils.escapeHtml(this.getDescription(prop))); 095 leaf.setNodeType(RuleEditorTreeNode.COMPOUND_NODE_TYPE); 096 leaf.setData(new RuleEditorTreeNode(prop)); 097 098 sprout.getChildren().add(leaf); 099 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}