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

org.ehrbase.dao.access.jooq.StatusAccess Maven / Gradle / Ivy

There is a newer version: 2.12.0
Show newest version
/*
 * Copyright (c) 2019 vitasystems GmbH and Hannover Medical School.
 *
 * 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.dao.access.jooq;

import static org.ehrbase.jooq.pg.Tables.PARTY_IDENTIFIED;
import static org.ehrbase.jooq.pg.Tables.STATUS;
import static org.ehrbase.jooq.pg.Tables.STATUS_HISTORY;
import static org.jooq.impl.DSL.count;

import com.nedap.archie.rm.datastructures.ItemStructure;
import com.nedap.archie.rm.datavalues.DvCodedText;
import com.nedap.archie.rm.datavalues.DvText;
import com.nedap.archie.rm.ehr.EhrStatus;
import com.nedap.archie.rm.generic.PartySelf;
import com.nedap.archie.rm.support.identification.HierObjectId;
import com.nedap.archie.rm.support.identification.ObjectVersionId;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.ehrbase.api.exception.InternalServerException;
import org.ehrbase.api.exception.InvalidApiParameterException;
import org.ehrbase.api.exception.ObjectNotFoundException;
import org.ehrbase.dao.access.interfaces.I_AuditDetailsAccess;
import org.ehrbase.dao.access.interfaces.I_ConceptAccess;
import org.ehrbase.dao.access.interfaces.I_ConceptAccess.ContributionChangeType;
import org.ehrbase.dao.access.interfaces.I_ContributionAccess;
import org.ehrbase.dao.access.interfaces.I_DomainAccess;
import org.ehrbase.dao.access.interfaces.I_StatusAccess;
import org.ehrbase.dao.access.jooq.party.PersistedPartyProxy;
import org.ehrbase.dao.access.support.DataAccess;
import org.ehrbase.dao.access.util.ContributionDef;
import org.ehrbase.jooq.pg.tables.records.StatusHistoryRecord;
import org.ehrbase.jooq.pg.tables.records.StatusRecord;
import org.ehrbase.service.RecordedDvCodedText;
import org.jooq.AggregateFunction;
import org.jooq.DSLContext;
import org.jooq.Param;
import org.jooq.Record1;
import org.jooq.Result;
import org.jooq.Table;
import org.jooq.impl.DSL;

/**
 * Persistence operations on EHR status.
 *
 * @author Christian Chevalley
 * @author Jake Smolka
 * @author Luis Marco-Ruiz
 * @since 1.0.0
 */
public class StatusAccess extends DataAccess implements I_StatusAccess {

    private StatusRecord statusRecord;
    private I_ContributionAccess contributionAccess; // locally referenced contribution associated to this status
    private I_AuditDetailsAccess auditDetailsAccess; // audit associated with this status

    public StatusAccess(I_DomainAccess domainAccess, UUID ehrId, Short sysTenant) {
        super(domainAccess);

        statusRecord = getContext().newRecord(STATUS);
        statusRecord.setSysTenant(sysTenant);

        // associate a contribution with this composition
        contributionAccess = I_ContributionAccess.getInstance(this, ehrId, sysTenant);
        contributionAccess.setState(ContributionDef.ContributionState.COMPLETE);

        // associate status' own audit with this status access instance
        auditDetailsAccess = I_AuditDetailsAccess.getInstance(getDataAccess(), sysTenant);
    }

    @Override
    public UUID commit(LocalDateTime timestamp, UUID committerId, UUID systemId, String description) {
        createAndSetContribution(committerId, systemId, description, ContributionChangeType.CREATION);
        return internalCommit(timestamp);
    }

    @Override
    public UUID commit(LocalDateTime timestamp, UUID contribution, UUID audit) {
        if (contribution == null) {
            throw new InternalServerException("Invalid null valued contribution.");
        }
        setContributionId(contribution);

        if (audit != null) {
            statusRecord.setHasAudit(audit);
        }

        return internalCommit(timestamp);
    }

    private UUID internalCommit(LocalDateTime transactionTime) {

        // generate if not externally set
        if (statusRecord.getHasAudit() == null) {
            auditDetailsAccess.setChangeType(
                    I_ConceptAccess.fetchContributionChangeType(this, I_ConceptAccess.ContributionChangeType.CREATION));
            if (auditDetailsAccess.getChangeType() == null
                    || auditDetailsAccess.getSystemId() == null
                    || auditDetailsAccess.getCommitter() == null) {
                throw new InternalServerException(
                        "Illegal to commit AuditDetailsAccess without setting mandatory fields.");
            }
            UUID auditId = auditDetailsAccess.commit();
            statusRecord.setHasAudit(auditId);
        }

        statusRecord.setSysTransaction(Timestamp.valueOf(transactionTime));

        if (statusRecord.store() == 0) {
            throw new InvalidApiParameterException("Input EHR couldn't be stored; Storing EHR_STATUS failed");
        }

        return statusRecord.getId();
    }

    @Override
    public boolean update(
            LocalDateTime timestamp,
            UUID committerId,
            UUID systemId,
            String description,
            ContributionChangeType changeType) {

        createAndSetContribution(committerId, systemId, description, ContributionChangeType.MODIFICATION);

        // new audit ID
        auditDetailsAccess.commit();
        statusRecord.setHasAudit(auditDetailsAccess.getId());

        return internalUpdate(timestamp);
    }

    @Override
    public boolean update(LocalDateTime timestamp, UUID contribution, UUID audit) {
        if (contribution == null) {
            throw new InternalServerException("Invalid null valued contribution.");
        }
        setContributionId(contribution);
        statusRecord.setHasAudit(audit);

        return internalUpdate(timestamp);
    }

    private Boolean internalUpdate(LocalDateTime transactionTime) {

        statusRecord.setSysTransaction(Timestamp.valueOf(transactionTime));

        try {
            return statusRecord.update() > 0;
        } catch (RuntimeException e) {
            throw new InvalidApiParameterException(
                    "Couldn't marshall given EHR_STATUS / OTHER_DETAILS, content probably breaks RM rules");
        }
    }

    @Override
    public int delete(LocalDateTime timestamp, UUID committerId, UUID systemId, String description) {

        createAndSetContribution(committerId, systemId, description, ContributionChangeType.DELETED);

        return internalDelete(timestamp, committerId, systemId, description);
    }

    @Override
    public int delete(LocalDateTime timestamp, UUID contribution, UUID audit) {
        if (contribution == null) {
            throw new InternalServerException("Invalid null valued contribution.");
        }
        setContributionId(contribution);

        // Retrieve audit metadata from given contribution
        var newContributionAccess = I_ContributionAccess.retrieveInstance(this.getDataAccess(), contribution);
        UUID systemId = newContributionAccess.getAuditsSystemId();
        UUID committerId = newContributionAccess.getAuditsCommitter();
        String description = newContributionAccess.getAuditsDescription();

        return internalDelete(timestamp, committerId, systemId, description);
    }

    private Integer internalDelete(LocalDateTime timestamp, UUID committerId, UUID systemId, String description) {
        Short sysTenant = statusRecord.getSysTenant();
        statusRecord.setSysTransaction(Timestamp.valueOf(timestamp));
        statusRecord.delete();

        // create new deletion audit
        var delAudit = I_AuditDetailsAccess.getInstance(
                this, systemId, committerId, I_ConceptAccess.ContributionChangeType.DELETED, description, sysTenant);
        UUID delAuditId = delAudit.commit();

        // create new, BUT already moved to _history, version documenting the deletion
        return createAndCommitNewDeletedVersionAsHistory(delAuditId, statusRecord.getInContribution(), sysTenant);
    }

    private int createAndCommitNewDeletedVersionAsHistory(UUID delAuditId, UUID contrib, Short sysTenant) {
        // a bit hacky: create new, BUT already moved to _history, version documenting the deletion
        // (Normal approach of first .update() then .delete() won't work, because postgres' transaction optimizer will
        // just skip the update if it will get deleted anyway.)
        // so copy values, but add deletion meta data
        StatusHistoryRecord newRecord = getDataAccess().getContext().newRecord(STATUS_HISTORY);
        newRecord.setId(statusRecord.getId());
        newRecord.setEhrId(statusRecord.getEhrId());
        newRecord.setInContribution(contrib);
        newRecord.setArchetypeNodeId(statusRecord.getArchetypeNodeId());
        newRecord.setAttestationRef(statusRecord.getAttestationRef());
        newRecord.setName(statusRecord.getName());
        newRecord.setSysTenant(sysTenant);
        newRecord.setIsModifiable(statusRecord.getIsModifiable());
        newRecord.setIsQueryable(statusRecord.getIsQueryable());
        newRecord.setOtherDetails(statusRecord.getOtherDetails());
        newRecord.setParty(statusRecord.getParty());
        newRecord.setHasAudit(delAuditId);

        getDataAccess().getContext().attach(newRecord);
        if (newRecord.insert() != 1) {
            throw new InternalServerException("DB inconsistency");
        } else {
            return 1;
        }
    }

    private void createAndSetContribution(
            UUID committerId, UUID systemId, String description, ContributionChangeType changeType) {
        contributionAccess.setAuditDetailsChangeType(I_ConceptAccess.fetchContributionChangeType(this, changeType));
        if (contributionAccess.getAuditsCommitter() == null || contributionAccess.getAuditsSystemId() == null) {
            if (committerId == null || systemId == null) {
                throw new InternalServerException(
                        "Illegal to commit the contribution's AuditDetailsAccess without setting mandatory fields.");
            } else {
                contributionAccess.setAuditDetailsCommitter(committerId);
                contributionAccess.setAuditDetailsSystemId(systemId);
                contributionAccess.setAuditDetailsDescription(description);
            }
        }
        UUID contributionId = this.contributionAccess.commit();
        setContributionId(contributionId);
    }

    public static I_StatusAccess retrieveInstance(I_DomainAccess domainAccess, UUID statusId) {
        StatusRecord record = domainAccess.getContext().fetchOne(STATUS, STATUS.ID.eq(statusId));

        if (record == null) {
            return null;
        }

        return createStatusAccessForRetrieval(domainAccess, record, null, record.getSysTenant());
    }

    public static I_StatusAccess retrieveInstanceByNamedSubject(I_DomainAccess domainAccess, String partyName) {

        DSLContext context = domainAccess.getContext();

        StatusRecord record = domainAccess
                .getContext()
                .fetchOne(
                        STATUS,
                        STATUS.PARTY.eq(context.select(PARTY_IDENTIFIED.ID)
                                .from(PARTY_IDENTIFIED)
                                .where(PARTY_IDENTIFIED.NAME.eq(partyName))));

        if (record == null) {
            return null;
        }

        return createStatusAccessForRetrieval(domainAccess, record, null, record.getSysTenant());
    }

    public static I_StatusAccess retrieveInstanceByParty(I_DomainAccess domainAccess, UUID partyIdentified) {

        DSLContext context = domainAccess.getContext();

        StatusRecord record = domainAccess
                .getContext()
                .fetchOne(
                        STATUS,
                        STATUS.PARTY.eq(context.select(PARTY_IDENTIFIED.ID)
                                .from(PARTY_IDENTIFIED)
                                .where(PARTY_IDENTIFIED.ID.eq(partyIdentified))));

        if (record == null) {
            return null;
        }

        return createStatusAccessForRetrieval(domainAccess, record, null, record.getSysTenant());
    }

    public static I_StatusAccess retrieveByVersion(I_DomainAccess domainAccess, UUID statusId, int version) {
        if (version == getLatestVersionNumber(domainAccess, statusId)) return retrieveInstance(domainAccess, statusId);

        Map allVersions = getVersionMapOfStatus(domainAccess, statusId);

        return allVersions.get(Integer.valueOf(version));
    }

    // fetch latest status
    public static I_StatusAccess retrieveInstanceByEhrId(I_DomainAccess domainAccess, UUID ehrId) {
        StatusRecord record = null;

        if (domainAccess.getContext().fetchExists(STATUS, STATUS.EHR_ID.eq(ehrId))) {
            record = domainAccess.getContext().fetchOne(STATUS, STATUS.EHR_ID.eq(ehrId));
        } else {
            if (!domainAccess.getContext().fetchExists(STATUS_HISTORY, STATUS_HISTORY.EHR_ID.eq(ehrId)))
            // no current one (premise from above) and no history --> inconsistency
            {
                throw new InternalServerException("DB inconsistency. No STATUS for given EHR ID: " + ehrId);
            } else {
                Result recordsRes = domainAccess
                        .getContext()
                        .selectFrom(STATUS_HISTORY)
                        .where(STATUS_HISTORY.EHR_ID.eq(ehrId))
                        .orderBy(STATUS_HISTORY.SYS_TRANSACTION.desc()) // latest at top, i.e. [0]
                        .fetch();
                // get latest
                if (recordsRes.get(0) != null) {
                    record = historyRecToNormalRec(domainAccess, recordsRes.get(0));
                }
            }
        }

        if (record == null) {
            return null;
        }

        return createStatusAccessForRetrieval(domainAccess, record, null, record.getSysTenant());
    }

    public static Map retrieveInstanceByContribution(
            I_DomainAccess domainAccess, UUID contributionId, String node) {
        Set statuses = new HashSet<>(); // Set, because of unique values
        // add all compositions having a link to given contribution
        domainAccess
                .getContext()
                .select(STATUS.ID)
                .from(STATUS)
                .where(STATUS.IN_CONTRIBUTION.eq(contributionId))
                .fetch()
                .forEach(rec -> statuses.add(rec.value1()));
        // and older versions or deleted ones, too
        domainAccess
                .getContext()
                .select(STATUS_HISTORY.ID)
                .from(STATUS_HISTORY)
                .where(STATUS_HISTORY.IN_CONTRIBUTION.eq(contributionId))
                .fetch()
                .forEach(rec -> statuses.add(rec.value1()));

        // get whole "version map" of each matching status and do fine-grain check for matching contribution
        // precondition: each UUID in `statuses` set is unique, so for each the "version map" is only created once below
        // (meta: can't do that as jooq query, because the specific version number isn't stored in DB)
        Map resultMap = new HashMap<>();
        for (UUID statusId : statuses) {
            Map map = getVersionMapOfStatus(domainAccess, statusId);
            // fine-grained contribution ID check
            map.forEach((k, v) -> {
                if (v.getContributionId().equals(contributionId)) {
                    resultMap.put(new ObjectVersionId(statusId.toString(), node, k.toString()), v);
                }
            });
        }

        return resultMap;
    }

    public static Map getVersionMapOfStatus(I_DomainAccess domainAccess, UUID statusId) {
        Map versionMap = new HashMap<>();

        // create counter with highest version, to keep track of version number and allow check in the end
        Integer versionCounter = getLatestVersionNumber(domainAccess, statusId);

        // fetch matching entry
        StatusRecord record = domainAccess.getContext().fetchOne(STATUS, STATUS.ID.eq(statusId));
        if (record != null) {
            I_StatusAccess statusAccess =
                    createStatusAccessForRetrieval(domainAccess, record, null, record.getSysTenant());
            versionMap.put(versionCounter, statusAccess);

            versionCounter--;
        }

        // if composition was removed (i.e. from "COMPOSITION" table) *or* other versions are existing
        Result historyRecords = domainAccess
                .getContext()
                .selectFrom(STATUS_HISTORY)
                .where(STATUS_HISTORY.ID.eq(statusId))
                .orderBy(STATUS_HISTORY.SYS_TRANSACTION.desc())
                .fetch();

        for (StatusHistoryRecord historyRecord : historyRecords) {
            I_StatusAccess historyAccess =
                    createStatusAccessForRetrieval(domainAccess, null, historyRecord, historyRecord.getSysTenant());
            versionMap.put(versionCounter, historyAccess);
            versionCounter--;
        }

        if (versionCounter != 0) {
            throw new InternalServerException("Version Map generation failed");
        }

        return versionMap;
    }

    /**
     * Helper to create a new {@link StatusAccess} instance from a queried statusRecord (either as {@link
     * StatusRecord} or {@link StatusHistoryRecord}), to return to service layer.
     *
     * @param domainAccess  General access
     * @param statusRecord        Queried {@link StatusRecord} which contains ID of linked EHR, audit and
     *                      contribution. Give null if not used
     * @param historyRecord Option: Same as statusRecord but as history input type. Give null if not used
     * @return Resulting access object
     */
    private static I_StatusAccess createStatusAccessForRetrieval(
            I_DomainAccess domainAccess,
            StatusRecord statusRecord,
            StatusHistoryRecord historyRecord,
            Short sysTenant) {
        StatusAccess statusAccess;
        if (statusRecord != null) {
            statusAccess = new StatusAccess(domainAccess, statusRecord.getEhrId(), sysTenant);
            statusAccess.setStatusRecord(statusRecord);
        } else if (historyRecord != null) {
            statusAccess = new StatusAccess(domainAccess, historyRecord.getEhrId(), sysTenant);
            statusAccess.setStatusRecord(historyRecord);
        } else {
            throw new InternalServerException("Error creating version map of EHR_STATUS");
        }

        // retrieve corresponding audit
        I_AuditDetailsAccess auditAccess = new AuditDetailsAccess(domainAccess.getDataAccess(), sysTenant)
                .retrieveInstance(domainAccess.getDataAccess(), statusAccess.getAuditDetailsId());
        statusAccess.setAuditDetailsAccess(auditAccess);

        // retrieve corresponding contribution
        I_ContributionAccess retContributionAccess =
                I_ContributionAccess.retrieveInstance(domainAccess, statusAccess.getContributionId());
        statusAccess.setContributionAccess(retContributionAccess);

        return statusAccess;
    }

    @Override
    public UUID getId() {
        return statusRecord.getId();
    }

    @Override
    public DataAccess getDataAccess() {
        return this;
    }

    @Override
    public void setStatusRecord(StatusRecord record) {
        this.statusRecord = record;
    }

    @Override
    public void setStatusRecord(StatusHistoryRecord input) {
        statusRecord = StatusAccess.historyRecToNormalRec(getDataAccess(), input);
        statusRecord.setSysPeriod(null);
    }

    @Override
    public StatusRecord getStatusRecord() {
        return this.statusRecord;
    }

    @Override
    public void setAuditDetailsAccess(I_AuditDetailsAccess auditDetailsAccess) {
        this.auditDetailsAccess = auditDetailsAccess;
    }

    @Override
    public void setContributionAccess(I_ContributionAccess contributionAccess) {
        this.contributionAccess = contributionAccess;
    }

    @Override
    public I_AuditDetailsAccess getAuditDetailsAccess() {
        return this.auditDetailsAccess;
    }

    @Override
    public UUID getAuditDetailsId() {
        return statusRecord.getHasAudit();
    }

    @Override
    public void setContributionId(UUID contribution) {
        this.statusRecord.setInContribution(contribution);
    }

    @Override
    public UUID getContributionId() {
        return this.statusRecord.getInContribution();
    }

    @Override
    public void setAuditAndContributionAuditValues(
            UUID systemId, UUID committerId, String description, ContributionChangeType changeType) {
        if (committerId == null || systemId == null || changeType == null) {
            throw new IllegalArgumentException("arguments not optional");
        }
        this.auditDetailsAccess.setCommitter(committerId);
        this.auditDetailsAccess.setSystemId(systemId);
        this.auditDetailsAccess.setChangeType(I_ConceptAccess.fetchContributionChangeType(this, changeType));

        if (description != null) {
            this.auditDetailsAccess.setDescription(description);
        }

        this.contributionAccess.setAuditDetailsValues(committerId, systemId, description, changeType);
    }

    /**
     * Helper method to convert result from query on history table to a record of the normal table.
     *
     * @param statusHistoryRecord Given history record
     * @return Converted normal record
     */
    protected static StatusRecord historyRecToNormalRec(
            I_DomainAccess domainAccess, StatusHistoryRecord statusHistoryRecord) {
        StatusRecord statusRecord = domainAccess.getContext().newRecord(STATUS);
        statusRecord.setId(statusHistoryRecord.getId());
        statusRecord.setEhrId(statusHistoryRecord.getEhrId());
        statusRecord.setIsQueryable(statusHistoryRecord.getIsQueryable());
        statusRecord.setIsModifiable(statusHistoryRecord.getIsModifiable());
        statusRecord.setParty(statusHistoryRecord.getParty());
        statusRecord.setOtherDetails(statusHistoryRecord.getOtherDetails());
        statusRecord.setSysTransaction(statusHistoryRecord.getSysTransaction());
        statusRecord.setSysPeriod(statusHistoryRecord.getSysPeriod());
        statusRecord.setHasAudit(statusHistoryRecord.getHasAudit());
        statusRecord.setAttestationRef(statusHistoryRecord.getAttestationRef());
        statusRecord.setInContribution(statusHistoryRecord.getInContribution());
        statusRecord.setArchetypeNodeId(statusHistoryRecord.getArchetypeNodeId());
        statusRecord.setName(statusHistoryRecord.getName());
        statusRecord.setSysTenant(statusHistoryRecord.getSysTenant());
        return statusRecord;
    }

    public static Integer getLatestVersionNumber(I_DomainAccess domainAccess, UUID statusId) {

        DSLContext ctx = domainAccess.getContext();
        Param uuidParam = DSL.param("id", statusId);
        Table> unionAll = ctx.select(count(STATUS.ID))
                .from(STATUS)
                .where(STATUS.ID.eq(uuidParam))
                .unionAll(ctx.select(count(STATUS_HISTORY.ID))
                        .from(STATUS_HISTORY)
                        .where(STATUS_HISTORY.ID.eq(uuidParam)))
                .asTable("version_counts");

        AggregateFunction sum = DSL.sum(unionAll.field(0, Integer.class));

        int version = ctx.select(sum).from(unionAll).fetchOne(sum).intValue();

        return version;
    }

    public static boolean exists(I_DomainAccess domainAccess, UUID ehrStatusId) {
        return domainAccess.getContext().fetchExists(STATUS, STATUS.ID.eq(ehrStatusId));
    }

    @Override
    @SuppressWarnings("rawtypes") // `result` is raw so later iterating also gets the version number
    public int getEhrStatusVersionFromTimeStamp(Timestamp time) {
        UUID statusUid = this.statusRecord.getId();
        // retrieve current version from status tables
        I_StatusAccess retStatusAccess = I_StatusAccess.retrieveInstance(this.getDataAccess(), statusUid);

        // retrieve all other versions from status_history and sort by time
        Result result = getDataAccess()
                .getContext()
                .selectFrom(STATUS_HISTORY)
                .where(STATUS_HISTORY.ID.eq(statusUid))
                .orderBy(STATUS_HISTORY.SYS_TRANSACTION.desc()) // latest at top, i.e. [0]
                .fetch();

        // see 'what version was the top version at moment T?'
        // first: is time T after current version? then current version is result
        if (time.after(retStatusAccess.getStatusRecord().getSysTransaction())) {
            return getLatestVersionNumber(getDataAccess(), statusUid);
        }
        // second: if not, which one of the historical versions matches?
        for (int i = 0; i < result.size(); i++) {
            if (result.get(i) instanceof StatusHistoryRecord) {
                // is time T after this version? then return its version number
                if (time.after(((StatusHistoryRecord) result.get(i)).getSysTransaction())) {
                    return result.size()
                            - i; // reverses iterator because order was reversed above and always get non zero
                }
            } else {
                throw new InternalServerException("Problem comparing timestamps of EHR_STATUS versions");
            }
        }

        throw new ObjectNotFoundException("EHR_STATUS", "Could not find EHR_STATUS version matching given timestamp");
    }

    @Override
    public Timestamp getInitialTimeOfVersionedEhrStatus() {
        Result result = getDataAccess()
                .getContext()
                .selectFrom(STATUS_HISTORY)
                .where(STATUS_HISTORY.EHR_ID.eq(statusRecord.getEhrId())) // ehrId from this instance
                .orderBy(STATUS_HISTORY.SYS_TRANSACTION.asc()) // oldest at top, i.e. [0]
                .fetch();

        if (!result.isEmpty()) {
            StatusHistoryRecord statusHistoryRecord = result.get(0); // get oldest
            return statusHistoryRecord.getSysTransaction();
        }

        // if haven't returned above use time from latest version (already available in this instance)
        return statusRecord.getSysTransaction();
    }

    @Override
    public EhrStatus getStatus() {
        EhrStatus status = new EhrStatus();

        status.setModifiable(getStatusRecord().getIsModifiable());
        status.setQueryable(getStatusRecord().getIsQueryable());
        // set otherDetails if available
        if (getStatusRecord().getOtherDetails() != null) {
            status.setOtherDetails(getStatusRecord().getOtherDetails());
        }

        // Locatable attribute
        status.setArchetypeNodeId(getStatusRecord().getArchetypeNodeId());
        Object name = new RecordedDvCodedText().fromDB(getStatusRecord(), STATUS.NAME);
        status.setName(name instanceof DvText ? (DvText) name : (DvCodedText) name);

        UUID statusId = getStatusRecord().getId();
        status.setUid(new HierObjectId(statusId.toString() + "::"
                + getServerConfig().getNodename() + "::" + I_StatusAccess.getLatestVersionNumber(this, statusId)));

        PartySelf partySelf = (PartySelf)
                new PersistedPartyProxy(this).retrieve(getStatusRecord().getParty());
        status.setSubject(partySelf);

        return status;
    }

    @Override
    public void setOtherDetails(ItemStructure otherDetails) {
        if (otherDetails != null) {
            statusRecord.setOtherDetails(otherDetails);
        }
    }

    @Override
    public ItemStructure getOtherDetails() {
        return this.statusRecord.getOtherDetails();
    }

    @Override
    public void setEhrId(UUID ehrId) {
        this.statusRecord.setEhrId(ehrId);
    }

    @Override
    public UUID getEhrId() {
        return this.statusRecord.getEhrId();
    }

    @Override
    public Timestamp getSysTransaction() {
        return this.statusRecord.getSysTransaction();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy