001/**
002 * Copyright 2005-2017 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.kuali.rice.core.api.mo.common.active.MutableInactivatable;
019import org.kuali.rice.kew.api.KewApiConstants;
020import org.kuali.rice.kew.api.KewApiServiceLocator;
021import org.kuali.rice.kew.api.WorkflowRuntimeException;
022import org.kuali.rice.kew.api.extension.ExtensionUtils;
023import org.kuali.rice.kew.api.rule.RuleTemplateAttributeContract;
024import org.kuali.rice.kew.rule.RuleExtensionBo;
025import org.kuali.rice.kew.rule.RuleExtensionValue;
026import org.kuali.rice.kew.rule.RuleValidationAttribute;
027import org.kuali.rice.kew.rule.WorkflowRuleAttribute;
028import org.kuali.rice.kew.service.KEWServiceLocator;
029import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
030import org.kuali.rice.krad.data.jpa.converters.Boolean01BigDecimalConverter;
031import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator;
032
033import javax.persistence.CascadeType;
034import javax.persistence.Column;
035import javax.persistence.Convert;
036import javax.persistence.Entity;
037import javax.persistence.FetchType;
038import javax.persistence.GeneratedValue;
039import javax.persistence.Id;
040import javax.persistence.JoinColumn;
041import javax.persistence.ManyToOne;
042import javax.persistence.OneToMany;
043import javax.persistence.Table;
044import javax.persistence.Transient;
045import java.util.HashMap;
046import java.util.List;
047import java.util.Map;
048
049/**
050 * A model bean which services as the link between a {@link RuleTemplateBo} and
051 * a {@link RuleAttribute}.
052 *
053 * @author Kuali Rice Team (rice.collab@kuali.org)
054 */
055@Entity
056@Table(name="KREW_RULE_TMPL_ATTR_T")
057//@Sequence(name="KREW_RTE_TMPL_S", property="id")
058public class RuleTemplateAttributeBo extends PersistableBusinessObjectBase
059        implements Comparable<RuleTemplateAttributeBo>, MutableInactivatable, RuleTemplateAttributeContract {
060
061    private static final long serialVersionUID = -3580049225424553828L;
062    @Id
063    @PortableSequenceGenerator(name="KREW_RTE_TMPL_S")
064    @GeneratedValue(generator="KREW_RTE_TMPL_S")
065        @Column(name="RULE_TMPL_ATTR_ID")
066        private String id;
067    @Column(name="RULE_ATTR_ID", insertable=false, updatable=false)
068        private String ruleAttributeId;
069    @Column(name="REQ_IND")
070    @Convert(converter=Boolean01BigDecimalConverter.class)
071        private Boolean required;
072    @Column(name="ACTV_IND")
073    @Convert(converter=Boolean01BigDecimalConverter.class)
074        private Boolean active;
075    @Column(name="DSPL_ORD")
076        private Integer displayOrder;
077    @Column(name="DFLT_VAL")
078        private String defaultValue;
079
080    @Transient
081    private String ruleTemplateId;
082
083    @ManyToOne(fetch=FetchType.EAGER, cascade = CascadeType.ALL)
084        @JoinColumn(name="RULE_TMPL_ID", nullable = false)
085        private RuleTemplateBo ruleTemplate;
086    @ManyToOne(fetch=FetchType.EAGER)
087        @JoinColumn(name="RULE_ATTR_ID")
088        private RuleAttribute ruleAttribute;
089    @OneToMany(fetch=FetchType.LAZY,mappedBy="ruleTemplateAttribute")
090        private List<RuleExtensionBo> ruleExtensions;
091    
092    
093    public RuleTemplateAttributeBo() {
094        this.required = Boolean.FALSE;
095        this.active = Boolean.TRUE;
096    }
097   
098    public int compareTo(RuleTemplateAttributeBo ruleTemplateAttribute) {
099        if ((this.getDisplayOrder() != null) && (ruleTemplateAttribute.getDisplayOrder() != null)) {
100            return this.getDisplayOrder().compareTo(ruleTemplateAttribute.getDisplayOrder());
101        }
102        return 0;
103    }
104
105    public Object getAttribute() {
106        try {
107            //ObjectDefinition objectDefinition = new ObjectDefinition(getRuleAttribute().getResourceDescriptor(), getRuleAttribute().getApplicationId());
108            Object attribute = ExtensionUtils.loadExtension(RuleAttribute.to(getRuleAttribute()), getRuleAttribute().getApplicationId());
109            if (attribute == null) {
110                throw new WorkflowRuntimeException("Could not find attribute " + getRuleAttribute().getName());
111            }
112            if (attribute instanceof WorkflowRuleAttribute) {
113                ((WorkflowRuleAttribute) attribute).setRequired(required.booleanValue());
114            }
115            return attribute;
116        } catch (Exception e) {
117            throw new RuntimeException("Caught error attempting to load attribute class: " + getRuleAttribute().getResourceDescriptor(), e);
118        }
119    }
120
121    public boolean isWorkflowAttribute() {
122        return getRuleAttribute().isWorkflowAttribute();
123    }
124
125    public boolean isRuleValidationAttribute() {
126        // just check the type here to avoid having to load the class from the class loader if it's not actually there
127        return KewApiConstants.RULE_VALIDATION_ATTRIBUTE_TYPE.equals(getRuleAttribute().getType());
128    }
129
130    /**
131     * Instantiates and returns a new instance of the WorkflowAttribute class configured on this template.
132     * The calling code should be sure to call isWorkflowAttribute first to verify the type of this attribute
133     * is that of a WorkflowAttribute.  Otherwise a RuntimeException will be thrown.
134     */
135    public WorkflowRuleAttribute getWorkflowAttribute() {
136        try {
137            Object tempAttr = ExtensionUtils.loadExtension(RuleAttribute.to(getRuleAttribute()), getRuleAttribute().getApplicationId());
138
139            if (tempAttr == null
140                    || !WorkflowRuleAttribute.class.isAssignableFrom(tempAttr.getClass())) {
141                throw new WorkflowRuntimeException("Could not find workflow attribute " + getRuleAttribute().getName());
142            }
143            WorkflowRuleAttribute workflowAttribute = (WorkflowRuleAttribute)tempAttr;
144            workflowAttribute.setRequired(required.booleanValue());
145            return workflowAttribute;
146        } catch (Exception e) {
147            throw new RuntimeException("Caught exception instantiating new " + getRuleAttribute().getResourceDescriptor(), e);
148        }
149    }
150
151    /**
152     * Instantiates and returns a new instance of the RuleValidationAttribute class configured on this template.
153     * The calling code should be sure to call isRuleValidationAttribute first to verify the type of this attribute
154     * is that of a RuleValidationAttribute.  Otherwise a RuntimeException will be thrown.
155     */
156    public RuleValidationAttribute getRuleValidationAttribute() {
157        try {
158            RuleAttribute attrib = getRuleAttribute();
159            return KEWServiceLocator.getRuleValidationAttributeResolver().resolveRuleValidationAttribute(attrib.getName(), attrib.getApplicationId());
160        } catch (Exception e) {
161            throw new RuntimeException("Caught exception instantiating new " + getRuleAttribute().getResourceDescriptor(), e);
162        }
163    }
164
165    public List<RuleExtensionBo> getRuleExtensions() {
166        return ruleExtensions;
167    }
168
169    public Map<String, String> getRuleExtensionMap() {
170        Map<String, String> extensions = new HashMap<String, String>();
171        if (this.getRuleExtensions() != null) {
172            for (RuleExtensionBo ext : this.getRuleExtensions()) {
173                for (RuleExtensionValue value : ext.getExtensionValues()) {
174                    extensions.put(value.getKey(), value.getValue());
175                }
176            }
177        }
178        return extensions;
179    }
180
181    public void setRuleExtensions(List<RuleExtensionBo> ruleExtensions) {
182        this.ruleExtensions = ruleExtensions;
183    }
184
185    public RuleAttribute getRuleAttribute() {
186        if (ruleAttribute == null && ruleAttributeId != null) {
187            ruleAttribute = RuleAttribute.from(KewApiServiceLocator.getExtensionRepositoryService().getExtensionById(ruleAttributeId));
188        }
189        return ruleAttribute;
190    }
191
192    public void setRuleAttribute(org.kuali.rice.kew.rule.bo.RuleAttribute ruleAttribute) {
193        this.ruleAttribute = ruleAttribute;
194    }
195
196    public RuleTemplateBo getRuleTemplate() {
197        return ruleTemplate;
198    }
199
200    public void setRuleTemplate(RuleTemplateBo ruleTemplate) {
201        this.ruleTemplate = ruleTemplate;
202    }
203
204    public String getDefaultValue() {
205        return defaultValue;
206    }
207
208    public void setDefaultValue(String defaultValue) {
209        this.defaultValue = defaultValue;
210    }
211
212    public Integer getDisplayOrder() {
213        return displayOrder;
214    }
215
216    public void setDisplayOrder(Integer displayOrder) {
217        this.displayOrder = displayOrder;
218    }
219
220    public boolean isRequired() {
221        return (getRequired() == null) || (getRequired().booleanValue());
222    }
223
224    public Boolean getRequired() {
225        return required;
226    }
227
228    public void setRequired(Boolean required) {
229        this.required = required;
230    }
231
232    public boolean isActive() {
233        return (getActive() == null) || (getActive().booleanValue());
234    }
235
236    public Boolean getActive() {
237        return active;
238    }
239
240    public void setActive(Boolean active) {
241        this.active = active;
242    }
243    
244    public void setActive(boolean active) {
245        this.active = active;
246    }
247
248    public String getRuleAttributeId() {
249        return ruleAttributeId;
250    }
251
252    public void setRuleAttributeId(String ruleAttributeId) {
253        this.ruleAttributeId = ruleAttributeId;
254    }
255
256    public String getId() {
257        return id;
258    }
259
260    public void setId(String id) {
261        this.id = id;
262    }
263
264    public String getRuleTemplateId() {
265        return getRuleTemplate() != null ? getRuleTemplate().getId() : null;
266    }
267
268    /**
269     * @deprecated use {@link #setRuleTemplate(RuleTemplateBo)} instead
270     */
271    @Deprecated
272    public void setRuleTemplateId(String ruleTemplateId) {
273        // there's no way to do this now after the JPA conversion!
274    }
275
276}