Ver código fonte

Added a XML schema for progress reports. Added validation test.

Sascha Zelzer 12 anos atrás
pai
commit
1285553cd9

+ 9 - 0
Libs/CommandLineModules/Backend/LocalProcess/CMakeLists.txt

@@ -31,6 +31,7 @@ set(KIT_UI_FORMS
 
 # Resources
 set(KIT_resources
+  Resources/ctkCmdLineModulesBackendLocalProcess.qrc
 )
 
 # Target libraries - See CMake/ctkFunctionGetTargetLibraries.cmake
@@ -59,6 +60,14 @@ if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
     )
 endif()
 
+find_package(Doxygen)
+if(DOXYGEN_FOUND)
+  # Copy XML schema file to the Doxygen output directory
+  add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/Resources/ctkCmdLineModuleProcess.xsd
+                                                  ${CTK_BINARY_DIR}/Documentation/html/ctkCmdLineModuleProcess.xsd)
+endif()
+
 # Testing
 if(BUILD_TESTING)
   #add_subdirectory(Testing)

+ 137 - 0
Libs/CommandLineModules/Backend/LocalProcess/Resources/ctkCmdLineModuleProcess.xsd

@@ -0,0 +1,137 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="xs3p.xsl"?>
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:xs3p="http://titanium.dstc.edu.au/xml/xs3p">
+
+  <xsd:annotation>
+    <xsd:appinfo source="http://www.commontk.org/docs/html/CommandLineModules_Page.html">
+      <xs3p:title>CTK XML schema for progress and result reporting in command line modules.</xs3p:title>
+      <xs3p:printGlossary>false</xs3p:printGlossary>
+      <xs3p:printLegend>false</xs3p:printLegend>
+    </xsd:appinfo>
+    <xsd:documentation>The XML schema for the XML fragments used when reporting progress and results in command line modules.</xsd:documentation>
+  </xsd:annotation>
+
+  <!--
+  ===================================================================
+    MODULE-ROOT
+      Root element 
+  ===================================================================
+  -->
+  
+  <xsd:element name="module-root" type="RootType"/>
+  
+  <xsd:complexType name="RootType" mixed="true">
+    <xsd:annotation>
+      <xsd:documentation>The root element. This is added automatically and must not be printed out by the module.</xsd:documentation>
+    </xsd:annotation>
+    
+    <xsd:sequence>     
+      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="FilterGroup"/>   
+    </xsd:sequence>
+  </xsd:complexType>
+  
+  <xsd:group name="FilterGroup">
+    <xsd:sequence>        
+      <xsd:element maxOccurs="1" minOccurs="1" name="filter-start" type="FilterStartType"/>
+      <xsd:element maxOccurs="unbounded" minOccurs="0" name="filter-progress" type="FilterProgressType"/>
+      <xsd:element maxOccurs="unbounded" minOccurs="0" name="filter-progress-text" type="FilterProgressTextType"/>
+      <xsd:element maxOccurs="unbounded" minOccurs="0" name="filter-result" type="FilterResultType"/>
+      <xsd:element maxOccurs="1" minOccurs="1" name="filter-end" type="FilterEndType"/>
+    </xsd:sequence>
+  </xsd:group>
+  
+  <!--
+  ===================================================================
+    FILTER-START
+  ===================================================================
+  -->
+  <xsd:complexType name="FilterStartType">
+    <xsd:annotation>
+      <xsd:documentation>Marks the start of a set of processing instructions.</xsd:documentation>
+    </xsd:annotation>
+    
+    <xsd:sequence>
+      <xsd:element maxOccurs="1" minOccurs="1" name="filter-name" type="xsd:string">
+        <xsd:annotation>
+          <xsd:documentation>The name of the current "filter" (set of processing instructions).</xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element maxOccurs="1" minOccurs="0" name="filter-comment" type="xsd:string">
+        <xsd:annotation>
+          <xsd:documentation>A short, descriptive text about the purpose of this filter.</xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+  
+  <!--
+  ===================================================================
+    FILTER-PROGRESS
+  ===================================================================
+  -->
+  
+  <xsd:simpleType name="FilterProgressType">
+    <xsd:annotation>
+      <xsd:documentation>A float value between 0 and 1 to report the current overall progress.</xsd:documentation>
+    </xsd:annotation>
+    <xsd:restriction base="xsd:float">
+      <xsd:minInclusive value="0"/>
+      <xsd:maxInclusive value="1"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+  
+  <!--
+  ===================================================================
+    FILTER-PROGRESS-TEXT
+  ===================================================================
+  -->
+  
+  <xsd:complexType name="FilterProgressTextType" mixed="true">
+    <xsd:annotation>
+      <xsd:documentation>Report a progress value and corresponding progress text.</xsd:documentation>
+    </xsd:annotation>
+    
+    <xsd:attribute name="progress" use="required" type="FilterProgressType"/>
+  </xsd:complexType>
+  
+  <!--
+  ===================================================================
+    FILTER-RESULT
+  ===================================================================
+  -->
+  
+  <xsd:complexType name="FilterResultType" mixed="true">
+    <xsd:annotation>
+      <xsd:documentation>Report the current result.</xsd:documentation>
+    </xsd:annotation>
+    
+    <xsd:attribute name="name" use="required" type="xsd:string">
+      <xsd:annotation>
+        <xsd:documentation>The output parameter name to which this result belongs to.</xsd:documentation>
+      </xsd:annotation>
+    </xsd:attribute>
+  </xsd:complexType>
+  
+  <!--
+  ===================================================================
+    FILTER-END
+  ===================================================================
+  -->
+  
+  <xsd:complexType name="FilterEndType">
+    <xsd:annotation>
+      <xsd:documentation>Marks the end of a set of processing instructions.</xsd:documentation>
+    </xsd:annotation>
+    
+    <xsd:sequence>
+      <xsd:element maxOccurs="1" minOccurs="0" name="filter-comment" type="xsd:string">
+        <xsd:annotation>
+          <xsd:documentation>A short, descriptive text about the end state of this filter.</xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+  
+</xsd:schema>

+ 5 - 0
Libs/CommandLineModules/Backend/LocalProcess/Resources/ctkCmdLineModulesBackendLocalProcess.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>ctkCmdLineModuleProcess.xsd</file>
+    </qresource>
+</RCC>

+ 16 - 1
Libs/CommandLineModules/Core/ctkCmdLineModuleXmlProgressWatcher.cpp

@@ -33,6 +33,7 @@ static QString FILTER_START = "filter-start";
 static QString FILTER_NAME = "filter-name";
 static QString FILTER_COMMENT = "filter-comment";
 static QString FILTER_PROGRESS = "filter-progress";
+static QString FILTER_PROGRESS_TEXT = "filter-progress-text";
 static QString FILTER_RESULT = "filter-result";
 static QString FILTER_END = "filter-end";
 
@@ -91,7 +92,7 @@ public:
         }
 
         if (stack.size() == 2 &&
-            (stack.front() == FILTER_START || stack.front() == FILTER_END || stack.front() == FILTER_PROGRESS))
+            (stack.front() == FILTER_START || stack.front() == FILTER_END))
         {
           if (stack.back() == FILTER_NAME)
           {
@@ -106,6 +107,10 @@ public:
         {
           currentProgress = reader.text().toString().toFloat();
         }
+        else if (stack.size() == 1 && stack.back() == FILTER_PROGRESS_TEXT)
+        {
+          currentComment = reader.text().toString();
+        }
         else if (stack.size() == 1 && stack.back() == FILTER_RESULT)
         {
           currentResultValue = reader.text().toString();
@@ -125,6 +130,7 @@ public:
 
         if (name.compare(FILTER_START, Qt::CaseInsensitive) == 0 ||
             name.compare(FILTER_PROGRESS, Qt::CaseInsensitive) == 0 ||
+            name.compare(FILTER_PROGRESS_TEXT, Qt::CaseInsensitive) == 0 ||
             name.compare(FILTER_RESULT, Qt::CaseInsensitive) == 0 ||
             name.compare(FILTER_END, Qt::CaseInsensitive) == 0)
         {
@@ -140,6 +146,10 @@ public:
             currentComment = QString();
             currentProgress = 0;
           }
+          else if (name.compare(FILTER_PROGRESS_TEXT, Qt::CaseInsensitive) == 0)
+          {
+            currentProgress = reader.attributes().value("progress").toString().toFloat();
+          }
           else if (name.compare(FILTER_RESULT, Qt::CaseInsensitive) == 0)
           {
             currentResultParameter = reader.attributes().value("name").toString();
@@ -178,6 +188,11 @@ public:
             emit q->filterProgress(currentProgress, currentComment);
             currentComment = QString();
           }
+          else if (name.compare(FILTER_PROGRESS_TEXT, Qt::CaseInsensitive) == 0)
+          {
+            emit q->filterProgress(currentProgress, currentComment);
+            currentComment = QString();
+          }
           else if (name.compare(FILTER_RESULT, Qt::CaseInsensitive) == 0)
           {
             emit q->filterResult(currentResultParameter, currentResultValue);

+ 6 - 2
Libs/CommandLineModules/Testing/Cpp/CMakeLists.txt

@@ -9,8 +9,12 @@ if(CTK_LIB_CommandLineModules/Frontend/QtGui)
   include(${QT_USE_FILE})
 
   if(CTK_LIB_CommandLineModules/Backend/LocalProcess)
-    list(APPEND _test_srcs ctkCmdLineModuleFutureTest.cpp)
-    list(APPEND _test_mocs ctkCmdLineModuleFutureTest.cpp)
+    set(_test_cpp_files
+        ctkCmdLineModuleFutureTest.cpp
+        ctkCmdLineModuleProcessXmlOutputTest.cpp
+        )
+    list(APPEND _test_srcs ${_test_cpp_files})
+    list(APPEND _test_mocs ${_test_cpp_files})
   endif()
   if(CTK_LIB_CommandLineModules/Backend/FunctionPointer)
     list(APPEND _test_srcs ctkCmdLineModuleQtCustomizationTest.cpp)

+ 68 - 0
Libs/CommandLineModules/Testing/Cpp/ctkCmdLineModuleProcessXmlOutputTest.cpp

@@ -0,0 +1,68 @@
+/*=============================================================================
+  
+  Library: CTK
+  
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+    
+  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
+  
+    http://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.
+  
+=============================================================================*/
+
+#include "ctkCmdLineModuleXmlValidator.h"
+
+#include "ctkTest.h"
+
+#include <QProcess>
+#include <QCoreApplication>
+#include <QDebug>
+
+
+//-----------------------------------------------------------------------------
+class ctkCmdLineModuleProcessXmlOutputTester : public QObject
+{
+  Q_OBJECT
+
+private Q_SLOTS:
+
+  void testValidXmlOutput();
+
+};
+
+//-----------------------------------------------------------------------------
+void ctkCmdLineModuleProcessXmlOutputTester::testValidXmlOutput()
+{
+  QString processLocation = QCoreApplication::applicationDirPath() + "/ctkCmdLineModuleTestBed";
+  QProcess process;
+  process.start(processLocation, QStringList() << "--numOutputs" << "1" << "dummy");
+
+  QVERIFY(process.waitForFinished());
+  QByteArray output = process.readAllStandardOutput();
+  QVERIFY(!output.isEmpty());
+  output.prepend("<module-root>");
+  output.append("</module-root>");
+
+  QBuffer buffer(&output);
+  buffer.open(QIODevice::ReadOnly);
+  ctkCmdLineModuleXmlValidator xmlValidator(&buffer);
+
+  QFile schema(":/ctkCmdLineModuleProcess.xsd");
+  QVERIFY(schema.open(QIODevice::ReadOnly));
+  xmlValidator.setInputSchema(&schema);
+
+  QVERIFY(xmlValidator.validateInput());
+}
+
+// ----------------------------------------------------------------------------
+CTK_TEST_MAIN(ctkCmdLineModuleProcessXmlOutputTest)
+#include "moc_ctkCmdLineModuleProcessXmlOutputTest.cpp"

+ 2 - 2
Libs/CommandLineModules/Testing/Modules/TestBed/ctkCmdLineModuleTestBed.cpp

@@ -170,8 +170,8 @@ int main(int argc, char* argv[])
       out << output << endl;
 
       // report progress
-      out << "<filter-progress>" << (i+1)*progressStep
-          << "<filter-comment>Calculating output " << (i+2) << "...</filter-comment></filter-progress>" << endl;
+      out << QString("<filter-progress-text progress=\"%1\">").arg((i+1)*progressStep)
+          << "Calculating output " << (i+2) << "...</filter-progress-text>" << endl;
       // report the current output number as a result
       out << "<filter-result name=\"resultNumberOutput\">" << (i+1) << "</filter-result>" << endl;
     }