001package org.kuali.rice.krms.util;
002
003import org.apache.commons.lang.BooleanUtils;
004import org.kuali.rice.krad.uif.UifConstants;
005import org.kuali.rice.krad.uif.component.Component;
006import org.kuali.rice.krad.uif.container.Group;
007import org.kuali.rice.krad.uif.container.LinkGroup;
008import org.kuali.rice.krad.uif.container.TreeGroup;
009import org.kuali.rice.krad.uif.element.Action;
010import org.kuali.rice.krad.uif.element.Link;
011import org.kuali.rice.krad.uif.field.MessageField;
012import org.kuali.rice.krad.uif.util.ComponentFactory;
013import org.kuali.rice.krad.uif.util.ComponentUtils;
014import org.kuali.rice.krad.uif.view.View;
015import org.kuali.rice.krad.util.KRADConstants;
016import org.kuali.rice.krms.dto.*;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021import java.util.Properties;
022
023/**
024 * Created with IntelliJ IDEA.
025 * User: danie
026 * Date: 3/7/13
027 * Time: 12:08 PM
028 * To change this template use File | Settings | File Templates.
029 */
030public class AgendaBuilder {
031
032    private View view;
033    private Map<String, AgendaTypeInfo> typeRelationsMap;
034
035    private int agendaCounter;
036    private int ruleCounter;
037
038    private AlphaIterator alphaIterator = new AlphaIterator();
039
040    public AgendaBuilder(View view) {
041        this.view = view;
042    }
043
044    public void setTypeRelationsMap(Map<String, AgendaTypeInfo> typeRelationsMap) {
045        this.typeRelationsMap = typeRelationsMap;
046    }
047
048    public List<Component> build(RuleManagementWrapper ruleManagementWrapper){
049
050        // Get the list of existing agendas
051        List<AgendaEditor> agendas = ruleManagementWrapper.getAgendas();
052
053        // Initialize new array lists.
054        List<AgendaEditor> sortedAgendas = new ArrayList<AgendaEditor>();
055        List<Component> components = new ArrayList<Component>();
056
057        // Lookup existing agenda by type
058        List<AgendaTypeInfo> agendaTypeInfos = new ArrayList<AgendaTypeInfo>(typeRelationsMap.values());
059        for (AgendaTypeInfo agendaTypeInfo : agendaTypeInfos) {
060            boolean exist = false;
061            for (AgendaEditor agenda : agendas) {
062                if (agenda.getTypeId().equals(agendaTypeInfo.getId())) {
063                    components.add(this.buildAgenda(agenda));
064                    exist = true;
065                    sortedAgendas.add(agenda);
066                }
067            }
068            if (!exist) {
069                AgendaEditor emptyAgenda = new AgendaEditor();
070                emptyAgenda.setTypeId(agendaTypeInfo.getId());
071                components.add(this.buildAgenda(emptyAgenda));
072                sortedAgendas.add(emptyAgenda);
073            }
074        }
075
076        ruleManagementWrapper.setAgendas(sortedAgendas);
077
078        return components;
079    }
080
081    /**
082     * This method dynamically build the components on the screen to render an angenda.
083     *
084     * @param agenda
085     * @return
086     */
087    public Component buildAgenda(AgendaEditor agenda) {
088        // Reset the rule counter.
089        ruleCounter = 0;
090
091        AgendaTypeInfo agendaType = typeRelationsMap.get(agenda.getTypeId());
092        Group group = (Group) ComponentFactory.getNewComponentInstance("KRMS-AgendaSection-Template");
093        group.setHeaderText(agendaType.getDescription());
094
095        List<Component> components = new ArrayList<Component>();
096        List<RuleEditor> ruleEditors = new ArrayList<RuleEditor>();
097        for (RuleTypeInfo ruleType : agendaType.getRuleTypes()) {
098
099            // Add all existing rules of this type.
100            boolean exist = false;
101            if (agenda.getRuleEditors() != null) {
102                for (RuleEditor rule : agenda.getRuleEditors()) {
103                    if (rule.getTypeId().equals(ruleType.getId()) && (!rule.isDummy())) {
104                        rule.setKey((String)alphaIterator.next());
105                        rule.setRuleTypeInfo(ruleType);
106                        components.add(buildRule(rule, ruleType, this.buildEditRuleSection(rule, ruleType)));
107                        exist = true;
108
109                        ruleEditors.add(rule);
110                    }
111                }
112            }
113
114            // If the ruletype does not exist, add an empty rule section
115            if (!exist) {
116                RuleEditor ruleEditor = new RuleEditor();
117                components.add(buildRule(ruleEditor, ruleType, this.buildAddRuleSection(ruleEditor, ruleType)));
118
119                ruleEditor.setKey((String)alphaIterator.next());
120                ruleEditor.setDummy(true);
121                ruleEditor.setTypeId(ruleType.getId());
122                ruleEditor.setRuleTypeInfo(ruleType);
123                ruleEditors.add(ruleEditor);
124            }
125
126        }
127
128        group.setItems(components);
129        view.assignComponentIds(group);
130
131        agendaCounter++;
132        agenda.setRuleEditors(ruleEditors);
133        return group;
134    }
135
136    /**
137     * This method dynamically builds a disclosure section for each rule that already exists.
138     *
139     * @param rule
140     * @return
141     */
142    protected Component buildRule(RuleEditor rule, RuleTypeInfo ruleTypeInfo, Group ruleSection) {
143        Group group = (Group) ComponentFactory.getNewComponentInstance("KRMS-Rule-Template");
144        group.setHeaderText(ruleTypeInfo.getDescription());
145
146        //Add edit container to disclosure section
147        List<Component> items = new ArrayList<Component>();
148        items.add(ruleSection);
149        group.setItems(items);
150
151        ruleCounter++;
152        return group;
153    }
154
155    protected Group buildEditRuleSection(RuleEditor rule, RuleTypeInfo ruleTypeInfo){
156        Group editSection = (Group) ComponentFactory.getNewComponentInstance("KRMS-RuleEdit-Section");
157        LinkGroup links = (LinkGroup) ComponentUtils.findComponentInList((List<Component>) editSection.getItems(), "KRSM-RuleEdit-ActionLinks");
158        List<Action> actionLinks = (List<Action>) links.getItems();
159        for (Action actionLink : actionLinks) {
160            actionLink.getActionParameters().put("ruleKey", rule.getKey());
161        }
162        MessageField messageField = (MessageField) ComponentUtils.findComponentInList((List<Component>) editSection.getItems(), "KRMS-Instruction-EditMessage");
163        messageField.setMessageText(ruleTypeInfo.getInstruction());
164
165        Group sectionGroup = (Group) ComponentUtils.findComponentInList((List<Component>) editSection.getItems(), "KRMS-PreviewTree-Group");
166        List<TreeGroup> treeGroups = ComponentUtils.getComponentsOfType((List<Component>) sectionGroup.getItems(), TreeGroup.class);
167        if ((treeGroups != null) && (treeGroups.size() > 0)) {
168            treeGroups.get(0).setPropertyName("agendas[" + agendaCounter + "].ruleEditors[" + ruleCounter + "].viewTree");
169        }
170
171        return editSection;
172    }
173
174    /**
175     * This method dynamically builds a disclosure section to allow the user to add a new rule for this rule type.
176     *
177     * @param ruleTypeInfo
178     * @return
179     */
180    protected Group buildAddRuleSection(RuleEditor ruleEditor, RuleTypeInfo ruleTypeInfo) {
181        Group addSection = (Group) ComponentFactory.getNewComponentInstance("KRMS-RuleAdd-Section");
182        LinkGroup links = (LinkGroup) ComponentUtils.findComponentInList((List<Component>) addSection.getItems(), "KRMS-RuleAdd-ActionLink");
183        List<Action> actionLinks = (List<Action>) links.getItems();
184        for (Action actionLink : actionLinks) {
185            actionLink.getActionParameters().put("ruleType", ruleTypeInfo.getId());
186        }
187        MessageField messageField = (MessageField) ComponentUtils.findComponentInList((List<Component>) addSection.getItems(), "KRMS-Instruction-AddMessage");
188        messageField.setMessageText(ruleTypeInfo.getInstruction());
189
190        return addSection;
191    }
192
193}