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 }