All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ehrbase.repository.ContributionRepository Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2024 vitasystems GmbH.
 *
 * This file is part of project EHRbase
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ehrbase.repository;

import static org.ehrbase.jooq.pg.Tables.AUDIT_DETAILS;
import static org.ehrbase.jooq.pg.Tables.CONTRIBUTION;

import com.nedap.archie.rm.datatypes.CodePhrase;
import com.nedap.archie.rm.datavalues.DvCodedText;
import com.nedap.archie.rm.datavalues.DvText;
import com.nedap.archie.rm.datavalues.quantity.datetime.DvDateTime;
import com.nedap.archie.rm.generic.PartyProxy;
import com.nedap.archie.rm.support.identification.TerminologyId;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import org.ehrbase.api.exception.UnexpectedSwitchCaseException;
import org.ehrbase.api.service.ContributionService;
import org.ehrbase.api.service.SystemService;
import org.ehrbase.jooq.pg.enums.ContributionChangeType;
import org.ehrbase.jooq.pg.enums.ContributionDataType;
import org.ehrbase.jooq.pg.tables.AuditDetails;
import org.ehrbase.jooq.pg.tables.Contribution;
import org.ehrbase.jooq.pg.tables.records.AuditDetailsRecord;
import org.ehrbase.jooq.pg.tables.records.ContributionRecord;
import org.ehrbase.openehr.sdk.serialisation.jsonencoding.CanonicalJson;
import org.ehrbase.service.TimeProvider;
import org.ehrbase.service.UserService;
import org.ehrbase.util.UuidGenerator;
import org.jooq.DSLContext;
import org.jooq.JSONB;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Handles DB-Access to {@link Contribution} and {@link AuditDetails}
 */
@Repository
public class ContributionRepository {

    private final DSLContext context;
    private final SystemService systemService;
    private final UserService userService;
    private final PartyProxyRepository partyProxyRepository;

    private final TimeProvider timeProvider;

    public ContributionRepository(
            DSLContext context,
            SystemService systemService,
            UserService userService,
            PartyProxyRepository partyProxyRepository,
            TimeProvider timeProvider) {
        this.context = context;
        this.systemService = systemService;
        this.userService = userService;
        this.partyProxyRepository = partyProxyRepository;

        this.timeProvider = timeProvider;
    }

    /**
     * Create the default contribution in the DB for usage in case data is not saved via explicit provided contribution. Sets the committer from the auth context.
     *
     * @param ehrId
     * @param contributionType
     * @param contributionChangeType
     * @return {@link UUID} of the corresponding Database Record.
     */
    @Transactional
    public UUID createDefault(
            UUID ehrId, ContributionDataType contributionType, ContributionChangeType contributionChangeType) {

        UUID auditDetailsRecordId = createDefaultAudit(contributionChangeType, AuditDetailsTargetType.CONTRIBUTION);

        return createContribution(ehrId, UuidGenerator.randomUUID(), contributionType, auditDetailsRecordId);
    }

    /**
     * Create the default audit in the DB  for usage in case data is not saved via explicit provided contribution. Sets the committer from the auth context.
     *
     * @param contributionChangeType
     * @return {@link UUID} of the corresponding Database Record.
     */
    @Transactional
    public UUID createDefaultAudit(ContributionChangeType contributionChangeType, AuditDetailsTargetType targetType) {
        AuditDetailsRecord auditDetailsRecord = context.newRecord(AuditDetails.AUDIT_DETAILS);

        auditDetailsRecord.setId(UuidGenerator.randomUUID());
        auditDetailsRecord.setTimeCommitted(timeProvider.getNow());
        auditDetailsRecord.setTargetType(targetType.getAlias());

        auditDetailsRecord.setCommitter(null);
        auditDetailsRecord.setUserId(userService.getCurrentUserId());
        auditDetailsRecord.setChangeType(contributionChangeType);

        auditDetailsRecord.store();
        return auditDetailsRecord.getId();
    }

    @Transactional
    public UUID createContribution(
            UUID ehrId, UUID contributionUuid, ContributionDataType contributionType, UUID auditDetailsRecordId) {

        ContributionRecord contributionRecord = context.newRecord(Contribution.CONTRIBUTION);

        contributionRecord.setEhrId(ehrId);
        contributionRecord.setId(contributionUuid);
        contributionRecord.setContributionType(contributionType);
        contributionRecord.setHasAudit(auditDetailsRecordId);

        contributionRecord.store();

        return contributionRecord.getId();
    }

    /**
     * Creates a Audit in the Database
     *
     * @param auditDetails {@link AuditDetails} from which to take the data.
     * @param targetType
     * @return {@link UUID} of the corresponding Database Record.
     */
    @Transactional
    public UUID createAudit(com.nedap.archie.rm.generic.AuditDetails auditDetails, AuditDetailsTargetType targetType) {

        AuditDetailsRecord auditDetailsRecord = context.newRecord(AuditDetails.AUDIT_DETAILS);

        auditDetailsRecord.setId(UuidGenerator.randomUUID());
        auditDetailsRecord.setTimeCommitted(timeProvider.getNow());

        // save committer as json if not user
        if (!partyProxyRepository.fromUser(userService.getCurrentUserId()).equals(auditDetails.getCommitter())) {
            auditDetailsRecord.setCommitter(JSONB.jsonb(new CanonicalJson().marshal(auditDetails.getCommitter())));
        }

        auditDetailsRecord.setTargetType(targetType.getAlias());

        auditDetailsRecord.setChangeType(to(auditDetails.getChangeType()));
        // We just save the text here wich is not 100 % correct here.
        auditDetailsRecord.setDescription(Optional.ofNullable(auditDetails.getDescription())
                .map(DvText::getValue)
                .orElse(null));
        auditDetailsRecord.setUserId(userService.getCurrentUserId());

        auditDetailsRecord.store();
        return auditDetailsRecord.getId();
    }

    private ContributionChangeType to(DvCodedText changeType) {

        return switch (changeType.getDefiningCode().getCodeString()) {
            case "249" -> ContributionChangeType.creation;
            case "250" -> ContributionChangeType.amendment;
            case "251" -> ContributionChangeType.modification;
            case "252" -> ContributionChangeType.synthesis;
            case "253" -> ContributionChangeType.Unknown;
            case "523" -> ContributionChangeType.deleted;
            default -> throw new UnexpectedSwitchCaseException(changeType.toString());
        };
    }

    public ContributionRecord findById(UUID contibutionId) {

        return context.fetchOne(CONTRIBUTION, CONTRIBUTION.ID.eq(contibutionId));
    }

    public com.nedap.archie.rm.generic.AuditDetails findAuditDetails(UUID auditId) {

        AuditDetailsRecord auditDetailsRecord =
                context.fetchOne(AuditDetails.AUDIT_DETAILS, AUDIT_DETAILS.ID.eq(auditId));
        Objects.requireNonNull(auditDetailsRecord);

        com.nedap.archie.rm.generic.AuditDetails auditDetails = new com.nedap.archie.rm.generic.AuditDetails();

        auditDetails.setSystemId(systemService.getSystemId());

        if (auditDetailsRecord.getCommitter() != null) {
            auditDetails.setCommitter(new CanonicalJson()
                    .unmarshal(auditDetailsRecord.getCommitter().data(), PartyProxy.class));
        } else {
            auditDetails.setCommitter(partyProxyRepository.fromUser(auditDetailsRecord.getUserId()));
        }
        auditDetails.setDescription(new DvText(auditDetailsRecord.getDescription()));

        DvCodedText changeType = new DvCodedText(
                auditDetailsRecord.getChangeType().getLiteral(),
                new CodePhrase(
                        new TerminologyId("openehr"),
                        Integer.toString(ContributionService.ContributionChangeType.valueOf(auditDetailsRecord
                                        .getChangeType()
                                        .getLiteral()
                                        .toUpperCase())
                                .getCode())));
        auditDetails.setChangeType(changeType);

        DvDateTime time = new DvDateTime(auditDetailsRecord.getTimeCommitted());
        auditDetails.setTimeCommitted(time);

        return auditDetails;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy