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.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.core.api.util.jaxb.DateTimeAdapter;
025 import org.kuali.rice.kew.api.KewApiConstants;
026 import org.w3c.dom.Element;
027
028 import javax.xml.bind.annotation.XmlAccessType;
029 import javax.xml.bind.annotation.XmlAccessorType;
030 import javax.xml.bind.annotation.XmlAnyElement;
031 import javax.xml.bind.annotation.XmlElement;
032 import javax.xml.bind.annotation.XmlElementWrapper;
033 import javax.xml.bind.annotation.XmlRootElement;
034 import javax.xml.bind.annotation.XmlType;
035 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
036 import java.io.Serializable;
037 import java.util.ArrayList;
038 import java.util.Collection;
039 import java.util.Collections;
040 import java.util.HashMap;
041 import java.util.List;
042 import 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 })
065 public 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 }