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