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    }