@Override
  public void setProtocolStatus(
      Protocol protocol,
      ProtocolStatusEnum protocolStatusEnum,
      User user,
      Committee committee,
      String note) {
    try {
      ProtocolStatus protocolStatus = new ProtocolStatus();
      protocolStatus.setCauseByUser(user);
      protocolStatus.setCausedByCommittee(committee);
      protocolStatus.setModified(new Date());
      protocolStatus.setNote(note);
      protocolStatus.setProtocol(protocol);
      protocolStatus.setProtocolStatus(protocolStatusEnum);
      protocolStatus.setRetired(Boolean.FALSE);

      protocolStatusDao.saveOrUpdate(protocolStatus);

      String protocolMetaDataXml = protocol.getMetaDataXml();

      protocolMetaDataXml =
          xmlProcessor.replaceOrAddNodeValueByPath(
              "/protocol/status",
              protocolMetaDataXml,
              org.apache.commons.lang.StringEscapeUtils.escapeXml(
                  protocolStatusEnum.getDescription()));

      Map<String, String> attributes = Maps.newHashMap();
      attributes.put("priority", protocolStatusEnum.getPriorityLevel());

      protocolMetaDataXml =
          xmlProcessor.addAttributesByPath("/protocol/status", protocolMetaDataXml, attributes);

      protocol.setMetaDataXml(protocolMetaDataXml);
      protocolDao.saveOrUpdate(protocol);

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  @Override
  public boolean isPushedToPSC(String protocolMetaData) {
    boolean isPushedToPSC = false;
    try {
      Document assertXml = xmlProcessor.loadXmlStringToDOM(protocolMetaData);

      XPath xpathInstance = xmlProcessor.getXPathInstance();

      isPushedToPSC =
          (Boolean)
              (xpathInstance.evaluate(
                  "boolean(count(/protocol/pushed-to-psc[text()='y'])>0)",
                  assertXml,
                  XPathConstants.BOOLEAN));

    } catch (Exception e) {
      // don't care
    }

    return isPushedToPSC;
  }
  @Override
  public void addPushedToEpic(Protocol protocol) {
    try {
      String protocolMetaData = protocol.getMetaDataXml();

      protocolMetaData =
          xmlProcessor.replaceOrAddNodeValueByPath(
              "/protocol/pushed-to-epic", protocolMetaData, "y");

      protocolMetaData =
          xmlProcessor.replaceOrAddNodeValueByPath(
              "/protocol/pushed-to-epic-date",
              protocolMetaData,
              DateFormatUtil.formateDateToMDY(new Date()));

      protocol.setMetaDataXml(protocolMetaData);

      protocol = protocolDao.saveOrUpdate(protocol);

    } catch (Exception e) {
      // don't care
    }
  }
  private boolean isReportableOrNot(ProtocolFormXmlData protocolXmlData) {
    boolean isReportableOrNot = false;

    try {
      List<String> values =
          xmlProcessor.listElementStringValuesByPath(
              "/reportable-new-information/is-reportable", protocolXmlData.getXmlData());

      if (values.size() > 0) {
        if (values.get(0).equals("y")) {
          isReportableOrNot = true;
        } else {
          isReportableOrNot = false;
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
      isReportableOrNot = false;
    }

    return isReportableOrNot;
  }
  @Override
  public Protocol consolidateProtocol(Protocol protocol, List<String> xPathList) {
    String protocolMetaData = protocol.getMetaDataXml();

    Map<String, Object> resultMap = Maps.newHashMap();

    for (String xPath : xPathList) {
      try {
        resultMap = xmlProcessor.deleteElementByPath(xPath, protocolMetaData);
      } catch (Exception e) {

      }

      if (resultMap != null && !resultMap.isEmpty())
        protocolMetaData = resultMap.get("finalXml").toString();
    }

    protocol.setMetaDataXml(protocolMetaData);

    protocol = protocolDao.saveOrUpdate(protocol);

    return protocol;
  }
  @Override
  public Map<String, Boolean> checkStudyCharacteristic(String protocolMetaData) {
    Map<String, Boolean> studyCharacteristicMap = Maps.newHashMap();

    String isAchStudyXpath =
        "boolean(count(/protocol/site-responsible[text()='ach-achri'])>0 or count(/protocol/study-sites/site[@site-id=\"2\" or @site-id=\"1\"])>0)";

    String isAchStudyWithDrugXpath =
        "boolean((count(/protocol/site-responsible[text()='ach-achri'])>0 or count(/protocol/study-sites/site[@site-id=\"2\" or @site-id=\"1\"])>0) and count(/protocol/drugs/drug)>0)";

    String isInvestigatorStudyPath =
        "boolean(count(/protocol/study-type[text()='investigator-initiated'])>0)";

    String isIndustryOrCoorpStudyPath =
        "boolean(count(/protocol/study-type[text()='cooperative-group'])>0 or count(/protocol/study-type[text()='industry-sponsored'])>0)";

    String isUamsStudyPath = "boolean(count(/protocol/site-responsible[text()='uams'])>0)";

    try {
      boolean isAchStudy = false;
      boolean isAchStudyWithDrug = false;

      boolean isInvestigatorStudy = false;
      boolean isIndustryOrCoorpStudy = false;

      boolean isUAMSStudy = false;

      Document assertXml = xmlProcessor.loadXmlStringToDOM(protocolMetaData);

      XPath xpathInstance = xmlProcessor.getXPathInstance();

      isAchStudy =
          (Boolean) (xpathInstance.evaluate(isAchStudyXpath, assertXml, XPathConstants.BOOLEAN));

      studyCharacteristicMap.put("isAchStudy", isAchStudy);

      xpathInstance.reset();

      isAchStudyWithDrug =
          (Boolean)
              (xpathInstance.evaluate(isAchStudyWithDrugXpath, assertXml, XPathConstants.BOOLEAN));

      studyCharacteristicMap.put("isAchStudyWithDrug", isAchStudyWithDrug);

      xpathInstance.reset();

      isInvestigatorStudy =
          (Boolean)
              (xpathInstance.evaluate(isInvestigatorStudyPath, assertXml, XPathConstants.BOOLEAN));

      studyCharacteristicMap.put("isInvestigatorStudy", isInvestigatorStudy);

      xpathInstance.reset();

      isIndustryOrCoorpStudy =
          (Boolean)
              (xpathInstance.evaluate(
                  isIndustryOrCoorpStudyPath, assertXml, XPathConstants.BOOLEAN));

      studyCharacteristicMap.put("isIndustryOrCoorpStudy", isIndustryOrCoorpStudy);

      xpathInstance.reset();

      isUAMSStudy =
          (Boolean) (xpathInstance.evaluate(isUamsStudyPath, assertXml, XPathConstants.BOOLEAN));

      studyCharacteristicMap.put("isUAMSStudy", isUAMSStudy);

    } catch (Exception e) {
      // don't care
    }

    return studyCharacteristicMap;
  }
  @RequestMapping(
      value =
          "/ajax/protocols/{protocolId}/protocol-forms/{protocolFormId}/reportable-new-information/protocol-form-xml-datas/{protocolFormXmlDataId}/validate",
      method = RequestMethod.GET)
  public @ResponseBody List<ValidationResponse> validateProtocolReportableNewInformationForm(
      @PathVariable("protocolFormXmlDataId") long protocolFormXmlDataId) {

    ProtocolFormXmlData protocolXmlData = protocolFormXmlDataDao.findById(protocolFormXmlDataId);

    String xmldata = protocolXmlData.getXmlData();

    List<ValidationResponse> validationResponses = new ArrayList<ValidationResponse>();
    if (StringUtils.hasText(xmldata)) {

      List<Rule> reportableNewInformationValidationRules =
          getValidationRuleContainer()
              .getValidationRules("reportableNewInformationValidationRules");

      Assert.notNull(reportableNewInformationValidationRules);

      Set<String> valueKeys =
          getValidationRuleContainer()
              .getCachedValueKeys("reportableNewInformationValidationRules");

      Assert.notNull(valueKeys);

      Map<String, List<String>> values = null;

      // setup values
      try {
        values = xmlProcessor.listElementStringValuesByPaths(valueKeys, xmldata);
      } catch (XPathExpressionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (SAXException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      validationResponses =
          validationRuleHandler.validate(reportableNewInformationValidationRules, values);
    }

    if (!isReportableOrNot(protocolXmlData)) {
      Constraint notReportableConstraint = new Constraint();
      Map<String, Object> notReportableAdditionalData = new HashMap<String, Object>();

      notReportableConstraint.setConstraintLevel(ConstraintLevel.ERROR);
      notReportableConstraint.setErrorMessage(
          "This event/information does not meet the criteria for an Unanticipated Problem Involving Risk "
              + "to Subjects or Others (UPIRTSO) and does not require immediate reporting to the IRB."
              + "<br/>"
              + "Please submit the information in summary format at Continuing Review."
              + "<br/>"
              + "A suggested summary format is available at:<a href=\"http://www.uams.edu/irb/Reporting%20Events%20and%20Deviations.asp\" target=\"_blank\">http://www.uams.edu/irb/Reporting%20Events%20and%20Deviations.asp</a>"
              + "<br/>"
              + "The IRB recommends that events be compiled throughout the year."
              + "<br/>"
              + "If you need to update documents now, please do so using a Modification.");

      notReportableAdditionalData.put("pagename", "Review");
      notReportableAdditionalData.put("pageref", "review");

      ValidationResponse budgetVP =
          new ValidationResponse(notReportableConstraint, notReportableAdditionalData);

      validationResponses.add(budgetVP);
    }

    return validationResponses;
  }