// /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is part of dcm4che, an implementation of DICOM(TM) in * Java(TM), hosted at https://github.com/gunterze/dcm4che. * * The Initial Developer of the Original Code is * Agfa Healthcare. * Portions created by the Initial Developer are Copyright (C) 2011 * the Initial Developer. All Rights Reserved. * * Contributor(s): * See @authors listed below * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.dcm4chee.archive.qc; import java.util.Collection; import java.util.List; import java.util.Map; import javax.persistence.EntityNotFoundException; import org.dcm4che3.data.Attributes; import org.dcm4che3.data.Code; import org.dcm4che3.data.IDWithIssuer; import org.dcm4chee.archive.conf.ArchiveAEExtension; import org.dcm4chee.archive.conf.ArchiveDeviceExtension; import org.dcm4chee.archive.entity.Instance; import org.dcm4chee.archive.entity.Patient; import org.dcm4chee.archive.entity.history.ActionHistory; import org.dcm4chee.archive.entity.history.SeriesHistory; import org.dcm4chee.archive.entity.history.StudyHistory; import org.dcm4chee.archive.entity.history.UpdateHistory; /** * @author Hesham Elbadawi <bsdreko@gmail.com> * @author Alexander Hoermandinger <alexander.hoermandinger@agfa.com> */ public interface StructuralChangeService { /** * MergeStudies. * Merge each of the studies provided to the provided target study. * The method also takes care to enrich study and series attributes. * Throws an EJBException if the patient is different for any of the * source studies or the target study. Throws an EJB Exception if any * of the studies are not found. Utilizes the move method for performing * the suggested sub-operations. * * @param sourceStudyUids * the source study uids * @param targetStudyUID * the target study uid * @param targetStudyattributes * the target study attributes * @param targetSeriesattributes * the target series attributess * @param qcRejectionCode * the QC rejection code utilized by move * @return the QC event */ QCOperationContext mergeStudies(Enum<?> structuralChangeCtx, String[] sourceStudyUids, String targetStudyUID, Attributes targetStudyattributes, Attributes targetSeriesattributes, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Merge. * Used to perform the merge operation per study. The method is used by the * @link {@link #mergeStudies(String[], String, Attributes, Attributes, Code)} * to perform the suggested operation per source study. * * @param sourceStudyUid * the source study uid * @param targetStudyUid * the target study uid * @param targetStudyattributes * the target study attributes * @param targetSeriesattributes * the target series attributes * @param qcRejectionCode * the QC rejection code * @return the QC event */ QCOperationContext merge(Enum<?> structuralChangeCtx, String sourceStudyUid, String targetStudyUid, Attributes targetStudyattributes, Attributes targetSeriesattributes, Code qcRejectionCode) throws QCOperationNotPermittedException ; /** * Split. * Split study is a combined operation that uses the move basic operation. * Given a set of instances to move the method will create a study in case * the old study doesn't exist, using the provided createStudyAttributes * to enrich the created study. The method will also enrich the created * series with the targetSeriesAttributes (if provided). * Throws an EJBException if the patient is different for any of the * source study or the target study. Throws an EJB Exception if any * of the instances are not found or do not belong to the same study. * * @param toMove * the to move * @param pid * the patient id * @param targetStudyUID * the target study uid * @param createdStudyattributes * the created study attributes * @param targetSeriesattributes * the target series attributes * @param qcRejectionCode * the QC rejection code * @return the QC event */ QCOperationContext split(Enum<?> structuralChangeCtx, Collection<String> toMove, IDWithIssuer pid, String targetStudyUID, Attributes createdStudyattributes, Attributes targetSeriesattributes, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Segment. * The segment operation is used to group instances into different * studies/series (virtually segments/groups) * The operation takes two collections to move and to clone and * performs the appropriate action accordingly. * The method will use the provided attributes for study and/or series * to enrich the objects created. The method will throw EJB Exception * if all instances to move or to clone don't have the same study. * Throws an EJBException if the patient is different for any of the * source study or the target study. * * @param toMove * the to move * @param toClone * the to clone * @param pid * the pid * @param targetStudyUID * the target study uid * @param targetStudyattributes * the target study attributes * @param targetSeriesattributes * the target series attributes * @param qcRejectionCode * the QC rejection code * @return the QC event */ QCOperationContext segment(Enum<?> structuralChangeCtx, Collection<String> toMove, Collection<String> toClone, IDWithIssuer pid, String targetStudyUID, Attributes targetStudyattributes, Attributes targetSeriesattributes, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Can apply QC. * Checks if the method provided by the sopInstanceUID is rejected. * @param sopInstanceUID * the sop instance uid * @return true, if the object is not rejected */ boolean canApplyQC(Instance sopInstanceUID); /** * Update dicom object. * Used to update Patient/Study/Series/Instance with the provided attributes. * The method will create any entities required aand associate them with the * object being updated, the operation is reversible. * @param arcDevExt * the arc dev ext * @param scope * the scope * @param attributes * the attributes * @return the QC event * @throws EntityNotFoundException * the entity not found exception */ QCOperationContext updateDicomObject(Enum<?> structuralChangeCtx, ArchiveDeviceExtension arcDevExt, UpdateHistory.UpdateScope scope, Attributes attributes) throws QCOperationNotPermittedException, EntityNotFoundException; /** * Patient operation. * Patient operations are those operations supported by the patientservice * This interface provides a way to trigger them without having to use HL7 * operations performed include link/unlink/merge/updateid * * @param sourcePatientAttributes * the source patient attributes * @param targetPatientAttributes * the target patient attributes * @param arcAEExt * the arc ae ext * @param command * the command * @return true, if successful */ boolean patientOperation(Attributes sourcePatientAttributes, Attributes targetPatientAttributes, ArchiveAEExtension arcAEExt, PatientCommands command) throws QCOperationNotPermittedException; /** * Locate instances. * Used to locate the instances entities identified by the string array of * sopInstanceUIDs from the archive. * @param strings * the strings * @return the collection */ Collection<Instance> locateInstances(String... strings); /** * Delete study. * Deletes a study permanently * The method will use the archives delete queue to perform asynchronously * * @param studyInstanceUID * the study instance uid * @return the QC event * @throws Exception * the exception */ QCOperationContext deletePatient(Enum<?> structuralChangeCtx, IDWithIssuer pid, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Delete study. * Deletes a study permanently * The method will use the archives delete queue to perform asynchronously * * @param studyInstanceUID * the study instance uid * @return the QC event * @throws Exception * the exception */ QCOperationContext deleteStudy(Enum<?> structuralChangeCtx, String studyInstanceUID, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Delete series. * Deletes a series permanently * The method will use the archives delete queue to perform asynchronously * * @param seriesInstanceUID * the series instance uid * @return the QC event * @throws Exception * the exception */ QCOperationContext deleteSeries(Enum<?> structuralChangeCtx, String seriesInstanceUID, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Delete instance. * Deletes an instance permanently * The method will use the archives delete queue to perform asynchronously * * @param sopInstanceUID * the sop instance uid * @return the QC event * @throws Exception * the exception */ QCOperationContext deleteInstance(Enum<?> structuralChangeCtx, String sopInstanceUID, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Delete patient if empty. * Purges an empty patient. * * @param pid * the patient id * @return true, if successful */ boolean deletePatientIfEmpty(IDWithIssuer pid); /** * Delete study if empty. * Purges an empty study. * * @param studyInstanceUID * the study instance uid * @return true, if successful */ boolean deleteStudyIfEmpty(String studyInstanceUID); /** * Delete series if empty. * Purges an empty series. * * @param seriesInstanceUID * the series instance uid * @param studyInstanceUID * the study instance uid * @return true, if successful */ boolean deleteSeriesIfEmpty(String seriesInstanceUID, String studyInstanceUID); /** * Reject. * Used to call the rejection service on some instance give a code. * This interface is used by the restful service. * * @param sopInstanceUIDs * the sop instance ui ds * @param qcRejectionCode * the QC rejection code * @return the QC event */ QCOperationContext reject(Enum<?> structuralChangeCtx, String[] sopInstanceUIDs, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Restore. * Used to remove the previously applied rejection code on an instance. * * @param sopInstanceUIDs * the sop instance ui ds * @return the QC event */ QCOperationContext restore(Enum<?> structuralChangeCtx, String[] sopInstanceUIDs) throws QCOperationNotPermittedException; /** * Gets the patient from the archive. * * @param attrs * the attributes with the patient id and issuer * @return the patient */ Patient findPatient(Attributes attrs); /** * Perform additional QC and IOCM operation for the replacement done for an NoneIOCM Instance Update. * * @param oldIUID * @param newIUID * @param qcRejectionCode * @return 'UPDATE' QCEvent or null if operation was skipped. * @throws QCOperationNotPermittedException */ QCOperationContext replaced(Enum<?> structuralChangeCtx, Map<String, String> oldToNewIUIDs, Code qcRejectionCode) throws QCOperationNotPermittedException; /** * Creates a new Action History entry * * @param operation QC operation * @param hierarchyLevel dicom level * @return created ActionHistory */ ActionHistory generateQCAction(QC_OPERATION operation, ActionHistory.HierarchyLevel hierarchyLevel); /** * Creates a new Series History entry * * @param seriesInstanceUID series iuid * @param oldAttributes original attributes of the series * @param studyHistory associated study history entry * @param noneIocmSourceAET source AET * @return created SeriesHistory */ SeriesHistory createQCSeriesHistory(String seriesInstanceUID, Attributes oldAttributes, StudyHistory studyHistory, String noneIocmSourceAET); /** * Creates a new Study History entry * * @param studyInstanceUID original study UID * @param targetStudyUID new study UID * @param oldAttributes original attributes of the study * @param actionHistory associated action history entry * @return created StudyHistory */ StudyHistory createQCStudyHistory(String studyInstanceUID, String targetStudyUID, Attributes oldAttributes, ActionHistory actionHistory); /** * Given an original study uid, returns one ore more (a list) of study history * entities that replaced it. * * @param oldStudyInstanceUID original study uid * @return list of study History entities that replaced the original study. */ List<StudyHistory> findStudyHistory(String oldStudyInstanceUID); }