private RuleTemplateBo parseRuleTemplate(Element element, List<RuleTemplateBo> ruleTemplates)
      throws XmlException {
    String name = element.getChildText(NAME, RULE_TEMPLATE_NAMESPACE);
    String description = element.getChildText(DESCRIPTION, RULE_TEMPLATE_NAMESPACE);
    Attribute allowOverwriteAttrib = element.getAttribute("allowOverwrite");

    boolean allowOverwrite = false;
    if (allowOverwriteAttrib != null) {
      allowOverwrite = Boolean.valueOf(allowOverwriteAttrib.getValue()).booleanValue();
    }
    if (org.apache.commons.lang.StringUtils.isEmpty(name)) {
      throw new XmlException("RuleTemplate must have a name");
    }
    if (org.apache.commons.lang.StringUtils.isEmpty(description)) {
      throw new XmlException("RuleTemplate must have a description");
    }

    // look up the rule template by name first
    RuleTemplateBo ruleTemplate =
        KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(name);

    if (ruleTemplate == null) {
      // if it does not exist create a new one
      ruleTemplate = new RuleTemplateBo();
    } else {
      // if it does exist, update it, only if allowOverwrite is set
      if (!allowOverwrite) {
        throw new RuntimeException(
            "Attempting to overwrite template " + name + " without allowOverwrite set");
      }

      // the name should be equal if one was actually found
      assert (name.equals(ruleTemplate.getName()))
          : "Existing template definition name does not match incoming definition name";
    }

    // overwrite simple properties
    ruleTemplate.setName(name);
    ruleTemplate.setDescription(description);

    // update the delegation template
    updateDelegationTemplate(element, ruleTemplate, ruleTemplates);

    // update the attribute relationships
    updateRuleTemplateAttributes(element, ruleTemplate);

    // save the rule template first so that the default/template rule that is generated
    // in the process of setting defaults is associated properly with this rule template
    ruleTemplate = KEWServiceLocator.getRuleTemplateService().save(ruleTemplate);

    // update the default options
    updateRuleTemplateDefaultOptions(element, ruleTemplate);

    ruleTemplate = KEWServiceLocator.getRuleTemplateService().save(ruleTemplate);

    return ruleTemplate;
  }
  /**
   * Note that the assertion here will fail if you have multiple rules with the same description.
   */
  protected void assertExport() throws Exception {
    // export all existing rules and their dependencies (document types, rule templates, rule
    // attributes)
    List oldRules = KEWServiceLocator.getRuleService().fetchAllRules(true);
    assertAllRulesHaveUniqueNames(oldRules);
    List oldRuleDelegations =
        KEWServiceLocator.getRuleDelegationService().findAllCurrentRuleDelegations();
    assertAllRuleDelegationsHaveUniqueNames(oldRuleDelegations);

    KewExportDataSet dataSet = new KewExportDataSet();
    dataSet.getRules().addAll(oldRules);
    dataSet.getRuleDelegations().addAll(oldRuleDelegations);
    dataSet.getDocumentTypes().addAll(KEWServiceLocator.getDocumentTypeService().findAllCurrent());
    dataSet.getRuleTemplates().addAll(KEWServiceLocator.getRuleTemplateService().findAll());
    dataSet.getRuleAttributes().addAll(KEWServiceLocator.getRuleAttributeService().findAll());
    byte[] xmlBytes =
        CoreApiServiceLocator.getXmlExporterService().export(dataSet.createExportDataSet());
    assertTrue("XML should be non empty.", xmlBytes != null && xmlBytes.length > 0);

    // now clear the tables
    ClearDatabaseLifecycle clearLifeCycle = new ClearDatabaseLifecycle();
    clearLifeCycle.getTablesToClear().add("KREW_RULE_T");
    clearLifeCycle.getTablesToClear().add("KREW_RULE_RSP_T");
    clearLifeCycle.getTablesToClear().add("KREW_DLGN_RSP_T");
    clearLifeCycle.getTablesToClear().add("KREW_RULE_ATTR_T");
    clearLifeCycle.getTablesToClear().add("KREW_RULE_TMPL_T");
    clearLifeCycle.getTablesToClear().add("KREW_DOC_TYP_T");
    clearLifeCycle.start();
    new ClearCacheLifecycle().stop();

    // import the exported xml
    loadXmlStream(new BufferedInputStream(new ByteArrayInputStream(xmlBytes)));

    List newRules = KEWServiceLocator.getRuleService().fetchAllRules(true);
    assertEquals("Should have same number of old and new Rules.", oldRules.size(), newRules.size());
    for (Iterator iterator = oldRules.iterator(); iterator.hasNext(); ) {
      RuleBaseValues oldRule = (RuleBaseValues) iterator.next();
      boolean foundRule = false;
      for (Iterator iterator2 = newRules.iterator(); iterator2.hasNext(); ) {
        RuleBaseValues newRule = (RuleBaseValues) iterator2.next();
        if (oldRule.getDescription().equals(newRule.getDescription())) {
          assertRuleExport(oldRule, newRule);
          foundRule = true;
        }
      }
      assertTrue(
          "Could not locate the new rule for description " + oldRule.getDescription(), foundRule);
    }

    List newRuleDelegations =
        KEWServiceLocator.getRuleDelegationService().findAllCurrentRuleDelegations();
    assertDelegations(oldRuleDelegations, newRuleDelegations);
  }
  /**
   * Updates the rule template delegation template with the one specified in the XML (if any)
   *
   * @param ruleTemplateElement the XML ruleTemplate element
   * @param updatedRuleTemplate the rule template to update
   * @param parsedRuleTemplates the rule templates parsed in this parsing run
   * @throws XmlException if a delegation template was specified but could not be found
   */
  protected void updateDelegationTemplate(
      Element ruleTemplateElement,
      RuleTemplateBo updatedRuleTemplate,
      List<RuleTemplateBo> parsedRuleTemplates)
      throws XmlException {
    String delegateTemplateName =
        ruleTemplateElement.getChildText(DELEGATION_TEMPLATE, RULE_TEMPLATE_NAMESPACE);

    if (delegateTemplateName != null) {
      // if a delegateTemplate was set in the XML, then look it up and set it on the RuleTemplate
      // object
      // first try looking up an existing delegateTemplate in the system
      RuleTemplateBo delegateTemplate =
          KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(delegateTemplateName);

      // if not found, try the list of templates currently parsed
      if (delegateTemplate == null) {
        for (RuleTemplateBo rt : parsedRuleTemplates) {
          if (delegateTemplateName.equalsIgnoreCase(rt.getName())) {
            // set the expected next rule template id on the target delegateTemplate
            String ruleTemplateId =
                KEWServiceLocator.getRuleTemplateService().getNextRuleTemplateId();
            rt.setId(ruleTemplateId);
            delegateTemplate = rt;
            break;
          }
        }
      }

      if (delegateTemplate == null) {
        throw new XmlException("Cannot find delegation template " + delegateTemplateName);
      }

      updatedRuleTemplate.setDelegationTemplateId(delegateTemplate.getDelegationTemplateId());
      updatedRuleTemplate.setDelegationTemplate(delegateTemplate);
    } else {
      // the previously referenced template is left in the system
    }
  }
  protected void assertExport() throws Exception {
    // export all existing rule templates and their dependencies (rule attributes)
    List oldRuleTemplates = KEWServiceLocator.getRuleTemplateService().findAll();
    KewExportDataSet dataSet = new KewExportDataSet();
    dataSet.getRuleTemplates().addAll(oldRuleTemplates);
    dataSet.getRuleAttributes().addAll(KEWServiceLocator.getRuleAttributeService().findAll());
    byte[] xmlBytes =
        CoreApiServiceLocator.getXmlExporterService().export(dataSet.createExportDataSet());
    assertTrue("XML should be non empty.", xmlBytes != null && xmlBytes.length > 0);

    // now clear the tables
    new ClearDatabaseLifecycle(getPerTestTablesToClear(), getPerTestTablesNotToClear()).start();

    // import the exported xml
    loadXmlStream(new BufferedInputStream(new ByteArrayInputStream(xmlBytes)));

    List newRuleTemplates = KEWServiceLocator.getRuleTemplateService().findAll();
    assertEquals(
        "Should have same number of old and new RuleTemplates.",
        oldRuleTemplates.size(),
        newRuleTemplates.size());
    for (Iterator iterator = oldRuleTemplates.iterator(); iterator.hasNext(); ) {
      RuleTemplateBo oldRuleTemplate = (RuleTemplateBo) iterator.next();
      boolean foundTemplate = false;
      for (Iterator iterator2 = newRuleTemplates.iterator(); iterator2.hasNext(); ) {
        RuleTemplateBo newRuleTemplate = (RuleTemplateBo) iterator2.next();
        if (oldRuleTemplate.getName().equals(newRuleTemplate.getName())) {
          assertRuleTemplateExport(oldRuleTemplate, newRuleTemplate);
          foundTemplate = true;
        }
      }
      assertTrue(
          "Could not locate the new rule template for name " + oldRuleTemplate.getName(),
          foundTemplate);
    }
  }
 /**
  * Creates a KualiMaintenanceForm with the given rule template inside of its RuleBaseValues
  * instance.
  *
  * @param rtName The rule template to use.
  */
 private void createNewKualiMaintenanceForm(String rtName) {
   // Initialize the required variables.
   final KualiMaintenanceForm kmForm = new KualiMaintenanceForm();
   final MaintenanceDocument maintDoc = new MaintenanceDocumentBase();
   final Maintainable oldMaint = new RoutingRuleMaintainable();
   final Maintainable newMaint = new RoutingRuleMaintainable();
   final RuleBaseValues rbValues = new RuleBaseValues();
   // Setup the rule base and the maintainables.
   rbValues.setRuleTemplate(
       KEWServiceLocator.getRuleTemplateService().findByRuleTemplateName(rtName));
   oldMaint.setBusinessObject(rbValues);
   oldMaint.setBoClass(rbValues.getClass());
   newMaint.setBusinessObject(rbValues);
   newMaint.setBoClass(rbValues.getClass());
   // Setup the maintenance document and the maintenance form.
   maintDoc.setOldMaintainableObject(oldMaint);
   maintDoc.setNewMaintainableObject(newMaint);
   maintDoc.getDocumentHeader().setDocumentDescription("This is a rule template test");
   kmForm.setDocument(maintDoc);
   KNSGlobalVariables.setKualiForm(kmForm);
 }
  /**
   * Updates the default/template rule options with those in the defaults element
   *
   * @param defaultsElement the ruleDefaults element
   * @param updatedRuleTemplate the Rule Template being updated
   * @return whether this is a delegation rule template
   */
  protected boolean updateRuleDefaults(Element defaultsElement, RuleTemplateBo updatedRuleTemplate)
      throws XmlException {
    // NOTE: implementation detail: in contrast with the other options, the delegate template, and
    // the rule attributes,
    // we unconditionally blow away the default rule and re-create it (we don't update the existing
    // one, if there is one)
    if (updatedRuleTemplate.getId() != null) {
      RuleBaseValues ruleDefaults =
          KEWServiceLocator.getRuleService()
              .findDefaultRuleByRuleTemplateId(updatedRuleTemplate.getId());
      if (ruleDefaults != null) {
        List ruleDelegationDefaults =
            KEWServiceLocator.getRuleDelegationService().findByDelegateRuleId(ruleDefaults.getId());
        // delete the rule
        KEWServiceLocator.getRuleService().delete(ruleDefaults.getId());
        // delete the associated rule delegation defaults
        for (Iterator iterator = ruleDelegationDefaults.iterator(); iterator.hasNext(); ) {
          RuleDelegationBo ruleDelegation = (RuleDelegationBo) iterator.next();
          KEWServiceLocator.getRuleDelegationService().delete(ruleDelegation.getRuleDelegationId());
        }
      }
    }

    boolean isDelegation = false;

    if (defaultsElement != null) {
      String delegationTypeCode =
          defaultsElement.getChildText(DELEGATION_TYPE, RULE_TEMPLATE_NAMESPACE);
      DelegationType delegationType = null;
      isDelegation = !org.apache.commons.lang.StringUtils.isEmpty(delegationTypeCode);

      String description = defaultsElement.getChildText(DESCRIPTION, RULE_TEMPLATE_NAMESPACE);

      // would normally be validated via schema but might not be present if invoking RuleXmlParser
      // directly
      if (description == null) {
        throw new XmlException("Description must be specified in rule defaults");
      }

      String fromDate = defaultsElement.getChildText(FROM_DATE, RULE_TEMPLATE_NAMESPACE);
      String toDate = defaultsElement.getChildText(TO_DATE, RULE_TEMPLATE_NAMESPACE);
      // toBooleanObject ensures that if the value is null (not set) that the Boolean object will
      // likewise be null (will not default to a value)
      Boolean forceAction =
          BooleanUtils.toBooleanObject(
              defaultsElement.getChildText(FORCE_ACTION, RULE_TEMPLATE_NAMESPACE));
      Boolean active =
          BooleanUtils.toBooleanObject(
              defaultsElement.getChildText(ACTIVE, RULE_TEMPLATE_NAMESPACE));

      if (isDelegation) {
        delegationType = DelegationType.parseCode(delegationTypeCode);
        if (delegationType == null) {
          throw new XmlException(
              "Invalid delegation type '"
                  + delegationType
                  + "'."
                  + "  Expected one of: "
                  + DelegationType.PRIMARY.getCode()
                  + ","
                  + DelegationType.SECONDARY.getCode());
        }
      }

      // create our "default rule" which encapsulates the defaults for the rule
      RuleBaseValues ruleDefaults = new RuleBaseValues();

      // set simple values
      ruleDefaults.setRuleTemplate(updatedRuleTemplate);
      ruleDefaults.setRuleTemplateId(updatedRuleTemplate.getId());
      ruleDefaults.setDocTypeName(DUMMY_DOCUMENT_TYPE);
      ruleDefaults.setTemplateRuleInd(Boolean.TRUE);
      ruleDefaults.setCurrentInd(Boolean.TRUE);
      ruleDefaults.setVersionNbr(new Integer(0));
      ruleDefaults.setDescription(description);

      // these are non-nullable fields, so default them if they were not set in the defaults section
      ruleDefaults.setForceAction(Boolean.valueOf(BooleanUtils.isTrue(forceAction)));
      ruleDefaults.setActive(Boolean.valueOf(BooleanUtils.isTrue(active)));

      if (ruleDefaults.getActivationDate() == null) {
        ruleDefaults.setActivationDate(new Timestamp(System.currentTimeMillis()));
      }

      ruleDefaults.setFromDateValue(formatDate("fromDate", fromDate));
      ruleDefaults.setToDateValue(formatDate("toDate", toDate));

      // ok, if this is a "Delegate Template", then we need to set this other RuleDelegation object
      // which contains
      // some delegation-related info
      RuleDelegationBo ruleDelegationDefaults = null;
      if (isDelegation) {
        ruleDelegationDefaults = new RuleDelegationBo();
        ruleDelegationDefaults.setDelegationRule(ruleDefaults);
        ruleDelegationDefaults.setDelegationType(delegationType);
        ruleDelegationDefaults.setResponsibilityId(KewApiConstants.ADHOC_REQUEST_RESPONSIBILITY_ID);
      }

      // explicitly save the new rule delegation defaults and default rule
      KEWServiceLocator.getRuleTemplateService()
          .saveRuleDefaults(ruleDelegationDefaults, ruleDefaults);
    } else {
      // do nothing, rule defaults will be deleted if ruleDefaults element is omitted
    }

    return isDelegation;
  }