001/** 002 * Copyright 2005-2015 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 */ 016package org.kuali.rice.kew.api.rule; 017 018import org.apache.commons.collections.CollectionUtils; 019import org.apache.commons.lang.StringUtils; 020import org.joda.time.DateTime; 021import org.kuali.rice.core.api.CoreConstants; 022import org.kuali.rice.core.api.mo.AbstractDataTransferObject; 023import org.kuali.rice.core.api.mo.ModelBuilder; 024import org.kuali.rice.core.api.util.jaxb.DateTimeAdapter; 025import org.kuali.rice.kew.api.KewApiConstants; 026import org.w3c.dom.Element; 027 028import javax.xml.bind.annotation.XmlAccessType; 029import javax.xml.bind.annotation.XmlAccessorType; 030import javax.xml.bind.annotation.XmlAnyElement; 031import javax.xml.bind.annotation.XmlElement; 032import javax.xml.bind.annotation.XmlElementWrapper; 033import javax.xml.bind.annotation.XmlRootElement; 034import javax.xml.bind.annotation.XmlType; 035import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 036import java.io.Serializable; 037import java.util.ArrayList; 038import java.util.Collection; 039import java.util.Collections; 040import java.util.HashMap; 041import java.util.List; 042import java.util.Map; 043 044@XmlRootElement(name = Rule.Constants.ROOT_ELEMENT_NAME) 045@XmlAccessorType(XmlAccessType.NONE) 046@XmlType(name = Rule.Constants.TYPE_NAME, propOrder = { 047 Rule.Elements.ID, 048 Rule.Elements.NAME, 049 Rule.Elements.RULE_TEMPLATE, 050 Rule.Elements.ACTIVE, 051 Rule.Elements.DESCRIPTION, 052 Rule.Elements.DOC_TYPE_NAME, 053 Rule.Elements.FROM_DATE, 054 Rule.Elements.TO_DATE, 055 Rule.Elements.FORCE_ACTION, 056 Rule.Elements.PREVIOUS_VERSION_ID, 057 Rule.Elements.RULE_RESPONSIBILITIES, 058 Rule.Elements.RULE_EXTENSIONS, 059 Rule.Elements.RULE_TEMPLATE_NAME, 060 Rule.Elements.RULE_EXPRESSION_DEF, 061 Rule.Elements.FROM_DATE_VALUE, 062 Rule.Elements.TO_DATE_VALUE, 063 CoreConstants.CommonElements.FUTURE_ELEMENTS 064}) 065public final class Rule 066 extends AbstractDataTransferObject 067 implements RuleContract 068{ 069 @XmlElement(name = Elements.ID, required = false) 070 private final String id; 071 072 @XmlElement(name = Elements.NAME, required = false) 073 private final String name; 074 075 @XmlElement(name = Elements.RULE_TEMPLATE, required = false) 076 private final RuleTemplate ruleTemplate; 077 078 @XmlElement(name = Elements.ACTIVE, required = false) 079 private final boolean active; 080 081 @XmlElement(name = Elements.DESCRIPTION, required = false) 082 private final String description; 083 084 @XmlElement(name = Elements.DOC_TYPE_NAME, required = false) 085 private final String docTypeName; 086 087 @Deprecated 088 @XmlElement(name = Elements.FROM_DATE, required = false) 089 private final DateTime fromDate; 090 091 @Deprecated 092 @XmlElement(name = Elements.TO_DATE, required = false) 093 private final DateTime toDate; 094 095 @XmlElement(name = Elements.FROM_DATE_VALUE, required = false) 096 @XmlJavaTypeAdapter(DateTimeAdapter.class) 097 private final DateTime fromDateValue; 098 099 @XmlElement(name = Elements.TO_DATE_VALUE, required = false) 100 @XmlJavaTypeAdapter(DateTimeAdapter.class) 101 private final DateTime toDateValue; 102 103 @XmlElement(name = Elements.FORCE_ACTION, required = false) 104 private final boolean forceAction; 105 106 @XmlElement(name = Elements.PREVIOUS_VERSION_ID, required = false) 107 private final String previousRuleId; 108 109 @XmlElementWrapper(name = Elements.RULE_RESPONSIBILITIES, required = false) 110 @XmlElement(name = Elements.RULE_RESPONSIBILITY, required = false) 111 private final List<RuleResponsibility> ruleResponsibilities; 112 113 @XmlElementWrapper(name = Elements.RULE_EXTENSIONS, required = false) 114 @XmlElement(name = Elements.RULE_EXTENSION, required = false) 115 private final List<RuleExtension> ruleExtensions; 116 117 @XmlElement(name = Elements.RULE_TEMPLATE_NAME, required = false) 118 private final String ruleTemplateName; 119 120 @XmlElement(name = Elements.RULE_EXPRESSION_DEF, required = false) 121 private final RuleExpression ruleExpressionDef; 122 123 @SuppressWarnings("unused") 124 @XmlAnyElement 125 private final Collection<Element> _futureElements = null; 126 127 /** 128 * Private constructor used only by JAXB. 129 * 130 */ 131 private Rule() { 132 this.id = null; 133 this.name = null; 134 this.ruleTemplate = null; 135 this.active = false; 136 this.description = null; 137 this.docTypeName = null; 138 this.fromDate = null; 139 this.toDate = null; 140 this.fromDateValue = null; 141 this.toDateValue = null; 142 this.forceAction = false; 143 this.ruleResponsibilities = null; 144 this.ruleExtensions = null; 145 this.ruleTemplateName = null; 146 this.ruleExpressionDef = null; 147 this.previousRuleId = null; 148 } 149 150 private Rule(Builder builder) { 151 this.id = builder.getId(); 152 this.name = builder.getName(); 153 this.ruleTemplate = builder.getRuleTemplate() == null ? null : builder.getRuleTemplate().build(); 154 this.active = builder.isActive(); 155 this.description = builder.getDescription(); 156 this.docTypeName = builder.getDocTypeName(); 157 this.fromDate = builder.getFromDate(); 158 this.toDate = builder.getToDate(); 159 this.fromDateValue = builder.getFromDate(); 160 this.toDateValue = builder.getToDate(); 161 this.forceAction = builder.isForceAction(); 162 if (CollectionUtils.isNotEmpty(builder.getRuleResponsibilities())) { 163 List<RuleResponsibility> responsibilities = new ArrayList<RuleResponsibility>(); 164 for (RuleResponsibility.Builder b : builder.getRuleResponsibilities()) { 165 responsibilities.add(b.build()); 166 } 167 this.ruleResponsibilities = responsibilities; 168 } else { 169 this.ruleResponsibilities = Collections.emptyList(); 170 } 171 if (CollectionUtils.isNotEmpty(builder.getRuleExtensions())) { 172 List<RuleExtension> extensions = new ArrayList<RuleExtension>(); 173 for (RuleExtension.Builder b : builder.getRuleExtensions()) { 174 extensions.add(b.build()); 175 } 176 this.ruleExtensions = extensions; 177 } else { 178 this.ruleExtensions = Collections.emptyList(); 179 } 180 this.ruleTemplateName = builder.getRuleTemplateName(); 181 this.ruleExpressionDef = builder.getRuleExpressionDef() == null ? null : builder.getRuleExpressionDef().build(); 182 this.previousRuleId = builder.getPreviousRuleId(); 183 } 184 185 @Override 186 public String getId() { 187 return this.id; 188 } 189 190 @Override 191 public String getName() { 192 return this.name; 193 } 194 195 @Override 196 public RuleTemplate getRuleTemplate() { 197 return this.ruleTemplate; 198 } 199 200 @Override 201 public boolean isActive() { 202 return this.active; 203 } 204 205 @Override 206 public String getDescription() { 207 return this.description; 208 } 209 210 @Override 211 public String getPreviousRuleId() { 212 return this.previousRuleId; 213 } 214 215 @Override 216 public String getDocTypeName() { 217 return this.docTypeName; 218 } 219 220 @Override 221 public DateTime getFromDate() { 222 return this.fromDateValue == null ? this.fromDate : this.fromDateValue; 223 } 224 225 @Override 226 public DateTime getToDate() { 227 return this.toDateValue == null ? this.toDate : this.toDateValue; 228 } 229 230 @Override 231 public boolean isForceAction() { 232 return this.forceAction; 233 } 234 235 @Override 236 public List<RuleResponsibility> getRuleResponsibilities() { 237 return this.ruleResponsibilities; 238 } 239 240 @Override 241 public List<RuleExtension> getRuleExtensions() { 242 return this.ruleExtensions; 243 } 244 245 public Map<String, String> getRuleExtensionMap() { 246 Map<String, String> extensions = new HashMap<String, String>(); 247 for (RuleExtension ext : this.getRuleExtensions()) { 248 extensions.putAll(ext.getExtensionValuesMap()); 249 } 250 return Collections.unmodifiableMap(extensions); 251 } 252 253 @Override 254 public String getRuleTemplateName() { 255 return this.ruleTemplateName; 256 } 257 258 @Override 259 public RuleExpression getRuleExpressionDef() { 260 return this.ruleExpressionDef; 261 } 262 263 264 /** 265 * A builder which can be used to construct {@link Rule} instances. Enforces the constraints of the {@link RuleContract}. 266 * 267 */ 268 public final static class Builder 269 implements Serializable, ModelBuilder, RuleContract 270 { 271 private String id; 272 private String name; 273 private RuleTemplate.Builder ruleTemplate; 274 private boolean active; 275 private String description; 276 private String docTypeName; 277 private DateTime fromDate; 278 private DateTime toDate; 279 private boolean forceAction; 280 private List<RuleResponsibility.Builder> ruleResponsibilities = Collections.<RuleResponsibility.Builder>emptyList(); 281 private List<RuleExtension.Builder> ruleExtensions = Collections.emptyList(); 282 private String ruleTemplateName; 283 private String previousRuleId; 284 private RuleExpression.Builder ruleExpressionDef; 285 286 private Builder() { 287 setActive(true); 288 } 289 290 public static Builder create() { 291 return new Builder(); 292 } 293 294 public static Builder create(RuleContract contract) { 295 if (contract == null) { 296 throw new IllegalArgumentException("contract was null"); 297 } 298 Builder builder = create(); 299 builder.setId(contract.getId()); 300 builder.setName(contract.getName()); 301 builder.setRuleTemplate( 302 contract.getRuleTemplate() == null ? null : RuleTemplate.Builder.create(contract.getRuleTemplate())); 303 builder.setActive(contract.isActive()); 304 builder.setDescription(contract.getDescription()); 305 builder.setDocTypeName(contract.getDocTypeName()); 306 builder.setFromDate(contract.getFromDate()); 307 builder.setToDate(contract.getToDate()); 308 builder.setForceAction(contract.isForceAction()); 309 builder.setPreviousRuleId(contract.getPreviousRuleId()); 310 if (CollectionUtils.isNotEmpty(contract.getRuleResponsibilities())) { 311 List<RuleResponsibility.Builder> responsibilityBuilders = new ArrayList<RuleResponsibility.Builder>(); 312 for (RuleResponsibilityContract c : contract.getRuleResponsibilities()) { 313 responsibilityBuilders.add(RuleResponsibility.Builder.create(c)); 314 } 315 builder.setRuleResponsibilities(responsibilityBuilders); 316 } else { 317 builder.setRuleResponsibilities(Collections.<RuleResponsibility.Builder>emptyList()); 318 } 319 if (CollectionUtils.isNotEmpty(contract.getRuleExtensions())) { 320 List<RuleExtension.Builder> extensionBuilders = new ArrayList<RuleExtension.Builder>(); 321 for (RuleExtensionContract c : contract.getRuleExtensions()) { 322 extensionBuilders.add(RuleExtension.Builder.create(c)); 323 } 324 builder.setRuleExtensions(extensionBuilders); 325 } else { 326 builder.setRuleExtensions(Collections.<RuleExtension.Builder>emptyList()); 327 } 328 builder.setRuleTemplateName(contract.getRuleTemplateName()); 329 if (contract.getRuleExpressionDef() != null) { 330 builder.setRuleExpressionDef(RuleExpression.Builder.create(contract.getRuleExpressionDef())); 331 } 332 return builder; 333 } 334 335 public Rule build() { 336 return new Rule(this); 337 } 338 339 @Override 340 public String getId() { 341 return this.id; 342 } 343 344 @Override 345 public String getName() { 346 return this.name; 347 } 348 349 @Override 350 public RuleTemplate.Builder getRuleTemplate() { 351 return this.ruleTemplate; 352 } 353 354 @Override 355 public boolean isActive() { 356 return this.active; 357 } 358 359 @Override 360 public String getDescription() { 361 return this.description; 362 } 363 364 @Override 365 public String getDocTypeName() { 366 return this.docTypeName; 367 } 368 369 @Override 370 public DateTime getFromDate() { 371 return this.fromDate; 372 } 373 374 @Override 375 public DateTime getToDate() { 376 return this.toDate; 377 } 378 379 @Override 380 public boolean isForceAction() { 381 return this.forceAction; 382 } 383 384 @Override 385 public String getPreviousRuleId() { 386 return this.previousRuleId; 387 } 388 389 @Override 390 public List<RuleResponsibility.Builder> getRuleResponsibilities() { 391 return this.ruleResponsibilities; 392 } 393 394 @Override 395 public List<RuleExtension.Builder> getRuleExtensions() { 396 return this.ruleExtensions; 397 } 398 399 @Override 400 public String getRuleTemplateName() { 401 return this.ruleTemplateName; 402 } 403 404 @Override 405 public RuleExpression.Builder getRuleExpressionDef() { 406 return this.ruleExpressionDef; 407 } 408 409 public void setId(String id) { 410 if (StringUtils.isWhitespace(id)) { 411 throw new IllegalArgumentException("id is blank"); 412 } 413 this.id = id; 414 } 415 416 public void setName(String name) { 417 this.name = name; 418 } 419 public void setRuleTemplate(RuleTemplate.Builder ruleTemplate) { 420 this.ruleTemplate = ruleTemplate; 421 } 422 423 public void setActive(boolean active) { 424 this.active = active; 425 } 426 427 public void setDescription(String description) { 428 this.description = description; 429 } 430 431 public void setDocTypeName(String docTypeName) { 432 this.docTypeName = docTypeName; 433 } 434 435 public void setFromDate(DateTime fromDate) { 436 this.fromDate = fromDate; 437 } 438 439 public void setToDate(DateTime toDate) { 440 this.toDate = toDate; 441 } 442 443 public void setForceAction(boolean forceAction) { 444 this.forceAction = forceAction; 445 } 446 447 public void setPreviousRuleId(String previousRuleId) { 448 this.previousRuleId = previousRuleId; 449 } 450 451 public void setRuleResponsibilities(List<RuleResponsibility.Builder> ruleResponsibilities) { 452 this.ruleResponsibilities = Collections.unmodifiableList(ruleResponsibilities); 453 } 454 455 public void setRuleExtensions(List<RuleExtension.Builder> ruleExtensions) { 456 this.ruleExtensions = Collections.unmodifiableList(ruleExtensions); 457 } 458 459 public void setRuleTemplateName(String ruleTemplateName) { 460 this.ruleTemplateName = ruleTemplateName; 461 } 462 463 public void setRuleExpressionDef(RuleExpression.Builder ruleExpressionDef) { 464 this.ruleExpressionDef = ruleExpressionDef; 465 } 466 467 } 468 469 470 /** 471 * Defines some internal constants used on this class. 472 * 473 */ 474 static class Constants { 475 476 final static String ROOT_ELEMENT_NAME = "rule"; 477 final static String TYPE_NAME = "RuleType"; 478 479 } 480 481 482 /** 483 * A private class which exposes constants which define the XML element names to use when this object is marshalled to XML. 484 * 485 */ 486 static class Elements { 487 final static String ID = "id"; 488 final static String NAME = "name"; 489 final static String RULE_TEMPLATE = "ruleTemplate"; 490 final static String ACTIVE = "active"; 491 final static String DESCRIPTION = "description"; 492 final static String DOC_TYPE_NAME = "docTypeName"; 493 final static String FROM_DATE = "fromDate"; 494 final static String TO_DATE = "toDate"; 495 final static String FROM_DATE_VALUE = "fromDateValue"; 496 final static String TO_DATE_VALUE = "toDateValue"; 497 final static String FORCE_ACTION = "forceAction"; 498 final static String RULE_RESPONSIBILITIES = "ruleResponsibilities"; 499 final static String RULE_RESPONSIBILITY = "ruleResponsibility"; 500 final static String RULE_EXTENSIONS = "ruleExtensions"; 501 final static String RULE_EXTENSION = "ruleExtension"; 502 final static String RULE_TEMPLATE_NAME = "ruleTemplateName"; 503 final static String RULE_EXPRESSION_DEF = "ruleExpressionDef"; 504 final static String PREVIOUS_VERSION_ID = "previousRuleId"; 505 } 506 507 public static class Cache { 508 public static final String NAME = KewApiConstants.Namespaces.KEW_NAMESPACE_2_0 + "/" + Rule.Constants.TYPE_NAME; 509 } 510}