001/**
002 * Copyright 2005-2016 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.bo;
017
018import org.apache.commons.lang.ArrayUtils;
019import org.hibernate.annotations.Fetch;
020import org.hibernate.annotations.FetchMode;
021import org.hibernate.annotations.GenericGenerator;
022import org.hibernate.annotations.Parameter;
023import org.kuali.rice.kew.api.KewApiConstants;
024import org.kuali.rice.kew.api.rule.RoleName;
025import org.kuali.rice.kew.api.rule.RuleTemplate;
026import org.kuali.rice.kew.api.rule.RuleTemplateContract;
027import org.kuali.rice.kew.rule.RuleTemplateOptionBo;
028import org.kuali.rice.kew.service.KEWServiceLocator;
029import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
030
031import javax.persistence.CascadeType;
032import javax.persistence.Column;
033import javax.persistence.Entity;
034import javax.persistence.FetchType;
035import javax.persistence.GeneratedValue;
036import javax.persistence.Id;
037import javax.persistence.JoinColumn;
038import javax.persistence.NamedQueries;
039import javax.persistence.NamedQuery;
040import javax.persistence.OneToMany;
041import javax.persistence.OneToOne;
042import javax.persistence.Table;
043import javax.persistence.Transient;
044import java.net.URLEncoder;
045import java.util.ArrayList;
046import java.util.Collections;
047import java.util.Iterator;
048import java.util.List;
049
050
051/**
052 * A model bean which represents a template upon which a rule is created.
053 * The RuleTemplate is essentially a collection of {@link RuleAttribute}s
054 * (associated vai the {@link RuleTemplateAttributeBo} bean).
055 *
056 * @author Kuali Rice Team (rice.collab@kuali.org)
057 */
058@Entity
059@Table(name="KREW_RULE_TMPL_T")
060//@Sequence(name="KREW_RTE_TMPL_S", property="id")
061@NamedQueries({@NamedQuery(name="findAllOrderedByName", query="SELECT rt FROM RuleTemplate rt ORDER BY rt.name ASC")})
062public class RuleTemplateBo extends PersistableBusinessObjectBase implements RuleTemplateContract {
063
064    private static final long serialVersionUID = -3387940485523951302L;
065
066    /**
067     * A list of default rule template option keys.
068     */
069    public static final String[] DEFAULT_OPTION_KEYS = {
070        //KewApiConstants.RULE_INSTRUCTIONS_CD,
071        KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ,
072        KewApiConstants.ACTION_REQUEST_APPROVE_REQ,
073        KewApiConstants.ACTION_REQUEST_COMPLETE_REQ,
074        KewApiConstants.ACTION_REQUEST_FYI_REQ,
075        KewApiConstants.ACTION_REQUEST_DEFAULT_CD
076    };
077    
078    @Id
079    @GeneratedValue(generator="KREW_RTE_TMPL_S")
080        @GenericGenerator(name="KREW_RTE_TMPL_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={
081                        @Parameter(name="sequence_name",value="KREW_RTE_TMPL_S"),
082                        @Parameter(name="value_column",value="id")
083        })
084        @Column(name="RULE_TMPL_ID")
085        private String id;
086    @Column(name="NM")
087        private String name;
088    @Column(name="RULE_TMPL_DESC")
089        private String description;
090
091    @Column(name="DLGN_RULE_TMPL_ID", insertable=false, updatable=false)
092        private String delegationTemplateId;
093    @OneToOne(fetch=FetchType.EAGER)
094        @JoinColumn(name="DLGN_RULE_TMPL_ID")
095        private RuleTemplateBo delegationTemplate;
096    @Fetch(value = FetchMode.SELECT)
097    @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE},
098           mappedBy="ruleTemplate")
099        private List<RuleTemplateAttributeBo> ruleTemplateAttributes;
100    @Fetch(value = FetchMode.SELECT)
101    @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE},
102           mappedBy="ruleTemplate", orphanRemoval=true)
103        private List<RuleTemplateOptionBo> ruleTemplateOptions;
104
105    // required to be lookupable
106    @Transient
107    private String returnUrl;
108
109    public RuleTemplateBo() {
110        ruleTemplateAttributes = new ArrayList<RuleTemplateAttributeBo>();
111        ruleTemplateOptions = new ArrayList<RuleTemplateOptionBo>();
112    }
113    
114 
115    /**
116     * Removes any non-default rule template options on the template
117     */
118    public void removeNonDefaultOptions() {
119        Iterator<RuleTemplateOptionBo> it = ruleTemplateOptions.iterator();
120        while (it.hasNext()) {
121            RuleTemplateOptionBo option = it.next();
122            // if it's not one of the default options, remove it
123            if (!ArrayUtils.contains(DEFAULT_OPTION_KEYS, option.getCode())) {
124                it.remove();
125            }
126        }
127    }
128
129    public String getDelegateTemplateName() {
130        if (delegationTemplate != null) {
131            return delegationTemplate.getName();
132        }        
133        return "";
134    }
135
136    public String getRuleTemplateActionsUrl() {
137        return "<a href=\"RuleTemplate.do?methodToCall=report&currentRuleTemplateId=" + id + "\" >report</a>" /*+ "&nbsp;&nbsp;|&nbsp;&nbsp;<a href=\"RuleTemplate.do?methodToCall=edit&ruleTemplate.id=" + id + "\" >edit</a>"*/;
138    }
139
140    /**
141     * Returns the rule template attribute on this instance whose name matches the name of the rule template attribute
142     * passed as a parameter, qualified by it's active state, or null if a match was not found.
143     */
144    private RuleTemplateAttributeBo getRuleTemplateAttribute(RuleTemplateAttributeBo ruleTemplateAttribute, Boolean active) {
145        for (RuleTemplateAttributeBo currentRuleTemplateAttribute: getRuleTemplateAttributes()) {
146            if (currentRuleTemplateAttribute.getRuleAttribute().getName().equals(ruleTemplateAttribute.getRuleAttribute().getName())) {
147                if (active == null) {
148                    return currentRuleTemplateAttribute;
149                }
150                else if (active.compareTo(currentRuleTemplateAttribute.getActive()) == 0) {
151                    return currentRuleTemplateAttribute;
152                }
153            }
154        }
155        return null;
156    }
157    
158    public RuleTemplateAttributeBo getRuleTemplateAttribute(RuleTemplateAttributeBo ruleTemplateAttribute) {
159        return getRuleTemplateAttribute(ruleTemplateAttribute, null);
160    }
161    
162    public boolean containsActiveRuleTemplateAttribute(RuleTemplateAttributeBo templateAttribute) {
163        return (getRuleTemplateAttribute(templateAttribute, Boolean.TRUE) != null);
164    }
165
166    public boolean containsRuleTemplateAttribute(RuleTemplateAttributeBo templateAttribute) {
167        return (getRuleTemplateAttribute(templateAttribute, null) != null);
168    }
169
170    public RuleTemplateAttributeBo getRuleTemplateAttribute(int index) {
171        while (getRuleTemplateAttributes().size() <= index) {
172            getRuleTemplateAttributes().add(new RuleTemplateAttributeBo());
173        }
174        return (RuleTemplateAttributeBo) getRuleTemplateAttributes().get(index);
175    }
176
177    public List<RuleTemplateAttributeBo> getRuleTemplateAttributes() {
178        Collections.sort(ruleTemplateAttributes);
179        return ruleTemplateAttributes;
180    }
181
182    /**
183     * Returns a List of only the active RuleTemplateAttributes on the RuleTemplate
184     * sorted according to display order (ascending).
185     * @return
186     */
187    public List<RuleTemplateAttributeBo> getActiveRuleTemplateAttributes() {
188        List<RuleTemplateAttributeBo> activeAttributes = new ArrayList<RuleTemplateAttributeBo>();
189        for (RuleTemplateAttributeBo templateAttribute : getRuleTemplateAttributes())
190        {
191            if (templateAttribute.isActive())
192            {
193                activeAttributes.add(templateAttribute);
194            }
195        }
196        Collections.sort(activeAttributes);
197        return activeAttributes;
198    }
199    
200    /**
201     * This is implemented to allow us to use this collection on the inquiry for RuleTemplate.  In the
202     * KNS code it does an explicit check that the property is writable.
203     */
204    public void setActiveRuleTemplateAttributes(List<RuleTemplateAttributeBo> ruleTemplateAttributes) {
205        throw new UnsupportedOperationException("setActiveRuleTemplateAttributes is not implemented");
206    }
207
208    public void setRuleTemplateAttributes(List<RuleTemplateAttributeBo> ruleTemplateAttributes) {
209        this.ruleTemplateAttributes = ruleTemplateAttributes;
210    }
211
212    public String getDescription() {
213        return description;
214    }
215
216    public void setDescription(String description) {
217        this.description = description;
218    }
219
220    public String getName() {
221        return name;
222    }
223
224    public void setName(String name) {
225        this.name = name;
226    }
227
228    public String getId() {
229        return id;
230    }
231
232    public void setId(String id) {
233        this.id = id;
234    }
235
236    public String getDelegationTemplateId() {
237        return delegationTemplateId;
238    }
239
240    public void setDelegationTemplateId(String delegationTemplateId) {
241        this.delegationTemplateId = delegationTemplateId;
242    }
243
244    public RuleTemplateBo getDelegationTemplate() {
245        return delegationTemplate;
246    }
247
248    public void setDelegationTemplate(RuleTemplateBo delegationTemplate) {
249        this.delegationTemplate = delegationTemplate;
250    }
251
252    public String getReturnUrl() {
253        return returnUrl;
254    }
255
256    public void setReturnUrl(String returnUrl) {
257        this.returnUrl = returnUrl;
258    }
259
260    /**
261     * Used from the rule quicklinks when doing the focus channel.
262     */
263    public String getEncodedName() {
264        return URLEncoder.encode(getName());
265    }
266
267    public List<RuleTemplateOptionBo> getRuleTemplateOptions() {
268        return ruleTemplateOptions;
269    }
270
271    public void setRuleTemplateOptions(List<RuleTemplateOptionBo> ruleTemplateOptions) {
272        this.ruleTemplateOptions = ruleTemplateOptions;
273    }
274
275    public RuleTemplateOptionBo getRuleTemplateOption(String key) {
276        for (RuleTemplateOptionBo option: ruleTemplateOptions) {
277            if (option.getCode().equals(key)) {
278                return option;
279            }
280        }
281        return null;
282    }
283
284    public void setAcknowledge(RuleTemplateOptionBo acknowledge) {
285        RuleTemplateOptionBo option = getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ);
286        option.setValue(acknowledge.getValue());
287        option.setId(acknowledge.getId());
288        option.setVersionNumber(acknowledge.getVersionNumber());
289    }
290
291    public void setComplete(RuleTemplateOptionBo complete) {
292        RuleTemplateOptionBo option = getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_COMPLETE_REQ);
293        option.setValue(complete.getValue());
294        option.setId(complete.getId());
295        option.setVersionNumber(complete.getVersionNumber());
296    }
297
298    public void setApprove(RuleTemplateOptionBo approve) {
299        RuleTemplateOptionBo option = getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_APPROVE_REQ);
300        option.setValue(approve.getValue());
301        option.setId(approve.getId());
302        option.setVersionNumber(approve.getVersionNumber());
303    }
304
305    public void setFyi(RuleTemplateOptionBo fyi) {
306        RuleTemplateOptionBo option = getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_FYI_REQ);
307        option.setValue(fyi.getValue());
308        option.setId(fyi.getId());
309        option.setVersionNumber(fyi.getVersionNumber());
310    }
311
312    public void setDefaultActionRequestValue(RuleTemplateOptionBo defaultActionRequestValue) {
313        RuleTemplateOptionBo option = getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_DEFAULT_CD);
314        option.setValue(defaultActionRequestValue.getValue());
315        option.setId(defaultActionRequestValue.getId());
316        option.setVersionNumber(defaultActionRequestValue.getVersionNumber());
317    }
318
319    public RuleTemplateOptionBo getAcknowledge() {
320        return getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ);
321    }
322
323    public RuleTemplateOptionBo getComplete() {
324        return getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_COMPLETE_REQ);
325    }
326
327    public RuleTemplateOptionBo getApprove() {
328        return getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_APPROVE_REQ);
329    }
330
331    public RuleTemplateOptionBo getFyi() {
332        return getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_FYI_REQ);
333    }
334
335    public RuleTemplateOptionBo getDefaultActionRequestValue() {
336        return getRuleTemplateOption(KewApiConstants.ACTION_REQUEST_DEFAULT_CD);
337    }
338
339    /**
340     * Returns a List of Roles from all RoleAttributes attached to this template.
341     *
342     * @return list of roles
343     */
344    public List<RoleName> getRoles() {
345        List<RoleName> roleNames = new ArrayList<RoleName>();
346        List<RuleTemplateAttributeBo> templateAttributes = getRuleTemplateAttributes();
347        for (RuleTemplateAttributeBo templateAttribute : templateAttributes) {
348            if (!templateAttribute.isWorkflowAttribute())
349            {
350                                continue;
351                        }
352            roleNames.addAll(KEWServiceLocator.getWorkflowRuleAttributeMediator().getRoleNames(templateAttribute));
353        }
354        return roleNames;
355    }
356
357    public static RuleTemplate to(RuleTemplateBo bo) {
358        if (bo == null) {
359            return null;
360        }
361        return RuleTemplate.Builder.create(bo).build();
362    }
363}