/**
  * Updates or deletes a specified rule template option on the rule template
  *
  * @param updatedRuleTemplate the RuleTemplate being updated
  * @param key the option key
  * @param value the option value
  */
 protected void updateOrDeleteRuleTemplateOption(
     RuleTemplateBo updatedRuleTemplate, String key, Object value) {
   if (value != null) {
     // if the option exists and the incoming value is non-null (it's set), update it
     RuleTemplateOptionBo option = updatedRuleTemplate.getRuleTemplateOption(key);
     if (option != null) {
       option.setValue(value.toString());
     } else {
       updatedRuleTemplate
           .getRuleTemplateOptions()
           .add(new RuleTemplateOptionBo(key, value.toString()));
     }
   } else {
     // otherwise if the incoming value IS null (not set), then explicitly remove the entry (if it
     // exists)
     Iterator<RuleTemplateOptionBo> options =
         updatedRuleTemplate.getRuleTemplateOptions().iterator();
     while (options.hasNext()) {
       RuleTemplateOptionBo opt = options.next();
       if (key.equals(opt.getCode())) {
         options.remove();
         break;
       }
     }
   }
 }
  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;
  }
 private void exportRuleTemplate(Element parent, RuleTemplateBo ruleTemplate) {
   Element templateElement = renderer.renderElement(parent, RULE_TEMPLATE);
   renderer.renderTextElement(templateElement, NAME, ruleTemplate.getName());
   renderer.renderTextElement(templateElement, DESCRIPTION, ruleTemplate.getDescription());
   if (ruleTemplate.getDelegationTemplate() != null) {
     renderer.renderTextElement(
         templateElement, DELEGATION_TEMPLATE, ruleTemplate.getDelegationTemplate().getName());
   }
   exportAttributes(templateElement, ruleTemplate.getActiveRuleTemplateAttributes());
   exportDefaults(templateElement, ruleTemplate);
 }
  protected boolean validateCreateDelegateRule(DelegateRuleForm form) {
    if (form.getParentRule() == null) {
      GlobalVariables.getMessageMap().putError(PARENT_RULE_PROPERTY, PARENT_RULE_ERROR);
    } else {
      RuleTemplateBo ruleTemplate = form.getParentRule().getRuleTemplate();
      if (ruleTemplate == null || ruleTemplate.getDelegationTemplate() == null) {
        GlobalVariables.getMessageMap().putError(PARENT_RULE_PROPERTY, DELEGATE_RULE_INVALID_ERROR);
      }
    }
    if (form.getParentResponsibility() == null) {
      GlobalVariables.getMessageMap()
          .putError(PARENT_RESPONSIBILITY_PROPERTY, PARENT_RESPONSIBILITY_ERROR);
    }

    return GlobalVariables.getMessageMap().hasNoErrors();
  }
  /**
   * Updates the attributes set on the RuleTemplate
   *
   * @param ruleTemplateElement the XML ruleTemplate element
   * @param updatedRuleTemplate the RuleTemplate being updated
   * @throws XmlException if there was a problem parsing the rule template attributes
   */
  protected void updateRuleTemplateAttributes(
      Element ruleTemplateElement, RuleTemplateBo updatedRuleTemplate) throws XmlException {
    // add any newly defined rule template attributes to the rule template,
    // update the active and required flags of any existing ones.
    // if this is an update of an existing rule template, related attribute objects will be present
    // in this rule template object,
    // otherwise none will be present (so they'll all be new)

    Element attributesElement = ruleTemplateElement.getChild(ATTRIBUTES, RULE_TEMPLATE_NAMESPACE);
    List<RuleTemplateAttributeBo> incomingAttributes = new ArrayList<RuleTemplateAttributeBo>();
    if (attributesElement != null) {
      incomingAttributes.addAll(
          parseRuleTemplateAttributes(attributesElement, updatedRuleTemplate));
    }

    // inactivate all current attributes
    for (RuleTemplateAttributeBo currentRuleTemplateAttribute :
        updatedRuleTemplate.getRuleTemplateAttributes()) {
      String ruleAttributeName =
          (currentRuleTemplateAttribute.getRuleAttribute() != null)
              ? currentRuleTemplateAttribute.getRuleAttribute().getName()
              : "(null)";
      LOG.debug(
          "Inactivating rule template attribute with id "
              + currentRuleTemplateAttribute.getId()
              + " and rule attribute with name "
              + ruleAttributeName);
      currentRuleTemplateAttribute.setActive(Boolean.FALSE);
    }
    // NOTE: attributes are deactivated, not removed

    // add/update any new attributes
    for (RuleTemplateAttributeBo ruleTemplateAttribute : incomingAttributes) {
      RuleTemplateAttributeBo potentialExistingTemplateAttribute =
          updatedRuleTemplate.getRuleTemplateAttribute(ruleTemplateAttribute);
      if (potentialExistingTemplateAttribute != null) {
        // template attribute exists on rule template already; update the options
        potentialExistingTemplateAttribute.setActive(ruleTemplateAttribute.getActive());
        potentialExistingTemplateAttribute.setRequired(ruleTemplateAttribute.getRequired());
      } else {
        // template attribute does not yet exist on template so add it
        ruleTemplateAttribute.setRuleTemplate(updatedRuleTemplate);
        updatedRuleTemplate.getRuleTemplateAttributes().add(ruleTemplateAttribute);
      }
    }
  }
  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);
    }
  }
 private void exportDefaults(Element parent, RuleTemplateBo ruleTemplate) {
   RuleBaseValues defaultRuleValues =
       KEWServiceLocator.getRuleService().findDefaultRuleByRuleTemplateId(ruleTemplate.getId());
   if (defaultRuleValues != null) {
     RuleDelegationBo defaultDelegationValues = getDefaultDelegationValues(defaultRuleValues);
     Element defaultsElement = renderer.renderElement(parent, RULE_DEFAULTS);
     if (defaultDelegationValues != null) {
       renderer.renderTextElement(
           defaultsElement,
           DELEGATION_TYPE,
           defaultDelegationValues.getDelegationType().getCode());
     }
     renderer.renderTextElement(defaultsElement, DESCRIPTION, defaultRuleValues.getDescription());
     if (defaultRuleValues.getFromDateValue() != null) {
       renderer.renderDateElement(
           defaultsElement, FROM_DATE, defaultRuleValues.getFromDateValue());
     }
     if (defaultRuleValues.getToDateValue() != null) {
       renderer.renderDateElement(defaultsElement, TO_DATE, defaultRuleValues.getToDateValue());
     }
     renderer.renderBooleanElement(
         defaultsElement, FORCE_ACTION, defaultRuleValues.isForceAction(), false);
     renderer.renderBooleanElement(defaultsElement, ACTIVE, defaultRuleValues.isActive(), true);
     if (defaultDelegationValues == null) {
       RuleTemplateOptionBo defaultActionOption = ruleTemplate.getDefaultActionRequestValue();
       RuleTemplateOptionBo supportsComplete = ruleTemplate.getComplete();
       RuleTemplateOptionBo supportsApprove = ruleTemplate.getApprove();
       RuleTemplateOptionBo supportsAck = ruleTemplate.getAcknowledge();
       RuleTemplateOptionBo supportsFYI = ruleTemplate.getFyi();
       if (defaultActionOption != null) {
         String defaultActionValue =
             (defaultActionOption == null ? null : defaultActionOption.getValue());
         renderer.renderTextElement(defaultsElement, DEFAULT_ACTION_REQUESTED, defaultActionValue);
       }
       if (supportsComplete != null) {
         String supportsCompleteValue = supportsComplete.getValue();
         renderer.renderTextElement(defaultsElement, SUPPORTS_COMPLETE, supportsCompleteValue);
       }
       if (supportsApprove != null) {
         String supportsApproveValue = supportsApprove.getValue();
         renderer.renderTextElement(defaultsElement, SUPPORTS_APPROVE, supportsApproveValue);
       }
       if (supportsAck != null) {
         String supportsAckValue = supportsAck.getValue();
         renderer.renderTextElement(defaultsElement, SUPPORTS_ACKNOWLEDGE, supportsAckValue);
       }
       if (supportsFYI != null) {
         String supportsFYIValue = supportsFYI.getValue();
         renderer.renderTextElement(defaultsElement, SUPPORTS_FYI, supportsFYIValue);
       }
     }
   }
 }
  /**
   * 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
    }
  }
  /**
   * 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;
  }
  /**
   * Updates the rule template defaults options with those in the defaults element
   *
   * @param defaultsElement the ruleDefaults element
   * @param updatedRuleTemplate the Rule Template being updated
   */
  protected void updateRuleTemplateOptions(
      Element defaultsElement, RuleTemplateBo updatedRuleTemplate, boolean isDelegation)
      throws XmlException {
    // the possible defaults options
    // NOTE: the current implementation will remove any existing RuleTemplateOption records for any
    // values which are null, i.e. not set in the incoming XML.
    // to pro-actively set default values for omitted options, simply set those values here, and
    // records will be added if not present
    String defaultActionRequested = null;
    Boolean supportsComplete = null;
    Boolean supportsApprove = null;
    Boolean supportsAcknowledge = null;
    Boolean supportsFYI = null;

    // remove any RuleTemplateOptions the template may have but that we know we aren't going to
    // update/reset
    // (not sure if this case even exists...does anything else set rule template options?)
    updatedRuleTemplate.removeNonDefaultOptions();

    // read in new settings
    if (defaultsElement != null) {

      defaultActionRequested =
          defaultsElement.getChildText(DEFAULT_ACTION_REQUESTED, RULE_TEMPLATE_NAMESPACE);
      supportsComplete =
          BooleanUtils.toBooleanObject(
              defaultsElement.getChildText(SUPPORTS_COMPLETE, RULE_TEMPLATE_NAMESPACE));
      supportsApprove =
          BooleanUtils.toBooleanObject(
              defaultsElement.getChildText(SUPPORTS_APPROVE, RULE_TEMPLATE_NAMESPACE));
      supportsAcknowledge =
          BooleanUtils.toBooleanObject(
              defaultsElement.getChildText(SUPPORTS_ACKNOWLEDGE, RULE_TEMPLATE_NAMESPACE));
      supportsFYI =
          BooleanUtils.toBooleanObject(
              defaultsElement.getChildText(SUPPORTS_FYI, RULE_TEMPLATE_NAMESPACE));
    }

    if (!isDelegation) {
      // if this is not a delegation template, store the template options that govern rule action
      // constraints
      // in the RuleTemplateOptions of the template
      // we have two options for this behavior:
      // 1) conditionally parse above, and then unconditionally set/unset the properties; this will
      // have the effect of REMOVING
      //    any of these previously specified rule template options (and is arguably the right thing
      // to do)
      // 2) unconditionally parse above, and then conditionally set/unset the properties; this will
      // have the effect of PRESERVING
      //    the existing rule template options on this template if it is a delegation template
      // (which of course will be overwritten
      //    by this very same code if they subsequently upload without the delegation flag)
      // This is a minor point, but the second implementation is chosen as it preserved the current
      // behavior
      updateOrDeleteRuleTemplateOption(
          updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_DEFAULT_CD, defaultActionRequested);
      updateOrDeleteRuleTemplateOption(
          updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, supportsApprove);
      updateOrDeleteRuleTemplateOption(
          updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, supportsAcknowledge);
      updateOrDeleteRuleTemplateOption(
          updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_FYI_REQ, supportsFYI);
      updateOrDeleteRuleTemplateOption(
          updatedRuleTemplate, KewApiConstants.ACTION_REQUEST_COMPLETE_REQ, supportsComplete);
    }
  }
 private void assertRuleTemplateExport(
     RuleTemplateBo oldRuleTemplate, RuleTemplateBo newRuleTemplate) {
   assertFalse(
       "Ids should be different.", oldRuleTemplate.getId().equals(newRuleTemplate.getId()));
   assertEquals(oldRuleTemplate.getDescription(), newRuleTemplate.getDescription());
   assertEquals(oldRuleTemplate.getName(), newRuleTemplate.getName());
   if (oldRuleTemplate.getDelegationTemplate() != null) {
     assertRuleTemplateExport(
         oldRuleTemplate.getDelegationTemplate(), newRuleTemplate.getDelegationTemplate());
   } else {
     assertNull(newRuleTemplate.getDelegationTemplate());
   }
   assertAttributes(
       oldRuleTemplate.getRuleTemplateAttributes(),
       newRuleTemplate.getRuleTemplateAttributes(),
       "attribute");
   assertAttributes(
       oldRuleTemplate.getActiveRuleTemplateAttributes(),
       newRuleTemplate.getActiveRuleTemplateAttributes(),
       "active attribute");
   assertOptions(
       oldRuleTemplate.getRuleTemplateOptions(), newRuleTemplate.getRuleTemplateOptions());
 }