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 }