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