public List<RecordWeb> getMatchingEntities(EntityWeb entityModel, RecordWeb entity)
      throws Exception {
    log.debug(
        "Received request to retrieve a list of entity instance records that match the entity specified as a parameter.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      // pass the entity definition model for formatting the Date search string
      org.openhie.openempi.model.Record recordForMatch =
          ModelTransformer.mapToRecordForSearch(entityDef, entity, Record.class);

      List<Record> records =
          entityInstanceService.findRecordsByAttributes(entityDef, recordForMatch);

      List<RecordWeb> dtos = new java.util.ArrayList<RecordWeb>(records.size());
      for (Record record : records) {
        RecordWeb dto = ModelTransformer.mapToRecord(record, RecordWeb.class);
        dtos.add(dto);
      }

      return dtos;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  public List<RecordWeb> loadLinksFromRecord(EntityWeb entityModel, RecordWeb entity)
      throws Exception {
    log.debug("Received request to retrieve a list of entity record links.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      // loadRecordLinks without left and right Records
      List<Record> records =
          entityInstanceService.loadRecordLinksByRecordId(entityDef, entity.getRecordId());

      List<RecordWeb> dtos = new java.util.ArrayList<RecordWeb>(records.size());
      for (Record record : records) {
        RecordWeb dto = ModelTransformer.mapToRecord(record, RecordWeb.class);
        dtos.add(dto);
      }

      return dtos;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  public List<RecordLinkWeb> loadRecordLinks(
      EntityWeb entityModel, String state, int firstResult, int maxResults) throws Exception {
    log.debug("Received request to retrieve a list of entity record links.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      List<RecordLink> records =
          entityInstanceService.loadRecordLinks(
              entityDef, RecordLinkState.fromString(state), firstResult, maxResults);

      List<RecordLinkWeb> dtos = new java.util.ArrayList<RecordLinkWeb>(records.size());
      for (RecordLink record : records) {

        // loadRecordLinks without left and right Records
        RecordLinkWeb dto = ModelTransformer.mapToRecordLink(record, RecordLinkWeb.class, false);
        dtos.add(dto);
      }

      return dtos;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  public RecordLinkWeb updateRecordLink(EntityWeb entityModel, RecordLinkWeb linkPair)
      throws Exception {
    log.debug("Received request to updaty an entity record link.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      RecordManagerService entityInstanceManagerService = Context.getRecordManagerService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      RecordLink recordLink = ModelTransformer.mapToRecordLink(linkPair, RecordLink.class);

      RecordLink record =
          entityInstanceService.loadRecordLink(entityDef, recordLink.getRecordLinkId());
      record.setState(recordLink.getState());
      record = entityInstanceManagerService.updateRecordLink(record);

      RecordLinkWeb recordWeb = ModelTransformer.mapToRecordLink(record, RecordLinkWeb.class, true);

      return recordWeb;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  public RecordLinkWeb loadRecordLinks(
      EntityWeb entityModel, Long leftRecordId, Long rightRecordId, String state) throws Exception {
    log.debug("Received request to retrieve a list of entity record links.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      List<RecordLink> records =
          entityInstanceService.loadRecordLinks(
              entityDef, rightRecordId, RecordLinkState.fromString(state));

      for (RecordLink record : records) {

        // loadRecordLinks with left and right Records
        RecordLink recordlLink =
            entityInstanceService.loadRecordLink(entityDef, record.getRecordLinkId());
        if (recordlLink.getLeftRecord().getRecordId() == leftRecordId
            || recordlLink.getRightRecord().getRecordId() == leftRecordId) {

          RecordLinkWeb recordlLinkWeb =
              ModelTransformer.mapToRecordLink(recordlLink, RecordLinkWeb.class, true);
          return recordlLinkWeb;
        }
      }
      return null;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  public List<RecordWeb> findEntitiesByIdentifier(EntityWeb entityModel, IdentifierWeb identferWeb)
      throws Exception {
    log.debug(
        "Received request to retrieve a list of entity instance records that match the entity specified as a parameter.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      org.openhie.openempi.model.Identifier identifier =
          ModelTransformer.map(identferWeb, org.openhie.openempi.model.Identifier.class);

      List<Record> records = entityInstanceService.findRecordsByIdentifier(entityDef, identifier);

      List<RecordWeb> dtos = new java.util.ArrayList<RecordWeb>(records.size());
      for (Record record : records) {
        RecordWeb dto = ModelTransformer.mapToRecord(record, RecordWeb.class);
        dtos.add(dto);
      }

      return dtos;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  @Override
  public RecordListWeb getEntityRecordsBySearch(RecordSearchCriteriaWeb searchCriteria)
      throws Exception {
    log.debug("Get Entity Records By Search");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();

      EntityWeb entityModel = searchCriteria.getEntityModel();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      RecordWeb entity = searchCriteria.getRecord();
      int offset = searchCriteria.getFirstResult();
      int pageSize = searchCriteria.getMaxResults();

      org.openhie.openempi.model.Record recordForMatch =
          ModelTransformer.mapToRecordForSearch(entityDef, entity, Record.class);

      // Get total count
      Long totalCount = searchCriteria.getTotalCount();
      if (totalCount == 0) {
        totalCount = entityInstanceService.getRecordCount(entityDef, recordForMatch);
      }

      // get List of Record
      List<Record> records =
          entityInstanceService.findRecordsByAttributes(
              entityDef, recordForMatch, offset, pageSize);

      List<RecordWeb> dtos = new java.util.ArrayList<RecordWeb>(records.size());
      for (Record record : records) {
        RecordWeb dto = ModelTransformer.mapToRecord(record, RecordWeb.class);
        dtos.add(dto);
      }

      RecordListWeb recordList = new RecordListWeb();
      recordList.setTotalCount(totalCount);
      recordList.setRecords(dtos);

      return recordList;

    } catch (Exception e) {
      log.error("Failed while trying to get audit events: " + e, e);
    }
    return null;
  }
  @Override
  public RecordLinksListWeb loadRecordLinksPaged(RecordSearchCriteriaWeb searchCriteria)
      throws Exception {
    log.debug("Get Record Links");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();

      EntityWeb entityModel = searchCriteria.getEntityModel();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      int offset = searchCriteria.getFirstResult();
      int pageSize = searchCriteria.getMaxResults();
      String state = searchCriteria.getSearchMode().substring(0, 1);

      // Get total count
      Long totalCount = searchCriteria.getTotalCount();
      if (totalCount == 0) {
        totalCount =
            entityInstanceService.getRecordLinkCount(entityDef, RecordLinkState.fromString(state));
      }

      // get List of Record
      List<RecordLink> recordLinks =
          entityInstanceService.loadRecordLinks(
              entityDef, RecordLinkState.fromString(state), offset, pageSize);

      List<RecordLinkWeb> dtos = new java.util.ArrayList<RecordLinkWeb>(recordLinks.size());
      for (RecordLink record : recordLinks) {

        // loadRecordLinks without left and right Records
        RecordLinkWeb dto = ModelTransformer.mapToRecordLink(record, RecordLinkWeb.class, false);
        dtos.add(dto);
      }

      RecordLinksListWeb recordList = new RecordLinksListWeb();
      recordList.setTotalCount(totalCount);
      recordList.setRecordLinks(dtos);

      return recordList;

    } catch (Exception e) {
      log.error("Failed while trying to get audit events: " + e, e);
    }
    return null;
  }
  public RecordListWeb findEntitiesByIdentifier(RecordSearchCriteriaWeb searchCriteria)
      throws Exception {
    log.debug("Received entity records by identifier.");

    authenticateCaller();
    try {
      RecordQueryService entityInstanceService = Context.getRecordQueryService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();

      EntityWeb entityModel = searchCriteria.getEntityModel();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());

      IdentifierWeb identifierWeb = searchCriteria.getIdentifier();
      int offset = searchCriteria.getFirstResult();
      int pageSize = searchCriteria.getMaxResults();

      org.openhie.openempi.model.Identifier identifier =
          ModelTransformer.map(identifierWeb, org.openhie.openempi.model.Identifier.class);

      // Get total count
      Long totalCount = searchCriteria.getTotalCount();
      if (totalCount == 0) {
        totalCount = entityInstanceService.getRecordCount(entityDef, identifier);
      }

      // get List of Record
      List<Record> records =
          entityInstanceService.findRecordsByIdentifier(entityDef, identifier, offset, pageSize);

      List<RecordWeb> dtos = new java.util.ArrayList<RecordWeb>(records.size());
      for (Record record : records) {
        RecordWeb dto = ModelTransformer.mapToRecord(record, RecordWeb.class);
        dtos.add(dto);
      }

      RecordListWeb recordList = new RecordListWeb();
      recordList.setTotalCount(totalCount);
      recordList.setRecords(dtos);

      return recordList;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  public RecordWeb loadEntityById(EntityWeb entityModel, Long recordId) {
    log.debug("Received request to load entity instance record by Id.");

    authenticateCaller();
    try {
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());
      RecordQueryService entityInstanceService = Context.getRecordQueryService();

      Record record = entityInstanceService.loadRecordById(entityDef, recordId);
      if (record != null) {
        return ModelTransformer.mapToRecord(record, RecordWeb.class);
      }
      return null;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }
  @Override
  public LoggedLinkListWeb getLoggedLinks(LoggedLinkSearchCriteriaWeb search) throws Exception {
    authenticateCaller();
    try {
      AuditEventService auditEventService = Context.getAuditEventService();
      EntityDefinitionManagerService entityDefService = Context.getEntityDefinitionManagerService();
      RecordQueryService entityInstanceService = Context.getRecordQueryService();

      LoggedLinkListWeb loggedLinkList = new LoggedLinkListWeb();

      // entity model
      EntityWeb entityModel = search.getEntityModel();
      Entity entityDef = entityDefService.loadEntity(entityModel.getEntityVersionId());
      if (entityDef == null) {
        loggedLinkList.setTotalCount(0);
        loggedLinkList.setRecordPairs(new java.util.ArrayList<RecordLinkWeb>());
        return loggedLinkList;
      }

      //  total count
      int totalCount =
          auditEventService.getLoggedLinksCount(entityDef.getEntityVersionId(), search.getVector());
      if (totalCount == 0) {
        loggedLinkList.setTotalCount(0);
        loggedLinkList.setRecordPairs(new java.util.ArrayList<RecordLinkWeb>());
        return loggedLinkList;
      }

      // link logs
      List<LoggedLink> links =
          auditEventService.getLoggedLinks(
              entityDef.getEntityVersionId(),
              search.getVector(),
              search.getFirstResult(),
              search.getMaxResults());

      List<RecordLinkWeb> recordLinks = new java.util.ArrayList<RecordLinkWeb>();
      for (LoggedLink link : links) {

        Record leftRecord = entityInstanceService.loadRecordById(entityDef, link.getLeftRecordId());
        Record rightRecord =
            entityInstanceService.loadRecordById(entityDef, link.getRightRecordId());

        if (leftRecord != null && rightRecord != null) {
          RecordLinkWeb recordLinkWeb = new RecordLinkWeb();
          recordLinkWeb.setWeight(link.getWeight());
          recordLinkWeb.setVector(link.getVectorValue());
          recordLinkWeb.setDateCreated(link.getDateCreated());
          recordLinkWeb.setLeftRecord(ModelTransformer.mapToRecord(leftRecord, RecordWeb.class));
          recordLinkWeb.setRightRecord(ModelTransformer.mapToRecord(rightRecord, RecordWeb.class));

          if (link.getUserCreatedBy() != null) {
            UserWeb user =
                ModelTransformer.mapToUser(link.getUserCreatedBy(), UserWeb.class, false);
            recordLinkWeb.setUserCreatedBy(user);
          }

          recordLinks.add(recordLinkWeb);
        }
      }

      loggedLinkList.setTotalCount(totalCount);
      loggedLinkList.setRecordPairs(recordLinks);

      return loggedLinkList;
    } catch (Throwable t) {
      log.error("Failed to execute: " + t.getMessage(), t);
      throw new RuntimeException(t);
    }
  }