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