Search in sources :

Example 1 with CANCELLED

use of org.hl7.fhir.dstu3.model.Appointment.AppointmentStatus.CANCELLED in project org.hl7.fhir.core by hapifhir.

the class CCDAConverter method processProcedure.

protected void processProcedure(ListResource list, Element procedure, ProcedureType type) throws Exception {
    switch(type) {
        case Procedure:
            cda.checkTemplateId(procedure, "2.16.840.1.113883.10.20.22.4.14");
            break;
        case Observation:
            cda.checkTemplateId(procedure, "2.16.840.1.113883.10.20.22.4.13");
            break;
        case Act:
            cda.checkTemplateId(procedure, "2.16.840.1.113883.10.20.22.4.12");
    }
    checkNoNegationOrNullFlavor(procedure, "Procedure (" + type + ")");
    checkNoSubject(procedure, "Procedure (" + type + ")");
    Procedure p = new Procedure();
    addItemToList(list, p);
    // moodCode is either INT or EVN. INT is not handled yet. INT is deprecated anyway
    if (procedure.getAttribute("moodCode").equals("INT"))
        p.getModifierExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-planned", Factory.newBoolean(true), false));
    // SHALL contain at least one [1..*] id (CONF:7655).
    for (Element e : cda.getChildren(procedure, "id")) p.getIdentifier().add(convert.makeIdentifierFromII(e));
    // SHALL contain exactly one [1..1] code (CONF:7656).
    // This code @code in a procedure activity SHOULD be selected from LOINC or SNOMED CT and MAY be selected from CPT-4, ICD9 Procedures, ICD10 Procedures
    p.setCode(convert.makeCodeableConceptFromCD(cda.getChild(procedure, "code")));
    // SHALL contain exactly one [1..1] statusCode/@code, which SHALL be selected from ValueSet 2.16.840.1.113883.11.20.9.22 ProcedureAct
    // completed | active | aborted | cancelled - not in FHIR
    p.getModifierExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-status", Factory.newCode(cda.getStatus(procedure)), false));
    // SHOULD contain zero or one [0..1] effectiveTime (CONF:7662).
    p.setPerformed(convert.makePeriodFromIVL(cda.getChild(procedure, "effectiveTime")));
    // MAY contain zero or one [0..1] priorityCode/@code, which SHALL be selected from ValueSet 2.16.840.1.113883.1.11.16866 ActPriority DYNAMIC (CONF:7668)
    p.getExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-priority", convert.makeCodeableConceptFromCD(cda.getChild(procedure, "priorityCode")), false));
    // MAY contain zero or one [0..1] methodCode (CONF:7670).
    p.getExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-method", convert.makeCodeableConceptFromCD(cda.getChild(procedure, "methodCode")), false));
    if (type == ProcedureType.Observation) {
    // for Procedure-Observation:
    // 9.	SHALL contain exactly one [1..1] value (CONF:16846).
    // don't know what this is. It's not the actual result of the procedure (that goes in results "This section records ... procedure observations"), and there seems to be no value. The example as <value xsi:type="CD"/> which is not valid
    // so we ignore this for now
    }
    // SHOULD contain zero or more [0..*] targetSiteCode/@code, which SHALL be selected from ValueSet 2.16.840.1.113883.3.88.12.3221.8.9 Body site DYNAMIC (CONF:7683).
    for (Element e : cda.getChildren(procedure, "targetSiteCode")) p.addBodySite(convert.makeCodeableConceptFromCD(e));
    // SHOULD contain zero or more [0..*] performer (CONF:7718) such that it
    for (Element e : cda.getChildren(procedure, "performer")) {
        ProcedurePerformerComponent pp = new ProcedurePerformerComponent();
        p.getPerformer().add(pp);
        pp.setActor(makeReferenceToPractitionerForAssignedEntity(e, p));
    }
    for (Element participant : cda.getChildren(procedure, "participant")) {
        Element participantRole = cda.getlastChild(participant);
        if (type == ProcedureType.Procedure && cda.hasTemplateId(participantRole, "2.16.840.1.113883.10.20.22.4.37")) {
            // MAY contain zero or more [0..*] participant (CONF:7751) such that it  SHALL contain exactly one [1..1] @typeCode="DEV" Device
            // implanted devices
            p.getExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/implanted-devices", Factory.makeReference(processDevice(participantRole, p)), false));
        } else if (cda.hasTemplateId(participantRole, "2.16.840.1.113883.10.20.22.4.32")) {
            // MAY contain zero or more [0..*] participant (CONF:7765) such that it SHALL contain exactly one [1..1] Service Delivery Location (templateId:2.16.840.1.113883.10.20.22.4.32) (CONF:7767)
            p.getExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/location", Factory.makeReference(processSDLocation(participantRole, p)), false));
        }
    }
    for (Element e : cda.getChildren(procedure, "entryRelationship")) {
        Element a = /* act*/
        cda.getlastChild(e);
        if (a.getLocalName().equals("encounter")) {
        // MAY contain zero or more [0..*] entryRelationship (CONF:7768) such that it SHALL contain exactly one encounter which SHALL contain exactly one [1..1] id (CONF:7773).
        // todo - and process as a full encounter while we're at it
        } else if (cda.hasTemplateId(a, "2.16.840.1.113883.10.20.22.4.20")) {
            // MAY contain zero or one [0..1] entryRelationship (CONF:7775) such that it SHALL contain exactly one [1..1] Instructions (templateId:2.16.840.1.113883.10.20.22.4.20) (CONF:7778).
            // had code for type, plus text for instructions
            Extension n = Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-instructions", null, true);
            n.getExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-instructions-type", convert.makeCodeableConceptFromCD(cda.getChild(a, "code")), false));
            n.getExtension().add(Factory.newExtension("http://www.healthintersections.com.au/fhir/extensions/procedure-instructions-text", convert.makeStringFromED(cda.getChild(a, "text")), false));
            p.getExtension().add(n);
        } else if (cda.hasTemplateId(a, "2.16.840.1.113883.10.20.22.4.19")) {
            // MAY contain zero or more [0..*] entryRelationship (CONF:7779) such that it SHALL contain exactly one [1..1] Indication (templateId:2.16.840.1.113883.10.20.22.4.19) (CONF:7781).
            p.addReasonCode(processIndication(a));
        } else if (cda.hasTemplateId(cda.getlastChild(e), "2.16.840.1.113883.10.20.22.4.16")) {
        // MAY contain zero or one [0..1] entryRelationship (CONF:7886) such that it SHALL contain exactly one [1..1] Medication Activity (templateId:2.16.840.1.113883.10.20.22.4.16) (CONF:7888).
        // todo
        }
    }
}
Also used : Element(org.w3c.dom.Element) ProcedurePerformerComponent(org.hl7.fhir.dstu3.model.Procedure.ProcedurePerformerComponent)

Example 2 with CANCELLED

use of org.hl7.fhir.dstu3.model.Appointment.AppointmentStatus.CANCELLED in project org.hl7.fhir.core by hapifhir.

the class ImagingStudy30_50 method convertImagingStudy.

public static org.hl7.fhir.dstu3.model.ImagingStudy convertImagingStudy(org.hl7.fhir.r5.model.ImagingStudy src) throws FHIRException {
    if (src == null)
        return null;
    org.hl7.fhir.dstu3.model.ImagingStudy tgt = new org.hl7.fhir.dstu3.model.ImagingStudy();
    ConversionContext30_50.INSTANCE.getVersionConvertor_30_50().copyDomainResource(src, tgt);
    for (org.hl7.fhir.r5.model.Identifier t : src.getIdentifier()) {
        if (URN_DICOM_UID.equals(t.getSystem())) {
            tgt.setUid(t.getValue());
        } else {
            tgt.addIdentifier(Identifier30_50.convertIdentifier(t));
        }
    }
    if (src.hasStatus()) {
        org.hl7.fhir.r5.model.ImagingStudy.ImagingStudyStatus s = src.getStatus();
        switch(s) {
            case REGISTERED:
                tgt.setAvailability(org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability.OFFLINE);
                break;
            case AVAILABLE:
                tgt.setAvailability(org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability.ONLINE);
                break;
            case CANCELLED:
                tgt.setAvailability(org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability.UNAVAILABLE);
                break;
            default:
                break;
        }
    }
    for (org.hl7.fhir.r5.model.Coding t : src.getModality()) {
        tgt.addModalityList(Coding30_50.convertCoding(t));
    }
    if (src.hasSubject()) {
        if (src.hasSubject())
            tgt.setPatient(Reference30_50.convertReference(src.getSubject()));
    }
    if (src.hasEncounter()) {
        if (src.hasEncounter())
            tgt.setContext(Reference30_50.convertReference(src.getEncounter()));
    }
    if (src.hasStarted()) {
        if (src.hasStartedElement())
            tgt.setStartedElement(DateTime30_50.convertDateTime(src.getStartedElement()));
    }
    for (org.hl7.fhir.r5.model.Reference t : src.getBasedOn()) {
        tgt.addBasedOn(Reference30_50.convertReference(t));
    }
    if (src.hasReferrer()) {
        if (src.hasReferrer())
            tgt.setReferrer(Reference30_50.convertReference(src.getReferrer()));
    }
    for (org.hl7.fhir.r5.model.Reference t : src.getInterpreter()) {
        tgt.addInterpreter(Reference30_50.convertReference(t));
    }
    for (org.hl7.fhir.r5.model.Reference t : src.getEndpoint()) {
        tgt.addEndpoint(Reference30_50.convertReference(t));
    }
    if (src.hasNumberOfSeries()) {
        if (src.hasNumberOfSeriesElement())
            tgt.setNumberOfSeriesElement(UnsignedInt30_50.convertUnsignedInt(src.getNumberOfSeriesElement()));
    }
    if (src.hasNumberOfInstances()) {
        if (src.hasNumberOfInstancesElement())
            tgt.setNumberOfInstancesElement(UnsignedInt30_50.convertUnsignedInt(src.getNumberOfInstancesElement()));
    }
    for (CodeableReference t : src.getProcedure()) {
        if (t.hasReference()) {
            tgt.addProcedureReference(Reference30_50.convertReference(t.getReference()));
        } else {
            tgt.addProcedureCode(CodeableConcept30_50.convertCodeableConcept(t.getConcept()));
        }
    }
    List<CodeableReference> reasonCodes = src.getReason();
    if (reasonCodes.size() > 0) {
        tgt.setReason(CodeableConcept30_50.convertCodeableConcept(reasonCodes.get(0).getConcept()));
        if (reasonCodes.size() > 1) {
        }
    }
    if (src.hasDescription()) {
        if (src.hasDescriptionElement())
            tgt.setDescriptionElement(String30_50.convertString(src.getDescriptionElement()));
    }
    for (org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesComponent t : src.getSeries()) {
        tgt.addSeries(convertImagingStudySeriesComponent(t));
    }
    return tgt;
}
Also used : CodeableReference(org.hl7.fhir.r5.model.CodeableReference)

Example 3 with CANCELLED

use of org.hl7.fhir.dstu3.model.Appointment.AppointmentStatus.CANCELLED in project redmatch by aehrc.

the class RedmatchApi method exportAll.

/**
 * Runs an operation on all the Redmatch rule documents found in the base folder.
 *
 * @param baseFolder The folder that contains the Redmatch rule documents , one or more schemas referenced by the
 *                   rules and a redmatch-config.yaml file with source server details.
 * @param progressReporter An object used to report progress. Can be null.
 * @param cancelToken Used to check if the user has cancelled the operation.
 * @return Map of diagnostic messages. Key is file where error happened.
 */
public List<Diagnostic> exportAll(@NotNull File baseFolder, ProgressReporter progressReporter, CancelChecker cancelToken) {
    if (!baseFolder.canRead() || !baseFolder.canWrite()) {
        return List.of(new Diagnostic(zeroZero, "Unable to read or write on the base folder.", DiagnosticSeverity.Error, "API"));
    }
    // Get .rdm files
    List<File> rdmFiles;
    try (Stream<Path> walk = Files.walk(baseFolder.toPath())) {
        rdmFiles = walk.filter(p -> !Files.isDirectory(p)).map(Path::toFile).filter(f -> f.getName().endsWith(".rdm")).collect(Collectors.toList());
    } catch (IOException e) {
        return List.of(new Diagnostic(zeroZero, "Unexpected I/O error: " + e.getLocalizedMessage(), DiagnosticSeverity.Error, "API"));
    }
    try {
        List<Diagnostic> diagnostics = new ArrayList<>();
        Map<String, DomainResource> resourcesMap = new HashMap<>();
        for (File rdmFile : rdmFiles) {
            Pair<Map<String, DomainResource>, List<Diagnostic>> data = transform(rdmFile, progressReporter, cancelToken);
            resourcesMap.putAll(data.getValue0());
            diagnostics.addAll(data.getValue1());
        }
        // Group resources by type
        final Map<String, List<DomainResource>> grouped = new HashMap<>();
        for (String key : resourcesMap.keySet()) {
            DomainResource dr = resourcesMap.get(key);
            String resourceType = dr.getResourceType().toString();
            List<DomainResource> list = grouped.computeIfAbsent(resourceType, k -> new ArrayList<>());
            list.add(dr);
        }
        Path outputFolder = createOutputFolder(baseFolder).toPath();
        save(grouped, outputFolder, progressReporter, cancelToken);
        return diagnostics;
    } catch (Exception e) {
        log.error(e);
        return List.of(new Diagnostic(zeroZero, "Could not complete transformation:" + e.getLocalizedMessage(), DiagnosticSeverity.Error, "API"));
    }
}
Also used : Path(java.nio.file.Path) DomainResource(org.hl7.fhir.r4.model.DomainResource) Diagnostic(org.eclipse.lsp4j.Diagnostic)

Example 4 with CANCELLED

use of org.hl7.fhir.dstu3.model.Appointment.AppointmentStatus.CANCELLED in project redmatch by aehrc.

the class RedmatchApi method generateGraph.

/**
 * Exports a graph representation of the generated resources.
 *
 * @param resources A collection of FHIR resources.
 * @param progressReporter An object used to report progress.
 * @param cancelToken A token to check if the operation has been cancelled.
 * @return A graph representation of the FHIR resources.
 */
public D3Graph generateGraph(Collection<DomainResource> resources, ProgressReporter progressReporter, CancelChecker cancelToken) {
    try {
        if (progressReporter != null) {
            progressReporter.reportProgress(Progress.reportStart("Generating graph"));
        }
        log.info("Creating graph representation for visualisation.");
        D3Graph d3Graph = new D3Graph();
        if (cancelToken != null && cancelToken.isCanceled()) {
            return d3Graph;
        }
        // Add vertices
        for (Resource res : resources) {
            d3Graph.addNode(new D3Node(generateId(res)));
            if (cancelToken != null && cancelToken.isCanceled()) {
                return d3Graph;
            }
        }
        // Add edges
        for (Resource src : resources) {
            for (FhirUtils.Target tgt : FhirUtils.getReferencedResources(src)) {
                d3Graph.addLink(new D3Link(generateId(src), tgt.getResourceId(), tgt.getAttributeName()));
                if (cancelToken != null && cancelToken.isCanceled()) {
                    return d3Graph;
                }
            }
        }
        return d3Graph;
    } finally {
        if (progressReporter != null) {
            progressReporter.reportProgress(Progress.reportEnd());
        }
    }
}
Also used : Resource(org.hl7.fhir.r4.model.Resource) DomainResource(org.hl7.fhir.r4.model.DomainResource)

Example 5 with CANCELLED

use of org.hl7.fhir.dstu3.model.Appointment.AppointmentStatus.CANCELLED in project gpconnect-demonstrator by nhsconnect.

the class AppointmentResourceProvider method updateAppointment.

@Update
public MethodOutcome updateAppointment(@IdParam IdType appointmentId, @ResourceParam Appointment appointment) {
    MethodOutcome methodOutcome = new MethodOutcome();
    OperationOutcome operationalOutcome = new OperationOutcome();
    AppointmentDetail appointmentDetail = appointmentResourceConverterToAppointmentDetail(appointment);
    // URL ID and Resource ID must be the same
    if (!Objects.equals(appointmentId.getIdPartAsLong(), appointmentDetail.getId())) {
        operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("Id in URL (" + appointmentId.getIdPart() + ") should match Id in Resource (" + appointmentDetail.getId() + ")");
        methodOutcome.setOperationOutcome(operationalOutcome);
        return methodOutcome;
    }
    // Make sure there is an existing appointment to be amended
    AppointmentDetail oldAppointmentDetail = appointmentSearch.findAppointmentByID(appointmentId.getIdPartAsLong());
    if (oldAppointmentDetail == null) {
        operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("No appointment details found for ID: " + appointmentId.getIdPart());
        methodOutcome.setOperationOutcome(operationalOutcome);
        return methodOutcome;
    }
    String oldAppointmentVersionId = String.valueOf(oldAppointmentDetail.getLastUpdated().getTime());
    String newAppointmentVersionId = appointmentId.getVersionIdPart();
    if (newAppointmentVersionId != null && !newAppointmentVersionId.equalsIgnoreCase(oldAppointmentVersionId)) {
        throw new ResourceVersionConflictException("The specified version (" + newAppointmentVersionId + ") did not match the current resource version (" + oldAppointmentVersionId + ")");
    }
    // Determin if it is a cancel or an amend
    if (appointmentDetail.getCancellationReason() != null) {
        if (appointmentDetail.getCancellationReason().isEmpty()) {
            operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("The cancellation reason can not be blank");
            methodOutcome.setOperationOutcome(operationalOutcome);
            return methodOutcome;
        }
        // This is a Cancellation - so copy across fields which can be
        // altered
        boolean cancelComparisonResult = compareAppointmentsForInvalidPropertyCancel(oldAppointmentDetail, appointmentDetail);
        if (cancelComparisonResult) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(400, "Invalid Appointment property has been amended (cancellation)"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        oldAppointmentDetail.setCancellationReason(appointmentDetail.getCancellationReason());
        String oldStatus = oldAppointmentDetail.getStatus();
        appointmentDetail = oldAppointmentDetail;
        appointmentDetail.setStatus("cancelled");
        if (!"cancelled".equalsIgnoreCase(oldStatus)) {
            for (Long slotId : appointmentDetail.getSlotIds()) {
                SlotDetail slotDetail = slotSearch.findSlotByID(slotId);
                // slotDetail.setAppointmentId(null);
                slotDetail.setFreeBusyType("FREE");
                slotDetail.setLastUpdated(new Date());
                slotStore.saveSlot(slotDetail);
            }
        }
    } else {
        if (appointment.getStatus().equals("cancelled")) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(400, "Appointment has been cancelled and cannot be amended"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        boolean amendComparisonResult = compareAppointmentsForInvalidPropertyAmend(appointmentDetail, oldAppointmentDetail);
        if (amendComparisonResult) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(403, "Invalid Appointment property has been amended"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        // This is an Amend
        oldAppointmentDetail.setComment(appointmentDetail.getComment());
        oldAppointmentDetail.setReasonCode(appointmentDetail.getReasonCode());
        oldAppointmentDetail.setDescription(appointmentDetail.getDescription());
        oldAppointmentDetail.setReasonDisplay(appointmentDetail.getReasonDisplay());
        oldAppointmentDetail.setTypeCode(appointmentDetail.getTypeCode());
        oldAppointmentDetail.setTypeDisplay(appointmentDetail.getTypeDisplay());
        appointmentDetail = oldAppointmentDetail;
    }
    List<SlotDetail> slots = new ArrayList<>();
    for (Long slotId : appointmentDetail.getSlotIds()) {
        SlotDetail slotDetail = slotSearch.findSlotByID(slotId);
        if (slotDetail == null) {
            throw new UnprocessableEntityException("Slot resource reference is not a valid resource");
        }
        slots.add(slotDetail);
    }
    // Update version and
    appointmentDetail.setLastUpdated(new Date());
    // lastUpdated timestamp
    appointmentDetail = appointmentStore.saveAppointment(appointmentDetail, slots);
    methodOutcome.setId(new IdDt("Appointment", appointmentDetail.getId()));
    methodOutcome.setResource(appointmentDetailToAppointmentResourceConverter(appointmentDetail));
    return methodOutcome;
}
Also used : UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) AppointmentDetail(uk.gov.hscic.model.appointment.AppointmentDetail) ArrayList(java.util.ArrayList) IdDt(ca.uhn.fhir.model.primitive.IdDt) ResourceVersionConflictException(ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException) MethodOutcome(ca.uhn.fhir.rest.api.MethodOutcome) Date(java.util.Date) UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) OperationOutcome(org.hl7.fhir.dstu3.model.OperationOutcome) SlotDetail(uk.gov.hscic.model.appointment.SlotDetail) Update(ca.uhn.fhir.rest.annotation.Update)

Aggregations

DomainResource (org.hl7.fhir.r4.model.DomainResource)3 SlotDetail (uk.gov.hscic.model.appointment.SlotDetail)3 IdDt (ca.uhn.fhir.model.primitive.IdDt)2 MethodOutcome (ca.uhn.fhir.rest.api.MethodOutcome)2 Path (java.nio.file.Path)2 Date (java.util.Date)2 Diagnostic (org.eclipse.lsp4j.Diagnostic)2 Appointment (org.hl7.fhir.dstu3.model.Appointment)2 CodeableConcept (org.hl7.fhir.r4.model.CodeableConcept)2 Resource (org.hl7.fhir.r4.model.Resource)2 StatusMessage (org.sagebionetworks.bridge.models.StatusMessage)2 AppointmentDetail (uk.gov.hscic.model.appointment.AppointmentDetail)2 ScheduleDetail (uk.gov.hscic.model.appointment.ScheduleDetail)2 IParser (ca.uhn.fhir.parser.IParser)1 Update (ca.uhn.fhir.rest.annotation.Update)1 ResourceVersionConflictException (ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException)1 UnclassifiedServerFailureException (ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException)1 UnprocessableEntityException (ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException)1 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 ConverterConfiguration (io.github.linuxforhealth.core.config.ConverterConfiguration)1