View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.xml;
17  
18  import org.apache.commons.lang.BooleanUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.jdom.Attribute;
21  import org.jdom.Document;
22  import org.jdom.Element;
23  import org.jdom.JDOMException;
24  import org.kuali.rice.core.api.delegation.DelegationType;
25  import org.kuali.rice.core.api.util.RiceConstants;
26  import org.kuali.rice.core.api.util.xml.XmlException;
27  import org.kuali.rice.core.api.util.xml.XmlHelper;
28  import org.kuali.rice.kew.rule.RuleBaseValues;
29  import org.kuali.rice.kew.rule.RuleDelegationBo;
30  import org.kuali.rice.kew.rule.RuleTemplateOptionBo;
31  import org.kuali.rice.kew.rule.bo.RuleAttribute;
32  import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
33  import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
34  import org.kuali.rice.kew.service.KEWServiceLocator;
35  import org.kuali.rice.kew.api.KewApiConstants;
36  import org.xml.sax.SAXException;
37  
38  import javax.xml.parsers.ParserConfigurationException;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.sql.Timestamp;
42  import java.text.ParseException;
43  import java.util.ArrayList;
44  import java.util.Collection;
45  import java.util.Iterator;
46  import java.util.List;
47  
48  import static org.kuali.rice.core.api.impex.xml.XmlConstants.*;
49  /**
50   * Parses {@link org.kuali.rice.kew.rule.bo.RuleTemplateBo}s from XML.
51   *
52   * @see org.kuali.rice.kew.rule.bo.RuleTemplateBo
53   *
54   * @author Kuali Rice Team (rice.collab@kuali.org)
55   */
56  public class RuleTemplateXmlParser {
57  
58      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RuleTemplateXmlParser.class);
59  
60      /**
61       * By default make attributes defined without a <required> element
62       */
63      private static final boolean DEFAULT_ATTRIBUTE_REQUIRED = true;
64      private static final boolean DEFAULT_ATTRIBUTE_ACTIVE = true;
65  
66      /**
67       * A dummy document type used in the default rule
68       */
69      private static final String DUMMY_DOCUMENT_TYPE = "dummyDocumentType";
70  
71      /**
72       * Used to set the display order of attributes encountered in parsing runs during the lifetime of this object
73       */
74      private int templateAttributeCounter = 0;
75  
76      public List<RuleTemplateBo> parseRuleTemplates(InputStream input) throws IOException, XmlException {
77  
78          try {
79              Document doc = XmlHelper.trimSAXXml(input);
80              Element root = doc.getRootElement();
81              return parseRuleTemplates(root);
82          } catch (JDOMException e) {
83              throw new XmlException("Parse error.", e);
84          } catch (SAXException e) {
85              throw new XmlException("Parse error.", e);
86          } catch (ParserConfigurationException e) {
87              throw new XmlException("Parse error.", e);
88          }
89      }
90  
91      public List<RuleTemplateBo> parseRuleTemplates(Element element) throws XmlException {
92          List<RuleTemplateBo> ruleTemplates = new ArrayList<RuleTemplateBo>();
93  
94          // iterate over any RULE_TEMPLATES elements
95          Collection<Element> ruleTemplatesElements = XmlHelper.findElements(element, RULE_TEMPLATES);
96          Iterator ruleTemplatesIterator = ruleTemplatesElements.iterator();
97          while (ruleTemplatesIterator.hasNext()) {
98              Element ruleTemplatesElement = (Element) ruleTemplatesIterator.next();
99              Collection<Element> ruleTemplateElements = XmlHelper.findElements(ruleTemplatesElement, RULE_TEMPLATE);
100             for (Iterator iterator = ruleTemplateElements.iterator(); iterator.hasNext();) {
101                 ruleTemplates.add(parseRuleTemplate((Element) iterator.next(), ruleTemplates));
102             }
103         }
104         return ruleTemplates;
105     }
106 
107     private RuleTemplateBo parseRuleTemplate(Element element, List<RuleTemplateBo> ruleTemplates) throws XmlException {
108         String name = element.getChildText(NAME, RULE_TEMPLATE_NAMESPACE);
109         String description = element.getChildText(DESCRIPTION, RULE_TEMPLATE_NAMESPACE);
110         Attribute allowOverwriteAttrib = element.getAttribute("allowOverwrite");
111 
112         boolean allowOverwrite = false;
113         if (allowOverwriteAttrib != null) {
114             allowOverwrite = Boolean.valueOf(allowOverwriteAttrib.getValue()).booleanValue();
115         }
116         if (org.apache.commons.lang.StringUtils.isEmpty(name)) {
117             throw new XmlException("RuleTemplate must have a name");
118         }
119         if (org.apache.commons.lang.StringUtils.isEmpty(description)) {
120             throw new XmlException("RuleTemplate must have a description");
121         }
122 
123         // look up the rule template by name first
124         RuleTemplateBo ruleTemplate = KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(name);
125 
126         if (ruleTemplate == null) {
127             // if it does not exist create a new one
128             ruleTemplate = new RuleTemplateBo();
129         } else {
130             // if it does exist, update it, only if allowOverwrite is set
131             if (!allowOverwrite) {
132                 throw new RuntimeException("Attempting to overwrite template " + name + " without allowOverwrite set");
133             }
134 
135             // the name should be equal if one was actually found
136             assert(name.equals(ruleTemplate.getName())) : "Existing template definition name does not match incoming definition name";
137         } 
138 
139         // overwrite simple properties
140         ruleTemplate.setName(name);
141         ruleTemplate.setDescription(description);
142 
143         // update the delegation template
144         updateDelegationTemplate(element, ruleTemplate, ruleTemplates);
145 
146         // update the attribute relationships
147         updateRuleTemplateAttributes(element, ruleTemplate);
148 
149         // save the rule template first so that the default/template rule that is generated
150         // in the process of setting defaults is associated properly with this rule template
151         KEWServiceLocator.getRuleTemplateService().save(ruleTemplate);
152 
153         // update the default options
154         updateRuleTemplateDefaultOptions(element, ruleTemplate);
155 
156         KEWServiceLocator.getRuleTemplateService().save(ruleTemplate);
157 
158         return ruleTemplate;
159     }
160 
161     /**
162      * Updates the rule template default options.  Updates any existing options, removes any omitted ones.
163      * @param ruleTemplateElement the rule template XML element
164      * @param updatedRuleTemplate the RuleTemplate being updated
165      * @throws XmlException
166      */
167     /*
168      <element name="description" type="c:LongStringType"/>
169      <element name="fromDate" type="c:ShortStringType" minOccurs="0"/>
170      <element name="toDate" type="c:ShortStringType" minOccurs="0"/>
171      <element name="forceAction" type="boolean"/>
172      <element name="active" type="boolean"/>
173      <element name="defaultActionRequested" type="c:ShortStringType"/>
174      <element name="supportsComplete" type="boolean" default="true"/>
175      <element name="supportsApprove" type="boolean" default="true"/>
176      <element name="supportsAcknowledge" type="boolean" default="true"/>
177      <element name="supportsFYI" type="boolean" default="true"/>
178     */
179     protected void updateRuleTemplateDefaultOptions(Element ruleTemplateElement, RuleTemplateBo updatedRuleTemplate) throws XmlException {
180         Element defaultsElement = ruleTemplateElement.getChild(RULE_DEFAULTS, RULE_TEMPLATE_NAMESPACE);
181 
182         // update the rule defaults; this yields whether or not this is a delegation rule template
183         boolean isDelegation = updateRuleDefaults(defaultsElement, updatedRuleTemplate);
184 
185         // update the rule template options
186         updateRuleTemplateOptions(defaultsElement, updatedRuleTemplate, isDelegation);
187 
188     }
189 
190     /**
191      * Updates the rule template defaults options with those in the defaults element
192      * @param defaultsElement the ruleDefaults element
193      * @param updatedRuleTemplate the Rule Template being updated
194      */
195     protected void updateRuleTemplateOptions(Element defaultsElement, RuleTemplateBo updatedRuleTemplate, boolean isDelegation) throws XmlException {
196         // the possible defaults options
197         // NOTE: the current implementation will remove any existing RuleTemplateOption records for any values which are null, i.e. not set in the incoming XML.
198         // to pro-actively set default values for omitted options, simply set those values here, and records will be added if not present
199         String defaultActionRequested = null;
200         Boolean supportsComplete = null;
201         Boolean supportsApprove = null;
202         Boolean supportsAcknowledge = null;
203         Boolean supportsFYI = null;
204         
205         // remove any RuleTemplateOptions the template may have but that we know we aren't going to update/reset
206         // (not sure if this case even exists...does anything else set rule template options?)
207         updatedRuleTemplate.removeNonDefaultOptions();
208         
209         // read in new settings
210         if (defaultsElement != null) {
211 
212         	defaultActionRequested = defaultsElement.getChildText(DEFAULT_ACTION_REQUESTED, RULE_TEMPLATE_NAMESPACE);
213             supportsComplete = BooleanUtils.toBooleanObject(defaultsElement.getChildText(SUPPORTS_COMPLETE, RULE_TEMPLATE_NAMESPACE));
214             supportsApprove = BooleanUtils.toBooleanObject(defaultsElement.getChildText(SUPPORTS_APPROVE, RULE_TEMPLATE_NAMESPACE));
215             supportsAcknowledge = BooleanUtils.toBooleanObject(defaultsElement.getChildText(SUPPORTS_ACKNOWLEDGE, RULE_TEMPLATE_NAMESPACE));
216             supportsFYI = BooleanUtils.toBooleanObject(defaultsElement.getChildText(SUPPORTS_FYI, RULE_TEMPLATE_NAMESPACE));
217         }
218 
219         if (!isDelegation) {
220             // if this is not a delegation template, store the template options that govern rule action constraints
221             // in the RuleTemplateOptions of the template
222             // we have two options for this behavior:
223             // 1) conditionally parse above, and then unconditionally set/unset the properties; this will have the effect of REMOVING
224             //    any of these previously specified rule template options (and is arguably the right thing to do)
225             // 2) unconditionally parse above, and then conditionally set/unset the properties; this will have the effect of PRESERVING
226             //    the existing rule template options on this template if it is a delegation template (which of course will be overwritten
227             //    by this very same code if they subsequently upload without the delegation flag)
228             // This is a minor point, but the second implementation is chosen as it preserved the current behavior
229             updateOrDeleteRuleTemplateOption(updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_DEFAULT_CD, defaultActionRequested);
230             updateOrDeleteRuleTemplateOption(updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, supportsApprove);
231             updateOrDeleteRuleTemplateOption(updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, supportsAcknowledge);
232             updateOrDeleteRuleTemplateOption(updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_FYI_REQ, supportsFYI);
233             updateOrDeleteRuleTemplateOption(updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_COMPLETE_REQ, supportsComplete);
234         }
235 
236     }
237     
238     /**
239      * 
240      * Updates the default/template rule options with those in the defaults element
241      * @param defaultsElement the ruleDefaults element
242      * @param updatedRuleTemplate the Rule Template being updated
243      * @return whether this is a delegation rule template
244      */
245     protected boolean updateRuleDefaults(Element defaultsElement, RuleTemplateBo updatedRuleTemplate) throws XmlException {
246         // NOTE: implementation detail: in contrast with the other options, the delegate template, and the rule attributes,
247         // we unconditionally blow away the default rule and re-create it (we don't update the existing one, if there is one)
248         if (updatedRuleTemplate.getId() != null) {
249             RuleBaseValues ruleDefaults = KEWServiceLocator.getRuleService().findDefaultRuleByRuleTemplateId(updatedRuleTemplate.getId());
250             if (ruleDefaults != null) {
251                 List ruleDelegationDefaults = KEWServiceLocator.getRuleDelegationService().findByDelegateRuleId(ruleDefaults.getId());
252                 // delete the rule
253                 KEWServiceLocator.getRuleService().delete(ruleDefaults.getId());
254                 // delete the associated rule delegation defaults
255                 for (Iterator iterator = ruleDelegationDefaults.iterator(); iterator.hasNext();) {
256                     RuleDelegationBo ruleDelegation = (RuleDelegationBo) iterator.next();
257                     KEWServiceLocator.getRuleDelegationService().delete(ruleDelegation.getRuleDelegationId());
258                 }
259             }
260         }
261 
262         boolean isDelegation = false;
263 
264         if (defaultsElement != null) {
265             String delegationTypeCode = defaultsElement.getChildText(DELEGATION_TYPE, RULE_TEMPLATE_NAMESPACE);
266             DelegationType delegationType = null;
267             isDelegation = !org.apache.commons.lang.StringUtils.isEmpty(delegationTypeCode);
268 
269             String description = defaultsElement.getChildText(DESCRIPTION, RULE_TEMPLATE_NAMESPACE);
270             
271             // would normally be validated via schema but might not be present if invoking RuleXmlParser directly
272             if (description == null) {
273                 throw new XmlException("Description must be specified in rule defaults");
274             }
275             
276             String fromDate = defaultsElement.getChildText(FROM_DATE, RULE_TEMPLATE_NAMESPACE);
277             String toDate = defaultsElement.getChildText(TO_DATE, RULE_TEMPLATE_NAMESPACE);
278             // toBooleanObject ensures that if the value is null (not set) that the Boolean object will likewise be null (will not default to a value)
279             Boolean forceAction = BooleanUtils.toBooleanObject(defaultsElement.getChildText(FORCE_ACTION, RULE_TEMPLATE_NAMESPACE));
280             Boolean active = BooleanUtils.toBooleanObject(defaultsElement.getChildText(ACTIVE, RULE_TEMPLATE_NAMESPACE));
281 
282             if (isDelegation) {
283                 delegationType = DelegationType.parseCode(delegationTypeCode);
284                 if (delegationType == null) {
285                     throw new XmlException("Invalid delegation type '" + delegationType + "'." + "  Expected one of: "
286                                             + DelegationType.PRIMARY.getCode() + "," + DelegationType.SECONDARY.getCode());
287                 }
288             }
289     
290             // create our "default rule" which encapsulates the defaults for the rule
291             RuleBaseValues ruleDefaults = new RuleBaseValues();
292     
293             // set simple values
294             ruleDefaults.setRuleTemplate(updatedRuleTemplate);
295             ruleDefaults.setDocTypeName(DUMMY_DOCUMENT_TYPE);
296             ruleDefaults.setTemplateRuleInd(Boolean.TRUE);
297             ruleDefaults.setCurrentInd(Boolean.TRUE);
298             ruleDefaults.setVersionNbr(new Integer(0));
299             ruleDefaults.setDescription(description);
300     
301             // these are non-nullable fields, so default them if they were not set in the defaults section
302             ruleDefaults.setForceAction(Boolean.valueOf(BooleanUtils.isTrue(forceAction)));
303             ruleDefaults.setActive(Boolean.valueOf(BooleanUtils.isTrue(active)));
304         
305             if (ruleDefaults.getActivationDate() == null) {
306                 ruleDefaults.setActivationDate(new Timestamp(System.currentTimeMillis()));
307             }
308     
309             ruleDefaults.setFromDateValue(formatDate("fromDate", fromDate));
310             ruleDefaults.setToDateValue(formatDate("toDate", toDate));
311             
312             // ok, if this is a "Delegate Template", then we need to set this other RuleDelegation object which contains
313             // some delegation-related info
314             RuleDelegationBo ruleDelegationDefaults = null;
315             if (isDelegation) {
316                 ruleDelegationDefaults = new RuleDelegationBo();
317                 ruleDelegationDefaults.setDelegationRule(ruleDefaults);
318                 ruleDelegationDefaults.setDelegationType(delegationType);
319                 ruleDelegationDefaults.setResponsibilityId(KewApiConstants.ADHOC_REQUEST_RESPONSIBILITY_ID);
320             }
321 
322             // explicitly save the new rule delegation defaults and default rule
323             KEWServiceLocator.getRuleTemplateService().saveRuleDefaults(ruleDelegationDefaults, ruleDefaults);
324         } else {
325             // do nothing, rule defaults will be deleted if ruleDefaults element is omitted
326         }
327         
328         return isDelegation;
329     }
330 
331 
332     /**
333      * Updates or deletes a specified rule template option on the rule template
334      * @param updatedRuleTemplate the RuleTemplate being updated
335      * @param key the option key
336      * @param value the option value
337      */
338     protected void updateOrDeleteRuleTemplateOption(RuleTemplateBo updatedRuleTemplate, String key, Object value) {
339         if (value != null) {
340             // if the option exists and the incoming value is non-null (it's set), update it
341             RuleTemplateOptionBo option = updatedRuleTemplate.getRuleTemplateOption(key);
342             if (option != null) {
343                 option.setValue(value.toString());
344             } else {
345                 updatedRuleTemplate.getRuleTemplateOptions().add(new RuleTemplateOptionBo(key, value.toString()));
346             }
347         } else {
348             // otherwise if the incoming value IS null (not set), then explicitly remove the entry (if it exists)
349             Iterator<RuleTemplateOptionBo> options = updatedRuleTemplate.getRuleTemplateOptions().iterator();
350             while (options.hasNext()) {
351                 RuleTemplateOptionBo opt = options.next();
352                 if (key.equals(opt.getCode())) {
353                     options.remove();
354                     break;
355                 }
356             }
357         }
358     }
359 
360     /**
361      * Updates the rule template delegation template with the one specified in the XML (if any)
362      * @param ruleTemplateElement the XML ruleTemplate element
363      * @param updatedRuleTemplate the rule template to update
364      * @param parsedRuleTemplates the rule templates parsed in this parsing run
365      * @throws XmlException if a delegation template was specified but could not be found
366      */
367     protected void updateDelegationTemplate(Element ruleTemplateElement, RuleTemplateBo updatedRuleTemplate, List<RuleTemplateBo> parsedRuleTemplates) throws XmlException {
368         String delegateTemplateName = ruleTemplateElement.getChildText(DELEGATION_TEMPLATE, RULE_TEMPLATE_NAMESPACE);
369 
370         if (delegateTemplateName != null) {
371             // if a delegateTemplate was set in the XML, then look it up and set it on the RuleTemplate object
372             // first try looking up an existing delegateTemplate in the system
373             RuleTemplateBo delegateTemplate = KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(delegateTemplateName);
374 
375             // if not found, try the list of templates currently parsed
376             if (delegateTemplate == null) {
377                 for (RuleTemplateBo rt: parsedRuleTemplates) {
378                     if (delegateTemplateName.equalsIgnoreCase(rt.getName())) {
379                         // set the expected next rule template id on the target delegateTemplate
380                     	String ruleTemplateId = KEWServiceLocator.getRuleTemplateService().getNextRuleTemplateId();
381                         rt.setId(ruleTemplateId);
382                         delegateTemplate = rt;
383                         break;
384                     }
385                 }
386             }
387 
388             if (delegateTemplate == null) {
389                 throw new XmlException("Cannot find delegation template " + delegateTemplateName);
390             }
391 
392             updatedRuleTemplate.setDelegationTemplateId(delegateTemplate.getDelegationTemplateId());
393             updatedRuleTemplate.setDelegationTemplate(delegateTemplate);           
394         } else {
395             // the previously referenced template is left in the system
396         }
397     }
398 
399     /**
400      * Updates the attributes set on the RuleTemplate
401      * @param ruleTemplateElement the XML ruleTemplate element
402      * @param updatedRuleTemplate the RuleTemplate being updated
403      * @throws XmlException if there was a problem parsing the rule template attributes
404      */
405     protected void updateRuleTemplateAttributes(Element ruleTemplateElement, RuleTemplateBo updatedRuleTemplate) throws XmlException {
406         // add any newly defined rule template attributes to the rule template,
407         // update the active and required flags of any existing ones.
408         // if this is an update of an existing rule template, related attribute objects will be present in this rule template object,
409         // otherwise none will be present (so they'll all be new)
410 
411         Element attributesElement = ruleTemplateElement.getChild(ATTRIBUTES, RULE_TEMPLATE_NAMESPACE);
412         List<RuleTemplateAttributeBo> incomingAttributes = new ArrayList<RuleTemplateAttributeBo>();
413         if (attributesElement != null) {
414             incomingAttributes.addAll(parseRuleTemplateAttributes(attributesElement, updatedRuleTemplate));
415         }
416 
417         // inactivate all current attributes
418         for (RuleTemplateAttributeBo currentRuleTemplateAttribute: updatedRuleTemplate.getRuleTemplateAttributes()) {
419             String ruleAttributeName = (currentRuleTemplateAttribute.getRuleAttribute() != null) ? currentRuleTemplateAttribute.getRuleAttribute().getName() : "(null)";
420             LOG.debug("Inactivating rule template attribute with id " + currentRuleTemplateAttribute.getId() + " and rule attribute with name " + ruleAttributeName);
421             currentRuleTemplateAttribute.setActive(Boolean.FALSE);
422         }
423         // NOTE: attributes are deactivated, not removed
424 
425         // add/update any new attributes
426         for (RuleTemplateAttributeBo ruleTemplateAttribute: incomingAttributes) {
427             RuleTemplateAttributeBo potentialExistingTemplateAttribute = updatedRuleTemplate.getRuleTemplateAttribute(ruleTemplateAttribute);
428             if (potentialExistingTemplateAttribute != null) {
429                 // template attribute exists on rule template already; update the options
430                 potentialExistingTemplateAttribute.setActive(ruleTemplateAttribute.getActive());
431                 potentialExistingTemplateAttribute.setRequired(ruleTemplateAttribute.getRequired());
432             } else {
433                 // template attribute does not yet exist on template so add it
434                 updatedRuleTemplate.getRuleTemplateAttributes().add(ruleTemplateAttribute);
435             }
436         }
437     }
438 
439     /**
440      * Parses the RuleTemplateAttributes defined on the rule template element
441      * @param attributesElement the jdom Element object for the Rule Template attributes
442      * @param ruleTemplate the RuleTemplate object
443      * @return the RuleTemplateAttributes defined on the rule template element
444      * @throws XmlException
445      */
446     private List<RuleTemplateAttributeBo> parseRuleTemplateAttributes(Element attributesElement, RuleTemplateBo ruleTemplate) throws XmlException {
447         List<RuleTemplateAttributeBo> ruleTemplateAttributes = new ArrayList<RuleTemplateAttributeBo>();
448         Collection<Element> attributeElements = XmlHelper.findElements(attributesElement, ATTRIBUTE);
449         for (Iterator iterator = attributeElements.iterator(); iterator.hasNext();) {
450             ruleTemplateAttributes.add(parseRuleTemplateAttribute((Element) iterator.next(), ruleTemplate));
451         }
452         return ruleTemplateAttributes;
453     }
454 
455     /**
456      * Parses a rule template attribute
457      * @param element the attribute XML element
458      * @param ruleTemplate the ruleTemplate to update
459      * @return a parsed rule template attribute
460      * @throws XmlException if the attribute does not exist
461      */
462     private RuleTemplateAttributeBo parseRuleTemplateAttribute(Element element, RuleTemplateBo ruleTemplate) throws XmlException {
463         String attributeName = element.getChildText(NAME, RULE_TEMPLATE_NAMESPACE);
464         String requiredValue = element.getChildText(REQUIRED, RULE_TEMPLATE_NAMESPACE);
465         String activeValue = element.getChildText(ACTIVE, RULE_TEMPLATE_NAMESPACE);
466         if (org.apache.commons.lang.StringUtils.isEmpty(attributeName)) {
467             throw new XmlException("Attribute name must be non-empty");
468         }
469         boolean required = DEFAULT_ATTRIBUTE_REQUIRED;
470         if (requiredValue != null) {
471             required = Boolean.parseBoolean(requiredValue);
472         }
473         boolean active = DEFAULT_ATTRIBUTE_ACTIVE;
474         if (activeValue != null) {
475             active = Boolean.parseBoolean(activeValue);
476         }
477         RuleAttribute ruleAttribute = KEWServiceLocator.getRuleAttributeService().findByName(attributeName);
478         if (ruleAttribute == null) {
479             throw new XmlException("Could not locate rule attribute for name '" + attributeName + "'");
480         }
481         RuleTemplateAttributeBo templateAttribute = new RuleTemplateAttributeBo();
482         templateAttribute.setRuleAttribute(ruleAttribute);
483         templateAttribute.setRuleAttributeId(ruleAttribute.getId());
484         templateAttribute.setRuleTemplate(ruleTemplate);
485         templateAttribute.setRequired(Boolean.valueOf(required));
486         templateAttribute.setActive(Boolean.valueOf(active));
487         templateAttribute.setDisplayOrder(new Integer(templateAttributeCounter++));
488         return templateAttribute;
489     }
490     
491     public Timestamp formatDate(String dateLabel, String dateString) throws XmlException {
492     	if (StringUtils.isBlank(dateString)) {
493     		return null;
494     	}
495     	try {
496     		return new Timestamp(RiceConstants.getDefaultDateFormat().parse(dateString).getTime());
497     	} catch (ParseException e) {
498     		throw new XmlException(dateLabel + " is not in the proper format.  Should have been: " + RiceConstants.DEFAULT_DATE_FORMAT_PATTERN);
499     	}
500     }
501 
502 }