diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp index 326a1b014a..b6066c4223 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp @@ -1,199 +1,228 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataSequentialPlayer.h" //for the pause #include #include #include #include +//Exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + mitk::NavigationDataSequentialPlayer::NavigationDataSequentialPlayer() : mitk::NavigationDataPlayerBase() , m_Doc(new TiXmlDocument) , m_DataElem(0) , m_CurrentElem(0) , m_Repeat(false) , m_NumberOfSnapshots(0) , m_LastGoTo(0) { } mitk::NavigationDataSequentialPlayer::~NavigationDataSequentialPlayer() { delete m_Doc; } void mitk::NavigationDataSequentialPlayer::ReinitXML() { m_DataElem = m_Doc->FirstChildElement("Data"); int toolcount; if(!m_DataElem) + { + //throwing an exception + mitkThrowException(mitk::IGTException) << "Data element not found"; MITK_WARN << "Data element not found"; + } else { m_DataElem->QueryIntAttribute("ToolCount", &toolcount); this->SetNumberOfOutputs(toolcount); mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); emptyNd->SetPosition(position); emptyNd->SetOrientation(orientation); emptyNd->SetDataValid(false); mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { tmp = mitk::NavigationData::New(); tmp->Graft(emptyNd); this->SetNthOutput(index, tmp); } // find out _NumberOfSnapshots m_NumberOfSnapshots = 0; TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); while(nextND) { ++m_NumberOfSnapshots; nextND = nextND->NextSiblingElement("NavigationData"); } // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; } } void mitk::NavigationDataSequentialPlayer::GoToSnapshot(int i) { assert(m_DataElem); int numOfUpdateCalls = 0; // i.e. number of snapshots 10 // goto(7), m_LastGoTo=3 => numOfUpdateCalls = 4 if(m_LastGoTo <= i) numOfUpdateCalls = i - m_LastGoTo; // goto(4), m_LastGoTo=7 => numOfUpdateCalls = 7 else { if(!m_Repeat) { + //throwing an exception + mitkThrowException(mitk::IGTException)<<"cannot go back to snapshot " << i << " because the " + << this->GetNameOfClass() << " is configured to not repeat the" + << " navigation data"; + MITK_WARN << "cannot go back to snapshot " << i << " because the " << this->GetNameOfClass() << " is configured to not repeat the" << " navigation data"; } else { numOfUpdateCalls = (m_NumberOfSnapshots - m_LastGoTo) + i; } } for(int j=0; jUpdate(); m_LastGoTo = i; } void mitk::NavigationDataSequentialPlayer:: SetFileName(const std::string& _FileName) { m_FileName = _FileName; + // if Loading wasnt succesfull + // (!m_Doc->LoadFile(m_FileName)=false) wherase (m_Doc->LoadFile(m_FileName)=true) if(!m_Doc->LoadFile(m_FileName)) { this->SetNumberOfOutputs(0); std::ostringstream s; s << "File " << _FileName << " could not be loaded"; - throw std::invalid_argument(s.str()); + //may be we need to change to mitk::exception + mitkThrowException(mitk::IGTIOException)<ReinitXML(); this->Modified(); } +//NEW PART is ADDED void mitk::NavigationDataSequentialPlayer:: SetXMLString(const std::string& _XMLString) { m_XMLString = _XMLString; - - m_Doc->Parse( m_XMLString.c_str() ); + if((m_Doc->Parse( m_XMLString.c_str()))== NULL) + { this->ReinitXML(); + } else + { + //if the string is not an XML string + std::ostringstream s; + s << "String" << _XMLString << " is not an XML string"; + mitkThrowException(mitk::IGTIOException)<Modified(); } void mitk::NavigationDataSequentialPlayer::GenerateData() { assert(m_DataElem); - - // very important: go through the tools (there could be more then one) + // very important: go through the tools (there could be more than one) mitk::NavigationData::Pointer tmp; //MITK_INFO << "this->GetNumberOfOutputs()" << this->GetNumberOfOutputs(); for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { //MITK_INFO << "index" << index; // go to the first element if(!m_CurrentElem) m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); // go to the next element else m_CurrentElem = m_CurrentElem->NextSiblingElement(); // if repeat is on: go back to the first element (prior calls delivered NULL // elem) if(!m_CurrentElem && m_Repeat) m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); mitk::NavigationData* output = this->GetOutput(index); tmp = this->ReadVersion1(); if(tmp.IsNotNull()) { output->Graft(tmp); m_StreamValid = true; } else // no valid output { output->SetDataValid(false); m_StreamValid = false; - m_ErrorMessage = "Error: Cannot parse input file."; + //throwing exception + mitkThrowException(mitk::IGTException)<<"Error: Cannot parse input file."; + //m_ErrorMessage = "Error: Cannot parse input file."; } } } mitk::NavigationData::Pointer mitk::NavigationDataSequentialPlayer::ReadVersion1() { TiXmlElement* elem = m_CurrentElem; if(!elem) return NULL; return this->ReadNavigationData(elem); } void mitk::NavigationDataSequentialPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } + + + diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h index 4354ef96b9..5c0fbf50c6 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h @@ -1,110 +1,117 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #include #include "tinyxml.h" namespace mitk { /**Documentation * \brief This class is a slightly changed reimplementation of the * NavigationDataPlayer which does not care about timestamps and just * outputs the navigationdatas in their sequential order * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataSequentialPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataSequentialPlayer, NavigationDataPlayerBase); itkNewMacro(Self); /** * \brief sets the file name and path (if XMLString is set, this is neglected) + * @throws Throws an exception if the given file cannot be loaded */ void SetFileName(const std::string& _FileName); /** - * \brief returns the file name and path + * \brief returns the file name and path */ itkGetStringMacro(FileName); /** * \brief sets a xml string (by this, the xml string is not read from file) + * @throws Throws an mitk::IGT excepton if the string to set is not an XMLString */ void SetXMLString(const std::string& _XMLString); /** * \brief returns the current xml string */ itkGetStringMacro(XMLString); /// /// set to true if the data player should repeat the outputs /// itkSetMacro(Repeat, bool); /// /// set if the data player should repeat the outputs /// itkGetMacro(Repeat, bool); /// /// \return the number of navigation data snapshots available in the file /// itkGetMacro(NumberOfSnapshots, unsigned int); /// /// advance the output to the i-th snapshot /// e.g. if you want to have the NavData of snapshot /// 17 then you can call GoToSnapshot(17). index begins at 1! /// you can then also go back to snapshot 1 with GoToSnapshot(1) /// + //@throws Throws an exception if cannot go back to particular snapshot void GoToSnapshot(int i); /** * \brief Used for pipeline update just to tell the pipeline * that we always have to update */ virtual void UpdateOutputInformation(); protected: NavigationDataSequentialPlayer(); virtual ~NavigationDataSequentialPlayer(); + //@throws Throws an exception if data element is not found void ReinitXML(); mitk::NavigationData::Pointer ReadVersion1(); /// /// do the work here /// + /* + *@throws Throws an exception if cannot parse input file + */ virtual void GenerateData(); std::string m_FileName; std::string m_XMLString; TiXmlDocument* m_Doc; TiXmlElement* m_DataElem; TiXmlElement* m_CurrentElem; bool m_Repeat; unsigned int m_NumberOfSnapshots; int m_LastGoTo; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index 01e947fee3..c7ba6139a3 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,135 +1,268 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkTestingMacros.h" #include #include +//foe exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + + const char* XML_STRING = "" "" "" "" "" "" "" ""; vnl_vector tTool0Snapshot1(3); vnl_vector tTool1Snapshot2(3); mitk::Quaternion qTool0Snapshot0; mitk::Quaternion qTool1Snapshot1; mitk::NavigationDataSequentialPlayer::Pointer player( mitk::NavigationDataSequentialPlayer::New()); void runLoop() { mitk::NavigationData::Pointer nd0; mitk::NavigationData::Pointer nd1; for(unsigned int i=0; iGetNumberOfSnapshots();++i) { player->Update(); nd0 = player->GetOutput(); nd1 = player->GetOutput(1); // test some values MITK_TEST_CONDITION_REQUIRED(nd0.IsNotNull(), "nd0.IsNotNull()"); MITK_TEST_CONDITION_REQUIRED(nd1.IsNotNull(), "nd1.IsNotNull()"); if(i==0) { MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), "qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector()"); } else if(i==1) { MITK_TEST_CONDITION(tTool0Snapshot1 == nd0->GetPosition().GetVnlVector(), "tTool0Snapshot1 == nd0->GetPosition().GetVnlVector()"); MITK_TEST_CONDITION(qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector(), "qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector()"); } else if(i==2) // should be repeated { MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), "tTool1Snapshot2 == nd1->GetPosition().GetVnlVector()"); } } } + +void TestSetFileNameException() +{ //testing exception if file name hasnt been set + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer = mitk::NavigationDataSequentialPlayer::New(); + bool exceptionThrown=false; + try + { + myTestPlayer->SetFileName(""); + } + catch(mitk::IGTIOException) + { + exceptionThrown=true; + MITK_TEST_OUTPUT(<<"Tested exception for the case when file version is wrong in SetFileName. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetFileName method if exception (if file name hasnt been set) was thrown."); + + //testing ReInItXML method if data element is not found + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer1 = mitk::NavigationDataSequentialPlayer::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestDataInvalidTags.xml", "Modules/IGT/Testing/Data"); + bool exceptionThrown1=false; + try + { + myTestPlayer1->SetFileName(file); + } + catch(mitk::IGTException) + { + exceptionThrown1=true; + MITK_TEST_OUTPUT(<<"Tested exception for the case when file version is wrong in SetFileName. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing SetFileName method if exception (if data element not found) was thrown."); + +} + +void TestGoToSnapshotException() +{ + //testing GoToSnapShot for exception + + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New(); + //std::string file2 = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestDataInvalidTags.xml", "Modules/IGT/Testing/Data"); + // create test values valid for the xml data above + tTool0Snapshot1[0] = -336.65; + tTool0Snapshot1[1] = 138.5; + tTool0Snapshot1[2]= -2061.07; + tTool1Snapshot2[0] = -56.93; + tTool1Snapshot2[1] = 233.79; + tTool1Snapshot2[2]= -2042.6; + + myTestPlayer2 + ->SetXMLString(XML_STRING); + + MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfSnapshots() == 3, + "player->GetNumberOfSnapshots() == 3"); + myTestPlayer2 + ->SetRepeat(true); + + runLoop(); + // repeat is on should work a second time + runLoop(); + + bool exceptionThrown2=false; + try + { + myTestPlayer2->GoToSnapshot(1000000); + } + catch(mitk::IGTException) + { + exceptionThrown2=true; + MITK_TEST_OUTPUT(<<"Tested exception for the case when cannot go back to particular snapshot in GoToSnapShot. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing GoToSnapShot method if exception (cannot go back to particular snapshot) was thrown."); + +} + +void TestSetXMLStringException() +{ +mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New(); + // create test values valid for the xml data above + tTool0Snapshot1[0] = -336.65; + tTool0Snapshot1[1] = 138.5; + tTool0Snapshot1[2]= -2061.07; + tTool1Snapshot2[0] = -56.93; + tTool1Snapshot2[1] = 233.79; + tTool1Snapshot2[2]= -2042.6; + vnl_vector_fixed qVec; + qVec[0] = 0.0085; + qVec[1] = -0.0576; + qVec[2]= -0.0022; + qVec[3]= 0.9982; + qTool0Snapshot0 = mitk::Quaternion(qVec); + qVec[0] = 0.4683; + qVec[1] = 0.0188; + qVec[2]= -0.8805; + qVec[3]= 0.0696; + qTool1Snapshot1 = mitk::Quaternion(qVec); + +const char* XML_TESTSTRING = + "< ToolCount=\"2\">" + "" + "" + "" + "" + "" + "" + ""; + + bool exceptionThrown3=false; + //The string above XML_TESTSTRING is a wrong string, some element were deleted in above + try + { + myTestPlayer3->SetXMLString(XML_TESTSTRING); + } + catch(mitk::IGTException) + { + exceptionThrown3=true; + MITK_TEST_OUTPUT(<<"Tested exception for the case when. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing SetXMLString method if exception (string is not an XML String) was thrown."); +} + + + + /**Documentation * test for the class "NavigationDataRecorder". */ int mitkNavigationDataSequentialPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataSequentialPlayer"); // create test values valid for the xml data above tTool0Snapshot1[0] = -336.65; tTool0Snapshot1[1] = 138.5; tTool0Snapshot1[2]= -2061.07; tTool1Snapshot2[0] = -56.93; tTool1Snapshot2[1] = 233.79; tTool1Snapshot2[2]= -2042.6; vnl_vector_fixed qVec; qVec[0] = 0.0085; qVec[1] = -0.0576; qVec[2]= -0.0022; qVec[3]= 0.9982; qTool0Snapshot0 = mitk::Quaternion(qVec); qVec[0] = 0.4683; qVec[1] = 0.0188; qVec[2]= -0.8805; qVec[3]= 0.0696; qTool1Snapshot1 = mitk::Quaternion(qVec); player ->SetXMLString(XML_STRING); MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfSnapshots() == 3, "player->GetNumberOfSnapshots() == 3"); player ->SetRepeat(true); runLoop(); // repeat is on should work a second time runLoop(); // now test the go to snapshot function player->GoToSnapshot(3); mitk::NavigationData::Pointer nd1 = player->GetOutput(1); MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), "tTool1Snapshot2 == nd1->GetPosition().GetVnlVector()"); player->GoToSnapshot(1); mitk::NavigationData::Pointer nd0 = player->GetOutput(0); MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), "qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector()"); player->GoToSnapshot(3); // and a third time runLoop(); + //Testing exceptions + TestSetFileNameException(); + TestSetXMLStringException(); + TestGoToSnapshotException(); + + // always end with this! MITK_TEST_END(); }