Coverage Report - org.kuali.student.core.statement.ui.client.widgets.rules.StatementVO
 
Classes in this File Line Coverage Branch Coverage Complexity
StatementVO
0%
0/496
0%
0/444
4.2
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.core.statement.ui.client.widgets.rules;
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collections;
 21  
 import java.util.List;
 22  
 
 23  
 import org.kuali.student.core.statement.dto.ReqComponentInfo;
 24  
 import org.kuali.student.core.statement.dto.StatementInfo;
 25  
 import org.kuali.student.core.statement.dto.StatementOperatorTypeKey;
 26  
 import org.kuali.student.core.statement.dto.StatementTreeViewInfo;
 27  
 import org.kuali.student.core.statement.ui.client.widgets.table.Node;
 28  
 
 29  
 import com.google.gwt.core.client.GWT;
 30  
 import com.google.gwt.user.client.Window;
 31  
 
 32  
 public class StatementVO extends Token implements Serializable {
 33  
 
 34  
     private static final long serialVersionUID = 1L;
 35  
     private StatementInfo statementInfo;       //TODO do we really need this and do we need to duplicate this in sub rules?
 36  0
     private List<ReqComponentVO> reqComponentVOs = new ArrayList<ReqComponentVO>();
 37  0
     private List<StatementVO> statementVOs = new ArrayList<StatementVO>();
 38  
 
 39  
 
 40  
     //TODO remove after refactoring rule table related classes, removing StatementVO
 41  
     public void setStatementTreeViewInfo(StatementTreeViewInfo stmtTreeInfo) {
 42  
         try {
 43  0
             composeStatementVO(stmtTreeInfo, this);
 44  0
         } catch (Exception e) {
 45  0
             Window.alert(e.getMessage());
 46  0
             GWT.log("failed", e);
 47  0
         }
 48  0
     }
 49  
 
 50  
     public StatementTreeViewInfo getStatementTreeViewInfo() {
 51  
 
 52  0
         StatementTreeViewInfo stmtTreeInfo = new StatementTreeViewInfo();
 53  
 
 54  
         try {
 55  0
             composeStatementTreeViewInfo(this, stmtTreeInfo);
 56  0
         } catch (Exception e) {
 57  0
             e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
 58  0
         }
 59  
 
 60  0
         return stmtTreeInfo;
 61  
     }
 62  
 
 63  0
     public StatementVO() {
 64  0
     }
 65  
 
 66  0
     public StatementVO(StatementInfo statementInfo) {
 67  0
         setStatementInfo(statementInfo);
 68  0
     }
 69  
 
 70  
     public void printTree(Node node) {
 71  0
         int level = 0;
 72  
         ReqComponentVO content;
 73  
 //        level++;
 74  
 
 75  0
         if (node == null) {
 76  0
             GWT.log("null node found",null);
 77  0
             return;
 78  
         }
 79  
 
 80  0
         level = node.getDistance(node);
 81  0
         if (node.getUserObject() != null) {
 82  0
             Token token = (Token) node.getUserObject();
 83  
             //content = (ReqComponentVO) token.value;
 84  0
             GWT.log("Node level " + level + ", content: " + token.value,null);
 85  0
         }
 86  0
         else GWT.log("Node user object null, level: " + level, null);
 87  0
         for (int i = 0; i < node.getChildCount(); i++) {
 88  0
             Node child = node.getChildAt(i);
 89  0
             if (child.isLeaf()) {
 90  0
                 Token token = (Token) child.getUserObject();
 91  0
                 content = (ReqComponentVO) child.getUserObject();
 92  0
                 GWT.log("Node level " + child.getDistance(child) + ", content: " + content, null);
 93  0
             } else {
 94  0
                 printTree(child);
 95  
             }
 96  
         }
 97  0
     }
 98  
 
 99  
     /**
 100  
      * Gets the immediate parent statement of reqComponentVO
 101  
      * Example: (a and b) or (c and d) or (e)
 102  
      *     Where the statements are enclosed in brackets.  So in this example there are 3 statements.  Namely (a and b), (c and d), and (e).
 103  
      *     There are 5 requirement components a, b, c, d, and e. If requirement component b is passed in as a parameter, then (a and b)
 104  
      *     is returned.  If e is passed in, then (e) is returned.  If d is is passed in, then (c and d) is returned.
 105  
      * @param reqComponentVO
 106  
      * @return
 107  
      */
 108  
     public StatementVO getEnclosingStatementVO(StatementVO root, ReqComponentVO reqComponentVO) {
 109  0
         return doGetEnclosingStatementVO(root, reqComponentVO);
 110  
     }
 111  
 
 112  
     private StatementVO doGetEnclosingStatementVO(StatementVO statementVO, ReqComponentVO reqComponentVO) {
 113  0
         StatementVO result = null;
 114  0
         List<StatementVO> statementVOs = (statementVO == null)? null : statementVO.getStatementVOs();
 115  0
         List<ReqComponentVO> reqComponentVOs = (statementVO == null)? null : statementVO.getReqComponentVOs();
 116  
 
 117  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 118  0
             for (StatementVO subStatementVO : statementVOs) {
 119  0
                 List<ReqComponentVO>subStatementReqComponentVOs = subStatementVO.getReqComponentVOs();
 120  0
                 if (subStatementReqComponentVOs.size() == 1) {
 121  0
                     if (subStatementReqComponentVOs.get(0) == reqComponentVO) {
 122  0
                         result = statementVO;
 123  0
                         break;
 124  
                     }
 125  
                 }
 126  
                 else {
 127  0
                     result = doGetEnclosingStatementVO(subStatementVO, reqComponentVO);
 128  
                     // found the enclosing statement exit
 129  0
                     if (result != null) {
 130  0
                         break;
 131  
                     }
 132  
                 }
 133  0
             }
 134  0
         } else if (reqComponentVOs != null && !reqComponentVOs.isEmpty()) {
 135  0
             for (ReqComponentVO leafReqComponentVO : reqComponentVOs) {
 136  0
                 if (leafReqComponentVO == reqComponentVO) {
 137  0
                     result = statementVO;
 138  0
                     break;
 139  
                 }
 140  
             }
 141  
         }
 142  0
         return result;
 143  
     }
 144  
 
 145  
     public StatementVO getParentStatementVO(StatementVO root, StatementVO nodeStatement) {
 146  0
         StatementVO parentStatementVO = null;
 147  0
         if (nodeStatement == root) {
 148  0
             parentStatementVO = null;
 149  
         } else {
 150  0
             parentStatementVO = doGetParentStatementVO(root, nodeStatement);
 151  
         }
 152  0
         return parentStatementVO;
 153  
     }
 154  
 
 155  
     private StatementVO doGetParentStatementVO(StatementVO statementVO, StatementVO nodeStatement) {
 156  0
         StatementVO parentStatementVO = null;
 157  0
         if (statementVO.getStatementVOCount() > 0) {
 158  0
             for (StatementVO childStatementVO : statementVO.getStatementVOs()) {
 159  0
                 if (childStatementVO == nodeStatement) {
 160  0
                     return statementVO;
 161  
                 } else {
 162  0
                     parentStatementVO = doGetParentStatementVO(childStatementVO, nodeStatement);
 163  
                 }
 164  
             }
 165  
         }
 166  0
         return parentStatementVO;
 167  
     }
 168  
 
 169  
     /**
 170  
      * returns the number of leaf requirement componentVO of the this statement
 171  
      * excluding those compound sub statements.
 172  
      * e.g. if this method is called on S1, the return value will be 2.
 173  
      * <pre>
 174  
      *                    S1:OR
 175  
      *           S2:OR    S3:OR   S4:AND
 176  
      *             a        b     c d e
 177  
      * </pre>
 178  
      * @return
 179  
      */
 180  
     /*
 181  
     public int getImmediateChildReqComponentCount() {
 182  
         int result = 0;
 183  
         if (reqComponentVOs != null && !reqComponentVOs.isEmpty()) {
 184  
             result = reqComponentVOs.size();
 185  
         } else if (statementVOs != null && !statementVOs.isEmpty()) {
 186  
             for (StatementVO subStatementVO : statementVOs) {
 187  
                 List<ReqComponentVO> subStatementReqComponentVOs =
 188  
                     subStatementVO.getReqComponentVOs();
 189  
                 if (subStatementReqComponentVOs != null &&
 190  
                         subStatementReqComponentVOs.size() == 1) {
 191  
                     result++;
 192  
                 }
 193  
             }
 194  
         }
 195  
         return result;
 196  
     } */
 197  
 
 198  
     private void validate() {
 199  0
         if (statementVOs != null && !statementVOs.isEmpty() && reqComponentVOs != null && !reqComponentVOs.isEmpty()) {
 200  0
             throw new IllegalStateException("Requirement components and statements can not exist together in a statement");
 201  
         }
 202  0
         checkDuplicateRC(this, new ArrayList<ReqComponentVO>());
 203  0
     }
 204  
 
 205  
     private void checkDuplicateRC(StatementVO statementVO, List<ReqComponentVO> seenRCs) {
 206  0
         if (statementVO.getStatementVOs() != null &&
 207  
                 !statementVO.getStatementVOs().isEmpty()) {
 208  0
             for (StatementVO childStatementVO : statementVO.getStatementVOs()) {
 209  0
                 checkDuplicateRC(childStatementVO, seenRCs);
 210  
             }
 211  
         } else {
 212  0
             if (statementVO.getReqComponentVOs() != null &&
 213  
                     !statementVO.getReqComponentVOs().isEmpty()) {
 214  0
                 for (ReqComponentVO childReqComponent : statementVO.getReqComponentVOs()) {
 215  0
                     if (seenRCs.contains(childReqComponent)) {
 216  0
                         throw new IllegalStateException(
 217  
                                 "statement and sub statements cannot have duplicated components");
 218  
                     } else {
 219  0
                         seenRCs.add(childReqComponent);
 220  
                     }
 221  
                 }
 222  
             }
 223  
         }
 224  0
     }
 225  
 
 226  
     public void addStatementVO(StatementVO statementVO) {
 227  0
         doAddStatementVO(statementVO);
 228  0
         validate();
 229  0
     }
 230  
 
 231  
     private void doAddStatementVO(StatementVO statementVO) {
 232  
         // if there are currently requirement components in this StatementVO
 233  
         // move all the existing requirement components into separate wrapping
 234  
         // StatementVOs
 235  0
         if (reqComponentVOs != null && !reqComponentVOs.isEmpty()) {
 236  0
             List<ReqComponentVO> tempReqComponentVOs = new ArrayList<ReqComponentVO>(reqComponentVOs);
 237  0
             for (ReqComponentVO currReqComponentVO : tempReqComponentVOs) {
 238  0
                 StatementVO wrapStatementVO = new StatementVO(statementInfo);
 239  0
                 wrapStatementVO.addReqComponentVO(currReqComponentVO);
 240  0
                 reqComponentVOs.remove(currReqComponentVO);
 241  0
                 statementVOs.add(wrapStatementVO);
 242  0
             }
 243  
         }
 244  0
         statementVOs.add(statementVO);
 245  0
     }
 246  
 
 247  
     public void addReqComponentVO(ReqComponentVO reqComponentVO) {
 248  0
         doAddReqComponentVO(reqComponentVO);
 249  0
         validate();
 250  0
     }
 251  
 
 252  
     private void doAddReqComponentVO(ReqComponentVO reqComponentVO) {
 253  
         // if there are sub statements in this statement already
 254  
         // add a new sub statement with the same operator as this statement
 255  
         // and a the requirement component
 256  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 257  0
             StatementInfo newStatementInfo = new StatementInfo();
 258  0
             StatementVO newStatementVO = new StatementVO();
 259  0
             newStatementInfo.setOperator(statementInfo.getOperator());
 260  0
             newStatementVO.setStatementInfo(newStatementInfo);
 261  0
             newStatementVO.getReqComponentVOs().add(reqComponentVO);
 262  0
             statementVOs.add(newStatementVO);
 263  0
         } else {
 264  0
             reqComponentVOs.add(reqComponentVO);
 265  
         }
 266  0
     }
 267  
 
 268  
     public void addReqComponentVO(ReqComponentVO reqComponentVO, String type) {
 269  0
         doAddReqComponentVO(reqComponentVO, type);
 270  0
         validate();
 271  0
     }
 272  
 
 273  
     private void doAddReqComponentVO(ReqComponentVO reqComponentVO, String type) {
 274  
         // if there are sub statements in this statement already
 275  
         // add a new sub statement with the same operator as this statement
 276  
         // and a the requirement component
 277  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 278  0
             StatementInfo newStatementInfo = new StatementInfo();
 279  0
             newStatementInfo.setType(type);
 280  0
             StatementVO newStatementVO = new StatementVO();
 281  0
             newStatementInfo.setOperator(statementInfo.getOperator());
 282  0
             newStatementVO.setStatementInfo(newStatementInfo);
 283  0
             newStatementVO.getReqComponentVOs().add(reqComponentVO);
 284  0
             statementVOs.add(newStatementVO);
 285  0
         } else {
 286  0
             reqComponentVOs.add(reqComponentVO);
 287  
         }
 288  0
     }
 289  
 
 290  
     public void removeStatementVO(StatementVO statementVO) {
 291  0
         statementVOs.remove(statementVO);
 292  0
         validate();
 293  0
     }
 294  
 
 295  
     public void removeReqComponentVO(ReqComponentVO reqComponentVO) {
 296  0
         doRemoveReqComponentVO(reqComponentVO);
 297  0
         validate();
 298  0
     }
 299  
 
 300  
     private void doRemoveReqComponentVO(ReqComponentVO reqComponentVO) {
 301  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 302  0
             List<StatementVO> tempStatementVOs = new ArrayList<StatementVO>(statementVOs);
 303  0
             for (StatementVO subStatementVO : tempStatementVOs) {
 304  0
                 List<ReqComponentVO> subStatementReqComponentVOs =
 305  
                     (subStatementVO == null)? null : subStatementVO.getReqComponentVOs();
 306  0
                 if (subStatementReqComponentVOs != null &&
 307  
                         subStatementReqComponentVOs.size() == 1 &&
 308  
                         subStatementReqComponentVOs.get(0) == reqComponentVO) {
 309  0
                     subStatementVO.removeReqComponentVO(reqComponentVO);
 310  
                     // cleans up empty statements with neither statements nor requirement components.
 311  0
                     statementVOs.remove(subStatementVO);
 312  
                 }
 313  0
             }
 314  0
         } else {
 315  0
             reqComponentVOs.remove(reqComponentVO);
 316  
         }
 317  0
     }
 318  
 
 319  
     public StatementInfo getStatementInfo() {
 320  0
         return statementInfo;
 321  
     }
 322  
 
 323  
     public void setStatementInfo(StatementInfo statementInfo) {
 324  0
         this.statementInfo = statementInfo;
 325  0
         this.setType(statementInfo.getOperator() == StatementOperatorTypeKey.OR ? Token.Or : Token.And);
 326  0
     }
 327  
 
 328  
     public List<ReqComponentVO> getReqComponentVOs() {
 329  0
         return reqComponentVOs;
 330  
     }
 331  
 
 332  
     public List<StatementVO> getStatementVOs() {
 333  0
         return statementVOs;
 334  
     }
 335  
 
 336  
     public void clearStatementAndReqComponents() {
 337  0
         if (statementVOs != null) {
 338  0
             statementVOs.clear();
 339  
         }
 340  0
         if (reqComponentVOs != null) {
 341  0
             reqComponentVOs.clear();
 342  
         }
 343  0
     }
 344  
 
 345  
     public void shiftReqComponent(String shiftType, final ReqComponentVO reqComponentVO) {
 346  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 347  
             // the statementVO that wraps the reqComponentVO
 348  0
             StatementVO reqComponentVOWrap = null;
 349  0
             for (StatementVO currStatementVO : statementVOs) {
 350  0
                 List<ReqComponentVO> currReqComponentVOs = (currStatementVO == null)? null :
 351  
                         currStatementVO.getReqComponentVOs();
 352  0
                 if (currReqComponentVOs != null && currReqComponentVOs.size() == 1 &&
 353  
                         currReqComponentVOs.get(0) == reqComponentVO) {
 354  0
                     reqComponentVOWrap = currStatementVO;
 355  
                 }
 356  0
             }
 357  0
             if (reqComponentVOWrap != null) {
 358  0
                 swapElement(statementVOs, reqComponentVOWrap, shiftType);
 359  
             }
 360  0
         } else if (reqComponentVOs != null && reqComponentVOs.size() > 1) {
 361  0
             swapElement(reqComponentVOs, reqComponentVO, shiftType);
 362  
         }
 363  0
     }
 364  
 
 365  
     private <T> void swapElement(List<T> elements, T element, String direction) {
 366  0
         int elementIndex = 0;
 367  0
         if (elements != null && elements.size() > 1) {
 368  0
             for (T currElement : elements) {
 369  0
                 if (direction != null && direction.equals("RIGHT")) {
 370  0
                     if (currElement == element && elementIndex + 1 < elements.size()) {
 371  0
                         Collections.swap(elements, elementIndex, elementIndex + 1);
 372  0
                         break;
 373  
                     }
 374  0
                 } else if (direction != null && direction.equals("LEFT")) {
 375  0
                     if (currElement == element && elementIndex > 0) {
 376  0
                         Collections.swap(elements, elementIndex, elementIndex - 1);
 377  0
                         break;
 378  
                     }
 379  
                 }
 380  0
                 elementIndex++;
 381  
             }
 382  
         }
 383  0
     }
 384  
 
 385  
     /**
 386  
      * returns A, B, C, ... etc depending on the number of
 387  
      * Requirement components in the list.
 388  
      * @param rcs
 389  
      * @return
 390  
      */
 391  
     private String getNextGuiRCId(List<ReqComponentVO> rcs) {
 392  0
         int charCode = 65; // ASCII code for capitalized A
 393  0
         int newCharCode = -1;
 394  
 
 395  0
         while (newCharCode == -1) {
 396  0
             boolean charUsed = false;
 397  0
             if (rcs != null) {
 398  0
                 for (ReqComponentVO rc : rcs) {
 399  0
                     String currGuiRCId = rc.getGuiReferenceLabelId();
 400  0
                     currGuiRCId = (currGuiRCId == null)? "" : currGuiRCId;
 401  0
                     if (currGuiRCId.equals(Character.toString((char)charCode))) {
 402  0
                         charUsed = true;
 403  0
                         charCode++;
 404  
                     }
 405  0
                 }
 406  
             }
 407  0
             if (!charUsed) {
 408  0
                 newCharCode = charCode;
 409  
             }
 410  0
         }
 411  
 
 412  
         // the next GUI id will be A - Z, and A1, A2, A3 afterwards.
 413  
         String guiRCId;
 414  0
         if (newCharCode < 65 + 26) {
 415  0
             guiRCId = Character.toString((char)newCharCode);
 416  
         } else {
 417  0
             guiRCId = Character.toString((char)(65 + 26));
 418  0
             guiRCId = guiRCId + Integer.toString(newCharCode - 65 + 26 - 1);
 419  
         }
 420  0
         return guiRCId;
 421  
     }
 422  
 
 423  
     private void assignGuiRCId() {
 424  0
         doAssignGuiRCId(this, new ArrayList<ReqComponentVO>());
 425  0
     }
 426  
 
 427  
     private void doAssignGuiRCId(StatementVO statementVO, List<ReqComponentVO> rcs) {
 428  0
         List<StatementVO> statementVOs = statementVO.getStatementVOs();
 429  0
         List<ReqComponentVO> reqComponentVOs = statementVO.getReqComponentVOs();
 430  
 
 431  0
         if (statementVOs != null) {
 432  0
             for (StatementVO childStatementVO : statementVOs) {
 433  0
                 doAssignGuiRCId(childStatementVO, rcs);
 434  
             }
 435  
         }
 436  
 
 437  0
         if (reqComponentVOs != null) {
 438  0
             for (int rcIndex = 0, rcCount = reqComponentVOs.size(); rcIndex < rcCount; rcIndex++) {
 439  0
                 ReqComponentVO childReqComponentVO = reqComponentVOs.get(rcIndex);
 440  0
                 if (childReqComponentVO.getGuiReferenceLabelId() == null ||
 441  
                         childReqComponentVO.getGuiReferenceLabelId().trim().length() == 0) {
 442  0
                     String guiRCId = getNextGuiRCId(rcs);
 443  0
                     childReqComponentVO.setGuiReferenceLabelId(guiRCId);
 444  
                 }
 445  0
                 rcs.add(childReqComponentVO);
 446  
             }
 447  
         }
 448  0
     }
 449  
 
 450  
     public Node getTree() {
 451  0
         Node node = new Node();
 452  0
         assignGuiRCId();
 453  0
         addChildrenNodes(node, this);
 454  0
         return node;
 455  
     }
 456  
 
 457  
     private void addChildrenNodes(Node node, StatementVO statementVO) {
 458  0
         List<StatementVO> statementVOs = statementVO.getStatementVOs();
 459  0
         List<ReqComponentVO> reqComponentVOs = statementVO.getReqComponentVOs();
 460  
 
 461  0
         if (statementVOs != null) {
 462  0
             node.setUserObject(statementVO);
 463  0
             setOperatorNode(node, statementVO);
 464  0
             for (int i = 0; i < statementVOs.size(); i++) {
 465  0
                 StatementVO childStatementVO = statementVOs.get(i);
 466  0
                 childStatementVO.setTokenOperator(true);
 467  0
                 Node childNode = new Node();
 468  0
                 node.addNode(childNode);
 469  0
                 addChildrenNodes(childNode, childStatementVO);
 470  
             }
 471  
         }
 472  
 
 473  0
         if (reqComponentVOs != null) {
 474  0
             for (int rcIndex = 0, rcCount = reqComponentVOs.size(); rcIndex < rcCount; rcIndex++) {
 475  0
                 ReqComponentVO childReqComponentVO = reqComponentVOs.get(rcIndex);
 476  0
                 if (rcCount > 1) {
 477  0
                     node.addNode(new Node(childReqComponentVO));
 478  
                 } else {
 479  0
                     node.setUserObject(childReqComponentVO);
 480  
                 }
 481  
             }
 482  
         }
 483  0
     }
 484  
 
 485  
     private void setOperatorNode(Node node, StatementVO statementVO) {
 486  0
         if (statementVO.getStatementInfo() != null && statementVO.getStatementInfo().getOperator() == StatementOperatorTypeKey.AND) {
 487  0
             statementVO.type = Token.And;
 488  0
             statementVO.value = "and";
 489  0
             node.setUserObject(statementVO);
 490  0
         } else if (statementVO.getStatementInfo() != null && statementVO.getStatementInfo().getOperator() == StatementOperatorTypeKey.OR) {
 491  0
             statementVO.type = Token.Or;
 492  0
             statementVO.value = "or";
 493  0
             node.setUserObject(statementVO);
 494  
         }
 495  0
     }
 496  
 
 497  
     public List<StatementVO> getSelectedStatementVOs() {
 498  0
         List<StatementVO> selectedStatementVOs = new ArrayList<StatementVO>();
 499  0
         return doGetSelectedStatmentVOs(this, selectedStatementVOs);
 500  
     }
 501  
 
 502  
     private List<StatementVO> doGetSelectedStatmentVOs(StatementVO statementVO, List<StatementVO> selectedStatementVOs) {
 503  0
         List<StatementVO> childrenStatementVOs = statementVO.getStatementVOs();
 504  0
         if (statementVO.isCheckBoxOn()) {
 505  0
             selectedStatementVOs.add(statementVO);
 506  
         }
 507  
         // check children
 508  0
         if (childrenStatementVOs != null && !childrenStatementVOs.isEmpty()) {
 509  0
             for (StatementVO childStatementVO : statementVO.getStatementVOs()) {
 510  0
                 doGetSelectedStatmentVOs(childStatementVO, selectedStatementVOs);
 511  
             }
 512  
         }
 513  0
         return selectedStatementVOs;
 514  
     }
 515  
 
 516  
     /**
 517  
      * goes through the entire tree recursively and returns the list of all RCs
 518  
      * @return
 519  
      */
 520  
     public List<ReqComponentVO> getAllReqComponentVOs() {
 521  0
         return doGetAllReqComponentVOs(this, new ArrayList<ReqComponentVO>());
 522  
     }
 523  
 
 524  
     public ReqComponentVO getReqComponentVOByGuiKey(String guiKey) {
 525  0
         ReqComponentVO result = null;
 526  0
         List<ReqComponentVO> allRCs = getAllReqComponentVOs();
 527  0
         for (ReqComponentVO rc : allRCs) {
 528  0
             if (rc.getGuiReferenceLabelId() != null && rc.getGuiReferenceLabelId().equals(guiKey)) {
 529  0
                 result = rc;
 530  0
                 break;
 531  
             }
 532  
         }
 533  0
         return result;
 534  
     }
 535  
 
 536  
     private List<ReqComponentVO> doGetAllReqComponentVOs(StatementVO statementVO,
 537  
             List<ReqComponentVO> allRCs) {
 538  0
         List<ReqComponentVO> childrenReqComponentVOs = statementVO.getReqComponentVOs();
 539  0
         List<StatementVO> childrenStatementVOs = statementVO.getStatementVOs();
 540  0
         if (childrenReqComponentVOs != null && !childrenReqComponentVOs.isEmpty()) {
 541  0
             for (ReqComponentVO childReqComponentVO : childrenReqComponentVOs) {
 542  0
                 allRCs.add(childReqComponentVO);
 543  
             }
 544  
         }
 545  0
         if (childrenStatementVOs != null && !childrenStatementVOs.isEmpty()) {
 546  0
             for (StatementVO childStatementVO : statementVO.getStatementVOs()) {
 547  0
                 doGetAllReqComponentVOs(childStatementVO, allRCs);
 548  
             }
 549  
         }
 550  0
         return allRCs;
 551  
     }
 552  
 
 553  
     public List<ReqComponentVO> getSelectedReqComponentVOs() {
 554  0
         List<ReqComponentVO> selectedReqComponentVOs = new ArrayList<ReqComponentVO>();
 555  0
         return doGetSelectedReqComponentVOs(this, selectedReqComponentVOs);
 556  
     }
 557  
 
 558  
     private List<ReqComponentVO> doGetSelectedReqComponentVOs(StatementVO statementVO, List<ReqComponentVO> selectedReqComponentVOs) {
 559  0
         List<ReqComponentVO> childrenReqComponentVOs = statementVO.getReqComponentVOs();
 560  0
         List<StatementVO> childrenStatementVOs = statementVO.getStatementVOs();
 561  0
         if (childrenReqComponentVOs != null && !childrenReqComponentVOs.isEmpty()) {
 562  0
             for (ReqComponentVO childReqComponentVO : childrenReqComponentVOs) {
 563  0
                 if (childReqComponentVO.isCheckBoxOn()) {
 564  0
                     selectedReqComponentVOs.add(childReqComponentVO);
 565  
                 }
 566  
             }
 567  
         }
 568  0
         if (childrenStatementVOs != null && !childrenStatementVOs.isEmpty()) {
 569  0
             for (StatementVO childStatementVO : statementVO.getStatementVOs()) {
 570  0
                 doGetSelectedReqComponentVOs(childStatementVO, selectedReqComponentVOs);
 571  
             }
 572  
         }
 573  0
         return selectedReqComponentVOs;
 574  
     }
 575  
 
 576  
     public boolean isFirstSelectedReqComp() {
 577  0
         return doIsFirstSelectedReqComp(this);
 578  
     }
 579  
 
 580  
     public boolean doIsFirstSelectedReqComp(StatementVO statementVO) {
 581  0
         List<ReqComponentVO> childrenReqComponentVOs = statementVO.getReqComponentVOs();
 582  0
         boolean isFirst = false;
 583  0
         if (childrenReqComponentVOs != null && !childrenReqComponentVOs.isEmpty()) {
 584  0
             isFirst = true;
 585  0
             for (ReqComponentVO childReqComponentVO : childrenReqComponentVOs) {
 586  0
                 if (childReqComponentVO.isCheckBoxOn()) {
 587  0
                     return isFirst;
 588  
                 }
 589  0
                 isFirst = false;
 590  
             }
 591  
         }
 592  0
         return isFirst;
 593  
     }
 594  
 
 595  
     public boolean isLastSelectedReqComp() {
 596  0
         return doIsLastSelectedReqComp(this);
 597  
     }
 598  
 
 599  
     public boolean doIsLastSelectedReqComp(StatementVO statementVO) {
 600  0
         List<ReqComponentVO> childrenReqComponentVOs = statementVO.getReqComponentVOs();
 601  0
         boolean isLast = false;
 602  0
         if (childrenReqComponentVOs != null && !childrenReqComponentVOs.isEmpty()) {
 603  0
             isLast = true;
 604  0
             for (ReqComponentVO childReqComponentVO : childrenReqComponentVOs) {
 605  0
                 isLast = childReqComponentVO.isCheckBoxOn();
 606  
             }
 607  
         }
 608  0
         return isLast;
 609  
     }
 610  
 
 611  
     public boolean isNodeSelected() {
 612  0
         return ((getSelectedStatementVOs().size() + getSelectedReqComponentVOs().size()) > 0);
 613  
     }
 614  
 
 615  
     public int getNestingDepth() {
 616  0
         return doGetNestingDepth(this);
 617  
     }
 618  
 
 619  
     private int doGetNestingDepth(StatementVO statementVO) {
 620  0
         int depth = 0;
 621  0
         List<StatementVO> statementVOs = getStatementVOs();
 622  0
         if (this == statementVO) {
 623  0
             return depth;
 624  
         }
 625  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 626  0
             for (StatementVO childStatementVO : statementVOs) {
 627  0
                 depth = depth + doGetNestingDepth(childStatementVO);
 628  
             }
 629  
         }
 630  0
         return depth;
 631  
     }
 632  
 
 633  
     public int getReqComponentVOCount() {
 634  0
         return (reqComponentVOs == null)? 0 : reqComponentVOs.size();
 635  
     }
 636  
 
 637  
     public int getStatementVOCount() {
 638  0
         return (statementVOs == null)? 0 : statementVOs.size();
 639  
     }
 640  
 
 641  
     public int getChildCount() {
 642  0
         return getReqComponentVOCount() + getStatementVOCount();
 643  
     }
 644  
 
 645  
     public boolean isWrapperStatementVO() {
 646  0
         boolean result = false;
 647  0
         if (getReqComponentVOCount() == 1 && getStatementVOCount() == 0) {
 648  0
             result = true;
 649  
         }
 650  0
         return result;
 651  
     }
 652  
 
 653  
     public void addStatementVOs(List<StatementVO> statementVOs) {
 654  0
         if (statementVOs != null && !statementVOs.isEmpty()) {
 655  0
             for (StatementVO s : statementVOs) {
 656  0
                 this.addStatementVO(s);
 657  
             }
 658  
         }
 659  0
     }
 660  
 
 661  
     public void addReqComponentVOs(List<ReqComponentVO> reqComponentVOs) {
 662  0
         if (reqComponentVOs != null && !reqComponentVOs.isEmpty()) {
 663  0
             for (ReqComponentVO rc : reqComponentVOs) {
 664  0
                 this.addReqComponentVO(rc);
 665  
             }
 666  
         }
 667  0
     }
 668  
 
 669  
     /**************************************************************************************************
 670  
      * simplifies statement
 671  
      * @return true if statement has been changed as a result of the call
 672  
      */
 673  
     public boolean simplify() {
 674  0
         boolean structureChanged = false;
 675  0
         structureChanged = structureChanged || doSimplify(this, null);
 676  0
         structureChanged = structureChanged || doCleanupStatementVO(this, null);
 677  0
         structureChanged = structureChanged || doUnwrapRCs(this, 0);
 678  0
         return structureChanged;
 679  
     }
 680  
 
 681  
     private boolean doSimplify(StatementVO statementVO, StatementVO parent) {
 682  0
         boolean structureChanged = false;
 683  0
         StatementOperatorTypeKey op = (statementVO == null || statementVO.getStatementInfo() == null)? null :
 684  
                                         statementVO.getStatementInfo().getOperator();
 685  0
         StatementOperatorTypeKey parentOp = (parent == null || parent.getStatementInfo() == null)? null : parent.getStatementInfo().getOperator();
 686  
         
 687  0
         if (parent != null && parentOp != op && statementVO.isWrapperStatementVO()) {
 688  0
             statementVO.getStatementInfo().setOperator(parentOp);
 689  
         }
 690  
         
 691  0
         if (parentOp == op && !statementVO.isWrapperStatementVO()) {
 692  0
             structureChanged = true;
 693  0
             if (statementVO.getReqComponentVOCount() > 0) {
 694  0
                 parent.removeStatementVO(statementVO);
 695  0
                 for (ReqComponentVO rc : statementVO.getReqComponentVOs()) {
 696  0
                     parent.addReqComponentVO(rc, statementVO.getStatementInfo().getType());
 697  
                 }
 698  0
             } else if (statementVO.getStatementVOCount() > 0) {
 699  0
                 if (parent != null) {
 700  0
                     parent.removeStatementVO(statementVO);
 701  
                 }
 702  0
                 List<StatementVO> subSs = new ArrayList<StatementVO>(statementVO.getStatementVOs());
 703  0
                 for (StatementVO subS : subSs) {
 704  0
                     doSimplify(subS, statementVO);
 705  
                 }
 706  0
                 parent.addStatementVOs(statementVO.getStatementVOs());
 707  0
             }
 708  0
         } else if (statementVO!=null && statementVO.getStatementVOCount() > 0) {
 709  0
             List<StatementVO> subSs = new ArrayList<StatementVO>(statementVO.getStatementVOs());
 710  0
             for (StatementVO subS : subSs) {
 711  0
                 structureChanged = structureChanged || doSimplify(subS, statementVO);
 712  
             }
 713  
         }
 714  0
         return structureChanged;
 715  
     }
 716  
 
 717  
     private boolean doCleanupStatementVO(StatementVO statementVO, StatementVO parent) {
 718  0
         boolean structureChanged = false;
 719  0
         if (statementVO.getStatementVOCount() == 0 && statementVO.getReqComponentVOCount() == 0) {
 720  0
             if (parent != null) {
 721  0
                 parent.removeStatementVO(statementVO);
 722  0
                 structureChanged = true;
 723  
             }
 724  0
         } else if (statementVO.getStatementVOCount() > 0) {
 725  0
             for (StatementVO subS : statementVO.getStatementVOs()) {
 726  0
                 structureChanged = structureChanged || doCleanupStatementVO(subS, statementVO);
 727  
             }
 728  
         }
 729  0
         return structureChanged;
 730  
     }
 731  
 
 732  
     private boolean doUnwrapRCs(StatementVO statementVO, int level) {
 733  0
         boolean structureChanged = false;
 734  0
         List<ReqComponentVO> wrappedRCs = new ArrayList<ReqComponentVO>();
 735  0
         if (statementVO.getStatementVOCount() > 0) {
 736  0
             List<StatementVO> subSs = new ArrayList<StatementVO>(statementVO.getStatementVOs());
 737  0
             for (StatementVO subS : subSs) {
 738  0
                 if (!subS.isWrapperStatementVO()) {
 739  0
                     structureChanged = structureChanged || doUnwrapRCs(subS, level + 1);
 740  
                 }
 741  
             }
 742  
 
 743  0
             for (StatementVO subS : subSs) {
 744  0
                 if (subS.isWrapperStatementVO()) {
 745  0
                     wrappedRCs.add(subS.getReqComponentVOs().get(0));
 746  
                 }
 747  
             }
 748  0
             if (wrappedRCs != null && wrappedRCs.size() == statementVO.getChildCount()) {
 749  0
                 structureChanged = true;
 750  0
                 for (StatementVO subS : subSs) {
 751  0
                     statementVO.removeStatementVO(subS);
 752  
                 }
 753  0
                 for (ReqComponentVO wrappedRC : wrappedRCs) {
 754  0
                     statementVO.addReqComponentVO(wrappedRC);
 755  
                 }
 756  
             }
 757  
         }
 758  0
         return structureChanged;
 759  
     }
 760  
 
 761  
     /*************************************************************************************************/
 762  
 
 763  
     public String getPrintableStatement() {
 764  0
         return doConvertToExpression(new StringBuilder(), this, true).toString();
 765  
     }
 766  
 
 767  
     public String convertToExpression() {
 768  0
         assignGuiRCId();
 769  0
         return doConvertToExpression(new StringBuilder(), this, false).toString();
 770  
     }
 771  
 
 772  
     private StringBuilder doConvertToExpression(StringBuilder inSbResult,
 773  
             StatementVO statementVO,
 774  
             boolean extraBrackets) {
 775  0
         List<StatementVO> currStatementVOs = (statementVO == null)? null : statementVO.getStatementVOs();
 776  0
         List<ReqComponentVO> currReqComponentVOs = (statementVO == null)? null : statementVO.getReqComponentVOs();
 777  0
         if (currStatementVOs != null && !currStatementVOs.isEmpty()) {
 778  0
             int statementCounter = 0;
 779  0
             for (StatementVO childStatementVO : statementVO.getStatementVOs()) {
 780  0
                 if (statementCounter > 0) {
 781  0
                     StatementOperatorTypeKey operator = (statementVO == null ||
 782  
                                 statementVO.getStatementInfo() == null)? null :
 783  
                                     statementVO.getStatementInfo().getOperator();
 784  0
                     inSbResult.append(" " + operator + " ");
 785  
                 }
 786  0
                 if (extraBrackets || !childStatementVO.isWrapperStatementVO()) {
 787  0
                     inSbResult.append("(");
 788  
                 }
 789  0
                 inSbResult.append(doConvertToExpression(new StringBuilder(), childStatementVO,
 790  
                         extraBrackets).toString());
 791  0
                 if (extraBrackets || !childStatementVO.isWrapperStatementVO()) {
 792  0
                     inSbResult.append(")");
 793  
                 }
 794  0
                 statementCounter++;
 795  
             }
 796  0
         } else if (currReqComponentVOs != null && !currReqComponentVOs.isEmpty()) {
 797  0
             int rcCounter = 0;
 798  0
             for (ReqComponentVO childReqComponentInfo : currReqComponentVOs) {
 799  0
                 if (rcCounter > 0) {
 800  0
                     if(statementVO != null &&
 801  
                        statementVO.getStatementInfo() != null &&
 802  
                        statementVO.getStatementInfo().getOperator() != null) {
 803  0
                                 StatementOperatorTypeKey operator = statementVO.getStatementInfo().getOperator();
 804  0
                             inSbResult.append(" " + operator.toString().toLowerCase() + " ");
 805  
                     }
 806  
                 }
 807  0
                 inSbResult.append(childReqComponentInfo.getGuiReferenceLabelId());
 808  0
                 rcCounter++;
 809  
             }
 810  
         }
 811  0
         return inSbResult;
 812  
     }
 813  
 
 814  
     public void clearSelections() {
 815  0
         doClearSelections(this);
 816  0
     }
 817  
 
 818  
     private void doClearSelections(StatementVO statementVO) {
 819  0
         statementVO.setCheckBoxOn(false);
 820  0
         if (statementVO.getStatementVOCount() > 0) {
 821  0
             for (StatementVO childS : statementVO.getStatementVOs()) {
 822  0
                 doClearSelections(childS);
 823  
             }
 824  0
         } else if (statementVO.getReqComponentVOCount() > 0) {
 825  0
             for (ReqComponentVO rc : statementVO.getReqComponentVOs()) {
 826  0
                 rc.setCheckBoxOn(false);
 827  
             }
 828  
         }
 829  0
     }
 830  
 
 831  
     public boolean isSimple() {
 832  0
         boolean simple = false;
 833  0
         if (getStatementVOCount() == 0 && getReqComponentVOCount() <= 1) {
 834  0
             simple = true;
 835  
         }
 836  0
         return simple;
 837  
     }
 838  
 
 839  
     public boolean isEmpty() {
 840  0
         boolean simple = false;
 841  0
         if (getStatementVOCount() == 0 && getReqComponentVOCount() == 0) {
 842  0
             simple = true;
 843  
         }
 844  0
         return simple;
 845  
     }
 846  
 
 847  
     public String composeStatementTreeViewInfo(StatementVO statementVO, StatementTreeViewInfo statementTreeViewInfo) throws Exception {
 848  0
         String rc = "";
 849  0
         List<StatementVO> statementVOs = statementVO.getStatementVOs();
 850  0
         List<ReqComponentVO> reqComponentVOs = statementVO.getReqComponentVOs();
 851  
 
 852  0
         if ((statementVOs != null) && (reqComponentVOs != null) && (statementVOs.size() > 0) && (reqComponentVOs.size() > 0))
 853  
         {
 854  0
             return "Internal error: found both Statements and Requirement Components on the same level of boolean expression";
 855  
         }
 856  
 
 857  0
         statementVO.setFieldsTo(statementTreeViewInfo);
 858  
 
 859  0
         if ((statementVOs != null) && (statementVOs.size() > 0)) {
 860  
             // retrieve all statements
 861  0
             List<StatementTreeViewInfo> subStatementTVInfos = new ArrayList<StatementTreeViewInfo>();
 862  0
             for (StatementVO statement : statementVOs) {
 863  0
                 StatementTreeViewInfo subStatementTVInfo = new StatementTreeViewInfo();
 864  0
                 statement.setFieldsTo(subStatementTVInfo);
 865  0
                 rc = composeStatementTreeViewInfo(statement, subStatementTVInfo); // inside set the children of this statementTreeViewInfo
 866  0
                 subStatementTVInfos.add(subStatementTVInfo);
 867  0
             }
 868  0
             statementTreeViewInfo.setStatements(subStatementTVInfos);
 869  0
         } else {
 870  
             // retrieve all req. component LEAFS
 871  0
             List<ReqComponentInfo> reqComponentList = new ArrayList<ReqComponentInfo>();
 872  0
             for (ReqComponentVO reqComponent : reqComponentVOs) {
 873  0
                 ReqComponentInfo newReqComp = RulesUtil.clone(reqComponent.getReqComponentInfo());
 874  0
                 reqComponentList.add(newReqComp);
 875  0
             }
 876  0
             statementTreeViewInfo.setReqComponents(reqComponentList);
 877  
         }
 878  
 
 879  0
         return rc;
 880  
     }
 881  
 
 882  
     private void setFieldsTo(final StatementTreeViewInfo stvInfo) {
 883  0
         stvInfo.setAttributes(getStatementInfo().getAttributes());
 884  0
         stvInfo.setDesc(getStatementInfo().getDesc());
 885  0
         stvInfo.setId(getStatementInfo().getId());
 886  0
         stvInfo.setMetaInfo(getStatementInfo().getMetaInfo());
 887  0
         stvInfo.setName(getStatementInfo().getName());
 888  0
         stvInfo.setOperator(getStatementInfo().getOperator());
 889  0
         stvInfo.setState(getStatementInfo().getState());
 890  0
         stvInfo.setType(getStatementInfo().getType());
 891  0
     }
 892  
 
 893  
     public String composeStatementVO(StatementTreeViewInfo statementTreeViewInfo, StatementVO statementVO) throws Exception {
 894  0
         String rc = "";
 895  0
         List<StatementTreeViewInfo> statements = statementTreeViewInfo.getStatements();
 896  0
         List<ReqComponentInfo> reqComponentInfos = statementTreeViewInfo.getReqComponents();
 897  
 
 898  0
         if ((statements != null) && (reqComponentInfos != null) && (statements.size() > 0) && (reqComponentInfos.size() > 0))
 899  
         {
 900  0
             return "Internal error: found both Statements and Requirement Components on the same level of boolean expression";
 901  
         }
 902  
 
 903  0
         statementVO.setFields(statementTreeViewInfo);
 904  0
         statementVO.setTokenOperator(true);
 905  
 
 906  0
         if ((statements != null) && (statements.size() > 0)) {
 907  
             // retrieve all statements
 908  0
             List<StatementVO> newStatementList = new ArrayList<StatementVO>();
 909  0
             for (StatementTreeViewInfo statement : statements) {
 910  0
                 StatementVO newStatementVO = new StatementVO();
 911  0
                 newStatementVO.setFields(statement);
 912  0
                 newStatementVO.getStatementInfo().setId("123");
 913  0
                 rc = composeStatementVO(statement, newStatementVO); // inside set the children of this statementTreeViewInfo
 914  0
                 newStatementList.add(newStatementVO);
 915  0
             }
 916  0
             statementVO.statementVOs = newStatementList;
 917  0
         } else if ((reqComponentInfos != null) && (reqComponentInfos.size() > 0)) {
 918  
             // retrieve all req. component LEAFS
 919  0
             List<ReqComponentVO> reqComponentList = new ArrayList<ReqComponentVO>();
 920  0
             for (ReqComponentInfo reqComponent : reqComponentInfos) {
 921  0
                 ReqComponentVO newReqComp = new ReqComponentVO();
 922  0
                 newReqComp.setReqComponentInfo(RulesUtil.clone(reqComponent));
 923  0
                 reqComponentList.add(newReqComp);
 924  0
             }
 925  0
             statementVO.reqComponentVOs = reqComponentList;
 926  
         }
 927  
 
 928  0
         return rc;
 929  
     }
 930  
 
 931  
     private void setFields(final StatementTreeViewInfo statementTreeViewInfo) {
 932  0
         statementInfo = new StatementInfo();
 933  0
         getStatementInfo().setAttributes(statementTreeViewInfo.getAttributes());
 934  0
         getStatementInfo().setDesc(statementTreeViewInfo.getDesc());
 935  0
         getStatementInfo().setId(statementTreeViewInfo.getId());
 936  0
         getStatementInfo().setMetaInfo(statementTreeViewInfo.getMetaInfo());
 937  0
         getStatementInfo().setName(statementTreeViewInfo.getName());
 938  0
         getStatementInfo().setOperator(statementTreeViewInfo.getOperator());
 939  0
         getStatementInfo().setState(statementTreeViewInfo.getState());
 940  0
         getStatementInfo().setType(statementTreeViewInfo.getType());
 941  0
     }
 942  
 
 943  
     @Override
 944  
     public String toString() {
 945  0
         StringBuilder sbResult = new StringBuilder();
 946  0
         sbResult.append(value);
 947  0
         return sbResult.toString();
 948  
     }
 949  
 
 950  
     @Override
 951  
     public boolean equals(Object obj) {
 952  0
         return this == obj;
 953  
     }
 954  
 
 955  
 }