use of com.nedap.archie.rm.support.identification.ObjectVersionId 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 com.nedap.archie.rm.support.identification.ObjectVersionId 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);
}
use of com.nedap.archie.rm.support.identification.ObjectVersionId in project ehrbase by ehrbase.
the class CompositionController method delete.
@DeleteMapping(path = "/{uid}")
public ResponseEntity<ActionRestResponseData> delete(@PathVariable("uid") String compositionUid) {
ObjectVersionId objectVersionId = getObjectVersionId(compositionUid);
UUID compositionIdentifier = getCompositionIdentifier(compositionUid);
UUID ehrId = getEhrId(compositionIdentifier);
compositionService.delete(ehrId, objectVersionId);
ActionRestResponseData responseData = new ActionRestResponseData();
responseData.setAction(Action.DELETE);
responseData.setMeta(buildMeta(""));
return ResponseEntity.ok(responseData);
}
use of com.nedap.archie.rm.support.identification.ObjectVersionId in project openEHR_SDK by ehrbase.
the class DefaultRestFolderDAO method addCompositionEntity.
@Override
public <T> T addCompositionEntity(T entity) {
T updatedEntity = directoryEndpoint.getCompositionEndpoint().mergeCompositionEntity(entity);
UUID uuid = DefaultRestCompositionEndpoint.extractVersionUid(updatedEntity).orElseThrow(() -> new ClientException(String.format("No Id Element for %s", entity.getClass()))).getUuid();
Folder folder = getFolder();
if (folder.getItems() == null) {
folder.setItems(new ArrayList<>());
}
folder.getItems().add(new ObjectRef(new ObjectVersionId(uuid.toString()), "dffddfd", "VERSIONED_COMPOSITION"));
directoryEndpoint.saveToDb();
return updatedEntity;
}
use of com.nedap.archie.rm.support.identification.ObjectVersionId in project ehrbase by ehrbase.
the class EntryAccess method retrieveInstanceInComposition.
/**
* @throws IllegalArgumentException if DB is inconsistent or operation fails
*/
public static List<I_EntryAccess> retrieveInstanceInComposition(I_DomainAccess domainAccess, I_CompositionAccess compositionAccess) {
Result<EntryRecord> entryRecords = domainAccess.getContext().selectFrom(ENTRY).where(ENTRY.COMPOSITION_ID.eq(compositionAccess.getId())).fetch();
// build the list of parameters to recreate the composition
Map<SystemValue, Object> values = new HashMap<>();
values.put(SystemValue.COMPOSER, new PersistedPartyProxy(domainAccess).retrieve(compositionAccess.getComposerId()));
// optional handling for persistent compositions that do not have a context
Optional<I_ContextAccess> opContextAccess = compositionAccess.getContextId().map(id -> I_ContextAccess.retrieveInstance(domainAccess, id));
opContextAccess.ifPresent(context -> values.put(SystemValue.CONTEXT, context.mapRmEventContext()));
values.put(SystemValue.LANGUAGE, new CodePhrase(new TerminologyId("ISO_639-1"), compositionAccess.getLanguageCode()));
String territory2letters = domainAccess.getContext().fetchOne(TERRITORY, TERRITORY.CODE.eq(compositionAccess.getTerritoryCode())).getTwoletter();
values.put(SystemValue.TERRITORY, new CodePhrase(new TerminologyId("ISO_3166-1"), territory2letters));
if (compositionAccess.getFeederAudit() != null) {
values.put(SystemValue.FEEDER_AUDIT, new FeederAuditEncoding().fromDB(compositionAccess.getFeederAudit()));
}
if (compositionAccess.getLinks() != null) {
values.put(SystemValue.LINKS, new LinksEncoding().fromDB(compositionAccess.getLinks()));
}
List<I_EntryAccess> content = new ArrayList<>();
try {
EntryAccess entryAccess = new EntryAccess(domainAccess);
for (EntryRecord record : entryRecords) {
// set the record UID in the composition with matching version number
Integer version = I_CompositionAccess.getLastVersionNumber(domainAccess, compositionAccess.getId());
values.put(SystemValue.UID, new ObjectVersionId(compositionAccess.getId().toString() + "::" + domainAccess.getServerConfig().getNodename() + "::" + version));
entryAccess.entryRecord = record;
String value = record.getEntry().data();
entryAccess.composition = new RawJson().unmarshal(value, Composition.class);
// continuing optional handling for persistent compositions
opContextAccess.map(I_ContextAccess::mapRmEventContext).ifPresent(ec -> values.put(SystemValue.CONTEXT, ec));
values.put(SystemValue.CATEGORY, new RecordedDvCodedText().fromDB(record, ENTRY.CATEGORY));
setCompositionAttributes(entryAccess.composition, values);
buildArchetypeDetails(entryAccess);
content.add(entryAccess);
}
} catch (Exception e) {
throw new IllegalArgumentException(DB_INCONSISTENCY + e);
}
return content;
}
Aggregations