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 }