public DocQueryAcknowledgementType crossGatewayQueryRequest(
      RespondingGatewayCrossGatewayQuerySecuredRequestType crossGatewayQueryRequest,
      WebServiceContext context) {
    getLogger()
        .debug("Beginning of PassthruDocQueryDeferredRequestSecured.crossGatewayQueryRequest()");

    AssertionType assertion = extractAssertion(context);

    // Extract the message id value from the WS-Addressing Header and place it in the Assertion
    // Class
    if (assertion != null) {
      assertion.setMessageId(getAsyncMessageIdExtractor().GetAsyncMessageId(context));
    }

    // Fwd request to orchestrator
    DocQueryAcknowledgementType ackResponse =
        getPassthruDocQueryDeferredRequestOrchImpl()
            .crossGatewayQueryRequest(
                crossGatewayQueryRequest.getAdhocQueryRequest(),
                assertion,
                crossGatewayQueryRequest.getNhinTargetSystem());

    getLogger().debug("End of PassthruDocQueryDeferredRequestSecured.crossGatewayQueryRequest()");

    return ackResponse;
  }
  public MCCIIN000002UV01 processPatientDiscoveryAsyncReqError(
      PRPAIN201305UV02 request, PRPAIN201306UV02 response, AssertionType assertion, String errMsg) {
    MCCIIN000002UV01 ack = HL7AckTransforms.createAckErrorFrom201305(request, errMsg);

    AsyncMessageProcessHelper asyncProcess = createAsyncProcesser();

    // Add a new inbound PD request entry to the local deferred queue
    boolean bIsQueueOk =
        asyncProcess.addPatientDiscoveryRequest(
            request, assertion, AsyncMsgRecordDao.QUEUE_DIRECTION_INBOUND);

    // check for valid queue entry
    if (bIsQueueOk) {
      bIsQueueOk =
          asyncProcess.processAck(
              assertion.getMessageId(),
              AsyncMsgRecordDao.QUEUE_STATUS_REQRCVDERR,
              AsyncMsgRecordDao.QUEUE_STATUS_REQRCVDERR,
              ack);
    } else {
      String ackMsg =
          "Deferred Patient Discovery processing halted; deferred queue repository error encountered; "
              + errMsg;

      // Set the error acknowledgement status
      // fatal error with deferred queue repository
      ack = HL7AckTransforms.createAckErrorFrom201305(request, ackMsg);
    }

    return ack;
  }
  private boolean isPolicyValid(
      RespondingGatewayProvideAndRegisterDocumentSetSecuredRequestType request,
      AssertionType assertion) {
    boolean isValid = false;

    if (hasNhinTargetHomeCommunityId(request)) {
      String senderHCID =
          getSubjectHelper()
              .determineSendingHomeCommunityId(assertion.getHomeCommunity(), assertion);
      String receiverHCID = getNhinTargetHomeCommunityId(request);
      LOG.debug("Receiving home community id: " + receiverHCID);
      isValid =
          getXDRPolicyChecker()
              .checkXDRRequestPolicy(
                  request.getProvideAndRegisterDocumentSetRequest(),
                  assertion,
                  senderHCID,
                  receiverHCID,
                  NhincConstants.POLICYENGINE_OUTBOUND_DIRECTION);
    } else {
      LOG.warn(
          "Check on policy requires a non null target home community ID specified in the request");
    }
    LOG.debug("Check on policy returns: " + isValid);

    return isValid;
  }
  protected MCCIIN000002UV01 addPatientDiscoveryAsyncReq(
      RespondingGatewayPRPAIN201305UV02RequestType request) {
    MCCIIN000002UV01 ack = new MCCIIN000002UV01();

    // "process" the request and send a response out to the Nhin.
    PatientDiscovery201305Processor msgProcessor = new PatientDiscovery201305Processor();
    PRPAIN201306UV02 resp =
        msgProcessor.process201305(request.getPRPAIN201305UV02(), request.getAssertion());

    // Generate a new response assertion
    AsyncMessageProcessHelper asyncProcess = createAsyncProcesser();
    AssertionType newAssertion = asyncProcess.copyAssertionTypeObject(request.getAssertion());
    // Original request message id is now set as the relates to id
    newAssertion.getRelatesToList().add(request.getAssertion().getMessageId());
    // Generate a new unique response assertion Message ID
    newAssertion.setMessageId(AsyncMessageIdCreator.generateMessageId());
    // Set user info homeCommunity
    String homeCommunityId = HomeCommunityMap.getLocalHomeCommunityId();
    HomeCommunityType homeCommunityType = new HomeCommunityType();
    homeCommunityType.setHomeCommunityId(homeCommunityId);
    homeCommunityType.setName(homeCommunityId);
    newAssertion.setHomeCommunity(homeCommunityType);
    if (newAssertion.getUserInfo() != null && newAssertion.getUserInfo().getOrg() != null) {
      newAssertion.getUserInfo().getOrg().setHomeCommunityId(homeCommunityId);
      newAssertion.getUserInfo().getOrg().setName(homeCommunityId);
    }

    ack = sendToNhin(resp, newAssertion, request.getNhinTargetCommunities());

    return ack;
  }
  public MCCIIN000002UV01 addPatientDiscoveryAsyncReq(
      PRPAIN201305UV02 request, AssertionType assertion, NhinTargetCommunitiesType targets) {
    MCCIIN000002UV01 resp = new MCCIIN000002UV01();
    RespondingGatewayPRPAIN201305UV02RequestType unsecureRequest =
        new RespondingGatewayPRPAIN201305UV02RequestType();
    unsecureRequest.setAssertion(assertion);
    unsecureRequest.setNhinTargetCommunities(targets);
    unsecureRequest.setPRPAIN201305UV02(request);

    // Audit the incoming Nhin 201305 Message
    PatientDiscoveryAuditLogger auditLogger = new PatientDiscoveryAuditLogger();
    AcknowledgementType ack =
        auditLogger.auditEntityDeferred201305(
            unsecureRequest,
            unsecureRequest.getAssertion(),
            NhincConstants.AUDIT_LOG_INBOUND_DIRECTION,
            NhincConstants.AUDIT_LOG_RESPONSE_PROCESS);

    // ASYNCMSG PROCESSING - RSPPROCESS
    AsyncMessageProcessHelper asyncProcess = createAsyncProcesser();
    String messageId = assertion.getMessageId();
    boolean bIsQueueOk =
        asyncProcess.processMessageStatus(messageId, AsyncMsgRecordDao.QUEUE_STATUS_RSPPROCESS);

    // check for valid queue entry
    if (bIsQueueOk) {
      resp = addPatientDiscoveryAsyncReq(unsecureRequest);

      asyncProcess.processAck(
          messageId,
          AsyncMsgRecordDao.QUEUE_STATUS_RSPSENTACK,
          AsyncMsgRecordDao.QUEUE_STATUS_RSPSENTERR,
          resp);
    } else {
      String ackMsg =
          "Deferred Patient Discovery response processing halted; deferred queue repository error encountered";

      // Set the error acknowledgement status
      // fatal error with deferred queue repository
      resp = HL7AckTransforms.createAckErrorFrom201305(request, ackMsg);
    }

    // Audit the responding Acknowledgement Message
    ack =
        auditLogger.auditAck(
            resp,
            unsecureRequest.getAssertion(),
            NhincConstants.AUDIT_LOG_OUTBOUND_DIRECTION,
            NhincConstants.AUDIT_LOG_ENTITY_INTERFACE);

    return resp;
  }
  public LogEventRequestType transformNhinNotifyRequestToAuditMessage(
      LogNhinNotifyRequestType message) {
    LogEventRequestType response = new LogEventRequestType();
    AuditMessageType auditMsg = new AuditMessageType();

    LOG.info("******************************************************************");
    LOG.info("Entering transformNhinNotifyRequestToAuditMessage() method.");
    LOG.info("******************************************************************");

    if (message == null || message.getDirection() == null || message.getInterface() == null) {
      LOG.error(
          "DocumentQueryTransforms.transformDocQueryReq2AuditMsg() has insufficient data to log a message audfit");
      return null;
    }

    String _interface = message.getInterface();
    String direction = message.getDirection();
    response.setDirection(direction);
    response.setInterface(_interface);

    AssertionType assertion = null;
    UserType userInfo = null;
    // Extract Assertion and UserInfo from Message.Assertion
    if (message != null
        && message.getMessage() != null
        && message.getMessage().getAssertion() != null) {
      assertion = message.getMessage().getAssertion();
      if (assertion.getUserInfo() != null) {
        userInfo = message.getMessage().getAssertion().getUserInfo();
      }
    }

    // Create EventIdentification
    CodedValueType eventID = null;
    eventID =
        AuditDataTransformHelper.createCodedValue(
            AuditDataTransformConstants.EVENT_ID_CODE_SYS_NAME_NOT,
            AuditDataTransformConstants.EVENT_ID_DISPLAY_NAME_NOTIFY,
            AuditDataTransformConstants.EVENT_ID_CODE_SYS_NAME_NOT,
            AuditDataTransformConstants.EVENT_ID_DISPLAY_NAME_NOTIFY,
            null);

    auditMsg.setEventIdentification(
        AuditDataTransformHelper.createEventIdentification(
            AuditDataTransformConstants.EVENT_ACTION_CODE_CREATE,
            AuditDataTransformConstants.EVENT_OUTCOME_INDICATOR_SUCCESS,
            eventID,
            null));

    // Create Active Participant Section
    boolean isSender = AuditDataTransformHelper.isSender(_interface, direction);
    boolean isRecipient = isSender ? false : true;

    if (userInfo != null) {
      ActiveParticipant participant =
          AuditDataTransformHelper.createActiveParticipantForHuman(userInfo);
      auditMsg.getActiveParticipant().add(participant);
    }

    ActiveParticipant source =
        AuditDataTransformHelper.createActiveParticipantSource(isSender, null);
    auditMsg.getActiveParticipant().add(source);

    ActiveParticipant destination =
        AuditDataTransformHelper.createActiveParticipantDestination(
            assertion.getSamlAuthnStatement(), isRecipient);
    auditMsg.getActiveParticipant().add(destination);

    /* Assign AuditSourceIdentification */

    String patientId = "";
    if (message != null
        && NullChecker.isNotNullish(message.getMessage().getAssertion().getUniquePatientId())
        && NullChecker.isNotNullish(
            message.getMessage().getAssertion().getUniquePatientId().get(0))) {
      patientId = message.getMessage().getAssertion().getUniquePatientId().get(0);
    }

    String communityId = "";
    String communityName = "";
    if (userInfo != null && userInfo.getOrg() != null) {

      if (userInfo.getOrg().getHomeCommunityId() != null) {
        communityId = userInfo.getOrg().getHomeCommunityId();
      }
      if (userInfo.getOrg().getName() != null) {
        communityName = userInfo.getOrg().getName();
      }
    }

    AuditSourceIdentificationType auditSource =
        AuditDataTransformHelper.createAuditSourceIdentification(communityId, communityName, null);
    auditMsg.getAuditSourceIdentification().add(auditSource);

    /* Assign ParticipationObjectIdentification */
    /** Create a ParticipantObjectIdentification entry for Patient */
    ParticipantObjectIdentificationType partObjId = null;
    if ((patientId != null) && (!patientId.isEmpty())) {
      CodedValueType partObjectIdType =
          AuditDataTransformHelper.getPatientParticipantRoleIdCodedValue();

      // Participant Object Identification Entry $1 Patient
      partObjId =
          AuditDataTransformHelper.createParticipantObjectIdentification(
              AuditDataTransformConstants.PARTICIPANT_OBJECT_TYPE_CODE_PERSON,
              AuditDataTransformConstants.PARTICIPANT_OBJECT_TYPE_CODE_ROLE_PATIENT,
              partObjectIdType,
              patientId,
              null);

      auditMsg.getParticipantObjectIdentification().add(partObjId);
    }

    // TODO: Illegal piggybacking of message in ParticipantObjectIdentification.ObjectQuery
    boolean addDone = true;
    if (partObjId == null) {
      partObjId = new ParticipantObjectIdentificationType();
      addDone = false;
    }

    // Fill in the message field with the contents of the event message
    try {
      JAXBContextHandler oHandler = new JAXBContextHandler();
      JAXBContext jc =
          oHandler.getJAXBContext(
              org.oasis_open.docs.wsn.b_2.ObjectFactory.class,
              ihe.iti.xds_b._2007.ObjectFactory.class);
      Marshaller marshaller = jc.createMarshaller();
      ByteArrayOutputStream baOutStrm = new ByteArrayOutputStream();
      baOutStrm.reset();
      if (message != null) {
        marshaller.marshal(message.getMessage().getNotify(), baOutStrm);
      }
      LOG.debug("Done marshalling the message.");

      partObjId.setParticipantObjectQuery(baOutStrm.toByteArray());

    } catch (Exception e) {
      e.printStackTrace();
      LOG.error("EXCEPTION when marshalling Nhin Notify Request : " + e);
      throw new RuntimeException();
    }

    if (!addDone) {
      auditMsg.getParticipantObjectIdentification().add(partObjId);
    }

    response.setAuditMessage(auditMsg);

    LOG.info("******************************************************************");
    LOG.info("Exiting transformNhinNotifyRequestToAuditMessage() method.");
    LOG.info("******************************************************************");

    return response;
  }
  public LogEventRequestType transformEntityNotifyResponseToGenericAudit(
      LogEntityNotifyResponseType message) {
    LogEventRequestType response = new LogEventRequestType();
    AuditMessageType auditMsg = new AuditMessageType();

    LOG.info("******************************************************************");
    LOG.info("Entering transformEntityNotifyResponseToGenericAudit() method.");
    LOG.info("******************************************************************");

    if (message == null || message.getDirection() == null || message.getInterface() == null) {
      LOG.error(
          "DocumentQueryTransforms.transformDocQueryReq2AuditMsg() has insufficient data to log a message audfit");
      return null;
    }

    String _interface = message.getInterface();
    String direction = message.getDirection();
    response.setDirection(direction);
    response.setInterface(_interface);

    AssertionType assertion = null;
    UserType userInfo = null;
    // Extract Assertion and UserInfo from Message.Assertion
    if (message != null
        && message.getMessage() != null
        && message.getMessage().getAssertion() != null) {
      assertion = message.getMessage().getAssertion();
      if (assertion.getUserInfo() != null) {
        userInfo = message.getMessage().getAssertion().getUserInfo();
      }
    }

    // Create EventIdentification
    CodedValueType eventID = null;
    eventID =
        AuditDataTransformHelper.createCodedValue(
            AuditDataTransformConstants.EVENT_ID_CODE_SYS_NAME_NOT,
            AuditDataTransformConstants.EVENT_ID_DISPLAY_NAME_NOTIFY,
            AuditDataTransformConstants.EVENT_ID_CODE_SYS_NAME_NOT,
            AuditDataTransformConstants.EVENT_ID_DISPLAY_NAME_NOTIFY,
            null);

    auditMsg.setEventIdentification(
        AuditDataTransformHelper.createEventIdentification(
            AuditDataTransformConstants.EVENT_ACTION_CODE_CREATE,
            AuditDataTransformConstants.EVENT_OUTCOME_INDICATOR_SUCCESS,
            eventID,
            null));

    // Create Active Participant Section
    boolean isSender = AuditDataTransformHelper.isSender(_interface, direction);
    boolean isRecipient = isSender ? false : true;

    if (userInfo != null) {
      ActiveParticipant participant =
          AuditDataTransformHelper.createActiveParticipantForHuman(userInfo);
      auditMsg.getActiveParticipant().add(participant);
    }

    ActiveParticipant source =
        AuditDataTransformHelper.createActiveParticipantSource(isSender, null);
    auditMsg.getActiveParticipant().add(source);

    ActiveParticipant destination =
        AuditDataTransformHelper.createActiveParticipantDestination(
            assertion.getSamlAuthnStatement(), isRecipient);
    auditMsg.getActiveParticipant().add(destination);

    /* Assign AuditSourceIdentification */

    String patientId = "";
    if (message != null
        && NullChecker.isNotNullish(message.getMessage().getAssertion().getUniquePatientId())
        && NullChecker.isNotNullish(
            message.getMessage().getAssertion().getUniquePatientId().get(0))) {
      patientId = message.getMessage().getAssertion().getUniquePatientId().get(0);
    }

    String communityId = "";
    String communityName = "";
    if (userInfo != null && userInfo.getOrg() != null) {

      if (userInfo.getOrg().getHomeCommunityId() != null) {
        communityId = userInfo.getOrg().getHomeCommunityId();
      }
      if (userInfo.getOrg().getName() != null) {
        communityName = userInfo.getOrg().getName();
      }
    }

    AuditSourceIdentificationType auditSource =
        AuditDataTransformHelper.createAuditSourceIdentification(communityId, communityName, null);
    auditMsg.getAuditSourceIdentification().add(auditSource);

    /* Assign ParticipationObjectIdentification */
    /** Create a ParticipantObjectIdentification entry for Patient */
    ParticipantObjectIdentificationType partObjId = null;
    if ((patientId != null) && (!patientId.isEmpty())) {
      CodedValueType partObjectIdType =
          AuditDataTransformHelper.getPatientParticipantRoleIdCodedValue();

      // Participant Object Identification Entry $1 Patient
      partObjId =
          AuditDataTransformHelper.createParticipantObjectIdentification(
              AuditDataTransformConstants.PARTICIPANT_OBJECT_TYPE_CODE_PERSON,
              AuditDataTransformConstants.PARTICIPANT_OBJECT_TYPE_CODE_ROLE_PATIENT,
              partObjectIdType,
              patientId,
              null);

      auditMsg.getParticipantObjectIdentification().add(partObjId);
    }

    // TODO: Illegal piggybacking of message in ParticipantObjectIdentification.ObjectQuery

    if (partObjId == null) {
      partObjId = new ParticipantObjectIdentificationType();
    }

    response.setAuditMessage(auditMsg);

    LOG.info("******************************************************************");
    LOG.info("Exiting transformEntityNotifyResponseToGenericAudit() method.");
    LOG.info("******************************************************************");
    return response;
  }