001/**
002 * Copyright 2005-2016 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.impl.repository;
017
018import org.apache.commons.collections.CollectionUtils;
019import org.apache.commons.lang.StringUtils;
020import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
021import org.kuali.rice.krad.service.KRADServiceLocator;
022import org.kuali.rice.krad.service.SequenceAccessorService;
023import org.kuali.rice.krad.util.ObjectUtils;
024import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
025import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
026
027import java.util.ArrayList;
028import java.util.List;
029import java.util.Map;
030
031/**
032 * Agenda Item business object
033 * 
034 * @author Kuali Rice Team (rice.collab@kuali.org)
035 *
036 */
037public class AgendaItemBo extends PersistableBusinessObjectBase {
038
039    public static final String COPY_OF_TEXT = "Copy of ";
040    private static final String KRMS_AGENDA_ITM_S = "KRMS_AGENDA_ITM_S";
041
042        private String id;
043        private String agendaId;
044        private String ruleId;
045        private String subAgendaId;
046        private String whenTrueId;
047        private String whenFalseId;
048        private String alwaysId;
049        
050        private RuleBo rule;
051        
052        private AgendaItemBo whenTrue;
053        private AgendaItemBo whenFalse;
054        private AgendaItemBo always;
055
056    private static SequenceAccessorService sequenceAccessorService;
057        
058        public String getUl(AgendaItemBo firstItem) {
059                return ("<ul>" + getUlHelper(firstItem) + "</ul>");
060        }
061        
062        public String getUlHelper(AgendaItemBo item) {
063                StringBuilder sb = new StringBuilder();
064                sb.append("<li>" + ruleId + "</li>");
065                if (whenTrue != null) {
066                        sb.append("<ul><li>when true</li><ul>");
067                        sb.append(getUlHelper(whenTrue));
068                        sb.append("</ul></ul>");
069                }
070                if (whenFalse != null) {
071                        sb.append("<ul><li>when false</li><ul>");
072                        sb.append(getUlHelper(whenFalse));
073                        sb.append("</ul></ul>");
074                }
075                if (always != null) {
076                        sb.append(getUlHelper(always));
077                }
078                return sb.toString();
079        }
080
081    public String getRuleText() {
082        StringBuilder resultBuilder = new StringBuilder();
083        if (getRule() != null) {
084            if (StringUtils.isBlank(getRule().getName())) {
085                resultBuilder.append("- unnamed rule -");
086            } else {
087                resultBuilder.append(getRule().getName());
088            }
089            if (!StringUtils.isBlank(getRule().getDescription())) {
090                resultBuilder.append(": ");
091                resultBuilder.append(getRule().getDescription());
092            }
093            // add a description of the action configured on the rule, if there is one
094            if (!CollectionUtils.isEmpty(getRule().getActions())) {
095                resultBuilder.append("   [");
096                ActionBo action = getRule().getActions().get(0);
097
098                KrmsTypeDefinition krmsTypeDefn =
099                        KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService().getTypeById(action.getTypeId());
100
101                resultBuilder.append(krmsTypeDefn.getName());
102                resultBuilder.append(": ");
103                resultBuilder.append(action.getName());
104
105                if (getRule().getActions().size() > 1) {
106                    resultBuilder.append(" ... ");
107                }
108                resultBuilder.append("]");
109            }
110        } else {
111            throw new IllegalStateException();
112        }
113        return resultBuilder.toString();
114    }
115
116//      def List<AgendaItemBo> alwaysList
117//      def List<AgendaItemBo> whenTrueList
118//      def List<AgendaItemBo> whenFalseList
119        
120        public List<AgendaItemBo> getAlwaysList() {
121                List<AgendaItemBo> results = new ArrayList<AgendaItemBo>();
122                
123                AgendaItemBo currentNode = this;
124                while (currentNode.always != null) {
125                        results.add(currentNode.always);
126                        currentNode = currentNode.always;
127                }
128                
129                return results;
130        }
131
132        /**
133         * @return the id
134         */
135        public String getId() {
136                return this.id;
137        }
138
139        /**
140         * @param id the id to set
141         */
142        public void setId(String id) {
143                this.id = id;
144        }
145
146        /**
147         * @return the agendaId
148         */
149        public String getAgendaId() {
150                return this.agendaId;
151        }
152
153        /**
154         * @param agendaId the agendaId to set
155         */
156        public void setAgendaId(String agendaId) {
157                this.agendaId = agendaId;
158        }
159
160        /**
161         * @return the ruleId
162         */
163        public String getRuleId() {
164                return this.ruleId;
165        }
166
167        /**
168         * @param ruleId the ruleId to set
169         */
170        public void setRuleId(String ruleId) {
171                this.ruleId = ruleId;
172        }
173
174        /**
175         * @return the subAgendaId
176         */
177        public String getSubAgendaId() {
178                return this.subAgendaId;
179        }
180
181        /**
182         * @param subAgendaId the subAgendaId to set
183         */
184        public void setSubAgendaId(String subAgendaId) {
185                this.subAgendaId = subAgendaId;
186        }
187
188
189        /**
190         * @return the whenTrueId
191         */
192        public String getWhenTrueId() {
193                return this.whenTrueId;
194        }
195
196        /**
197         * @param whenTrueId the whenTrueId to set
198         */
199        public void setWhenTrueId(String whenTrueId) {
200                this.whenTrueId = whenTrueId;
201        }
202
203        /**
204         * @return the whenFalseId
205         */
206        public String getWhenFalseId() {
207                return this.whenFalseId;
208        }
209
210        /**
211         * @param whenFalseId the whenFalseId to set
212         */
213        public void setWhenFalseId(String whenFalseId) {
214                this.whenFalseId = whenFalseId;
215        }
216
217        /**
218         * @return the alwaysId
219         */
220        public String getAlwaysId() {
221                return this.alwaysId;
222        }
223
224        /**
225         * @param alwaysId the alwaysId to set
226         */
227        public void setAlwaysId(String alwaysId) {
228                this.alwaysId = alwaysId;
229        }
230
231        /**
232         * @return the whenTrue
233         */
234        public AgendaItemBo getWhenTrue() {
235                return this.whenTrue;
236        }
237
238        /**
239         * @param whenTrue the whenTrue to set
240         */
241        public void setWhenTrue(AgendaItemBo whenTrue) {
242                this.whenTrue = whenTrue;
243        if (whenTrue != null) {
244            setWhenTrueId(whenTrue.getId());
245        } else {
246            setWhenTrueId(null);
247        }
248        }
249
250        /**
251         * @return the whenFalse
252         */
253        public AgendaItemBo getWhenFalse() {
254                return this.whenFalse;
255        }
256
257        /**
258         * @param whenFalse the whenFalse to set
259         */
260        public void setWhenFalse(AgendaItemBo whenFalse) {
261                this.whenFalse = whenFalse;
262        if (whenFalse != null) {
263            setWhenFalseId(whenFalse.getId());
264        } else {
265            setWhenFalseId(null);
266        }
267        }
268
269        /**
270         * @return the always
271         */
272        public AgendaItemBo getAlways() {
273                return this.always;
274        }
275
276        /**
277         * @param always the always to set
278         */
279        public void setAlways(AgendaItemBo always) {
280                this.always = always;
281        if (always != null) {
282            setAlwaysId(always.getId());
283        } else {
284            setAlwaysId(null);
285        }
286        }
287        
288    /**
289     * @return the rule
290     */
291    public RuleBo getRule() {
292        return this.rule;
293    }
294
295    /**
296     * @param rule the rule to set
297     */
298    public void setRule(RuleBo rule) {
299        this.rule = rule;
300        if (rule != null) {
301            setRuleId(rule.getId());
302        } else {
303            setRuleId(null);
304        }
305    }
306
307        
308    /**
309        * Converts a mutable bo to it's immutable counterpart
310        * @param bo the mutable business object
311        * @return the immutable object
312        */
313   static AgendaItemDefinition to(AgendaItemBo bo) {
314           if (bo == null) { return null; }
315           AgendaItemDefinition.Builder builder =
316                   AgendaItemDefinition.Builder.create(bo.getId(), bo.getAgendaId());
317           builder.setRuleId(bo.getRuleId());
318           builder.setSubAgendaId(bo.getSubAgendaId());
319           builder.setWhenTrueId(bo.getWhenTrueId());
320           builder.setWhenFalseId(bo.getWhenFalseId());
321           builder.setAlwaysId(bo.getAlwaysId());
322           
323           return builder.build();
324   }
325
326   /**
327        * Converts a immutable object to it's mutable bo counterpart
328        * @param im immutable object
329        * @return the mutable bo
330        */
331   static AgendaItemBo from(AgendaItemDefinition im) {
332           if (im == null) { return null; }
333
334           AgendaItemBo bo = new AgendaItemBo();
335           bo.id = im.getId();
336           bo.agendaId = im.getAgendaId();
337           bo.ruleId = im.getRuleId();
338           bo.subAgendaId = im.getSubAgendaId();
339           bo.whenTrueId = im.getWhenTrueId();
340           bo.whenFalseId = im.getWhenFalseId();
341           bo.alwaysId = im.getAlwaysId();
342           
343           return bo;
344   }
345
346    /**
347     * Returns a copy of this AgendaItem
348     * @param copiedAgenda the new Agenda that the copied AgendiaItem will be associated with
349     * @param oldRuleIdToNew Map<String, RuleBo> mapping of old rule id to the new RuleBo
350     * @param dts DateTimeStamp to append to the copied AgendaItem name
351     * @return AgendaItemBo copy of this AgendaItem with new id and name
352     */
353    public AgendaItemBo copyAgendaItem(AgendaBo copiedAgenda,  Map<String, RuleBo> oldRuleIdToNew,
354            Map<String, AgendaItemBo> oldAgendaItemIdToNew, List<AgendaItemBo> copiedAgendaItems, final String dts) {
355        // Use deepCopy and update all the ids.
356        AgendaItemBo copiedAgendaItem = (AgendaItemBo) ObjectUtils.deepCopy(this);
357        copiedAgendaItem.setId(getNewId());
358        copiedAgendaItem.setAgendaId(copiedAgenda.getId());
359
360        oldAgendaItemIdToNew.put(this.getId(), copiedAgendaItem);
361
362        // Don't create another copy of a rule that we have already copied.
363        if (!oldRuleIdToNew.containsKey(this.getRuleId())) {
364            if (this.getRule() != null) {
365                copiedAgendaItem.setRule(this.getRule().copyRule(COPY_OF_TEXT + this.getRule().getName() + " " + dts));
366                oldRuleIdToNew.put(this.getRuleId(), copiedAgendaItem.getRule());
367            }
368        } else {
369            copiedAgendaItem.setRule(oldRuleIdToNew.get(this.getRuleId()));
370        }
371
372        if (copiedAgendaItem.getWhenFalse() != null) {
373            if (!oldAgendaItemIdToNew.containsKey(this.getWhenFalseId())) {
374                copiedAgendaItem.setWhenFalse(this.getWhenFalse().copyAgendaItem(copiedAgenda, oldRuleIdToNew, oldAgendaItemIdToNew, copiedAgendaItems, dts));
375                oldAgendaItemIdToNew.put(this.getWhenFalseId(), copiedAgendaItem.getWhenFalse());
376                copiedAgendaItems.add(copiedAgendaItem.getWhenFalse());
377            } else {
378                copiedAgendaItem.setWhenFalse(oldAgendaItemIdToNew.get(this.getWhenFalseId()));
379            }
380        }
381
382        if (copiedAgendaItem.getWhenTrue() != null) {
383            if (!oldAgendaItemIdToNew.containsKey(this.getWhenTrueId())) {
384                copiedAgendaItem.setWhenTrue(this.getWhenTrue().copyAgendaItem(copiedAgenda, oldRuleIdToNew, oldAgendaItemIdToNew, copiedAgendaItems, dts));
385                oldAgendaItemIdToNew.put(this.getWhenTrueId(), copiedAgendaItem.getWhenTrue());
386                copiedAgendaItems.add(copiedAgendaItem.getWhenTrue());
387            } else {
388                copiedAgendaItem.setWhenTrue(oldAgendaItemIdToNew.get(this.getWhenTrueId()));
389            }
390        }
391
392        if (copiedAgendaItem.getAlways() != null) {
393            if (!oldAgendaItemIdToNew.containsKey(this.getAlwaysId())) {
394                copiedAgendaItem.setAlways(this.getAlways().copyAgendaItem(copiedAgenda, oldRuleIdToNew, oldAgendaItemIdToNew, copiedAgendaItems, dts));
395                oldAgendaItemIdToNew.put(this.getAlwaysId(), copiedAgendaItem.getAlways());
396                copiedAgendaItems.add(copiedAgendaItem.getAlways());
397            } else {
398                copiedAgendaItem.setAlways(oldAgendaItemIdToNew.get(this.getAlwaysId()));
399            }
400        }
401        return copiedAgendaItem;
402    }
403
404
405    /**
406     * Set the SequenceAccessorService, useful for testing.
407     * @param sas SequenceAccessorService to use for getNewId()
408     */
409    public static void setSequenceAccessorService(SequenceAccessorService sas) {
410        sequenceAccessorService = sas;
411    }
412
413    /**
414     * Returns the next available AgendaItem id.
415     * @return String the next available id
416     */
417    private static String getNewId() {
418        if (sequenceAccessorService == null) {
419            // we don't assign to sequenceAccessorService to preserve existing behavior
420            return KRADServiceLocator.getSequenceAccessorService().getNextAvailableSequenceNumber(KRMS_AGENDA_ITM_S, AgendaItemBo.class) + "";
421        }
422        Long id = sequenceAccessorService.getNextAvailableSequenceNumber(KRMS_AGENDA_ITM_S, AgendaItemBo.class);
423        return id.toString();
424    }
425}