package uk.nhs.careconnect.ri.stu3.dao; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.TokenParam; import org.hl7.fhir.dstu3.model.EpisodeOfCare; import org.hl7.fhir.dstu3.model.IdType; import org.hl7.fhir.dstu3.model.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Repository; import uk.nhs.careconnect.fhir.OperationOutcomeException; import uk.nhs.careconnect.ri.database.daointerface.*; import uk.nhs.careconnect.ri.stu3.dao.transforms.EpisodeOfCareEntityToFHIREpisodeOfCareTransformer; import uk.nhs.careconnect.ri.database.entity.codeSystem.ConceptEntity; import uk.nhs.careconnect.ri.database.entity.codeSystem.SystemEntity; import uk.nhs.careconnect.ri.database.entity.episode.EpisodeOfCareIdentifier; import uk.nhs.careconnect.ri.database.entity.episode.EpisodeOfCareEntity; import uk.nhs.careconnect.ri.database.entity.organization.OrganisationEntity; import uk.nhs.careconnect.ri.database.entity.patient.PatientEntity; import uk.nhs.careconnect.ri.database.entity.practitioner.PractitionerEntity; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.criteria.*; import javax.transaction.Transactional; import java.net.URI; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @Repository @Transactional public class EpisodeOfCareDao implements EpisodeOfCareRepository { @PersistenceContext EntityManager em; @Autowired PatientRepository patientDao; @Autowired @Lazy ConceptRepository conceptDao; @Autowired private CodeSystemRepository codeSystemSvc; @Autowired PractitionerRepository practitionerDao; @Autowired OrganisationRepository organisationDao; @Autowired private LibDao libDao; @Autowired private EpisodeOfCareEntityToFHIREpisodeOfCareTransformer episodeOfCareEntityToFHIREpisodeOfCareTransformer; private static final Logger log = LoggerFactory.getLogger(EpisodeOfCareDao.class); @Override public Long count() { CriteriaBuilder qb = em.getCriteriaBuilder(); CriteriaQuery<Long> cq = qb.createQuery(Long.class); cq.select(qb.count(cq.from(EpisodeOfCareEntity.class))); //cq.where(/*your stuff*/); return em.createQuery(cq).getSingleResult(); } @Override public EpisodeOfCareEntity readEntity(FhirContext ctx, IdType theId) { if (daoutils.isNumeric(theId.getIdPart())) { EpisodeOfCareEntity episodeOfCareEntity = (EpisodeOfCareEntity) em.find(EpisodeOfCareEntity.class, Long.parseLong(theId.getIdPart())); return episodeOfCareEntity; } else { return null; } } @Override public void save(FhirContext ctx, EpisodeOfCareEntity resource) { } @Override public void save(FhirContext ctx, EpisodeOfCare episode) { } @Override public EpisodeOfCare read(FhirContext ctx,IdType theId) { if (daoutils.isNumeric(theId.getIdPart())) { EpisodeOfCareEntity episode = (EpisodeOfCareEntity) em.find(EpisodeOfCareEntity.class, Long.parseLong(theId.getIdPart())); return episode == null ? null : episodeOfCareEntityToFHIREpisodeOfCareTransformer.transform(episode); } else { return null; } } @Override public EpisodeOfCare create(FhirContext ctx,EpisodeOfCare episode, IdType theId, String theConditional) throws OperationOutcomeException { log.debug("EpisodeOfCare.save"); // log.info(ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(episode)); EpisodeOfCareEntity episodeEntity = null; if (theId !=null && daoutils.isNumeric(theId.getIdPart()) ) episodeEntity = em.find(EpisodeOfCareEntity.class, Long.parseLong(theId.getIdPart())); if (theConditional != null) { try { //CareConnectSystem.ODSOrganisationCode if (theConditional.contains("fhir.leedsth.nhs.uk/Id/episode")) { URI uri = new URI(theConditional); String scheme = uri.getScheme(); String host = uri.getHost(); String query = uri.getRawQuery(); log.debug(query); String[] spiltStr = query.split("%7C"); log.debug(spiltStr[1]); List<EpisodeOfCareEntity> results = searchEntity(ctx, null, null,null, new TokenParam().setValue(spiltStr[1]).setSystem("https://fhir.leedsth.nhs.uk/Id/episode")); for (EpisodeOfCareEntity enc : results) { episodeEntity = enc; break; } } else { log.info("NOT SUPPORTED: Conditional Url = "+theConditional); } } catch (Exception ex) { } } if (episodeEntity == null) episodeEntity = new EpisodeOfCareEntity(); PatientEntity patientEntity = null; if (episode.hasPatient()) { log.trace(episode.getPatient().getReference()); patientEntity = patientDao.readEntity(ctx, new IdType(episode.getPatient().getReference())); episodeEntity.setPatient(patientEntity); } if (episode.hasType()) { ConceptEntity code = conceptDao.findAddCode(episode.getType().get(0).getCoding().get(0)); if (code != null) { episodeEntity.setType(code); } else { log.info("Code: Missing System/Code = "+episode.getType().get(0).getCoding().get(0).getSystem() +" code = "+episode.getType().get(0).getCoding().get(0).getCode()); throw new IllegalArgumentException("Missing System/Code = "+ episode.getType().get(0).getCoding().get(0).getSystem() +" code = "+episode.getType().get(0).getCoding().get(0).getCode()); } } if (episode.hasStatus()) { episodeEntity.setStatus(episode.getStatus()); } if (episode.hasManagingOrganization()) { OrganisationEntity organisationEntity = organisationDao.readEntity(ctx, new IdType(episode.getManagingOrganization().getReference())); if (organisationEntity != null) episodeEntity.setManagingOrganisation(organisationEntity); } if (episode.hasPeriod()) { if (episode.getPeriod().hasStart()) { episodeEntity.setPeriodStartDate(episode.getPeriod().getStart()); if (episode.getPeriod().hasEnd()) { if (episode.getPeriod().getEnd().after(episode.getPeriod().getStart())) episodeEntity.setPeriodEndDate(episode.getPeriod().getEnd()); else episodeEntity.setPeriodEndDate(null); // KGM 15/12/2017 Ensure end date is after start date , if not set end date to null } } } if (episode.hasCareManager()) { PractitionerEntity practitionerEntity = practitionerDao.readEntity(ctx, new IdType(episode.getCareManager().getReference())); if (practitionerEntity != null) episodeEntity.setCareManager(practitionerEntity); } em.persist(episodeEntity); for (Identifier identifier : episode.getIdentifier()) { EpisodeOfCareIdentifier episodeIdentifier = null; for (EpisodeOfCareIdentifier orgSearch : episodeEntity.getIdentifiers()) { if (identifier.getSystem().equals(orgSearch.getSystemUri()) && identifier.getValue().equals(orgSearch.getValue())) { episodeIdentifier = orgSearch; break; } } if (episodeIdentifier == null) episodeIdentifier = new EpisodeOfCareIdentifier(); episodeIdentifier= (EpisodeOfCareIdentifier) libDao.setIdentifier(identifier, episodeIdentifier ); episodeIdentifier.setEpisode(episodeEntity); em.persist(episodeIdentifier); } return episodeOfCareEntityToFHIREpisodeOfCareTransformer.transform(episodeEntity); } @Override public List<EpisodeOfCare> search(FhirContext ctx,ReferenceParam patient, DateRangeParam date, StringParam resid, TokenParam identifier) { List<EpisodeOfCareEntity> qryResults = searchEntity(ctx,patient, date,resid,identifier); List<EpisodeOfCare> results = new ArrayList<>(); for (EpisodeOfCareEntity episodeEntity : qryResults) { // log.trace("HAPI Custom = "+doc.getId()); EpisodeOfCare episode = episodeOfCareEntityToFHIREpisodeOfCareTransformer.transform(episodeEntity); results.add(episode); } return results; } @Override public List<EpisodeOfCareEntity> searchEntity(FhirContext ctx,ReferenceParam patient, DateRangeParam date, StringParam resid, TokenParam identifier) { List<EpisodeOfCareEntity> qryResults = null; CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<EpisodeOfCareEntity> criteria = builder.createQuery(EpisodeOfCareEntity.class); Root<EpisodeOfCareEntity> root = criteria.from(EpisodeOfCareEntity.class); List<Predicate> predList = new LinkedList<Predicate>(); List<EpisodeOfCare> results = new ArrayList<EpisodeOfCare>(); if (patient != null) { // KGM 4/1/2018 only search on patient id if (daoutils.isNumeric(patient.getIdPart())) { Join<EpisodeOfCareEntity, PatientEntity> join = root.join("patient", JoinType.LEFT); Predicate p = builder.equal(join.get("id"), patient.getIdPart()); predList.add(p); } else { Join<EpisodeOfCareEntity, PatientEntity> join = root.join("patient", JoinType.LEFT); Predicate p = builder.equal(join.get("id"), -1); predList.add(p); } } if (resid != null) { Predicate p = builder.equal(root.get("id"),resid.getValue()); predList.add(p); } if (identifier !=null) { Join<EpisodeOfCareEntity, EpisodeOfCareIdentifier> join = root.join("identifiers", JoinType.LEFT); Join<EpisodeOfCareIdentifier, SystemEntity> joinSystem = join.join("systemEntity",JoinType.LEFT); Predicate pvalue = builder.like( builder.upper(join.get("value")), builder.upper(builder.literal(daoutils.removeSpace(identifier.getValue()))) ); if (identifier.getSystem() != null) { Predicate psystem = builder.like( builder.upper(joinSystem.get("codeSystemUri")), builder.upper(builder.literal(identifier.getSystem())) ); Predicate p = builder.and(pvalue, psystem); predList.add(p); } else { predList.add(pvalue); } } Predicate[] predArray = new Predicate[predList.size()]; predList.toArray(predArray); if (predList.size()>0) { criteria.select(root).where(predArray); } else { criteria.select(root); } qryResults = em.createQuery(criteria).setMaxResults(daoutils.MAXROWS).getResultList(); return qryResults; } }