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    }