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.StringUtils;
019import org.kuali.rice.core.api.util.tree.Node;
020import org.kuali.rice.core.api.util.tree.Tree;
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.CompareTreeNode;
025import org.kuali.rice.krms.util.KRMSConstants;
026import org.kuali.rice.krms.util.PropositionTreeUtil;
027
028import java.util.List;
029
030/**
031 * Build a tree to display to different rules next to each other.
032 *
033 * Used on the compare lightbox in KRMS.
034 *
035 * @author Kuali Student Team
036 */
037public class RuleCompareTreeBuilder extends AbstractTreeBuilder{
038
039    private static final long serialVersionUID = 1L;
040
041    private static final int margin = 18;
042
043    public Tree<CompareTreeNode, String> buildTree(RuleEditor firstElement, RuleEditor secondElement) {
044        Tree<CompareTreeNode, String> myTree = initCompareTree();
045        Node<CompareTreeNode, String> firstNode = myTree.getRootElement().getChildren().get(0);
046
047        //Add the nodes recursively.
048        addTreeNode(firstNode, getRootProposition(firstElement), getRootProposition(secondElement));
049
050        //Underline the first node in the preview.
051        if ((firstNode.getChildren() != null) && (firstNode.getChildren().size() > 0)){
052            Node<CompareTreeNode, String> childNode = firstNode.getChildren().get(0);
053            if(childNode.getData() != null){
054                CompareTreeNode compareTreeNode = childNode.getData();
055
056                if(colonRequired(firstElement)) {
057                    if(!compareTreeNode.getFirstElement().trim().isEmpty()){
058                        compareTreeNode.setFirstElement(compareTreeNode.getFirstElement() + ":");
059                    }
060                }
061
062                if(colonRequired(secondElement)) {
063                    if(!compareTreeNode.getSecondElement().trim().isEmpty()){
064                        compareTreeNode.setSecondElement(compareTreeNode.getSecondElement() + ":");
065                    }
066                }
067            }
068        }
069
070        return myTree;
071    }
072
073    protected boolean colonRequired(RuleEditor element) {
074        if(element != null && element.getProposition() != null) {
075            if(element.getProposition().getPropositionTypeCode().equals(PropositionType.COMPOUND.getCode())) {
076                return true;
077            }
078        }
079        return false;
080    }
081
082    protected PropositionEditor getRootProposition(RuleEditor rule){
083        if(rule!=null){
084            return rule.getPropositionEditor();
085        }
086        return null;
087    }
088
089    public static Tree<CompareTreeNode, String> initCompareTree() {
090        Tree<CompareTreeNode, String> myTree = new Tree<CompareTreeNode, String>();
091
092        Node<CompareTreeNode, String> rootNode = createCompareNode();
093        myTree.setRootElement(rootNode);
094
095        rootNode.getChildren().add(createCompareNode());
096
097        return myTree;
098    }
099
100    private static Node<CompareTreeNode, String> createCompareNode() {
101        Node<CompareTreeNode, String> rootNode = new Node<CompareTreeNode, String>();
102        rootNode.setNodeType(KRMSConstants.NODE_TYPE_SUBRULEELEMENT);
103        rootNode.setData(new CompareTreeNode(350));
104        return rootNode;
105    }
106
107    protected void addTreeNode(Node<CompareTreeNode, String> currentNode, PropositionEditor firstElement, PropositionEditor secondElement) {
108        if ((firstElement == null) && (secondElement == null)) {
109            return;
110        }
111
112        Node<CompareTreeNode, String> newNode = new Node<CompareTreeNode, String>();
113        CompareTreeNode tNode = new CompareTreeNode(this.getNodeWidth(currentNode), this.getDescription(firstElement), this.getDescription(secondElement));
114        tNode.setFirstElementItems(this.getListItems(firstElement));
115        tNode.setSecondElementItems(this.getListItems(secondElement));
116        newNode.setNodeType(KRMSConstants.NODE_TYPE_SUBRULEELEMENT);
117        if (!tNode.getFirstElement().equals(tNode.getSecondElement())){
118            addNodeType(newNode, KRMSConstants.NODE_TYPE_COMPAREELEMENT);
119        }
120
121        newNode.setData(tNode);
122        currentNode.getChildren().add(newNode);
123
124        this.addCompoundTreeNode(newNode, firstElement, secondElement);
125    }
126
127    protected void addCompoundTreeNode(Node<CompareTreeNode, String> newNode, PropositionEditor firstElement, PropositionEditor secondElement) {
128
129        // Retrieve the opreator code of the propositions
130        String firstOpCode = this.getLabelForOperator(firstElement);
131        String secondOpCode = this.getLabelForOperator(secondElement);
132
133        // Get the size of the biggest children list
134        int size = Math.max(getChildrenSize(firstElement), getChildrenSize(secondElement));
135
136        for (int i = 0; i < size; i++) {
137
138            PropositionEditor first = getChildForIndex(firstElement, i);
139            PropositionEditor second = getChildForIndex(secondElement, i);
140
141            // add an opcode node in between each of the children.
142            if (i>0) {
143                this.addOperatorTreeNode(newNode, getLabelForChild(first, firstOpCode), getLabelForChild(second, secondOpCode));
144            }
145
146            // call to build the childs node
147            addTreeNode(newNode, first, second);
148        }
149
150    }
151
152    protected String getLabelForChild(PropositionEditor proposition, String label){
153        if (proposition!=null){
154            return label;
155        }
156        return StringUtils.EMPTY;
157    }
158
159    protected String getLabelForOperator(PropositionEditor proposition){
160        if(proposition!=null){
161            return PropositionTreeUtil.getLabelForOperator(proposition.getCompoundOpCode());
162        }
163        return " ";
164    }
165
166    protected int getChildrenSize(PropositionEditor parent) {
167        if ((parent != null) && (parent.getCompoundComponents()!=null)){
168            return parent.getCompoundEditors().size();
169        }
170        return 0;
171    }
172
173    protected PropositionEditor getChildForIndex(PropositionEditor parent, int index) {
174        if ((parent != null) && (parent.getCompoundComponents()!=null)){
175            if(parent.getCompoundComponents().size() > index){
176                return parent.getCompoundEditors().get(index);
177            }
178        }
179        return null;
180    }
181
182    protected int getNodeWidth(Node<CompareTreeNode, String> parent){
183        return parent.getData().getWidth() - margin;
184    }
185
186    protected void addOperatorTreeNode(Node<CompareTreeNode, String> newNode, String firstElement, String secondElement) {
187        Node<CompareTreeNode, String> opNode = new Node<CompareTreeNode, String>();
188        if (!firstElement.equals(secondElement)){
189            opNode.setNodeType(KRMSConstants.NODE_TYPE_COMPAREELEMENT);
190        }
191        opNode.setData(new CompareTreeNode(this.getNodeWidth(newNode), firstElement, secondElement));
192        newNode.getChildren().add(opNode);
193    }
194
195    public List<String> getListItems(PropositionEditor propositionEditor) {
196        return null;
197    }
198
199    public String getNaturalLanguageUsageKey(){
200        return null;
201    }
202
203}