Logo Search packages:      
Sourcecode: pixelmed version File versions  Download package

StorageSOPClassSCU.java

/* Copyright (c) 2001-2009, David A. Clunie DBA Pixelmed Publishing. All rights reserved. */

package com.pixelmed.network;

import com.pixelmed.utils.*;
import com.pixelmed.dicom.*;

import java.util.Iterator;
import java.util.ListIterator;
import java.util.LinkedList;
import java.util.Set;
import java.io.*;

/**
 * <p>This class implements the SCU role of SOP Classes of the Storage Service Class.</p>
 *
 * <p>The class has no methods other than the constructor (and a main method for testing). The
 * constructor establishes an association, sends the C-STORE request, and releases the
 * association.</p>
 *
 * <p>Debugging messages with a varying degree of verbosity can be activated.</p>
 *
 * <p>For example:</p>
 * <pre>
try {
    new StorageSOPClassSCU("theirhost","11112","STORESCP","STORESCU","/tmp/testfile.dcm","1.2.840.10008.5.1.4.1.1.7","1.3.6.1.4.1.5962.1.1.0.0.0.1064923879.2077.3232235877",0,0);
}
catch (Exception e) {
    e.printStackTrace(System.err);
}
 * </pre>
 *
 * <p>From the command line, sending multiple files:</p>
 * <pre>
find /tmp -name '*.dcm' | java -cp pixelmed.jar:lib/additional/commons-codec-1.3.jar:lib/additional/excalibur-bzip2-1.0.jar com/pixelmed.network.StorageSOPClassSCU theirhost 11112 STORESCP STORESCU -  0 0
 * </pre>
 *
 *
 * @author  dclunie
 */
00041 public class StorageSOPClassSCU extends SOPClass {

      /***/
      private static final String identString = "@(#) $Header: /userland/cvs/pixelmed/imgbook/com/pixelmed/network/StorageSOPClassSCU.java,v 1.43 2009/07/17 21:48:55 dclunie Exp $";

      /***/
      protected int debugLevel;
      
      /***/
      protected class CStoreResponseHandler extends CompositeResponseHandler {
            /**
             * @param   debugLevel
             */
            CStoreResponseHandler(int debugLevel) {
                  super(debugLevel);
            }
            
            /**
             * @param   list
             */
            protected void evaluateStatusAndSetSuccess(AttributeList list) {
                  // could check all sorts of things, like:
                  // - AffectedSOPClassUID is what we sent
                  // - CommandField is 0x8001 C-STORE-RSP
                  // - MessageIDBeingRespondedTo is what we sent
                  // - DataSetType is 0101 (no data set)
                  // - Status is success and consider associated elements
                  // - AffectedSOPInstanceUID is what we sent
                  //
                  // for now just treat success or warning as success (and absence as failure)
                  int status = Attribute.getSingleIntegerValueOrDefault(list,TagFromName.Status,0xffff);
                  success =  status == 0x0000   // success
                        || status == 0xB000     // coercion of data element
                        || status == 0xB007     // data set does not match SOP Class
                        || status == 0xB006;    // element discarded
            }
      }
      
      /**
       * @param   association
       * @param   affectedSOPClass
       * @param   affectedSOPInstance
       * @param   inputTransferSyntaxUID
       * @param   din
       * @param   presentationContextID
       * @param   outputTransferSyntaxUID
       * @exception     IOException
       * @exception     DicomException
       * @exception     DicomNetworkException
       * @exception     AReleaseException
       */
00092       protected boolean sendOneSOPInstance(Association association,
                  String affectedSOPClass,String affectedSOPInstance,
                  String inputTransferSyntaxUID,DicomInputStream din,
                  byte presentationContextID,String outputTransferSyntaxUID
                  ) throws AReleaseException, DicomNetworkException, DicomException, IOException {
            return sendOneSOPInstance(association,affectedSOPClass,affectedSOPInstance,inputTransferSyntaxUID,din,
                  presentationContextID,outputTransferSyntaxUID,null,-1);
      }
      
      /**
       * @param   association
       * @param   affectedSOPClass
       * @param   affectedSOPInstance
       * @param   inputTransferSyntaxUID
       * @param   din
       * @param   presentationContextID
       * @param   outputTransferSyntaxUID
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @exception     IOException
       * @exception     DicomException
       * @exception     DicomNetworkException
       * @exception     AReleaseException
       */
00116       protected boolean sendOneSOPInstance(Association association,
                  String affectedSOPClass,String affectedSOPInstance,
                  String inputTransferSyntaxUID,DicomInputStream din,
                  byte presentationContextID,String outputTransferSyntaxUID,
                  String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID) throws AReleaseException, DicomNetworkException, DicomException, IOException {
            byte cStoreRequestCommandMessage[] = new CStoreRequestCommandMessage(affectedSOPClass,affectedSOPInstance,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID).getBytes();
            CStoreResponseHandler receivedDataHandler = new CStoreResponseHandler(debugLevel);
            association.setReceivedDataHandler(receivedDataHandler);
            association.send(presentationContextID,cStoreRequestCommandMessage,null);
            OutputStream out = association.getAssociationOutputStream(presentationContextID);
            if (inputTransferSyntaxUID.equals(outputTransferSyntaxUID)) {
            //if (false) {
//if (debugLevel > 0) System.err.println("StorageSOPClassSCU.sendOneSOPInstance(): same transfer syntax so raw binary copy");
                  CopyStream.copy(din,out);           // be careful ... this will not remove DataSetTrailingPadding, which will kill GE AW
//if (debugLevel > 0) System.err.println("StorageSOPClassSCU.sendOneSOPInstance(): back from raw binary copy");
                  out.close();
            }
            else {
if (debugLevel > 0) System.err.println("StorageSOPClassSCU.sendOneSOPInstance(): different transfer syntaxes; converting "+inputTransferSyntaxUID+" to "+outputTransferSyntaxUID);
                  // din will already be positioned after meta-header and set for reading data set
                  // copier will push any transfer syntax specific decompression filter onto the stream before reading
                  DicomOutputStream dout = new DicomOutputStream(out,null/*meta*/,outputTransferSyntaxUID/*dataset*/);
                  new DicomStreamCopier(din,dout);
                  // Do not need dout.close() since DicomStreamCopier always closes output stream itself
            }
if (debugLevel > 0) System.err.println("StorageSOPClassSCU.sendOneSOPInstance(): about to wait for PDUs");
            association.waitForCommandPDataPDUs();
            return receivedDataHandler.wasSuccessful();
      }
      
      /**
       * @param   association
       * @param   affectedSOPClass
       * @param   affectedSOPInstance
       * @param   list
       * @param   presentationContextID
       * @param   outputTransferSyntaxUID
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @exception     IOException
       * @exception     DicomException
       * @exception     DicomNetworkException
       * @exception     AReleaseException
       */
00160       protected boolean sendOneSOPInstance(Association association,
                  String affectedSOPClass,String affectedSOPInstance,
                  AttributeList list,
                  byte presentationContextID,String outputTransferSyntaxUID,
                  String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID) throws AReleaseException, DicomNetworkException, DicomException, IOException {
            byte cStoreRequestCommandMessage[] = new CStoreRequestCommandMessage(affectedSOPClass,affectedSOPInstance,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID).getBytes();
            CStoreResponseHandler receivedDataHandler = new CStoreResponseHandler(debugLevel);
            association.setReceivedDataHandler(receivedDataHandler);
            association.send(presentationContextID,cStoreRequestCommandMessage,null);
            OutputStream out = association.getAssociationOutputStream(presentationContextID);
if (debugLevel > 0) System.err.println("StorageSOPClassSCU.sendOneSOPInstance(): writing attribute list as "+outputTransferSyntaxUID);
            list.write(out,outputTransferSyntaxUID,false/*useMeta*/,true/*useBufferedStream*/,false/*closeAfterWrite*/);
if (debugLevel > 0) System.err.println("StorageSOPClassSCU.sendOneSOPInstance(): about to wait for PDUs");
            association.waitForCommandPDataPDUs();
            return receivedDataHandler.wasSuccessful();
      }
      
      /**
       * <p>Dummy constructor allows testing subclasses to use different constructor.</p>
       *
       */
00181       protected StorageSOPClassSCU() throws DicomNetworkException, DicomException, IOException {
      }
      
      /**
       * <p>Establish an association to the specified AE, send the instance contained in the file, and release the association.</p>
       *
       * @param   hostname                            their hostname or IP address
       * @param   port                                their port
       * @param   calledAETitle                       their AE Title
       * @param   callingAETitle                      our AE Title
       * @param   fileName                            the name of the file containing the data set to send
       * @param   affectedSOPClass              must be the same as the SOP Class UID contained within the data set
       * @param   affectedSOPInstance                 must be the same as the SOP Instance UID contained within the data set
       * @param   compressionLevel              0=none,1=propose deflate,2=propose deflate and bzip2
       * @param   debugLevel                          zero for no debugging messages, higher values more verbose messages
       * @exception     IOException
       * @exception     DicomException
       * @exception     DicomNetworkException
       */
00200       public StorageSOPClassSCU(String hostname,int port,String calledAETitle,String callingAETitle,String fileName,
                  String affectedSOPClass,String affectedSOPInstance,int compressionLevel,
                  int debugLevel) throws DicomNetworkException, DicomException, IOException {
            this(hostname,port,calledAETitle,callingAETitle,fileName,affectedSOPClass,affectedSOPInstance,compressionLevel,null,-1,debugLevel);
      }
      
      /**
       * <p>Establish an association to the specified AE, send the instance contained in the file, and release the association.</p>
       *
       * @param   hostname                                              their hostname or IP address
       * @param   port                                                  their port
       * @param   calledAETitle                                         their AE Title
       * @param   callingAETitle                                        our AE Title
       * @param   fileName                                              the name of the file containing the data set to send
       * @param   affectedSOPClass                                must be the same as the SOP Class UID contained within the data set
       * @param   affectedSOPInstance                                   must be the same as the SOP Instance UID contained within the data set
       * @param   compressionLevel                                0=none,1=propose deflate,2=propose deflate and bzip2
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @param   debugLevel                                            zero for no debugging messages, higher values more verbose messages
       * @exception     IOException
       * @exception     DicomException
       * @exception     DicomNetworkException
       */
00224       public StorageSOPClassSCU(String hostname,int port,String calledAETitle,String callingAETitle,String fileName,
                  String affectedSOPClass,String affectedSOPInstance,int compressionLevel,String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID,
                  int debugLevel) throws DicomNetworkException, DicomException, IOException {
            this.debugLevel=debugLevel;
            
if (debugLevel > 0) System.err.println("StorageSOPClassSCU: storing "+fileName);
            // Don't even begin until we know we can open the file ...
            InputStream in = new BufferedInputStream(new FileInputStream(fileName));
            try {
                  String inputTransferSyntax;
                  DicomInputStream din = new DicomInputStream(in);
                  if (din.haveMetaHeader()) {
                        AttributeList metaList = new AttributeList();
                        metaList.readOnlyMetaInformationHeader(din);
if (debugLevel > 0) System.err.println("Meta header information = "+metaList);
                        affectedSOPClass=Attribute.getSingleStringValueOrNull(metaList,TagFromName.MediaStorageSOPClassUID);
                        affectedSOPInstance=Attribute.getSingleStringValueOrNull(metaList,TagFromName.MediaStorageSOPInstanceUID);
                        inputTransferSyntax=Attribute.getSingleStringValueOrNull(metaList,TagFromName.TransferSyntaxUID);
                  }
                  else {
                        inputTransferSyntax=din.getTransferSyntaxToReadDataSet().getUID();
                  }
if (debugLevel > 0) System.err.println("Using inputTransferSyntax "+inputTransferSyntax);

                  if (affectedSOPClass == null) {
                        throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Affected SOP Class UID");
                  }
                  if (affectedSOPInstance == null) {
                        throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Affected SOP Instance UID");
                  }
            
                  PresentationContextListFactory presentationContextListFactory = new PresentationContextListFactory();
                  LinkedList presentationContexts = presentationContextListFactory.createNewPresentationContextList(affectedSOPClass,inputTransferSyntax,compressionLevel);

                  Association association = AssociationFactory.createNewAssociation(hostname,port,calledAETitle,callingAETitle,presentationContexts,null,false,debugLevel);
if (debugLevel > 0) System.err.println(association);
                  // Decide which presentation context we are going to use ...
                  byte presentationContextID = association.getSuitablePresentationContextID(affectedSOPClass);
                  //int presentationContextID = association.getSuitablePresentationContextID(affectedSOPClass,TransferSyntax.Default);
if (debugLevel > 0) System.err.println("Using context ID "+presentationContextID);
                  String outputTransferSyntax = association.getTransferSyntaxForPresentationContextID(presentationContextID);
if (debugLevel > 0) System.err.println("Using outputTransferSyntax "+outputTransferSyntax);
                  boolean success = false;
                  try {
                        success = sendOneSOPInstance(association,affectedSOPClass,affectedSOPInstance,
                              inputTransferSyntax,din,
                              presentationContextID,outputTransferSyntax,
                              moveOriginatorApplicationEntityTitle,moveOriginatorMessageID);
                        // State 6
                        association.release();
                  }
                  catch (AReleaseException e) {
                        // State 1
                        // the other end released and didn't wait for us to do it
                  }
if (debugLevel > 0) System.err.println("Send "+(success ? "succeeded" : "failed"));
            }
            finally {
                  in.close();
            }
      }
      
      /**
       * <p>Send the specified instances contained in the files over an existing association.</p>
       *
       * @param   association                   already existing association to SCP
       * @param   dicomFiles                    the set of DICOM files containing names, SOP Class UIDs, SOP Instance UIDs and optionally Transfer Syntaxes
       * @param   debugLevel                    zero for no debugging messages, higher values more verbose messages
       */
00293       public StorageSOPClassSCU(Association association,SetOfDicomFiles dicomFiles,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                  int debugLevel) {
            this(association,dicomFiles,multipleInstanceTransferStatusHandler,null,-1,debugLevel);
      }

      /**
       * <p>Send the specified instances contained in the files over an existing association.</p>
       *
       * @param   association                                           already existing association to SCP
       * @param   dicomFiles                                            the set of DICOM files containing names, SOP Class UIDs, SOP Instance UIDs and optionally Transfer Syntaxes
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @param   debugLevel                                            zero for no debugging messages, higher values more verbose messages
       */
00307       public StorageSOPClassSCU(Association association,SetOfDicomFiles dicomFiles,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                  String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID,int debugLevel) {
            this.debugLevel=debugLevel;
            try {
                  sendMultipleSOPInstances(association,dicomFiles,multipleInstanceTransferStatusHandler,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID);
            }
            catch (AReleaseException e) {
                  // State 1
                  // the other end released
            }
            catch (DicomNetworkException e) {
                  e.printStackTrace(System.err);
            }
            catch (IOException e) {
                  e.printStackTrace(System.err);
            }
      }
      
      /**
       * <p>Establish an association to the specified AE, send the instances contained in the files, and release the association.</p>
       *
       * @param   hostname                                              their hostname or IP address
       * @param   port                                                  their port
       * @param   calledAETitle                                         their AE Title
       * @param   callingAETitle                                        our AE Title
       * @param   dicomFiles                                            the set of DICOM files containing names, SOP Class UIDs, SOP Instance UIDs and optionally Transfer Syntaxes
       * @param   compressionLevel                                0=none,1=propose deflate,2=propose deflate and bzip2
       * @param   multipleInstanceTransferStatusHandler     transfer handler for reporting pending status (may be null if not required)
       * @param   debugLevel                                            zero for no debugging messages, higher values more verbose messages
       */
00337       public StorageSOPClassSCU(String hostname,int port,String calledAETitle,String callingAETitle,
                  SetOfDicomFiles dicomFiles,int compressionLevel,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                  int debugLevel) {
            this(hostname,port,calledAETitle,callingAETitle,dicomFiles,compressionLevel,multipleInstanceTransferStatusHandler,null,-1,debugLevel);
      }

      /**
       * <p>Establish an association to the specified AE, send the instances contained in the files, and release the association.</p>
       *
       * @param   hostname                                              their hostname or IP address
       * @param   port                                                  their port
       * @param   calledAETitle                                         their AE Title
       * @param   callingAETitle                                        our AE Title
       * @param   dicomFiles                                            the set of DICOM files containing names, SOP Class UIDs, SOP Instance UIDs and optionally Transfer Syntaxes
       * @param   compressionLevel                                0=none,1=propose deflate,2=propose deflate and bzip2
       * @param   multipleInstanceTransferStatusHandler     transfer handler for reporting pending status (may be null if not required)
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @param   debugLevel                                            zero for no debugging messages, higher values more verbose messages
       */
00357       public StorageSOPClassSCU(String hostname,int port,String calledAETitle,String callingAETitle,
                  SetOfDicomFiles dicomFiles,int compressionLevel,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                  String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID,int debugLevel) {
//long startTime=System.currentTimeMillis();
            this.debugLevel=debugLevel;
            try {
                  PresentationContextListFactory presentationContextListFactory = new PresentationContextListFactory();
                  LinkedList presentationContexts = presentationContextListFactory.createNewPresentationContextList(dicomFiles,compressionLevel);
                  Association association = AssociationFactory.createNewAssociation(hostname,port,calledAETitle,callingAETitle,presentationContexts,null,false,debugLevel);
//System.err.println("StorageSOPClassSCU.StorageSOPClassSCU() established association in "+(System.currentTimeMillis()-startTime)+" ms");
                  
                  sendMultipleSOPInstances(association,dicomFiles,multipleInstanceTransferStatusHandler,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID);
                  
                  association.release();
            }
            catch (AReleaseException e) {
                  // State 1
                  // the other end released and didn't wait for us to do it
            }
            catch (DicomNetworkException e) {
                  e.printStackTrace(System.err);
            }
            catch (IOException e) {
                  e.printStackTrace(System.err);
            }
      }

      /**
       * <p>Establish an association to the specified AE, send the instances contained in the attribute lists, and release the association.</p>
       *
       * @param   hostname                                              their hostname or IP address
       * @param   port                                                  their port
       * @param   calledAETitle                                         their AE Title
       * @param   callingAETitle                                        our AE Title
       * @param   setOfSOPClassUIDs                               the set of SOP Classes contained in the attribute lists
       * @param   lists                                                 the attribute lists to send
       * @param   compressionLevel                                0=none,1=propose deflate,2=propose deflate and bzip2
       * @param   multipleInstanceTransferStatusHandler     transfer handler for reporting pending status (may be null if not required)
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @param   debugLevel                                            zero for no debugging messages, higher values more verbose messages
       */
00399       public StorageSOPClassSCU(String hostname,int port,String calledAETitle,String callingAETitle,
                  Set setOfSOPClassUIDs,AttributeList[] lists,
                  int compressionLevel,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                  String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID,int debugLevel) {
//long startTime=System.currentTimeMillis();
            this.debugLevel=debugLevel;
            try {
                  PresentationContextListFactory presentationContextListFactory = new PresentationContextListFactory();
                  LinkedList presentationContexts = presentationContextListFactory.createNewPresentationContextList(setOfSOPClassUIDs,compressionLevel);
                  Association association = AssociationFactory.createNewAssociation(hostname,port,calledAETitle,callingAETitle,presentationContexts,null,false,debugLevel);
//System.err.println("StorageSOPClassSCU.StorageSOPClassSCU() established association in "+(System.currentTimeMillis()-startTime)+" ms");
                  
                  sendMultipleSOPInstances(association,lists,multipleInstanceTransferStatusHandler,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID);
                  
                  association.release();
            }
            catch (AReleaseException e) {
                  // State 1
                  // the other end released and didn't wait for us to do it
            }
            catch (DicomNetworkException e) {
                  e.printStackTrace(System.err);
            }
            catch (IOException e) {
                  e.printStackTrace(System.err);
            }
      }
                  
      /**
       * <p>Send the specified instances contained in the files over an existing association.</p>
       *
       * @param   association                                           already existing association to SCP
       * @param   dicomFiles                                            the set of DICOM files containing names, SOP Class UIDs, SOP Instance UIDs and optionally Transfer Syntaxes
       * @param   multipleInstanceTransferStatusHandler     handler called after each transfer (may be null if not required)
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @exception     AReleaseException
       * @exception     DicomNetworkException
       * @exception     IOException
       */
00439       protected void sendMultipleSOPInstances(Association association,SetOfDicomFiles dicomFiles,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                        String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID)
                  throws AReleaseException, DicomNetworkException, IOException {
//long startTime=System.currentTimeMillis();
            int nRemaining = dicomFiles.size();
            int nCompleted = 0;
            int nFailed = 0;
            int nWarning = 0;
            {
if (debugLevel > 0) System.err.println(association);
                  Iterator fi = dicomFiles.iterator();
                  while (fi.hasNext()) {
                        --nRemaining;
                        ++nCompleted;
                        SetOfDicomFiles.DicomFile dicomFile = (SetOfDicomFiles.DicomFile)(fi.next());
                        String fileName = dicomFile.getFileName();
if (debugLevel > 0) System.err.println("Sending "+fileName);
                        boolean success = false;
                        String affectedSOPInstance = null;
                        try {
                              InputStream in = new BufferedInputStream(new FileInputStream(fileName));
                              try {
                                    String inputTransferSyntax = null;
                                    String affectedSOPClass = null;
                                    DicomInputStream din = new DicomInputStream(in);
                                    if (din.haveMetaHeader()) {
                                          AttributeList metaList = new AttributeList();
                                          metaList.readOnlyMetaInformationHeader(din);
if (debugLevel > 0) System.err.println("Meta header information = "+metaList);
                                          affectedSOPClass=Attribute.getSingleStringValueOrNull(metaList,TagFromName.MediaStorageSOPClassUID);
                                          affectedSOPInstance=Attribute.getSingleStringValueOrNull(metaList,TagFromName.MediaStorageSOPInstanceUID);
                                          inputTransferSyntax=Attribute.getSingleStringValueOrNull(metaList,TagFromName.TransferSyntaxUID);
                                    }
                                    else {
                                          affectedSOPClass=dicomFile.getSOPClassUID();
                                          affectedSOPInstance=dicomFile.getSOPInstanceUID();
                                          inputTransferSyntax=din.getTransferSyntaxToReadDataSet().getUID();
                                    }
if (debugLevel > 1) System.err.println("StorageSOPClassSCU(): affectedSOPClass = "+affectedSOPClass);
if (debugLevel > 1) System.err.println("StorageSOPClassSCU(): affectedSOPInstance = "+affectedSOPInstance);
if (debugLevel > 1) System.err.println("StorageSOPClassSCU(): inputTransferSyntax = "+inputTransferSyntax);

                                    if (affectedSOPClass == null) {
                                          throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Affected SOP Class UID");
                                    }
                                    if (affectedSOPInstance == null) {
                                          throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Affected SOP Instance UID");
                                    }
                                    if (inputTransferSyntax == null) {
                                          throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Transfer Syntax UID");
                                    }

                                    // Decide which presentation context we are going to use ...
                                    byte presentationContextID = association.getSuitablePresentationContextID(affectedSOPClass);
                                    //int presentationContextID = association.getSuitablePresentationContextID(affectedSOPClass,TransferSyntax.Default);
if (debugLevel > 0) System.err.println("Using context ID "+presentationContextID);
                                    String outputTransferSyntax = association.getTransferSyntaxForPresentationContextID(presentationContextID);
if (debugLevel > 0) System.err.println("Using outputTransferSyntax "+outputTransferSyntax);
                        
                                    success = sendOneSOPInstance(association,affectedSOPClass,affectedSOPInstance,
                                          inputTransferSyntax,din,
                                          presentationContextID,outputTransferSyntax,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID);
                                    // State 6
                              }
                              finally {
                                    in.close();
                              }
                        }
                        catch (DicomNetworkException e) {
                              e.printStackTrace(System.err);
                              success=false;
                        }
                        catch (DicomException e) {
                              e.printStackTrace(System.err);
                              success=false;
                        }
                        catch (IOException e) {
                              e.printStackTrace(System.err);
                              success=false;
                        }
                        if (!success) {
                              ++nFailed;
                        }
if (debugLevel > 0) System.err.println("Send "+fileName+" "+(success ? "succeeded" : "failed"));
                        if (multipleInstanceTransferStatusHandler != null) {
                              if (multipleInstanceTransferStatusHandler instanceof MultipleInstanceTransferStatusHandlerWithFileName) {
                                    ((MultipleInstanceTransferStatusHandlerWithFileName)multipleInstanceTransferStatusHandler).updateStatus(nRemaining,nCompleted,nFailed,nWarning,affectedSOPInstance,fileName,success);
                              }
                              else {
                                    multipleInstanceTransferStatusHandler.updateStatus(nRemaining,nCompleted,nFailed,nWarning,affectedSOPInstance);
                              }
                        }
                  }
if (debugLevel > 0) System.err.println("StorageSOPClassSCU(): Finished sending all files nRemaining="+nRemaining+" nCompleted="+nCompleted+" nFailed="+nFailed+" nWarning="+nWarning);
            }
//System.err.println("StorageSOPClassSCU.sendMultipleSOPInstances() sent "+nCompleted+" files in "+(System.currentTimeMillis()-startTime)+" ms");
      }
                  
      /**
       * <p>Send the specified instances contained in the attribute lists over an existing association.</p>
       *
       * @param   association                                           already existing association to SCP
       * @param   lists                                                 the array of attribute lists to send
       * @param   multipleInstanceTransferStatusHandler     handler called after each transfer (may be null if not required)
       * @param   moveOriginatorApplicationEntityTitle      the AET of the C-MOVE that originated this C-STORE, or null if none
       * @param   moveOriginatorMessageID                         the MessageID of the C-MOVE that originated this C-STORE, or -1 if none
       * @exception     AReleaseException
       * @exception     DicomNetworkException
       * @exception     IOException
       */
00549       protected void sendMultipleSOPInstances(Association association,AttributeList[] lists,MultipleInstanceTransferStatusHandler multipleInstanceTransferStatusHandler,
                        String moveOriginatorApplicationEntityTitle,int moveOriginatorMessageID)
                  throws AReleaseException, DicomNetworkException, IOException {
//long startTime=System.currentTimeMillis();
            int nRemaining = lists.length;
            int nCompleted = 0;
            int nFailed = 0;
            int nWarning = 0;
            {
if (debugLevel > 0) System.err.println(association);
                  for (int i=0; i<lists.length; ++i) {
                        --nRemaining;
                        ++nCompleted;
                        AttributeList list = lists[i];
                        boolean success = false;
                        String affectedSOPInstance = null;
                        try {
                              String affectedSOPClass = null;
                              affectedSOPClass=Attribute.getSingleStringValueOrNull(list,TagFromName.SOPClassUID);
                              affectedSOPInstance=Attribute.getSingleStringValueOrNull(list,TagFromName.SOPInstanceUID);
if (debugLevel > 0) System.err.println("Sending "+affectedSOPInstance);
if (debugLevel > 1) System.err.println("StorageSOPClassSCU(): affectedSOPClass = "+affectedSOPClass);
//if (debugLevel > 1) System.err.println("StorageSOPClassSCU(): affectedSOPInstance = "+affectedSOPInstance);

                              if (affectedSOPClass == null) {
                                    throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Affected SOP Class UID");
                              }
                              if (affectedSOPInstance == null) {
                                    throw new DicomNetworkException("Can't C-STORE SOP Instance - can't determine Affected SOP Instance UID");
                              }

                              // Decide which presentation context we are going to use ...
                              byte presentationContextID = association.getSuitablePresentationContextID(affectedSOPClass);
                              //int presentationContextID = association.getSuitablePresentationContextID(affectedSOPClass,TransferSyntax.Default);
if (debugLevel > 0) System.err.println("Using context ID "+presentationContextID);
                              String outputTransferSyntax = association.getTransferSyntaxForPresentationContextID(presentationContextID);
if (debugLevel > 0) System.err.println("Using outputTransferSyntax "+outputTransferSyntax);
                        
                              success = sendOneSOPInstance(association,affectedSOPClass,affectedSOPInstance,
                                    list,
                                    presentationContextID,outputTransferSyntax,moveOriginatorApplicationEntityTitle,moveOriginatorMessageID);
                              // State 6
                        }
                        catch (DicomNetworkException e) {
                              e.printStackTrace(System.err);
                              success=false;
                        }
                        catch (DicomException e) {
                              e.printStackTrace(System.err);
                              success=false;
                        }
                        catch (IOException e) {
                              e.printStackTrace(System.err);
                              success=false;
                        }
                        if (!success) {
                              ++nFailed;
                        }
if (debugLevel > 0) System.err.println("Send "+affectedSOPInstance+" "+(success ? "succeeded" : "failed"));
                        if (multipleInstanceTransferStatusHandler != null) {
                              multipleInstanceTransferStatusHandler.updateStatus(nRemaining,nCompleted,nFailed,nWarning,affectedSOPInstance);
                        }
                  }
if (debugLevel > 0) System.err.println("StorageSOPClassSCU(): Finished sending all files nRemaining="+nRemaining+" nCompleted="+nCompleted+" nFailed="+nFailed+" nWarning="+nWarning);
            }
//System.err.println("StorageSOPClassSCU.sendMultipleSOPInstances() sent "+nCompleted+" instances in "+(System.currentTimeMillis()-startTime)+" ms");
      }

      /**
       * <p>For testing, establish an association to the specified AE and send one or more DICOM instances (C-STORE requests).</p>
       *
       * @param   arg   array of seven or nine strings - their hostname, their port, their AE Title, our AE Title,
       *                the filename containing the instance to send (or a hyphen '-' if a list of one or more filenames is to be read from stdin)
       *                optionally the SOP Class and the SOP Instance (otherwise will be read from the file(s); if multiple files use an empty string for the SOP Instance),
       *                the compression level (0=none,1=propose deflate,2=propose deflate and bzip2) and the debugging level
       */
00625       public static void main(String arg[]) {
            try {
                  String      theirHost=null;
                  int         theirPort=-1;
                  String   theirAETitle=null;
                  String     ourAETitle=null;
                  String       fileName=null;
                  String    SOPClassUID=null;
                  String SOPInstanceUID=null;
                  int  compressionLevel=0;
                  int        debugLevel=0;
      
                  if (arg.length == 9) {
                             theirHost=arg[0];
                             theirPort=Integer.parseInt(arg[1]);
                          theirAETitle=arg[2];
                            ourAETitle=arg[3];
                              fileName=arg[4];
                           SOPClassUID=arg[5];
                        SOPInstanceUID=arg[6];
                        compressionLevel=Integer.parseInt(arg[7]);
                            debugLevel=Integer.parseInt(arg[8]);
                  }
                  else if (arg.length == 7) {
                             theirHost=arg[0];
                             theirPort=Integer.parseInt(arg[1]);
                          theirAETitle=arg[2];
                            ourAETitle=arg[3];
                              fileName=arg[4];
                           SOPClassUID=null;                // figured out by StorageSOPClassSCU() by reading the metaheader
                        SOPInstanceUID=null;                // figured out by StorageSOPClassSCU() by reading the metaheader
                        compressionLevel=Integer.parseInt(arg[5]);
                            debugLevel=Integer.parseInt(arg[6]);
                  }
                  else {
                        throw new Exception("Argument list must be 7 or 9 values");
                  }
                  if (fileName.equals("-")) {
                        SetOfDicomFiles setOfDicomFiles = new SetOfDicomFiles();
                        BufferedReader dicomFileNameReader = new BufferedReader(new InputStreamReader(System.in));
                        String dicomFileName = dicomFileNameReader.readLine();
                        while (dicomFileName != null) {
                              if (SOPClassUID == null) {
                                    setOfDicomFiles.add(dicomFileName);
                              }
                              else {
                                    setOfDicomFiles.add(dicomFileName,SOPClassUID,null,null);   // OK to leave instance and transfer syntax uids as null; only need SOP Class to negotiate
                              }
                              dicomFileName = dicomFileNameReader.readLine();
                        }
//System.err.println(setOfDicomFiles.toString());
                        new StorageSOPClassSCU(theirHost,theirPort,theirAETitle,ourAETitle,setOfDicomFiles,compressionLevel,null,null,0,debugLevel);
                  }
                  else {
                        new StorageSOPClassSCU(theirHost,theirPort,theirAETitle,ourAETitle,fileName,SOPClassUID,SOPInstanceUID,compressionLevel,debugLevel);
                  }
            }
            catch (Exception e) {
                  e.printStackTrace(System.err);
                  System.exit(0);
            }
      }
}





Generated by  Doxygen 1.6.0   Back to index