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