001/**
002 * Copyright 2005-2015 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 */
016package org.kuali.rice.kew.rule;
017
018import org.apache.commons.lang.StringUtils;
019import org.hibernate.annotations.Fetch;
020import org.hibernate.annotations.FetchMode;
021import org.hibernate.annotations.GenericGenerator;
022import org.hibernate.annotations.Parameter;
023import org.joda.time.DateTime;
024import org.kuali.rice.core.api.util.RiceConstants;
025import org.kuali.rice.kew.api.rule.RuleContract;
026import org.kuali.rice.kew.api.rule.RuleExtension;
027import org.kuali.rice.kew.api.util.CodeTranslator;
028import org.kuali.rice.kew.doctype.bo.DocumentType;
029import org.kuali.rice.kew.lookupable.MyColumns;
030import org.kuali.rice.kew.routeheader.DocumentContent;
031import org.kuali.rice.kew.rule.bo.RuleAttribute;
032import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
033import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
034import org.kuali.rice.kew.rule.service.RuleServiceInternal;
035import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
036import org.kuali.rice.kew.service.KEWServiceLocator;
037import org.kuali.rice.kew.api.KewApiConstants;
038import org.kuali.rice.kim.api.services.KimApiServiceLocator;
039import org.kuali.rice.kim.impl.group.GroupBo;
040import org.kuali.rice.kim.impl.identity.PersonImpl;
041import org.kuali.rice.kns.web.ui.Field;
042import org.kuali.rice.kns.web.ui.Row;
043import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
044
045import javax.persistence.CascadeType;
046import javax.persistence.Column;
047import javax.persistence.Entity;
048import javax.persistence.FetchType;
049import javax.persistence.GeneratedValue;
050import javax.persistence.Id;
051import javax.persistence.JoinColumn;
052import javax.persistence.ManyToOne;
053import javax.persistence.OneToMany;
054import javax.persistence.OneToOne;
055import javax.persistence.Table;
056import javax.persistence.Transient;
057import java.sql.Timestamp;
058import java.util.ArrayList;
059import java.util.Date;
060import java.util.HashMap;
061import java.util.Iterator;
062import java.util.List;
063import java.util.Map;
064
065/*import org.kuali.rice.kim.api.group.Group;*/
066
067
068/**
069 * A model bean for a Rule within the KEW rules engine.
070 *
071 * @author Kuali Rice Team (rice.collab@kuali.org)
072 */
073@Entity
074@Table(name="KREW_RULE_T")
075//@Sequence(name="KREW_RTE_TMPL_S", property="id")
076public class RuleBaseValues extends PersistableBusinessObjectBase implements RuleContract {
077
078    private static final long serialVersionUID = 6137765574728530156L;
079    @Id
080    @GeneratedValue(generator="KREW_RTE_TMPL_S")
081        @GenericGenerator(name="KREW_RTE_TMPL_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={
082                        @Parameter(name="sequence_name",value="KREW_RTE_TMPL_S"),
083                        @Parameter(name="value_column",value="id")
084        })
085        @Column(name="RULE_ID")
086    private String id;
087    /**
088     * Unique Rule name
089     */
090    @Column(name="NM")
091        private String name;
092    @Column(name="RULE_TMPL_ID", insertable=false, updatable=false)
093        private String ruleTemplateId;
094    @Column(name="PREV_VER_RULE_ID")
095        private String previousRuleId;
096    @Column(name="ACTV_IND")
097        private boolean active = true;
098    @Column(name="RULE_BASE_VAL_DESC")
099        private String description;
100    @Column(name="DOC_TYP_NM")
101        private String docTypeName;
102    @Column(name="DOC_HDR_ID")
103        private String documentId;
104        @Column(name="FRM_DT")
105        private Timestamp fromDateValue;
106        @Column(name="TO_DT")
107        private Timestamp toDateValue;
108        @Column(name="DACTVN_DT")
109        private Timestamp deactivationDate;
110    @Column(name="CUR_IND")
111        private Boolean currentInd = Boolean.TRUE;
112    @Column(name="RULE_VER_NBR")
113        private Integer versionNbr = new Integer(0);
114    @Column(name="FRC_ACTN")
115        private boolean forceAction;
116    @Fetch(value = FetchMode.SELECT)
117    @OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE},mappedBy="ruleBaseValues")
118        private List<RuleResponsibilityBo> ruleResponsibilities;
119    @Fetch(value = FetchMode.SELECT)
120    @OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE},mappedBy="ruleBaseValues")
121        private List<RuleExtensionBo> ruleExtensions;
122    @ManyToOne(fetch=FetchType.EAGER)
123        @JoinColumn(name="RULE_TMPL_ID")
124        private RuleTemplateBo ruleTemplate;
125    @OneToOne(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE})
126        @JoinColumn(name="RULE_EXPR_ID")
127        private RuleExpressionDef ruleExpressionDef;
128    @Transient
129    private RuleBaseValues previousVersion;
130    @Column(name="ACTVN_DT")
131        private Timestamp activationDate;
132    @Column(name="DLGN_IND")
133    private Boolean delegateRule = Boolean.FALSE;
134    /**
135     * Indicator that signifies that this rule is a defaults/template rule which contains
136     * template-defined rule defaults for other rules which use the associated template
137     */
138    @Column(name="TMPL_RULE_IND")
139    private Boolean templateRuleInd = Boolean.FALSE;
140
141    // required to be lookupable
142    @Transient
143    private String returnUrl;
144    @Transient
145    private String destinationUrl;
146    @Transient
147    private MyColumns myColumns;
148    @Transient
149    private List<PersonRuleResponsibility> personResponsibilities = new ArrayList<PersonRuleResponsibility>();
150    @Transient
151    private List<GroupRuleResponsibility> groupResponsibilities = new ArrayList<GroupRuleResponsibility>();
152    @Transient
153    private List<RoleRuleResponsibility> roleResponsibilities = new ArrayList<RoleRuleResponsibility>();
154    @Transient
155    private Map<String, String> fieldValues;
156    @Transient
157    private String groupReviewerName;
158    @Transient
159    private String groupReviewerNamespace;
160    @Transient
161    private String personReviewer;
162    @Transient
163    private String personReviewerType;
164
165    public RuleBaseValues() {
166        ruleResponsibilities = new ArrayList<RuleResponsibilityBo>();
167        ruleExtensions = new ArrayList<RuleExtensionBo>();
168        /*personResponsibilities = new AutoPopulatingList<PersonRuleResponsibility>(PersonRuleResponsibility.class);
169        groupResponsibilities = new AutoPopulatingList<GroupRuleResponsibility>(GroupRuleResponsibility.class);
170        roleResponsibilities = new AutoPopulatingList<RoleRuleResponsibility>(RoleRuleResponsibility.class);*/
171        fieldValues = new HashMap<String, String>();
172    }
173
174    /**
175     * @return the rule expression definition for this rule, if defined
176     */
177    public RuleExpressionDef getRuleExpressionDef() {
178        return ruleExpressionDef;
179    }
180
181    /**
182     * @param ruleExpressionDef the rule expression definition to set for this rule
183     */
184    public void setRuleExpressionDef(RuleExpressionDef ruleExpressionDef) {
185        this.ruleExpressionDef = ruleExpressionDef;
186    }
187
188    public String getRuleTemplateName() {
189        if (ruleTemplate != null) {
190            return ruleTemplate.getName();
191        }
192        return null;
193    }
194
195    public RuleBaseValues getPreviousVersion() {
196        if (previousVersion == null && previousRuleId != null) {
197            RuleServiceInternal ruleService = (RuleServiceInternal) KEWServiceLocator.getService(KEWServiceLocator.RULE_SERVICE);
198            return ruleService.findRuleBaseValuesById(previousRuleId);
199        }
200        return previousVersion;
201    }
202
203    public void setPreviousVersion(RuleBaseValues previousVersion) {
204        this.previousVersion = previousVersion;
205    }
206
207    public RuleResponsibilityBo getResponsibility(int index) {
208        while (getRuleResponsibilities().size() <= index) {
209            RuleResponsibilityBo ruleResponsibility = new RuleResponsibilityBo();
210            ruleResponsibility.setRuleBaseValues(this);
211            getRuleResponsibilities().add(ruleResponsibility);
212        }
213        return (RuleResponsibilityBo) getRuleResponsibilities().get(index);
214    }
215
216    public RuleExtensionBo getRuleExtension(int index) {
217        while (getRuleExtensions().size() <= index) {
218            getRuleExtensions().add(new RuleExtensionBo());
219        }
220        return (RuleExtensionBo) getRuleExtensions().get(index);
221    }
222
223    public RuleExtensionValue getRuleExtensionValue(String key) {
224        for (Iterator iter = getRuleExtensions().iterator(); iter.hasNext();) {
225            RuleExtensionBo ruleExtension = (RuleExtensionBo) iter.next();
226            for (Iterator iterator = ruleExtension.getExtensionValues().iterator(); iterator.hasNext();) {
227                RuleExtensionValue ruleExtensionValue = (RuleExtensionValue) iterator.next();
228                if (ruleExtensionValue.getKey().equals(key)) {
229                    return ruleExtensionValue;
230                }
231            }
232        }
233        return null;
234    }
235
236    public RuleExtensionValue getRuleExtensionValue(String ruleTemplateAttributeId, String key) {
237        for (Iterator iter = getRuleExtensions().iterator(); iter.hasNext();) {
238            RuleExtensionBo ruleExtension = (RuleExtensionBo) iter.next();
239            if (ruleExtension.getRuleTemplateAttributeId().equals(ruleTemplateAttributeId)) {
240                for (Iterator iterator = ruleExtension.getExtensionValues().iterator(); iterator.hasNext();) {
241                    RuleExtensionValue ruleExtensionValue = (RuleExtensionValue) iterator.next();
242                    if (ruleExtensionValue.getKey().equals(key)) {
243                        return ruleExtensionValue;
244                    }
245                }
246            }
247        }
248        return null;
249    }
250
251    public String getPreviousRuleId() {
252        return previousRuleId;
253    }
254
255    public void setPreviousRuleId(String previousVersion) {
256        this.previousRuleId = previousVersion;
257    }
258
259    public void addRuleResponsibility(RuleResponsibilityBo ruleResponsibility) {
260        addRuleResponsibility(ruleResponsibility, new Integer(getRuleResponsibilities().size()));
261    }
262
263    public void addRuleResponsibility(RuleResponsibilityBo ruleResponsibility, Integer counter) {
264        boolean alreadyAdded = false;
265        int location = 0;
266        if (counter != null) {
267            for (RuleResponsibilityBo ruleResponsibilityRow : getRuleResponsibilities()) {
268                if (counter.intValue() == location) {
269                    ruleResponsibilityRow.setPriority(ruleResponsibility.getPriority());
270                    ruleResponsibilityRow.setActionRequestedCd(ruleResponsibility.getActionRequestedCd());
271                    ruleResponsibilityRow.setVersionNumber(ruleResponsibility.getVersionNumber());
272                    ruleResponsibilityRow.setRuleBaseValuesId(ruleResponsibility.getRuleBaseValuesId());
273                    ruleResponsibilityRow.setRuleResponsibilityName(ruleResponsibility.getRuleResponsibilityName());
274                    ruleResponsibilityRow.setRuleResponsibilityType(ruleResponsibility.getRuleResponsibilityType());
275                    //ruleResponsibilityRow.setDelegationRules(ruleResponsibility.getDelegationRules());
276                    ruleResponsibilityRow.setApprovePolicy(ruleResponsibility.getApprovePolicy());
277                    alreadyAdded = true;
278                }
279                location++;
280            }
281        }
282        if (!alreadyAdded) {
283            getRuleResponsibilities().add(ruleResponsibility);
284        }
285    }
286
287    public RuleTemplateBo getRuleTemplate() {
288        return ruleTemplate;
289    }
290
291    public void setRuleTemplate(RuleTemplateBo ruleTemplate) {
292        this.ruleTemplate = ruleTemplate;
293    }
294
295    public String getRuleTemplateId() {
296        return ruleTemplateId;
297    }
298
299    public void setRuleTemplateId(String ruleTemplateId) {
300        this.ruleTemplateId = ruleTemplateId;
301    }
302
303    public DocumentType getDocumentType() {
304        return KEWServiceLocator.getDocumentTypeService().findByName(getDocTypeName());
305    }
306
307    public String getDocTypeName() {
308        return docTypeName;
309    }
310
311    public void setDocTypeName(String docTypeName) {
312        this.docTypeName = docTypeName;
313    }
314
315    public List<RuleExtensionBo> getRuleExtensions() {
316        return ruleExtensions;
317    }
318
319    public Map<String, String> getRuleExtensionMap() {
320        Map<String, String> extensions = new HashMap<String, String>();
321        for (RuleExtensionBo ext : this.getRuleExtensions()) {
322            for (RuleExtensionValue value : ext.getExtensionValues()) {
323                extensions.put(value.getKey(), value.getValue());
324            }
325        }
326        return extensions;
327    }
328
329    public void setRuleExtensions(List<RuleExtensionBo> ruleExtensions) {
330        this.ruleExtensions = ruleExtensions;
331    }
332
333    public List<RuleResponsibilityBo> getRuleResponsibilities() {
334        return this.ruleResponsibilities;
335    }
336
337    public void setRuleResponsibilities(List<RuleResponsibilityBo> ruleResponsibilities) {
338        this.ruleResponsibilities = ruleResponsibilities;
339    }
340
341    public RuleResponsibilityBo getResponsibility(Long ruleResponsibilityKey) {
342        for (Iterator iterator = getRuleResponsibilities().iterator(); iterator.hasNext();) {
343            RuleResponsibilityBo responsibility = (RuleResponsibilityBo) iterator.next();
344            if (responsibility.getId() != null
345                    && responsibility.getId().equals(ruleResponsibilityKey)) {
346                return responsibility;
347            }
348        }
349        return null;
350    }
351
352    public void removeResponsibility(int index) {
353        getRuleResponsibilities().remove(index);
354    }
355
356    @Override
357    public boolean isActive() {
358        return active;
359    }
360
361    public void setActive(boolean active) {
362        this.active = active;
363    }
364
365    public String getActiveIndDisplay() {
366        return CodeTranslator.getActiveIndicatorLabel(isActive());
367    }
368
369    public Boolean getCurrentInd() {
370        return currentInd;
371    }
372
373    public void setCurrentInd(Boolean currentInd) {
374        this.currentInd = currentInd;
375    }
376
377    public Timestamp getFromDateValue() {
378        return fromDateValue;
379    }
380    
381    @Override
382    public DateTime getFromDate() {
383        if (this.fromDateValue == null) {
384            return null;
385        }
386        return new DateTime(this.fromDateValue.getTime());
387    }
388
389    public void setFromDateValue(Timestamp fromDateValue) {
390        this.fromDateValue = fromDateValue;
391    }
392
393    public String getDescription() {
394        return description;
395    }
396
397    public void setDescription(String description) {
398        this.description = description;
399    }
400
401    public String getId() {
402        return id;
403    }
404
405    public void setId(String id) {
406        this.id = id;
407    }
408
409    public Timestamp getToDateValue() {
410        return toDateValue;
411    }
412    
413    @Override
414    public DateTime getToDate() {
415        if (this.toDateValue == null) {
416            return null;
417        }
418        return new DateTime(this.toDateValue.getTime());
419    }
420
421    public void setToDateValue(Timestamp toDateValue) {
422        this.toDateValue = toDateValue;
423    }
424
425    public Integer getVersionNbr() {
426        return versionNbr;
427    }
428
429    public void setVersionNbr(Integer versionNbr) {
430        this.versionNbr = versionNbr;
431    }
432
433    public String getReturnUrl() {
434        return returnUrl;
435    }
436
437    public void setReturnUrl(String returnUrl) {
438        this.returnUrl = returnUrl;
439    }
440
441    public String getFromDateString() {
442        if (this.fromDateValue != null) {
443            return RiceConstants.getDefaultDateFormat().format(this.fromDateValue);
444        }
445        return null;
446    }
447
448    public String getToDateString() {
449        if (this.toDateValue != null) {
450            return RiceConstants.getDefaultDateFormat().format(this.toDateValue);
451        }
452        return null;
453    }
454
455    @Override
456    public boolean isForceAction() {
457        return forceAction;
458    }
459
460    public void setForceAction(boolean forceAction) {
461        this.forceAction = forceAction;
462    }
463
464    public boolean isActive(Date date) {
465        boolean isAfterFromDate = getFromDateValue() == null || date.after(getFromDateValue());
466        boolean isBeforeToDate = getToDateValue() == null || date.before(getToDateValue());
467        return isActive() && isAfterFromDate && isBeforeToDate;
468    }
469
470    public boolean isMatch(DocumentContent docContent) {
471        for (RuleTemplateAttributeBo ruleTemplateAttribute : getRuleTemplate().getActiveRuleTemplateAttributes()) {
472            if (!ruleTemplateAttribute.isWorkflowAttribute()) {
473                continue;
474            }
475            WorkflowRuleAttribute routingAttribute = (WorkflowRuleAttribute) ruleTemplateAttribute.getWorkflowAttribute();
476
477            RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
478            if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
479                ((GenericXMLRuleAttribute) routingAttribute).setExtensionDefinition(RuleAttribute.to(ruleAttribute));
480            }
481            String className = ruleAttribute.getResourceDescriptor();
482            List<RuleExtension> editedRuleExtensions = new ArrayList<RuleExtension>();
483            for (RuleExtensionBo extension : getRuleExtensions()) {
484                if (extension.getRuleTemplateAttribute().getRuleAttribute().getResourceDescriptor().equals(className)) {
485                    editedRuleExtensions.add(RuleExtensionBo.to(extension));
486                }
487            }
488            if (!routingAttribute.isMatch(docContent, editedRuleExtensions)) {
489                return false;
490            }
491        }
492        return true;
493    }
494
495    public RuleResponsibilityBo findResponsibility(String roleName) {
496        for (Iterator iter = getRuleResponsibilities().iterator(); iter.hasNext();) {
497            RuleResponsibilityBo resp = (RuleResponsibilityBo) iter.next();
498            if (KewApiConstants.RULE_RESPONSIBILITY_ROLE_ID.equals(resp.getRuleResponsibilityType())
499                    && roleName.equals(resp.getRuleResponsibilityName())) {
500                return resp;
501            }
502        }
503        return null;
504    }
505
506    public String getDocumentId() {
507        return documentId;
508    }
509
510    public void setDocumentId(String documentId) {
511        this.documentId = documentId;
512    }
513
514    public Boolean getDelegateRule() {
515        return delegateRule;
516    }
517
518    public void setDelegateRule(Boolean isDelegateRule) {
519        this.delegateRule = isDelegateRule;
520    }
521
522    public Timestamp getActivationDate() {
523        return activationDate;
524    }
525
526    public void setActivationDate(Timestamp activationDate) {
527        this.activationDate = activationDate;
528    }
529
530    public MyColumns getMyColumns() {
531        return myColumns;
532    }
533
534    public void setMyColumns(MyColumns additionalColumns) {
535        this.myColumns = additionalColumns;
536    }
537
538    public String getDestinationUrl() {
539        return destinationUrl;
540    }
541
542    public void setDestinationUrl(String destinationUrl) {
543        this.destinationUrl = destinationUrl;
544    }
545
546    public Timestamp getDeactivationDate() {
547        return deactivationDate;
548    }
549
550    public void setDeactivationDate(Timestamp deactivationDate) {
551        this.deactivationDate = deactivationDate;
552    }
553
554    /**
555     * @return whether this is a defaults/template rule
556     */
557    public Boolean getTemplateRuleInd() {
558        return templateRuleInd;
559    }
560
561    /**
562     * @param templateRuleInd whether this is a defaults/template rule
563     */
564    public void setTemplateRuleInd(Boolean templateRuleInd) {
565        this.templateRuleInd = templateRuleInd;
566    }
567
568    /**
569     * Get the rule name
570     * @return the rule name
571     */
572    public String getName() {
573        return name;
574    }
575
576    /**
577     * Set the rule name
578     * @param name the rule name
579     */
580    public void setName(String name) {
581        this.name = name;
582    }
583
584        public List<PersonRuleResponsibility> getPersonResponsibilities() {
585                return this.personResponsibilities;
586        }
587
588        public void setPersonResponsibilities(List<PersonRuleResponsibility> personResponsibilities) {
589                this.personResponsibilities = personResponsibilities;
590        }
591
592        public List<GroupRuleResponsibility> getGroupResponsibilities() {
593                return this.groupResponsibilities;
594        }
595
596        public void setGroupResponsibilities(List<GroupRuleResponsibility> groupResponsibilities) {
597                this.groupResponsibilities = groupResponsibilities;
598        }
599
600        public List<RoleRuleResponsibility> getRoleResponsibilities() {
601                return this.roleResponsibilities;
602        }
603
604        public void setRoleResponsibilities(List<RoleRuleResponsibility> roleResponsibilities) {
605                this.roleResponsibilities = roleResponsibilities;
606        }
607
608        /**
609         * @return the fieldValues
610         */
611        public Map<String, String> getFieldValues() {
612                return this.fieldValues;
613        }
614
615        /**
616         * @param fieldValues the fieldValues to set
617         */
618        public void setFieldValues(Map<String, String> fieldValues) {
619                this.fieldValues = fieldValues;
620        }
621
622    public String getGroupReviewerName() {
623        return this.groupReviewerName;
624    }
625
626    public String getGroupReviewerNamespace() {
627        return this.groupReviewerNamespace;
628    }
629
630    public String getPersonReviewer() {
631        return this.personReviewer;
632    }
633
634    public void setGroupReviewerName(String groupReviewerName) {
635        this.groupReviewerName = groupReviewerName;
636    }
637
638    public void setGroupReviewerNamespace(String groupReviewerNamespace) {
639        this.groupReviewerNamespace = groupReviewerNamespace;
640    }
641
642    public void setPersonReviewer(String personReviewer) {
643        this.personReviewer = personReviewer;
644    }
645
646    public GroupBo getGroupBo() {
647        GroupBo groupBo = null;
648        if (StringUtils.isNotBlank(getGroupReviewerName())) {
649            if ( groupBo == null ) {
650                groupBo = GroupBo.from(KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(
651                        getGroupReviewerNamespace(), getGroupReviewerName()));
652            }
653        }
654        return groupBo;
655    }
656
657    public PersonImpl getPersonImpl() {
658        return new PersonImpl();
659    }
660
661    public String getPersonReviewerType() {
662        return this.personReviewerType;
663    }
664
665    public void setPersonReviewerType(String personReviewerType) {
666        this.personReviewerType = personReviewerType;
667    }
668
669        /**
670     * Converts a mutable bo to its immutable counterpart
671     * @param bo the mutable business object
672     * @return the immutable object
673     */
674    public static org.kuali.rice.kew.api.rule.Rule to(RuleBaseValues bo) {
675        if (bo == null) {
676            return null;
677        }
678        return org.kuali.rice.kew.api.rule.Rule.Builder.create(bo).build();
679    }
680}