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 }