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);
}
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);
}
}
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());
}
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();
}
}
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);
}
Aggregations