# HG changeset patch
# User Sebastien Jodogne <s.jodogne@gmail.com>
# Date 1379514141 -7200
# Node ID e0cfb413c86b2d1d5e19f8b1d36c39be0630e35e
# Parent  b26a7c397c34b82518a7b78d27ef9ce0e979e8af
find scp

diff -r b26a7c397c34 -r e0cfb413c86b Core/DicomFormat/DicomTag.h
--- a/Core/DicomFormat/DicomTag.h	Wed Sep 18 15:27:07 2013 +0200
+++ b/Core/DicomFormat/DicomTag.h	Wed Sep 18 16:22:21 2013 +0200
@@ -110,4 +110,8 @@
   // DICOM tags used for fMRI (thanks to Will Ryder)
   static const DicomTag DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS(0x0020, 0x0105);
   static const DicomTag DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER(0x0020, 0x0100);
+
+  // Tags for C-FIND and C-MOVE
+  static const DicomTag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005);
+  static const DicomTag DICOM_TAG_QUERY_RETRIEVE_LEVEL(0x0008, 0x0052);
 }
diff -r b26a7c397c34 -r e0cfb413c86b OrthancServer/ServerEnumerations.cpp
--- a/OrthancServer/ServerEnumerations.cpp	Wed Sep 18 15:27:07 2013 +0200
+++ b/OrthancServer/ServerEnumerations.cpp	Wed Sep 18 16:22:21 2013 +0200
@@ -33,6 +33,7 @@
 
 #include "../Core/OrthancException.h"
 #include "../Core/EnumerationDictionary.h"
+#include "../Core/Toolbox.h"
 
 #include <boost/thread.hpp>
 
@@ -291,4 +292,30 @@
   }
 
 
+  ResourceType StringToResourceType(const char* type)
+  {
+    std::string s(type);
+    Toolbox::ToUpperCase(s);
+
+    if (s == "PATIENT")
+    {
+      return ResourceType_Patient;
+    }
+    else if (s == "STUDY")
+    {
+      return ResourceType_Study;
+    }
+    else if (s == "SERIES")
+    {
+      return ResourceType_Series;
+    }
+    else if (s == "INSTANCE" || s == "IMAGE")
+    {
+      return ResourceType_Instance;
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
 }
diff -r b26a7c397c34 -r e0cfb413c86b OrthancServer/ServerEnumerations.h
--- a/OrthancServer/ServerEnumerations.h	Wed Sep 18 15:27:07 2013 +0200
+++ b/OrthancServer/ServerEnumerations.h	Wed Sep 18 16:22:21 2013 +0200
@@ -139,4 +139,6 @@
   ResourceType GetParentResourceType(ResourceType type);
 
   ResourceType GetChildResourceType(ResourceType type);
+
+  ResourceType StringToResourceType(const char* type);
 }
diff -r b26a7c397c34 -r e0cfb413c86b OrthancServer/main.cpp
--- a/OrthancServer/main.cpp	Wed Sep 18 15:27:07 2013 +0200
+++ b/OrthancServer/main.cpp	Wed Sep 18 16:22:21 2013 +0200
@@ -87,8 +87,69 @@
                       DicomFindAnswers& answers)
   {
     LOG(WARNING) << "Find-SCU request received";
-    DicomArray a(input);
-    a.Print(stdout);
+
+    /**
+     * Retrieve the query level.
+     **/
+
+    const DicomValue* levelTmp = input.TestAndGetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL);
+    if (levelTmp == NULL) 
+    {
+      throw OrthancException(ErrorCode_BadRequest);
+    }
+
+    ResourceType level = StringToResourceType(levelTmp->AsString().c_str());
+
+    if (level != ResourceType_Patient &&
+        level != ResourceType_Study &&
+        level != ResourceType_Series)
+    {
+      throw OrthancException(ErrorCode_NotImplemented);
+    }
+
+
+    /**
+     * Retrieve the constraints of the query.
+     **/
+
+    DicomArray query(input);
+
+    DicomMap constraintsTmp;
+    DicomMap wildcardConstraintsTmp;
+
+    for (size_t i = 0; i < query.GetSize(); i++)
+    {
+      if (!query.GetElement(i).GetValue().IsNull() &&
+          query.GetElement(i).GetTag() != DICOM_TAG_QUERY_RETRIEVE_LEVEL &&
+          query.GetElement(i).GetTag() != DICOM_TAG_SPECIFIC_CHARACTER_SET)
+      {
+        DicomTag tag = query.GetElement(i).GetTag();
+        std::string value = query.GetElement(i).GetValue().AsString();
+
+        if (value.find('*') != std::string::npos ||
+            value.find('?') != std::string::npos ||
+            value.find('\\') != std::string::npos ||
+            value.find('-') != std::string::npos)
+        {
+          wildcardConstraintsTmp.SetValue(tag, value);
+        }
+        else
+        {
+          constraintsTmp.SetValue(tag, value);
+        }
+      }
+    }
+
+    DicomArray constraints(constraintsTmp);
+    DicomArray wildcardConstraints(wildcardConstraintsTmp);
+
+    // http://www.itk.org/Wiki/DICOM_QueryRetrieve_Explained
+    // http://dicomiseasy.blogspot.be/2012/01/dicom-queryretrieve-part-i.html
+
+    constraints.Print(stdout);
+    printf("\n"); fflush(stdout);
+    wildcardConstraints.Print(stdout);
+    printf("\n"); fflush(stdout);
   }
 };
 
@@ -369,14 +430,13 @@
 
     MyDicomServerFactory serverFactory(context);
     
-
     {
       // DICOM server
       DicomServer dicomServer;
       dicomServer.SetCalledApplicationEntityTitleCheck(GetGlobalBoolParameter("DicomCheckCalledAet", false));
       dicomServer.SetStoreRequestHandlerFactory(serverFactory);
-      //dicomServer.SetMoveRequestHandlerFactory(serverFactory);
-      //dicomServer.SetFindRequestHandlerFactory(serverFactory);
+      dicomServer.SetMoveRequestHandlerFactory(serverFactory);
+      dicomServer.SetFindRequestHandlerFactory(serverFactory);
       dicomServer.SetPortNumber(GetGlobalIntegerParameter("DicomPort", 4242));
       dicomServer.SetApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "ORTHANC"));
 
diff -r b26a7c397c34 -r e0cfb413c86b UnitTests/main.cpp
--- a/UnitTests/main.cpp	Wed Sep 18 15:27:07 2013 +0200
+++ b/UnitTests/main.cpp	Wed Sep 18 16:22:21 2013 +0200
@@ -387,6 +387,13 @@
   ASSERT_EQ("IndexInSeries", EnumerationToString(MetadataType_Instance_IndexInSeries));
   ASSERT_EQ("LastUpdate", EnumerationToString(MetadataType_LastUpdate));
 
+  ASSERT_EQ(ResourceType_Patient, StringToResourceType("PATienT"));
+  ASSERT_EQ(ResourceType_Study, StringToResourceType("STudy"));
+  ASSERT_EQ(ResourceType_Series, StringToResourceType("SeRiEs"));
+  ASSERT_EQ(ResourceType_Instance, StringToResourceType("INStance"));
+  ASSERT_EQ(ResourceType_Instance, StringToResourceType("IMagE"));
+  ASSERT_THROW(StringToResourceType("heLLo"), OrthancException);
+
   ASSERT_EQ(2047, StringToMetadata("2047"));
   ASSERT_THROW(StringToMetadata("Ceci est un test"), OrthancException);
   ASSERT_THROW(RegisterUserMetadata(128, ""), OrthancException); // too low (< 1024)