001 package org.kuali.rice.krms.util; 002 003 import org.kuali.rice.core.api.util.tree.Node; 004 import org.kuali.rice.krms.api.repository.LogicalOperator; 005 import org.kuali.rice.krms.api.repository.proposition.PropositionType; 006 import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition; 007 import org.kuali.rice.krms.dto.PropositionEditor; 008 import org.kuali.rice.krms.dto.PropositionParameterEditor; 009 import org.kuali.rice.krms.dto.RuleEditor; 010 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator; 011 import org.kuali.rice.krms.tree.node.RuleEditorTreeNode; 012 import org.kuali.student.enrollment.class2.courseoffering.service.decorators.PermissionServiceConstants; 013 014 import java.util.ArrayList; 015 import java.util.Arrays; 016 import java.util.List; 017 018 /** 019 * Created with IntelliJ IDEA. 020 * User: SW 021 * Date: 2012/12/03 022 * Time: 4:39 PM 023 * To change this template use File | Settings | File Templates. 024 */ 025 public class PropositionTreeUtil { 026 027 public static void setTypeForCompoundOpCode(PropositionEditor proposition, String compoundOpCode) { 028 proposition.setCompoundOpCode(compoundOpCode); 029 if (LogicalOperator.AND.getCode().equalsIgnoreCase(compoundOpCode)) { 030 proposition.setType("kuali.krms.proposition.type.compound.and"); 031 } else if (LogicalOperator.OR.getCode().equalsIgnoreCase(compoundOpCode)) { 032 proposition.setType("kuali.krms.proposition.type.compound.or"); 033 } 034 try { 035 KrmsTypeDefinition type = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService().getTypeByName(PermissionServiceConstants.KS_SYS_NAMESPACE, proposition.getType()); 036 proposition.setTypeId(type.getId()); 037 } catch (Exception e) { 038 //ignore if service not available. 039 } 040 041 } 042 043 public static Node<RuleEditorTreeNode, String> findParentPropositionNode(Node<RuleEditorTreeNode, String> currentNode, String selectedPropKey) { 044 Node<RuleEditorTreeNode, String> bingo = null; 045 if (selectedPropKey != null) { 046 // if it's in children, we have the parent 047 List<Node<RuleEditorTreeNode, String>> children = currentNode.getChildren(); 048 for (Node<RuleEditorTreeNode, String> child : children) { 049 RuleEditorTreeNode dataNode = child.getData(); 050 if (selectedPropKey.equalsIgnoreCase(dataNode.getProposition().getKey())) { 051 return currentNode; 052 } 053 } 054 055 // if not found check grandchildren 056 for (Node<RuleEditorTreeNode, String> kid : children) { 057 bingo = findParentPropositionNode(kid, selectedPropKey); 058 if (bingo != null) { 059 break; 060 } 061 } 062 } 063 return bingo; 064 } 065 066 /** 067 * @return the {@link org.kuali.rice.krms.impl.repository.PropositionBo} from the form 068 */ 069 public static PropositionEditor getProposition(RuleEditor ruleEditor) { 070 071 if (ruleEditor != null) { 072 String selectedPropKey = ruleEditor.getSelectedKey(); 073 return findProposition(ruleEditor.getEditTree().getRootElement(), selectedPropKey); 074 } 075 076 return null; 077 } 078 079 public static PropositionEditor findProposition(Node<RuleEditorTreeNode, String> currentNode, String selectedPropKey) { 080 081 if (selectedPropKey == null) { 082 return null; 083 } else if (selectedPropKey.isEmpty()) { 084 return currentNode.getChildren().get(0).getData().getProposition(); 085 } 086 087 // if it's in children, we have the parent 088 for (Node<RuleEditorTreeNode, String> child : currentNode.getChildren()) { 089 PropositionEditor proposition = child.getData().getProposition(); 090 if (selectedPropKey.equalsIgnoreCase(proposition.getKey())) { 091 return proposition; 092 } else if ("S".equals(proposition.getPropositionTypeCode()) && proposition.isEditMode()) { 093 return proposition; 094 } else if (!proposition.isEditMode()) { 095 // if not found check grandchildren 096 proposition = findProposition(child, selectedPropKey); 097 if (proposition != null) { 098 return proposition; 099 } 100 } 101 } 102 103 return null; 104 } 105 106 /** 107 * Find and return the node containing the proposition that is in currently in edit mode 108 * 109 * @param node the node to start searching from (typically the root) 110 * @return the node that is currently being edited, if any. Otherwise, null. 111 */ 112 public static Node<RuleEditorTreeNode, String> findEditedProposition(Node<RuleEditorTreeNode, String> node) { 113 Node<RuleEditorTreeNode, String> result = null; 114 if (node.getData() != null && node.getData().getProposition() != null && node.getData().getProposition() 115 .isEditMode()) { 116 result = node; 117 } else { 118 for (Node<RuleEditorTreeNode, String> child : node.getChildren()) { 119 result = findEditedProposition(child); 120 if (result != null) { 121 break; 122 } 123 } 124 } 125 return result; 126 } 127 128 public static void resetEditModeOnPropositionTree(RuleEditor ruleEditor) { 129 Node<RuleEditorTreeNode, String> root = ruleEditor.getEditTree().getRootElement(); 130 resetEditModeOnPropositionTree(root); 131 } 132 133 /** 134 * disable edit mode for all Nodes beneath and including the passed in Node 135 * 136 * @param currentNode 137 */ 138 public static void resetEditModeOnPropositionTree(Node<RuleEditorTreeNode, String> currentNode) { 139 if (currentNode.getData() != null) { 140 RuleEditorTreeNode dataNode = currentNode.getData(); 141 dataNode.getProposition().setEditMode(false); 142 } 143 List<Node<RuleEditorTreeNode, String>> children = currentNode.getChildren(); 144 for (Node<RuleEditorTreeNode, String> child : children) { 145 resetEditModeOnPropositionTree(child); 146 } 147 } 148 149 public static Node<RuleEditorTreeNode, String> findPropositionTreeNode(Node<RuleEditorTreeNode, String> currentNode, String selectedPropId) { 150 Node<RuleEditorTreeNode, String> bingo = null; 151 if (currentNode.getData() != null) { 152 RuleEditorTreeNode dataNode = currentNode.getData(); 153 if (selectedPropId.equalsIgnoreCase(dataNode.getProposition().getId())) { 154 return currentNode; 155 } 156 } 157 158 for (Node<RuleEditorTreeNode, String> child : currentNode.getChildren()) { 159 bingo = findPropositionTreeNode(child, selectedPropId); 160 if (bingo != null) break; 161 } 162 return bingo; 163 } 164 165 public static String configureLogicExpression(PropositionEditor proposition) { 166 // Depending on the type of proposition (simple/compound), and the editMode, 167 // Create a treeNode of the appropriate type for the node and attach it to the 168 // sprout parameter passed in. 169 // If the prop is a compound proposition, calls itself for each of the compoundComponents 170 String logicExpression = proposition.getKey(); 171 if (PropositionType.COMPOUND.getCode().equalsIgnoreCase(proposition.getPropositionTypeCode())) { 172 logicExpression += "("; 173 boolean first = true; 174 for (PropositionEditor child : proposition.getCompoundEditors()) { 175 // add an opcode node in between each of the children. 176 if (!first) { 177 if (LogicalOperator.AND.getCode().equalsIgnoreCase(proposition.getCompoundOpCode())) { 178 logicExpression += " AND "; 179 } else if (LogicalOperator.OR.getCode().equalsIgnoreCase(proposition.getCompoundOpCode())) { 180 logicExpression += " OR "; 181 } 182 } 183 first = false; 184 // call to build the childs node 185 logicExpression += configureLogicExpression(child); 186 } 187 logicExpression += ")"; 188 } 189 return logicExpression; 190 } 191 192 /** 193 * This method creates a partially populated Simple PropositionBo with 194 * three parameters: a term type paramter (value not assigned) 195 * a operation parameter 196 * a constant parameter (value set to empty string) 197 * The returned PropositionBo has an generatedId. The type code and ruleId properties are assigned the 198 * same value as the sibling param passed in. 199 * Each PropositionParameter has the id generated, and type, sequenceNumber, 200 * propId default values set. The value is set to "". 201 * 202 * @param sibling - 203 * @return a PropositionBo partially populated. 204 */ 205 public static PropositionEditor createSimplePropositionBoStub(PropositionEditor sibling, Class<? extends PropositionEditor> propClass) throws IllegalAccessException, InstantiationException { 206 // create a simple proposition Bo 207 PropositionEditor prop = propClass.newInstance(); 208 prop.setPropositionTypeCode(PropositionType.SIMPLE.getCode()); 209 prop.setNewProp(true); 210 prop.setEditMode(true); 211 if (sibling != null) { 212 prop.setRuleId(sibling.getRuleId()); 213 } 214 215 prop.setParameters(createParameterList()); 216 217 return prop; 218 } 219 220 public static List<PropositionParameterEditor> createParameterList() { 221 // create blank proposition parameters 222 PropositionParameterEditor pTerm = new PropositionParameterEditor("T", new Integer("0")); 223 PropositionParameterEditor pOp = new PropositionParameterEditor("O", new Integer("2")); 224 PropositionParameterEditor pConst = new PropositionParameterEditor("C", new Integer("1")); 225 226 return Arrays.asList(pTerm, pConst, pOp); 227 } 228 229 public static PropositionEditor createCompoundPropositionBoStub(PropositionEditor existing, boolean addNewChild, Class<? extends PropositionEditor> propClass) throws InstantiationException, IllegalAccessException { 230 // create a simple proposition Bo 231 PropositionEditor prop = createCompoundPropositionBoStub(existing, propClass); 232 233 if (addNewChild) { 234 PropositionEditor newProp = createSimplePropositionBoStub(existing, propClass); 235 prop.getCompoundEditors().add(newProp); 236 prop.setEditMode(false); // set the parent edit mode back to null or we end up with 2 props in edit mode 237 } 238 239 return prop; 240 } 241 242 public static PropositionEditor createCompoundPropositionBoStub(PropositionEditor existing, Class<? extends PropositionEditor> propClass) throws IllegalAccessException, InstantiationException { 243 // create a simple proposition Bo 244 PropositionEditor prop = propClass.newInstance(); 245 prop.setNewProp(true); 246 prop.setPropositionTypeCode(PropositionType.COMPOUND.getCode()); 247 prop.setRuleId(existing.getRuleId()); 248 prop.setCompoundOpCode(LogicalOperator.AND.getCode()); // default to and 249 prop.setDescription(""); 250 prop.setEditMode(true); 251 252 List<PropositionEditor> components = new ArrayList<PropositionEditor>(); 253 components.add(existing); 254 prop.setCompoundEditors(components); 255 return prop; 256 } 257 258 public static void cancelNewProp(PropositionEditor proposition) { 259 int i = 0; 260 if (proposition.getCompoundEditors() != null) { 261 while (i < proposition.getCompoundEditors().size()) { 262 PropositionEditor child = proposition.getCompoundEditors().get(i); 263 if (child.isNewProp()) { 264 proposition.getCompoundEditors().remove(child); 265 continue; 266 } else { 267 cancelNewProp(child); 268 } 269 i++; 270 } 271 } 272 } 273 274 public static void resetNewProp(PropositionEditor proposition) { 275 if (proposition.getCompoundEditors() != null) { 276 for (PropositionEditor child : proposition.getCompoundEditors()) { 277 child.setNewProp(false); 278 resetNewProp(child); 279 } 280 } 281 } 282 }