protected Dataset doNAction(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { Command cmd = rq.getCommand(); int actionTypeID = cmd.getInt(Tags.ActionTypeID, -1); String iuid = cmd.getRequestedSOPInstanceUID(); Dataset ds = rq.getDataset(); if (log.isDebugEnabled()) { log.debug("Received N-Action cmd with ds:"); log.debug(ds); } checkStudyIuid(iuid, ds); try { switch (actionTypeID) { case 1: service.moveSeriesToTrash(toSeriesIuids(ds)); break; case 2: service.moveInstancesToTrash(toSopIuids(ds)); break; } } catch (Exception e) { throw new DcmServiceException(Status.ProcessingFailure, e); } service.sendStudyMgtNotification(assoc, Command.N_ACTION_RQ, actionTypeID, iuid, ds); return null; }
protected Dataset doNSet(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { Command cmd = rq.getCommand(); String iuid = cmd.getRequestedSOPInstanceUID(); Dataset ds = rq.getDataset(); checkStudyIuid(iuid, ds); try { StudyMgt stymgt = getStudyMgtHome().create(); try { stymgt.updateStudy(iuid, ds, service.studyMovePatientMatching()); } finally { try { stymgt.remove(); } catch (Exception e) { log.warn("Failed to remove StudyMgt Session Bean", e); } } } catch (DcmServiceException e) { throw e; } catch (Exception e) { throw new DcmServiceException(Status.ProcessingFailure, e); } service.sendStudyMgtNotification(assoc, Command.N_SET_RQ, 0, iuid, ds); return null; }
protected Dataset doNCreate(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { Command cmd = rq.getCommand(); String iuid = cmd.getAffectedSOPInstanceUID(); Dataset ds = rq.getDataset(); String suid = ds.getString(Tags.StudyInstanceUID); if (suid == null) { throw new DcmServiceException(Status.MissingAttribute, "Missing Study Instance UID"); } if (iuid == null) { rspCmd.putUI(Tags.AffectedSOPInstanceUID, iuid = suid); } else { checkStudyIuid(iuid, ds); } try { StudyMgt stymgt = getStudyMgtHome().create(); try { stymgt.createStudy(ds, service.patientMatching()); } finally { try { stymgt.remove(); } catch (Exception e) { log.warn("Failed to remove StudyMgt Session Bean", e); } } } catch (DcmServiceException e) { throw e; } catch (Exception e) { throw new DcmServiceException(Status.ProcessingFailure, e); } service.sendStudyMgtNotification(assoc, Command.N_CREATE_RQ, 0, iuid, ds); return null; }
@Override protected Dataset doNGet(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { Command rqCmd = rq.getCommand(); Dataset rqData = rq.getDataset(); if (!abstractSyntaxEquals( assoc, rq, UIDs.UnifiedProcedureStepPullSOPClass, UIDs.UnifiedProcedureStepWatchSOPClass)) throw new DcmServiceException(Status.UnrecognizedOperation); if (rqData != null) throw new DcmServiceException(Status.MistypedArgument, "N-GET-RQ includes Data Set"); return service.getUPS( rspCmd.getAffectedSOPInstanceUID(), rqCmd.getTags(Tags.AttributeIdentifierList)); }
@Override protected Dataset doNCreate(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { String calledAET = assoc.getAssociation().getCalledAET(); Command rqCmd = rq.getCommand(); Dataset rqData = rq.getDataset(); if (!abstractSyntaxEquals(assoc, rq, UIDs.UnifiedProcedureStepPushSOPClass)) throw new DcmServiceException(UNRECOGNIZE_OPERATION); log.debug("Identifier:\n"); log.debug(rqData); checkNCreateRQ(rqCmd, rqData); coerceNCreateRQ(rspCmd, rqData); service.createUPS(calledAET, rqData); return null; }
@Override protected Dataset doNSet(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { String calledAET = assoc.getAssociation().getCalledAET(); Command rqCmd = rq.getCommand(); Dataset rqData = rq.getDataset(); if (!abstractSyntaxEquals(assoc, rq, UIDs.UnifiedProcedureStepPullSOPClass)) throw new DcmServiceException(UNRECOGNIZE_OPERATION); log.debug("Identifier:\n"); log.debug(rqData); checkNSetRQ(rqCmd, rqData); initSPSModificationDateandTime(rqData); service.updateUPS(calledAET, rspCmd.getAffectedSOPInstanceUID(), rqData); return null; }
protected Dataset doNDelete(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { Command cmd = rq.getCommand(); String iuid = cmd.getRequestedSOPInstanceUID(); Dataset ds = rq.getDataset(); // should be null try { service.moveStudyToTrash(iuid); } catch (ObjectNotFoundException e) { if (!ignoreDeleteFailed) { throw new DcmServiceException(Status.NoSuchObjectInstance); } } catch (Exception e) { throw new DcmServiceException(Status.ProcessingFailure, e); } service.sendStudyMgtNotification(assoc, Command.N_DELETE_RQ, 0, iuid, null); return null; }
@Override protected Dataset doNAction(ActiveAssociation assoc, Dimse rq, Command rspCmd) throws IOException, DcmServiceException { Association a = assoc.getAssociation(); String calledAET = a.getCalledAET(); String callingAET = a.getCallingAET(); String receivingAET; Command rqCmd = rq.getCommand(); Dataset rqData = rq.getDataset(); int actionTypeID = rqCmd.getInt(Tags.ActionTypeID, 0); rspCmd.putUS(Tags.ActionTypeID, actionTypeID); String iuid = rqCmd.getRequestedSOPInstanceUID(); String tuid; int state; boolean dellock; switch (actionTypeID) { case 1: if (abstractSyntaxEquals(assoc, rq, UIDs.UnifiedProcedureStepPullSOPClass)) { type1(rqData, Tags.UPSState); state = UPSScpService.upsStateAsInt(rqData.getString(Tags.UPSState)); if (state == UPSState.SCHEDULED) throw new DcmServiceException(MAY_ONLY_BECOME_SCHEDULED_VIA_NCREATE); tuid = rqData.getString(Tags.TransactionUID); if (tuid == null) throw new DcmServiceException(CORRECT_TRANSACTION_UID_NOT_PROVIDED); service.changeUPSState(calledAET, iuid, state, tuid); return rqData; } break; case 2: if (abstractSyntaxEquals( assoc, rq, UIDs.UnifiedProcedureStepPushSOPClass, UIDs.UnifiedProcedureStepWatchSOPClass)) { checkCodeItem(rqData, ItemCount.SINGLE, Tags.UPSDiscontinuationReasonCodeSeq); service.requestUPSCancel(calledAET, iuid, callingAET, rqData); return rqData; } break; case 3: if (abstractSyntaxEquals(assoc, rq, UIDs.UnifiedProcedureStepWatchSOPClass)) { type1(rqData, Tags.ReceivingAE); type1(rqData, Tags.DeletionLock); receivingAET = rqData.getString(Tags.ReceivingAE); dellock = deletionLockAsBoolean(rqData.getString(Tags.DeletionLock)); if (iuid.equals(UIDs.UnifiedWorklistandProcedureStepSOPInstance)) service.subscribeGlobally(calledAET, receivingAET, dellock); else service.subscribeReceiveUPSEventReports(calledAET, iuid, receivingAET, dellock); return rqData; } break; case 4: if (abstractSyntaxEquals(assoc, rq, UIDs.UnifiedProcedureStepWatchSOPClass)) { type1(rqData, Tags.ReceivingAE); receivingAET = rqData.getString(Tags.ReceivingAE); if (iuid.equals(UIDs.UnifiedWorklistandProcedureStepSOPInstance)) service.unsubscribeGlobally(receivingAET); else service.unsubscribeReceiveUPSEventReports(iuid, receivingAET); return rqData; } break; case 5: if (abstractSyntaxEquals(assoc, rq, UIDs.UnifiedProcedureStepWatchSOPClass) && iuid.equals(UIDs.UnifiedWorklistandProcedureStepSOPInstance)) { type1(rqData, Tags.ReceivingAE); receivingAET = rqData.getString(Tags.ReceivingAE); service.suspendGlobalSubscription(receivingAET); return rqData; } break; } throw new DcmServiceException(Status.NoSuchActionType).setActionTypeID(actionTypeID); }
/** * Ask archive to move one DICOM object to the destination (C-MOVE). See PS 3.4 - Annex C * QUERY/RETRIEVE SERVICE CLASS. * * <p>Use the Study Root Query/Retrieve Information Model to communicate with the archive. See PS * 3.4 - C.6.2 Study Root SOP Class Group. * * <p>PS 3.4 - C.4.2.1.4.1 Request Identifier Structure (for C-MOVE): An Identifier in a C-MOVE * request shall contain: * * <p>- the Query/Retrieve Level (0008,0052) which defines the level of the retrieval * * <p>- Unique Key Attributes which may include Patient ID, Study Instance UIDs, Series Instance * UIDs, and the SOP Instance UIDs * * <p>PS 3.4 - C.4.2.2.1 Baseline Behavior of SCU (of C-MOVE): * * <p>The SCU shall supply a single value in the Unique Key Attribute for each level above the * Query/Retrieve level. For the level of retrieve, the SCU shall supply one unique key if the * level of retrieve is above the STUDY level and shall supply one UID, or a list of UIDs if a * retrieval of several items is desired and the retrieve level is STUDY, SERIES or IMAGE. * * @param ds the DICOM object represented as a Dataset. * @return a result-code: 0x0000 = SUCCESS sub-operations complete no failures, 0xB000 = WARNING * sub-operations complete one or more failures, other = errors defined in PS 3.4 - C.4.2.1.5 * Status * @throws ConnectException * @throws InterruptedException * @throws IOException */ public Vector cMOVE(Dataset ds) throws ConnectException, InterruptedException, IOException { PresContext pc; List dimseList; Vector datasetVector; // An association must be active if (aassoc == null) { throw new ConnectException("No Association established"); } // Test, if Presentation Context for C-MOVE is supported // API doc: Association.getAcceptedPresContext(String asuid, String tsuid) if ((pc = aassoc .getAssociation() .getAcceptedPresContext( UIDs.StudyRootQueryRetrieveInformationModelMOVE, UIDs.ExplicitVRLittleEndian)) == null && (pc = aassoc .getAssociation() .getAcceptedPresContext( UIDs.StudyRootQueryRetrieveInformationModelMOVE, UIDs.ImplicitVRLittleEndian)) == null) { throw new ConnectException( "Association does not support presentation context for StudyRootQueryRetrieveInformationModelMOVE SOP."); } // Get the Study Instance UID of the study to mode String suid = ds.getString(Tags.StudyInstanceUID); // Prepare info for logging String patName = ds.getString(Tags.PatientName); String patID = ds.getString(Tags.PatientID); String studyDate = ds.getString(Tags.StudyDate); String prompt = "Study[" + suid + "] from " + studyDate + " for Patient[" + patID + "]: " + patName; // log.info("Moving: " + prompt); // New Cammand Set, see: DICOM Part 7: Message Exchange, 6.3.1 Command Set Structure Command rqCmd = dof.newCommand(); // API doc: Command.initCMoveRQ(int msgID, String sopClassUID, int priority, String moveDest) rqCmd.initCMoveRQ( assoc.nextMsgID(), UIDs.StudyRootQueryRetrieveInformationModelMOVE, priority, dest); Dataset rqDs = dof.newDataset(); rqDs.putCS(Tags.QueryRetrieveLevel, getQueryRetrieveLevel(STUDY_LEVEL)); // Only Unique Key allowed in C-MOVE. PS 3.4 -C.2.2.1 Attribute Types rqDs.putUI(Tags.StudyInstanceUID, suid); // API doc: AssociationFactorynewDimse(int pcid, Command cmd, Dataset ds) // DIMSE (DICOM Message Service Element) ist ein Nachrichtendienst in DICOM Dimse moveRq = aFact.newDimse(pc.pcid(), rqCmd, rqDs); // Invoke active association with move request Dimse FutureRSP future = aassoc.invoke(moveRq); // Response to the C-MOVE request. // The result cannot be accessed until it has been set. Dimse moveRsp = future.get(); Command rspCmd = moveRsp.getCommand(); Dataset dds = moveRsp.getDataset(); if (DEBUG) { StringWriter w = new StringWriter(); w.write("C-FIND RQ Identifier:\n"); keys.dumpDataset(w, null); log.debug(w.toString()); } // Invoke active association with find request Dimse // Response to the C-FIND request. // The result cannot be accessed until it has been set. // Get the list of found objects Dimse dms = future.get(); // >>>> Extract Dataset from Dimse datasetVector = new Vector(); // If no List of DIMSE objects was generated or it is empty return an empty Vector // if (dimseList == null || dimseList.isEmpty()) { // return datasetVector; // } // Process all elements // for (int i = 0; i < dimseList.size(); i++) { // datasetVector.addElement(((Dimse) dimseList.get(i)).getDataset()); // if(((Dimse) dimseList.get(i)).getDataset()==null) // System.out.println(" Dataset created succesffullyu "); // } // PS 3.7 - 9.3.4 C-MOVE PROTOCOL, 9.3.4.2 C-MOVE-RSP int status = rspCmd.getStatus(); switch (status) { case 0x0000: // log.info("Moved: " + prompt); break; case 0xB000: log.error("One or more failures during move of " + prompt); break; default: log.error("Failed to move " + prompt + "\n\terror tstatus: " + Integer.toHexString(status)); break; } // System.out.println("The move sise is : "+datasetVector.size()); return datasetVector; }