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