Search in sources :

Example 1 with CompositionDto

use of org.ehrbase.response.ehrscape.CompositionDto in project ehrbase by ehrbase.

the class CompositionServiceImp method getOriginalVersionComposition.

@Override
public Optional<OriginalVersion<Composition>> getOriginalVersionComposition(UUID versionedObjectUid, int version) {
    // check for valid version parameter
    if ((version == 0) || I_CompositionAccess.getLastVersionNumber(getDataAccess(), versionedObjectUid) < version) {
        throw new ObjectNotFoundException("versioned_composition", "No VERSIONED_COMPOSITION with given version: " + version);
    }
    // retrieve requested object
    I_CompositionAccess compositionAccess = I_CompositionAccess.retrieveCompositionVersion(getDataAccess(), versionedObjectUid, version);
    if (compositionAccess == null) {
        return Optional.empty();
    }
    // create data for output, i.e. fields of the OriginalVersion<Composition>
    ObjectVersionId versionId = new ObjectVersionId(versionedObjectUid + "::" + getServerConfig().getNodename() + "::" + version);
    DvCodedText lifecycleState = new DvCodedText("complete", new CodePhrase(// TODO: once lifecycle state is supported, get it here dynamically
    "532"));
    AuditDetails commitAudit = compositionAccess.getAuditDetailsAccess().getAsAuditDetails();
    ObjectRef<HierObjectId> contribution = new ObjectRef<>(new HierObjectId(compositionAccess.getContributionId().toString()), "openehr", "contribution");
    List<UUID> attestationIdList = I_AttestationAccess.retrieveListOfAttestationsByRef(getDataAccess(), compositionAccess.getAttestationRef());
    List<Attestation> attestations = // as default, gets content if available in the following lines
    null;
    if (!attestationIdList.isEmpty()) {
        attestations = new ArrayList<>();
        for (UUID id : attestationIdList) {
            I_AttestationAccess a = new AttestationAccess(getDataAccess()).retrieveInstance(id);
            attestations.add(a.getAsAttestation());
        }
    }
    ObjectVersionId precedingVersionId = null;
    // check if there is a preceding version and set it, if available
    if (version > 1) {
        // in the current scope version is an int and therefore: preceding = current - 1
        precedingVersionId = new ObjectVersionId(versionedObjectUid + "::" + getServerConfig().getNodename() + "::" + (version - 1));
    }
    Optional<CompositionDto> compositionDto = retrieve(versionedObjectUid, version);
    Composition composition = null;
    if (compositionDto.isPresent()) {
        composition = compositionDto.get().getComposition();
    }
    OriginalVersion<Composition> versionComposition = new OriginalVersion<>(versionId, precedingVersionId, composition, lifecycleState, commitAudit, contribution, null, null, attestations);
    return Optional.of(versionComposition);
}
Also used : OriginalVersion(com.nedap.archie.rm.changecontrol.OriginalVersion) Composition(com.nedap.archie.rm.composition.Composition) VersionedComposition(com.nedap.archie.rm.ehr.VersionedComposition) DvCodedText(com.nedap.archie.rm.datavalues.DvCodedText) CodePhrase(com.nedap.archie.rm.datatypes.CodePhrase) I_AttestationAccess(org.ehrbase.dao.access.interfaces.I_AttestationAccess) I_AttestationAccess(org.ehrbase.dao.access.interfaces.I_AttestationAccess) AttestationAccess(org.ehrbase.dao.access.jooq.AttestationAccess) ObjectVersionId(com.nedap.archie.rm.support.identification.ObjectVersionId) Attestation(com.nedap.archie.rm.generic.Attestation) ObjectNotFoundException(org.ehrbase.api.exception.ObjectNotFoundException) CompositionDto(org.ehrbase.response.ehrscape.CompositionDto) I_CompositionAccess(org.ehrbase.dao.access.interfaces.I_CompositionAccess) AuditDetails(com.nedap.archie.rm.generic.AuditDetails) ObjectRef(com.nedap.archie.rm.support.identification.ObjectRef) UUID(java.util.UUID) HierObjectId(com.nedap.archie.rm.support.identification.HierObjectId)

Example 2 with CompositionDto

use of org.ehrbase.response.ehrscape.CompositionDto in project ehrbase by ehrbase.

the class ContributionServiceImp method processMetadataVersion.

/**
 * Helper to process versions from a contribution, which do not have the optional "data" attribute and therefore are called metadata versions.
 * @param ehrId ID of given EHR scope
 * @param contributionId Top level contribution this version is part of
 * @param version The version wrapper object
 */
private void processMetadataVersion(UUID ehrId, UUID contributionId, Version version) {
    // access audit and extract method, e.g. CREATION
    I_ConceptAccess.ContributionChangeType changeType = I_ConceptAccess.ContributionChangeType.valueOf(version.getCommitAudit().getChangeType().getValue().toUpperCase());
    switch(changeType) {
        case DELETED:
            // deleting an object without knowing which type it is requires checking of type, here with nested try-catch blocks
            UUID objectUid = getVersionedUidFromVersion(version);
            try {
                // throw exception to signal no matching composition was found
                CompositionDto compo = compositionService.retrieve(objectUid, null).orElseThrow(Exception::new);
                String actualPreceding = getAndCheckActualPreceding(version);
                compositionService.delete(ehrId, new ObjectVersionId(actualPreceding), contributionId);
            } catch (Exception e) {
                // given version ID is not of type composition - ignoring the exception because it is expected possible outcome
                try {
                // TODO-396: add folder handling
                } catch (Exception ee) {
                    // given version ID is not of type folder - ignoring the exception because it is expected possible outcome
                    // current end of going through supported types - last step is checking for EHR_STATUS and throwing specific error
                    ehrService.getEhrStatus(ehrId).ifPresent(st -> {
                        if (st.getUid().equals(version.getPrecedingVersionUid()))
                            throw new InvalidApiParameterException("Invalid change type. EHR_STATUS can't be deleted.");
                    });
                    // TODO: type is technically wrong, if more than one type gets tested
                    throw new ObjectNotFoundException(Composition.class.getName(), "Couldn't find object matching id: " + objectUid);
                }
            }
            break;
        // TODO
        case SYNTHESIS:
        // TODO
        case UNKNOWN:
        // not expected in a metadata version (i.e. without payload)
        case CREATION:
        // not expected in a metadata version (i.e. without payload)
        case MODIFICATION:
        // not expected in a metadata version (i.e. without payload)
        case AMENDMENT:
        default:
            throw new UnexpectedSwitchCaseException(changeType);
    }
}
Also used : Composition(com.nedap.archie.rm.composition.Composition) CompositionDto(org.ehrbase.response.ehrscape.CompositionDto) ObjectVersionId(com.nedap.archie.rm.support.identification.ObjectVersionId)

Example 3 with CompositionDto

use of org.ehrbase.response.ehrscape.CompositionDto in project ehrbase by ehrbase.

the class OpenehrCompositionController method updateComposition.

@PutMapping("/{ehr_id}/composition/{versioned_object_uid}")
// checkAbacPre /-Post attributes (type, subject, payload, content type)
@PreAuthorize("checkAbacPre(@openehrCompositionController.COMPOSITION, " + "@ehrService.getSubjectExtRef(#ehrIdString), #composition, #contentType)")
@Override
public ResponseEntity updateComposition(String openehrVersion, @RequestHeader(value = "openEHR-AUDIT_DETAILS", required = false) String openehrAuditDetails, @RequestHeader(value = CONTENT_TYPE, required = false) String contentType, @RequestHeader(value = ACCEPT, required = false) String accept, @RequestHeader(value = PREFER, required = false) String prefer, @RequestHeader(value = IF_MATCH) String ifMatch, @PathVariable(value = "ehr_id") String ehrIdString, @PathVariable(value = "versioned_object_uid") String versionedObjectUidString, @RequestBody String composition, HttpServletRequest request) {
    UUID ehrId = getEhrUuid(ehrIdString);
    UUID versionedObjectUid = getCompositionVersionedObjectUidString(versionedObjectUidString);
    CompositionFormat compositionFormat = extractCompositionFormat(contentType);
    // check if composition ID path variable is valid
    compositionService.exists(versionedObjectUid);
    // If the If-Match is not the latest latest existing version, throw error
    if (!((versionedObjectUid + "::" + compositionService.getServerConfig().getNodename() + "::" + compositionService.getLastVersionNumber(extractVersionedObjectUidFromVersionUid(versionedObjectUid.toString()))).equals(ifMatch))) {
        throw new PreconditionFailedException("If-Match header does not match latest existing version");
    }
    // If body already contains a composition uid it must match the {versioned_object_uid} in request url
    Optional<String> inputUuid = Optional.ofNullable(compositionService.getUidFromInputComposition(composition, compositionFormat));
    inputUuid.ifPresent(id -> {
        // TODO it is further unclear what exactly the REST spec's "match" means, see: https://github.com/openEHR/specifications-ITS-REST/issues/83
        if (!versionedObjectUid.equals(extractVersionedObjectUidFromVersionUid(id))) {
            throw new PreconditionFailedException("UUID from input must match given versioned_object_uid in request URL");
        }
    });
    // variable to overload with more specific object if requested
    Optional<InternalResponse<CompositionResponseData>> respData = Optional.empty();
    try {
        Composition compoObj = compositionService.buildComposition(composition, compositionFormat, null);
        // TODO should have EHR as parameter and check for existence as precondition - see EHR-245 (no direct EHR access in this controller)
        // ifMatch header has to be tested for correctness already above
        Optional<CompositionDto> dtoOptional = compositionService.update(ehrId, new ObjectVersionId(ifMatch), compoObj);
        var compositionVersionUid = dtoOptional.orElseThrow(() -> new InternalServerException("Failed to create composition")).getComposition().getUid().toString();
        var uri = URI.create(this.encodePath(getBaseEnvLinkURL() + "/rest/openehr/v1/ehr/" + ehrId.toString() + "/composition/" + compositionVersionUid));
        List<String> headerList = Arrays.asList(LOCATION, ETAG, // whatever is required by REST spec - CONTENT_TYPE only needed for 200, so handled separately
        LAST_MODIFIED);
        UUID compositionId = extractVersionedObjectUidFromVersionUid(compositionVersionUid);
        if (RETURN_REPRESENTATION.equals(prefer)) {
            // both options extract needed info from versionUid
            respData = buildCompositionResponseData(compositionId, extractVersionFromVersionUid(compositionVersionUid), accept, uri, headerList, () -> new CompositionResponseData(null, null));
        } else {
            // "minimal" is default fallback
            respData = buildCompositionResponseData(compositionId, extractVersionFromVersionUid(compositionVersionUid), accept, uri, headerList, () -> null);
        }
        // Enriches request attributes with current compositionId for later audit processing
        request.setAttribute(OpenEhrAuditInterceptor.EHR_ID_ATTRIBUTE, Collections.singleton(ehrId));
        request.setAttribute(CompositionAuditInterceptor.COMPOSITION_ID_ATTRIBUTE, compositionId);
    } catch (ObjectNotFoundException e) {
        // composition not found
        return ResponseEntity.notFound().build();
    }
    // returns 200 with body + headers, 204 only with headers or 500 error depending on what processing above yields
    return respData.map(i -> Optional.ofNullable(i.getResponseData()).map(StructuredString::getValue).map(j -> ResponseEntity.ok().headers(i.getHeaders()).body(j)).orElse(ResponseEntity.noContent().headers(i.getHeaders()).build())).orElse(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
}
Also used : CompositionResponseData(org.ehrbase.response.openehr.CompositionResponseData) PathVariable(org.springframework.web.bind.annotation.PathVariable) Arrays(java.util.Arrays) RequestParam(org.springframework.web.bind.annotation.RequestParam) Composition(com.nedap.archie.rm.composition.Composition) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) ZonedDateTime(java.time.ZonedDateTime) LocalDateTime(java.time.LocalDateTime) ObjectNotFoundException(org.ehrbase.api.exception.ObjectNotFoundException) Autowired(org.springframework.beans.factory.annotation.Autowired) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) Supplier(java.util.function.Supplier) RequestBody(org.springframework.web.bind.annotation.RequestBody) HttpServletRequest(javax.servlet.http.HttpServletRequest) PutMapping(org.springframework.web.bind.annotation.PutMapping) CompositionResponseData(org.ehrbase.response.openehr.CompositionResponseData) CompositionAuditInterceptor(org.ehrbase.rest.openehr.audit.CompositionAuditInterceptor) GetMapping(org.springframework.web.bind.annotation.GetMapping) URI(java.net.URI) PreconditionFailedException(org.ehrbase.api.exception.PreconditionFailedException) ObjectVersionId(com.nedap.archie.rm.support.identification.ObjectVersionId) ResponseStatus(org.springframework.web.bind.annotation.ResponseStatus) DeleteMapping(org.springframework.web.bind.annotation.DeleteMapping) PostMapping(org.springframework.web.bind.annotation.PostMapping) HttpHeaders(org.springframework.http.HttpHeaders) MediaType(org.springframework.http.MediaType) CompositionDto(org.ehrbase.response.ehrscape.CompositionDto) PostAuthorize(org.springframework.security.access.prepost.PostAuthorize) UUID(java.util.UUID) RestController(org.springframework.web.bind.annotation.RestController) ZoneId(java.time.ZoneId) StructuredString(org.ehrbase.response.ehrscape.StructuredString) BaseController(org.ehrbase.rest.BaseController) Objects(java.util.Objects) HttpStatus(org.springframework.http.HttpStatus) List(java.util.List) OffsetDateTime(java.time.OffsetDateTime) CompositionService(org.ehrbase.api.service.CompositionService) InternalServerException(org.ehrbase.api.exception.InternalServerException) OpenEhrAuditInterceptor(org.ehrbase.rest.openehr.audit.OpenEhrAuditInterceptor) InternalResponse(org.ehrbase.rest.util.InternalResponse) Optional(java.util.Optional) CompositionApiSpecification(org.ehrbase.rest.openehr.specification.CompositionApiSpecification) ResponseEntity(org.springframework.http.ResponseEntity) RequestHeader(org.springframework.web.bind.annotation.RequestHeader) Collections(java.util.Collections) CompositionFormat(org.ehrbase.response.ehrscape.CompositionFormat) CompositionFormat(org.ehrbase.response.ehrscape.CompositionFormat) Composition(com.nedap.archie.rm.composition.Composition) InternalServerException(org.ehrbase.api.exception.InternalServerException) StructuredString(org.ehrbase.response.ehrscape.StructuredString) InternalResponse(org.ehrbase.rest.util.InternalResponse) ObjectVersionId(com.nedap.archie.rm.support.identification.ObjectVersionId) ObjectNotFoundException(org.ehrbase.api.exception.ObjectNotFoundException) CompositionDto(org.ehrbase.response.ehrscape.CompositionDto) StructuredString(org.ehrbase.response.ehrscape.StructuredString) PreconditionFailedException(org.ehrbase.api.exception.PreconditionFailedException) UUID(java.util.UUID) PutMapping(org.springframework.web.bind.annotation.PutMapping) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize)

Example 4 with CompositionDto

use of org.ehrbase.response.ehrscape.CompositionDto in project ehrbase by ehrbase.

the class CompositionController method getComposition.

@GetMapping(path = "/{uid}")
public ResponseEntity<CompositionResponseData> getComposition(@PathVariable("uid") String compositionUid, @RequestParam(value = "format", defaultValue = "XML") CompositionFormat format) {
    UUID identifier = getCompositionIdentifier(compositionUid);
    Integer version = null;
    if (isFullCompositionUid(compositionUid)) {
        // version number is inorder: 1, 2, 3 etc.
        version = getCompositionVersion(compositionUid);
    }
    Optional<CompositionDto> compositionDto = compositionService.retrieve(identifier, version);
    if (compositionDto.isPresent()) {
        // Serialize onto target format
        StructuredString serialize = compositionService.serialize(compositionDto.get(), format);
        CompositionResponseData responseDto = new CompositionResponseData();
        responseDto.setComposition(serialize);
        responseDto.setAction(Action.RETRIEVE);
        responseDto.setFormat(format);
        responseDto.setTemplateId(compositionDto.get().getTemplateId());
        responseDto.setCompositionUid(compositionDto.get().getUuid().toString());
        responseDto.setEhrId(compositionDto.get().getEhrId());
        Meta meta = buildMeta(responseDto.getCompositionUid());
        responseDto.setMeta(meta);
        return ResponseEntity.ok(responseDto);
    } else {
        return ResponseEntity.notFound().build();
    }
}
Also used : CompositionResponseData(org.ehrbase.rest.ehrscape.responsedata.CompositionResponseData) Meta(org.ehrbase.rest.ehrscape.responsedata.Meta) CompositionDto(org.ehrbase.response.ehrscape.CompositionDto) StructuredString(org.ehrbase.response.ehrscape.StructuredString) UUID(java.util.UUID) GetMapping(org.springframework.web.bind.annotation.GetMapping)

Example 5 with CompositionDto

use of org.ehrbase.response.ehrscape.CompositionDto in project ehrbase by ehrbase.

the class CompositionController method update.

@PutMapping(path = "/{uid}")
public ResponseEntity<ActionRestResponseData> update(@PathVariable("uid") String compositionUid, @RequestParam(value = "format", defaultValue = "XML") CompositionFormat format, @RequestParam(value = "templateId", required = false) String templateId, @RequestBody String content) {
    if ((format == CompositionFormat.FLAT || format == CompositionFormat.STRUCTURED || format == CompositionFormat.ECISFLAT) && StringUtils.isEmpty(templateId)) {
        throw new InvalidApiParameterException(String.format("Template Id needs to specified for format %s", format));
    }
    ObjectVersionId objectVersionId = getObjectVersionId(compositionUid);
    UUID compositionIdentifier = getCompositionIdentifier(compositionUid);
    UUID ehrId = getEhrId(compositionIdentifier);
    var compoObj = compositionService.buildComposition(content, format, templateId);
    // Actual update
    Optional<CompositionDto> dtoOptional = compositionService.update(ehrId, objectVersionId, compoObj);
    var compositionVersionUid = dtoOptional.orElseThrow(() -> new InternalServerException("Failed to create composition")).getComposition().getUid().toString();
    ActionRestResponseData responseData = new ActionRestResponseData();
    responseData.setAction(Action.UPDATE);
    responseData.setMeta(buildMeta(compositionVersionUid));
    return ResponseEntity.ok(responseData);
}
Also used : InvalidApiParameterException(org.ehrbase.api.exception.InvalidApiParameterException) InternalServerException(org.ehrbase.api.exception.InternalServerException) CompositionDto(org.ehrbase.response.ehrscape.CompositionDto) ObjectVersionId(com.nedap.archie.rm.support.identification.ObjectVersionId) UUID(java.util.UUID) ActionRestResponseData(org.ehrbase.rest.ehrscape.responsedata.ActionRestResponseData) PutMapping(org.springframework.web.bind.annotation.PutMapping)

Aggregations

CompositionDto (org.ehrbase.response.ehrscape.CompositionDto)7 ObjectVersionId (com.nedap.archie.rm.support.identification.ObjectVersionId)4 UUID (java.util.UUID)4 Composition (com.nedap.archie.rm.composition.Composition)3 InternalServerException (org.ehrbase.api.exception.InternalServerException)3 ObjectNotFoundException (org.ehrbase.api.exception.ObjectNotFoundException)3 StructuredString (org.ehrbase.response.ehrscape.StructuredString)3 VersionedComposition (com.nedap.archie.rm.ehr.VersionedComposition)2 HierObjectId (com.nedap.archie.rm.support.identification.HierObjectId)2 I_CompositionAccess (org.ehrbase.dao.access.interfaces.I_CompositionAccess)2 CompositionFormat (org.ehrbase.response.ehrscape.CompositionFormat)2 CompositionResponseData (org.ehrbase.response.openehr.CompositionResponseData)2 GetMapping (org.springframework.web.bind.annotation.GetMapping)2 PutMapping (org.springframework.web.bind.annotation.PutMapping)2 OriginalVersion (com.nedap.archie.rm.changecontrol.OriginalVersion)1 CodePhrase (com.nedap.archie.rm.datatypes.CodePhrase)1 DvCodedText (com.nedap.archie.rm.datavalues.DvCodedText)1 DvDateTime (com.nedap.archie.rm.datavalues.quantity.datetime.DvDateTime)1 Attestation (com.nedap.archie.rm.generic.Attestation)1 AuditDetails (com.nedap.archie.rm.generic.AuditDetails)1