diff --git a/Core/Code/IO/mitkIOUtil.cpp b/Core/Code/IO/mitkIOUtil.cpp index bf01ca9c70..afe76ce82f 100644 --- a/Core/Code/IO/mitkIOUtil.cpp +++ b/Core/Code/IO/mitkIOUtil.cpp @@ -1,768 +1,774 @@ /*=================================================================== 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 "mitkIOUtil.h" #include "mitkDataNodeFactory.h" #include "mitkImageWriter.h" #include "mitkPointSetWriter.h" #include "mitkSurfaceVtkWriter.h" #include #include #include #include #include #include #include //ITK #include //VTK #include #include #include #include #include static std::string GetLastErrorStr() { #ifdef US_PLATFORM_POSIX return std::string(strerror(errno)); #else // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); std::string errMsg((LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); return errMsg; #endif } #ifdef US_PLATFORM_WINDOWS #include #include // make the posix flags point to the obsolte bsd types on windows #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #else #include #include #include #endif #include #include static const char validLetters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // A cross-platform version of the mkstemps function static int mkstemps_compat(char* tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary files to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To - conform to POSIX, this must be no smaller than TMP_MAX. */ + conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return -1; } /* This is where the Xs start. */ char* XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return -1; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) - | static_cast(ftNow.dwLowDateTime)); + | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, NULL); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) - | static_cast(tv.tv_sec)); + | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif for (unsigned int count = 0; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; int fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd >= 0) { errno = savedErrno; return fd; } else if (errno != EEXIST) { return -1; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return -1; } // A cross-platform version of the POSIX mkdtemp function static char* mkdtemps_compat(char* tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary dirs to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary dir. To - conform to POSIX, this must be no smaller than TMP_MAX. */ + conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return NULL; } /* This is where the Xs start. */ char* XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return NULL; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) - | static_cast(ftNow.dwLowDateTime)); + | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, NULL); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) - | static_cast(tv.tv_sec)); + | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif unsigned int count = 0; for (; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; #ifdef US_PLATFORM_WINDOWS int fd = _mkdir (tmpl); //, _S_IREAD | _S_IWRITE | _S_IEXEC); #else int fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); #endif if (fd >= 0) { errno = savedErrno; return tmpl; } else if (errno != EEXIST) { return NULL; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return NULL; } //#endif namespace mitk { - -const std::string IOUtil::DEFAULTIMAGEEXTENSION = ".nrrd"; -const std::string IOUtil::DEFAULTSURFACEEXTENSION = ".stl"; -const std::string IOUtil::DEFAULTPOINTSETEXTENSION = ".mps"; + const std::string IOUtil::DEFAULTIMAGEEXTENSION = ".nrrd"; + const std::string IOUtil::DEFAULTSURFACEEXTENSION = ".stl"; + const std::string IOUtil::DEFAULTPOINTSETEXTENSION = ".mps"; #ifdef US_PLATFORM_WINDOWS -std::string IOUtil::GetProgramPath() -{ - char path[512]; - std::size_t index = std::string(path, GetModuleFileName(NULL, path, 512)).find_last_of('\\'); - return std::string(path, index); -} + std::string IOUtil::GetProgramPath() + { + char path[512]; + std::size_t index = std::string(path, GetModuleFileName(NULL, path, 512)).find_last_of('\\'); + return std::string(path, index); + } #elif defined(US_PLATFORM_APPLE) #include -std::string IOUtil::GetProgramPath() -{ - char path[512]; - uint32_t size = sizeof(path); - if (_NSGetExecutablePath(path, &size) == 0) + std::string IOUtil::GetProgramPath() { - std::size_t index = std::string(path).find_last_of('/'); - std::string strPath = std::string(path, index); - //const char* execPath = strPath.c_str(); - //mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch(execPath,false); - return strPath; + char path[512]; + uint32_t size = sizeof(path); + if (_NSGetExecutablePath(path, &size) == 0) + { + std::size_t index = std::string(path).find_last_of('/'); + std::string strPath = std::string(path, index); + //const char* execPath = strPath.c_str(); + //mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch(execPath,false); + return strPath; + } + return std::string(); } - return std::string(); -} #else #include #include #include -std::string IOUtil::GetProgramPath() -{ - std::stringstream ss; - ss << "/proc/" << getpid() << "/exe"; - char proc[512] = {0}; - ssize_t ch = readlink(ss.str().c_str(), proc, 512); - if (ch == -1) return std::string(); - std::size_t index = std::string(proc).find_last_of('/'); - return std::string(proc, index); -} + std::string IOUtil::GetProgramPath() + { + std::stringstream ss; + ss << "/proc/" << getpid() << "/exe"; + char proc[512] = {0}; + ssize_t ch = readlink(ss.str().c_str(), proc, 512); + if (ch == -1) return std::string(); + std::size_t index = std::string(proc).find_last_of('/'); + return std::string(proc, index); + } #endif -std::string IOUtil::GetTempPath() -{ - static std::string result; - if (result.empty()) + std::string IOUtil::GetTempPath() { -#ifdef US_PLATFORM_WINDOWS - char tempPathTestBuffer[1]; - DWORD bufferLength = ::GetTempPath(1, tempPathTestBuffer); - if (bufferLength == 0) + static std::string result; + if (result.empty()) { - mitkThrow() << GetLastErrorStr(); - } - std::vector tempPath(bufferLength); - bufferLength = ::GetTempPath(bufferLength, &tempPath[0]); - if (bufferLength == 0) - { - mitkThrow() << GetLastErrorStr(); - } - result.assign(tempPath.begin(), tempPath.begin() + static_cast(bufferLength)); +#ifdef US_PLATFORM_WINDOWS + char tempPathTestBuffer[1]; + DWORD bufferLength = ::GetTempPath(1, tempPathTestBuffer); + if (bufferLength == 0) + { + mitkThrow() << GetLastErrorStr(); + } + std::vector tempPath(bufferLength); + bufferLength = ::GetTempPath(bufferLength, &tempPath[0]); + if (bufferLength == 0) + { + mitkThrow() << GetLastErrorStr(); + } + result.assign(tempPath.begin(), tempPath.begin() + static_cast(bufferLength)); #else - result = "/tmp/"; + result = "/tmp/"; #endif - } - - return result; -} - -std::string IOUtil::CreateTemporaryFile(const std::string& templateName, std::string path) -{ - ofstream tmpOutputStream; - std::string returnValue = CreateTemporaryFile(tmpOutputStream,templateName,path); - tmpOutputStream.close(); - return returnValue; -} - -std::string IOUtil::CreateTemporaryFile(std::ofstream& f, const std::string& templateName, std::string path) -{ - return CreateTemporaryFile(f, std::ios_base::out | std::ios_base::trunc, templateName, path); -} + } -std::string IOUtil::CreateTemporaryFile(std::ofstream& f, std::ios_base::openmode mode, const std::string& templateName, std::string path) -{ - if (path.empty()) - { - path = GetTempPath(); + return result; } - path += "/" + templateName; - std::vector dst_path(path.begin(), path.end()); - dst_path.push_back('\0'); - - std::size_t lastX = path.find_last_of('X'); - std::size_t firstX = path.find_last_not_of('X', lastX); - int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; - while (lastX != std::string::npos && (lastX - firstNonX) < 6) + std::string IOUtil::CreateTemporaryFile(const std::string& templateName, std::string path) { - lastX = path.find_last_of('X', firstX); - firstX = path.find_last_not_of('X', lastX); - firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; + ofstream tmpOutputStream; + std::string returnValue = CreateTemporaryFile(tmpOutputStream,templateName,path); + tmpOutputStream.close(); + return returnValue; } - std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; - int fd = mkstemps_compat(&dst_path[0], suffixlen); - if(fd != -1) + std::string IOUtil::GetDirectorySeparator() { - path.assign(dst_path.begin(), dst_path.end() - 1); - f.open(path.c_str(), mode | std::ios_base::out | std::ios_base::trunc); - close(fd); +#ifdef US_PLATFORM_WINDOWS + return "\\"; +#else + return "/"; +#endif } - else + + std::string IOUtil::CreateTemporaryFile(std::ofstream& f, const std::string& templateName, std::string path) { - mitkThrow() << "Creating temporary file " << &dst_path[0] << " failed: " << GetLastErrorStr(); + return CreateTemporaryFile(f, std::ios_base::out | std::ios_base::trunc, templateName, path); } - return path; -} -std::string IOUtil::CreateTemporaryDirectory(const std::string& templateName, std::string path) -{ - if (path.empty()) + std::string IOUtil::CreateTemporaryFile(std::ofstream& f, std::ios_base::openmode mode, const std::string& templateName, std::string path) { - path = GetTempPath(); - } + if (path.empty()) + { + path = GetTempPath(); + } - path += "/" + templateName; - std::vector dst_path(path.begin(), path.end()); - dst_path.push_back('\0'); + path += GetDirectorySeparator() + templateName; + std::vector dst_path(path.begin(), path.end()); + dst_path.push_back('\0'); - std::size_t lastX = path.find_last_of('X'); - std::size_t firstX = path.find_last_not_of('X', lastX); - int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; - while (lastX != std::string::npos && (lastX - firstNonX) < 6) - { - lastX = path.find_last_of('X', firstX); - firstX = path.find_last_not_of('X', lastX); - firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; + std::size_t lastX = path.find_last_of('X'); + std::size_t firstX = path.find_last_not_of('X', lastX); + int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; + while (lastX != std::string::npos && (lastX - firstNonX) < 6) + { + lastX = path.find_last_of('X', firstX); + firstX = path.find_last_not_of('X', lastX); + firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; + } + std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; + + int fd = mkstemps_compat(&dst_path[0], suffixlen); + if(fd != -1) + { + path.assign(dst_path.begin(), dst_path.end() - 1); + f.open(path.c_str(), mode | std::ios_base::out | std::ios_base::trunc); + close(fd); + } + else + { + mitkThrow() << "Creating temporary file " << &dst_path[0] << " failed: " << GetLastErrorStr(); + } + return path; } - std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; - if(mkdtemps_compat(&dst_path[0], suffixlen) == NULL) + std::string IOUtil::CreateTemporaryDirectory(const std::string& templateName, std::string path) { - mitkThrow() << "Creating temporary directory " << &dst_path[0] << " failed: " << GetLastErrorStr(); - } + if (path.empty()) + { + path = GetTempPath(); + } - path.assign(dst_path.begin(), dst_path.end() - 1); - return path; -} + path += GetDirectorySeparator() + templateName; + std::vector dst_path(path.begin(), path.end()); + dst_path.push_back('\0'); -int IOUtil::LoadFiles(const std::vector &fileNames, DataStorage &ds) -{ + std::size_t lastX = path.find_last_of('X'); + std::size_t firstX = path.find_last_not_of('X', lastX); + int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; + while (lastX != std::string::npos && (lastX - firstNonX) < 6) + { + lastX = path.find_last_of('X', firstX); + firstX = path.find_last_not_of('X', lastX); + firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; + } + std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; + + if(mkdtemps_compat(&dst_path[0], suffixlen) == NULL) + { + mitkThrow() << "Creating temporary directory " << &dst_path[0] << " failed: " << GetLastErrorStr(); + } + + path.assign(dst_path.begin(), dst_path.end() - 1); + return path; + } + + int IOUtil::LoadFiles(const std::vector &fileNames, DataStorage &ds) + { // Get the set of registered mitk::IDataNodeReader services us::ModuleContext* context = us::GetModuleContext(); const std::vector > refs = context->GetServiceReferences(); std::vector services; services.reserve(refs.size()); for (std::vector >::const_iterator i = refs.begin(); - i != refs.end(); ++i) + i != refs.end(); ++i) { - IDataNodeReader* s = context->GetService(*i); - if (s != 0) - { - services.push_back(s); - } + IDataNodeReader* s = context->GetService(*i); + if (s != 0) + { + services.push_back(s); + } } mitk::ProgressBar::GetInstance()->AddStepsToDo(2*fileNames.size()); // Iterate over all file names and use the IDataNodeReader services // to load them. int nodesRead = 0; for (std::vector::const_iterator i = fileNames.begin(); - i != fileNames.end(); ++i) + i != fileNames.end(); ++i) { - for (std::vector::const_iterator readerIt = services.begin(); - readerIt != services.end(); ++readerIt) + for (std::vector::const_iterator readerIt = services.begin(); + readerIt != services.end(); ++readerIt) + { + try + { + int n = (*readerIt)->Read(*i, ds); + nodesRead += n; + if (n > 0) break; + } + catch (const std::exception& e) { - try - { - int n = (*readerIt)->Read(*i, ds); - nodesRead += n; - if (n > 0) break; - } - catch (const std::exception& e) - { - MITK_WARN << e.what(); - } + MITK_WARN << e.what(); } - mitk::ProgressBar::GetInstance()->Progress(2); + } + mitk::ProgressBar::GetInstance()->Progress(2); } for (std::vector >::const_iterator i = refs.begin(); - i != refs.end(); ++i) + i != refs.end(); ++i) { - context->UngetService(*i); + context->UngetService(*i); } return nodesRead; -} + } -DataStorage::Pointer IOUtil::LoadFiles(const std::vector& fileNames) -{ + DataStorage::Pointer IOUtil::LoadFiles(const std::vector& fileNames) + { mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); LoadFiles(fileNames, *ds); return ds.GetPointer(); -} + } -BaseData::Pointer IOUtil::LoadBaseData(const std::string& path) -{ - return LoadDataNode(path)->GetData(); -} + BaseData::Pointer IOUtil::LoadBaseData(const std::string& path) + { + return LoadDataNode(path)->GetData(); + } -DataNode::Pointer IOUtil::LoadDataNode(const std::string& path) -{ + DataNode::Pointer IOUtil::LoadDataNode(const std::string& path) + { mitk::DataNodeFactory::Pointer reader = mitk::DataNodeFactory::New(); try { - reader->SetFileName( path ); - reader->Update(); + reader->SetFileName( path ); + reader->Update(); - if((reader->GetNumberOfOutputs()<1)) - { - MITK_ERROR << "Could not find data '" << path << "'"; - mitkThrow() << "An exception occured during loading the file " << path << ". Exception says could not find data."; - } + if((reader->GetNumberOfOutputs()<1)) + { + MITK_ERROR << "Could not find data '" << path << "'"; + mitkThrow() << "An exception occured during loading the file " << path << ". Exception says could not find data."; + } - mitk::DataNode::Pointer node = reader->GetOutput(); + mitk::DataNode::Pointer node = reader->GetOutput(); - if(node.IsNull()) - { - MITK_ERROR << "Could not find path: '" << path << "'" << " datanode is NULL" ; - mitkThrow() << "An exception occured during loading the file " << path << ". Exception says datanode is NULL."; - } + if(node.IsNull()) + { + MITK_ERROR << "Could not find path: '" << path << "'" << " datanode is NULL" ; + mitkThrow() << "An exception occured during loading the file " << path << ". Exception says datanode is NULL."; + } - return reader->GetOutput( 0 ); - } + return reader->GetOutput( 0 ); + } catch ( itk::ExceptionObject & e ) { - MITK_ERROR << "Exception occured during load data of '" << path << "': Exception: " << e.what(); - mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: " << e.what(); + MITK_ERROR << "Exception occured during load data of '" << path << "': Exception: " << e.what(); + mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: " << e.what(); } -} + } -Image::Pointer IOUtil::LoadImage(const std::string& path) -{ + Image::Pointer IOUtil::LoadImage(const std::string& path) + { mitk::DataNode::Pointer node = LoadDataNode(path); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNull()) { - MITK_ERROR << "Image is NULL '" << path << "'"; - mitkThrow() << "An exception occured during loading the image " << path << ". Exception says: Image is NULL."; + MITK_ERROR << "Image is NULL '" << path << "'"; + mitkThrow() << "An exception occured during loading the image " << path << ". Exception says: Image is NULL."; } return image; -} + } -Surface::Pointer IOUtil::LoadSurface(const std::string& path) -{ + Surface::Pointer IOUtil::LoadSurface(const std::string& path) + { mitk::DataNode::Pointer node = LoadDataNode(path); mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if(surface.IsNull()) { - MITK_ERROR << "Surface is NULL '" << path << "'"; - mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: Surface is NULL."; + MITK_ERROR << "Surface is NULL '" << path << "'"; + mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: Surface is NULL."; } return surface; -} + } -PointSet::Pointer IOUtil::LoadPointSet(const std::string& path) -{ + PointSet::Pointer IOUtil::LoadPointSet(const std::string& path) + { mitk::DataNode::Pointer node = LoadDataNode(path); mitk::PointSet::Pointer pointset = dynamic_cast(node->GetData()); if(pointset.IsNull()) { - MITK_ERROR << "PointSet is NULL '" << path << "'"; - mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: Pointset is NULL."; + MITK_ERROR << "PointSet is NULL '" << path << "'"; + mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: Pointset is NULL."; } return pointset; -} + } -bool IOUtil::SaveImage(mitk::Image::Pointer image, const std::string& path) -{ + bool IOUtil::SaveImage(mitk::Image::Pointer image, const std::string& path) + { std::string dir = itksys::SystemTools::GetFilenamePath( path ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutExtension( path ); std::string extension = itksys::SystemTools::GetFilenameExtension( path ); if (dir == "") dir = "."; std::string finalFileName = dir + "/" + baseFilename; mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New(); //check if an extension is given, else use the defaul extension if( extension == "" ) { - MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName - << DEFAULTIMAGEEXTENSION; - extension = DEFAULTIMAGEEXTENSION; + MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName + << DEFAULTIMAGEEXTENSION; + extension = DEFAULTIMAGEEXTENSION; } // check if extension is suitable for writing image data if (!imageWriter->IsExtensionValid(extension)) { - MITK_WARN << extension << " extension is unknown. Extension set to default: " << finalFileName - << DEFAULTIMAGEEXTENSION; - extension = DEFAULTIMAGEEXTENSION; + MITK_WARN << extension << " extension is unknown. Extension set to default: " << finalFileName + << DEFAULTIMAGEEXTENSION; + extension = DEFAULTIMAGEEXTENSION; } try { - //write the data - imageWriter->SetInput(image); - imageWriter->SetFileName(finalFileName.c_str()); - imageWriter->SetExtension(extension.c_str()); - imageWriter->Write(); + //write the data + imageWriter->SetInput(image); + imageWriter->SetFileName(finalFileName.c_str()); + imageWriter->SetExtension(extension.c_str()); + imageWriter->Write(); } catch ( std::exception& e ) { - MITK_ERROR << " during attempt to write '" << finalFileName + extension << "' Exception says:"; - MITK_ERROR << e.what(); - mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); + MITK_ERROR << " during attempt to write '" << finalFileName + extension << "' Exception says:"; + MITK_ERROR << e.what(); + mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); } return true; -} + } -bool IOUtil::SaveSurface(Surface::Pointer surface, const std::string& path) -{ + bool IOUtil::SaveSurface(Surface::Pointer surface, const std::string& path) + { std::string dir = itksys::SystemTools::GetFilenamePath( path ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( path ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( path ); if (dir == "") dir = "."; std::string finalFileName = dir + "/" + baseFilename; if (extension == "") // if no extension has been set we use the default extension { - MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName - << DEFAULTSURFACEEXTENSION; - extension = DEFAULTSURFACEEXTENSION; + MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName + << DEFAULTSURFACEEXTENSION; + extension = DEFAULTSURFACEEXTENSION; } try { - finalFileName += extension; - if(extension == ".stl" ) - { - mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); - - // check if surface actually consists of triangles; if not, the writer will not do anything; so, convert to triangles... - vtkPolyData* polys = surface->GetVtkPolyData(); - if( polys->GetNumberOfStrips() > 0 ) - { - vtkSmartPointer triangleFilter = vtkSmartPointer::New(); - triangleFilter->SetInputData(polys); - triangleFilter->Update(); - polys = triangleFilter->GetOutput(); - polys->Register(NULL); - surface->SetVtkPolyData(polys); - } - surfaceWriter->SetInput( surface ); - surfaceWriter->SetFileName( finalFileName.c_str() ); - surfaceWriter->GetVtkWriter()->SetFileTypeToBinary(); - surfaceWriter->Write(); - } - else if(extension == ".vtp") - { - mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); - surfaceWriter->SetInput( surface ); - surfaceWriter->SetFileName( finalFileName.c_str() ); - surfaceWriter->GetVtkWriter()->SetDataModeToBinary(); - surfaceWriter->Write(); - } - else if(extension == ".vtk") - { - mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); - surfaceWriter->SetInput( surface ); - surfaceWriter->SetFileName( finalFileName.c_str() ); - surfaceWriter->Write(); - } - else + finalFileName += extension; + if(extension == ".stl" ) + { + mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); + + // check if surface actually consists of triangles; if not, the writer will not do anything; so, convert to triangles... + vtkPolyData* polys = surface->GetVtkPolyData(); + if( polys->GetNumberOfStrips() > 0 ) { - // file extension not suitable for writing specified data type - MITK_ERROR << "File extension is not suitable for writing'" << finalFileName; - mitkThrow() << "An exception occured during writing the file " << finalFileName << - ". File extension " << extension << " is not suitable for writing."; + vtkSmartPointer triangleFilter = vtkSmartPointer::New(); + triangleFilter->SetInputData(polys); + triangleFilter->Update(); + polys = triangleFilter->GetOutput(); + polys->Register(NULL); + surface->SetVtkPolyData(polys); } + surfaceWriter->SetInput( surface ); + surfaceWriter->SetFileName( finalFileName.c_str() ); + surfaceWriter->GetVtkWriter()->SetFileTypeToBinary(); + surfaceWriter->Write(); + } + else if(extension == ".vtp") + { + mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); + surfaceWriter->SetInput( surface ); + surfaceWriter->SetFileName( finalFileName.c_str() ); + surfaceWriter->GetVtkWriter()->SetDataModeToBinary(); + surfaceWriter->Write(); + } + else if(extension == ".vtk") + { + mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); + surfaceWriter->SetInput( surface ); + surfaceWriter->SetFileName( finalFileName.c_str() ); + surfaceWriter->Write(); + } + else + { + // file extension not suitable for writing specified data type + MITK_ERROR << "File extension is not suitable for writing'" << finalFileName; + mitkThrow() << "An exception occured during writing the file " << finalFileName << + ". File extension " << extension << " is not suitable for writing."; + } } catch(std::exception& e) { - MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; - MITK_ERROR << e.what(); - mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); + MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; + MITK_ERROR << e.what(); + mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); } return true; -} + } -bool IOUtil::SavePointSet(PointSet::Pointer pointset, const std::string& path) -{ + bool IOUtil::SavePointSet(PointSet::Pointer pointset, const std::string& path) + { mitk::PointSetWriter::Pointer pointSetWriter = mitk::PointSetWriter::New(); std::string dir = itksys::SystemTools::GetFilenamePath( path ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( path ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( path ); if (dir == "") dir = "."; std::string finalFileName = dir + "/" + baseFilename; if (extension == "") // if no extension has been entered manually into the filename { - MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName - << DEFAULTPOINTSETEXTENSION; - extension = DEFAULTPOINTSETEXTENSION; + MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName + << DEFAULTPOINTSETEXTENSION; + extension = DEFAULTPOINTSETEXTENSION; } // check if extension is valid if (!pointSetWriter->IsExtensionValid(extension)) { - MITK_WARN << extension << " extension is unknown. Extension set to default: " << finalFileName - << DEFAULTPOINTSETEXTENSION; - extension = DEFAULTPOINTSETEXTENSION; + MITK_WARN << extension << " extension is unknown. Extension set to default: " << finalFileName + << DEFAULTPOINTSETEXTENSION; + extension = DEFAULTPOINTSETEXTENSION; } try { - pointSetWriter->SetInput( pointset ); - finalFileName += extension; - pointSetWriter->SetFileName( finalFileName.c_str() ); - pointSetWriter->Update(); + pointSetWriter->SetInput( pointset ); + finalFileName += extension; + pointSetWriter->SetFileName( finalFileName.c_str() ); + pointSetWriter->Update(); } catch( std::exception& e ) { - MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; - MITK_ERROR << e.what(); - mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); + MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; + MITK_ERROR << e.what(); + mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); } return true; -} + } -bool IOUtil::SaveBaseData( mitk::BaseData* data, const std::string& path ) -{ - if (data == NULL || path.empty()) return false; + bool IOUtil::SaveBaseData( mitk::BaseData* data, const std::string& path ) + { + if (data == NULL || path.empty()) return false; - std::string dir = itksys::SystemTools::GetFilenamePath( path ); - std::string baseFilename = itksys::SystemTools::GetFilenameWithoutExtension( path ); - std::string extension = itksys::SystemTools::GetFilenameExtension( path ); - if (dir == "") - dir = "."; - std::string fileNameWithoutExtension = dir + "/" + baseFilename; + std::string dir = itksys::SystemTools::GetFilenamePath( path ); + std::string baseFilename = itksys::SystemTools::GetFilenameWithoutExtension( path ); + std::string extension = itksys::SystemTools::GetFilenameExtension( path ); + if (dir == "") + dir = "."; + std::string fileNameWithoutExtension = dir + "/" + baseFilename; - mitk::CoreObjectFactory::FileWriterList fileWriters = mitk::CoreObjectFactory::GetInstance()->GetFileWriters(); + mitk::CoreObjectFactory::FileWriterList fileWriters = mitk::CoreObjectFactory::GetInstance()->GetFileWriters(); - for (mitk::CoreObjectFactory::FileWriterList::iterator it = fileWriters.begin() ; it != fileWriters.end() ; ++it) - { - if ( (*it)->CanWriteBaseDataType(data) ) + for (mitk::CoreObjectFactory::FileWriterList::iterator it = fileWriters.begin() ; it != fileWriters.end() ; ++it) { - // Ensure a valid filename - if(baseFilename=="") - { - baseFilename = (*it)->GetDefaultFilename(); - } - // Check if an extension exists already and if not, append the default extension - if (extension=="" ) + if ( (*it)->CanWriteBaseDataType(data) ) { - extension=(*it)->GetDefaultExtension(); - } - else - { - if (!(*it)->IsExtensionValid(extension)) + // Ensure a valid filename + if(baseFilename=="") { - MITK_WARN << extension << " extension is unknown"; - continue; + baseFilename = (*it)->GetDefaultFilename(); + } + // Check if an extension exists already and if not, append the default extension + if (extension=="" ) + { + extension=(*it)->GetDefaultExtension(); + } + else + { + if (!(*it)->IsExtensionValid(extension)) + { + MITK_WARN << extension << " extension is unknown"; + continue; + } } - } - std::string finalFileName = fileNameWithoutExtension + extension; - try - { - (*it)->SetFileName( finalFileName.c_str() ); - (*it)->DoWrite( data ); - return true; - } - catch( const std::exception& e ) - { - MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; - MITK_ERROR << e.what(); - mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); + std::string finalFileName = fileNameWithoutExtension + extension; + try + { + (*it)->SetFileName( finalFileName.c_str() ); + (*it)->DoWrite( data ); + return true; + } + catch( const std::exception& e ) + { + MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; + MITK_ERROR << e.what(); + mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); + } } } - } - - return false; -} -} + return false; + } +} \ No newline at end of file diff --git a/Core/Code/IO/mitkIOUtil.h b/Core/Code/IO/mitkIOUtil.h index 215111d810..41f991ec96 100644 --- a/Core/Code/IO/mitkIOUtil.h +++ b/Core/Code/IO/mitkIOUtil.h @@ -1,267 +1,274 @@ /*=================================================================== 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 MITKIOUTIL_H #define MITKIOUTIL_H #include #include #include #include #include #include namespace mitk { /** * \ingroup IO * * \brief A utility class to load and save data from/to the local file system. * * This method LoadFiles queries the MITK Micro Services registry for registered mitk::IDataNodeReader service * instances. The service instance with the highest ranking will be asked first to load the * given file. On error (exception thrown) or if no mitk::DataNode was constructed, the next * service instance is used. * * The methods LoadImage, LoadSurface, and LoadPointSet are convenience methods for general loading of * the three main data types in MITK. They all use the more generic method LoadDataNode. * * The methods SaveImage, SaveSurface, and SurfacePointSet are also meant for convenience (e.g. during testing). * Currently, there is no generic way to save a generic DataNode with an appropriate format. Thus, every method * initializes the corresponding instance of the special writer for the data type. * * \see mitk::IDataNodeReader */ class MITK_CORE_EXPORT IOUtil { public: /** * Get the file system path where the running executable is located. * * @return The location of the currently running executable, without the filename. */ static std::string GetProgramPath(); /** * Get the default temporary path. * * @return The default path for temporary data. */ static std::string GetTempPath(); + /** + * Returns the Directory Seperator for the current OS. + * + * @return the Directory Seperator for the current OS, i.e. "\\" for Windows and "/" otherwise. + */ + static std::string GetDirectorySeparator(); + /** * Create and open a temporary file. * * This method generates a unique temporary filename from \c templateName, creates * and opens the file using the output stream \c tmpStream and returns the name of * the newly create file. * * The \c templateName argument must contain six consective 'X' characters ("XXXXXX") * and these are replaced with a string that makes the filename unique. * * The file is created with read and write permissions for owner only. * * @param tmpStream The output stream for writing to the temporary file. * @param templateName An optional template for the filename. * @param path An optional path where the temporary file should be created. Defaults * to the default temp path as returned by GetTempPath(). * @return The filename of the created temporary file. * * @throw mitk::Exception if the temporary file could not be created. */ static std::string CreateTemporaryFile(std::ofstream& tmpStream, const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Create and open a temporary file. * * This method generates a unique temporary filename from \c templateName, creates * and opens the file using the output stream \c tmpStream and the specified open * mode \c mode and returns the name of the newly create file. The open mode is always * OR'd with \begin{code}std::ios_base::out | std::ios_base::trunc\end{code}. * * The \c templateName argument must contain six consective 'X' characters ("XXXXXX") * and these are replaced with a string that makes the filename unique. * * The file is created with read and write permissions for owner only. * * @param tmpStream The output stream for writing to the temporary file. * @param mode The open mode for the temporary file stream. * @param templateName An optional template for the filename. * @param path An optional path where the temporary file should be created. Defaults * to the default temp path as returned by GetTempPath(). * @return The filename of the created temporary file. * * @throw mitk::Exception if the temporary file could not be created. */ static std::string CreateTemporaryFile(std::ofstream& tmpStream, std::ios_base::openmode mode, const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Creates an empty temporary file. * * This method generates a unique temporary filename from \c templateName and creates * this file. * * The file is created with read and write permissions for owner only. * * --- * This version is potentially unsafe because the created temporary file is not kept open * and could be used by another process between calling this method and opening the returned * file path for reading or writing. * --- * * @return The filename of the created temporary file. * @param templateName An optional template for the filename. * @param path An optional path where the temporary file should be created. Defaults * to the default temp path as returned by GetTempPath(). * @throw mitk::Exception if the temporary file could not be created. */ static std::string CreateTemporaryFile(const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Create a temporary directory. * * This method generates a uniquely named temporary directory from \c templateName. * The last set of six consecutive 'X' characters in \c templateName is replaced * with a string that makes the directory name unique. * * The directory is created with read, write and executable permissions for owner only. * * @param templateName An optional template for the directory name. * @param path An optional path where the temporary directory should be created. Defaults * to the default temp path as returned by GetTempPath(). * @return The filename of the created temporary file. * * @throw mitk::Exception if the temporary directory could not be created. */ static std::string CreateTemporaryDirectory(const std::string& templateName = "XXXXXX", std::string path = std::string()); /** * Load a files in fileNames and add the constructed mitk::DataNode instances * to the mitk::DataStorage storage * * \param fileNames A list (vector) of absolute file name paths. * \param storage The data storage to which the constructed data nodes are added. * \return The number of added mitk::DataNode instances. */ static int LoadFiles(const std::vector&fileNames, DataStorage& storage); /** * This method will create a new mitk::DataStorage instance and pass it to * LoadFiles(std::vector,DataStorage). * * \param fileNames A list (vector) of absolute file name paths. * \return The new mitk::DataStorage containing the constructed data nodes. * * \see LoadFiles(std::vector,DataStorage) */ static DataStorage::Pointer LoadFiles(const std::vector& fileNames); /** * @brief Create a BaseData object from the given file. * @param path The path to the file including file name and file extension. * @throws mitk::Exception In case of an error when reading the file. * @return Returns the created BaseData object. */ static mitk::BaseData::Pointer LoadBaseData(const std::string& path); /** * @brief LoadDataNode Method to load an arbitrary DataNode. * @param path The path to the file including file name and file extension. * @throws mitk::Exception This exception is thrown when the DataNodeFactory is not able to read/find the file * or the DataNode is NULL. * @return Returns the DataNode. */ static mitk::DataNode::Pointer LoadDataNode(const std::string& path); /** * @brief LoadImage Convenience method to load an arbitrary mitkImage. * @param path The path to the image including file name and file extension. * @throws mitk::Exception This exception is thrown when the Image is NULL. * @return Returns the mitkImage. */ static mitk::Image::Pointer LoadImage(const std::string& path); /** * @brief LoadSurface Convenience method to load an arbitrary mitkSurface. * @param path The path to the surface including file name and file extension. * @throws mitk::Exception This exception is thrown when the Surface is NULL. * @return Returns the mitkSurface. */ static mitk::Surface::Pointer LoadSurface(const std::string& path); /** * @brief LoadPointSet Convenience method to load an arbitrary mitkPointSet. * @param path The path to the pointset including file name and file extension (currently, only .mps is supported). * @throws mitk::Exception This exception is thrown when the PointSet is NULL. * @return Returns the mitkPointSet. */ static mitk::PointSet::Pointer LoadPointSet(const std::string& path); /** * @brief SaveImage Convenience method to save an arbitrary mitkImage. * @param path The path to the image including file name and file extension. * If not extention is set, the default value (defined in DEFAULTIMAGEEXTENSION) is used. * @param image The image to save. * @throws mitk::Exception This exception is thrown when the writer is not able to write the image. * @return Returns true for success else false. */ static bool SaveImage(mitk::Image::Pointer image, const std::string& path); /** * @brief SaveBaseData Convenience method to save arbitrary baseData. * @param path The path to the image including file name and file extension. * If not extention is set, the default value (defined in DEFAULTIMAGEEXTENSION) is used. * @param data The data to save. * @throws mitk::Exception This exception is thrown when the writer is not able to write the image. * @return Returns true for success else false. */ static bool SaveBaseData(mitk::BaseData* data, const std::string& path); /** * @brief SaveSurface Convenience method to save an arbitrary mitkSurface. * @param path The path to the surface including file name and file extension. * If not extention is set, the default value (defined in DEFAULTSURFACEEXTENSION) is used. * @throws mitk::Exception This exception is thrown when the writer is not able to write the surface. * or if the fileextension is not suitable for writing. * @return Returns true for success else false. */ static bool SaveSurface(mitk::Surface::Pointer surface, const std::string& path); /** * @brief SavePointSet Convenience method to save an mitkPointSet. * @param path The path to the pointset including file name and file extension (currently, only .mps is supported). * If not extention is set, the default value (defined in DEFAULTPOINTSETEXTENSION) is used. * @throws mitk::Exception This exception is thrown when the writer is not able to write the pointset. * @return Returns true for success else false. */ static bool SavePointSet(mitk::PointSet::Pointer pointset, const std::string& path); static const std::string DEFAULTIMAGEEXTENSION; static const std::string DEFAULTSURFACEEXTENSION; static const std::string DEFAULTPOINTSETEXTENSION; }; } #endif // MITKIOUTIL_H diff --git a/Modules/Persistence/Testing/mitkPersistenceTest.cpp b/Modules/Persistence/Testing/mitkPersistenceTest.cpp index 65c023e280..fbb1bdf525 100644 --- a/Modules/Persistence/Testing/mitkPersistenceTest.cpp +++ b/Modules/Persistence/Testing/mitkPersistenceTest.cpp @@ -1,169 +1,160 @@ /*=================================================================== 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 #include #include #include #include #include +#include + #include struct PersistenceTestClass { - PersistenceTestClass() - : id(""), param1(1), param2(2), param3(false) - { - } - std::string id; - int param1; - double param2; - bool param3; - - PERSISTENCE_CREATE3(PersistenceTestClass, id, param1, param2, param3) + PersistenceTestClass() + : id(""), param1(1), param2(2), param3(false) + { + } + std::string id; + int param1; + double param2; + bool param3; + + PERSISTENCE_CREATE3(PersistenceTestClass, id, param1, param2, param3) }; struct TestPropertyListReplacedObserver: public mitk::PropertyListReplacedObserver { - TestPropertyListReplacedObserver(): counter(0) {} - virtual void BeforePropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) - { - if( id == m_Id ) - counter++; - } - - virtual void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) - { - if( id == m_Id ) - counter++; - } - - int counter; - std::string m_Id; + TestPropertyListReplacedObserver(): counter(0) {} + virtual void BeforePropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) + { + if( id == m_Id ) + counter++; + } + + virtual void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) + { + if( id == m_Id ) + counter++; + } + + int counter; + std::string m_Id; }; std::string testClassId = "testClass"; int param1 = 100; double param2 = 201.56; bool param3 = true; void testParams( const PersistenceTestClass& testClass, const std::string& testClassName ) { - MITK_INFO << "Testing parameters of " << testClassName; - MITK_TEST_CONDITION( testClass.id == testClassId, "testClass.id (" << testClass.id << ") != testClassId (" << testClassId << ")" ); - MITK_TEST_CONDITION( testClass.param1 == param1, "testClass.param1 (" << testClass.param1 << ") != param1 (" << param1 << ")" ); - MITK_TEST_CONDITION( testClass.param2 == param2, "testClass.param2 (" << testClass.param2 << ") != param2 (" << param2 << ")" ); - MITK_TEST_CONDITION( testClass.param3 == param3, "testClass.param3 (" << testClass.param3 << ") != param3 (" << param3 << ")" ); + MITK_INFO << "Testing parameters of " << testClassName; + MITK_TEST_CONDITION( testClass.id == testClassId, "testClass.id (" << testClass.id << ") != testClassId (" << testClassId << ")" ); + MITK_TEST_CONDITION( testClass.param1 == param1, "testClass.param1 (" << testClass.param1 << ") != param1 (" << param1 << ")" ); + MITK_TEST_CONDITION( testClass.param2 == param2, "testClass.param2 (" << testClass.param2 << ") != param2 (" << param2 << ")" ); + MITK_TEST_CONDITION( testClass.param3 == param3, "testClass.param3 (" << testClass.param3 << ") != param3 (" << param3 << ")" ); } int mitkPersistenceTest(int /*argc*/, char* /*argv*/[]) { - MITK_TEST_BEGIN("PersistenceTest") + MITK_TEST_BEGIN("PersistenceTest") // dummy load of SceneIO, otherwise PersistenceService won't be available //mitk::PersistenceService::LoadModule(); MITK_INFO << "Testing availability of the PersistenceService."; - PERSISTENCE_GET_SERVICE_MACRO + PERSISTENCE_GET_SERVICE_MACRO MITK_TEST_CONDITION_REQUIRED(persistenceService, "IPersistenceService available") MITK_INFO << "Initialize testable parameter values."; - Poco::File defaultPersistenceFile(persistenceService->GetDefaultPersistenceFile()); - PersistenceTestClass autoLoadTestClass; - autoLoadTestClass.id = testClassId; - if( defaultPersistenceFile.exists() && persistenceService->GetAutoLoadAndSave() ) - { - MITK_INFO << "Testing auto load/save of the PersistenceService."; - defaultPersistenceFile.remove(); - autoLoadTestClass.FromPropertyList(); - - testParams( autoLoadTestClass, "autoLoadTestClass" ); - } - - MITK_INFO << "Removing left-over test files."; - Poco::File testTempFile("PersistenceTestFile.mitk"); - if( testTempFile.exists() ) - testTempFile.remove(false); - - Poco::File testXmlTempFile("PersistenceTestFile.xml"); - if( testXmlTempFile.exists() ) - testXmlTempFile.remove(false); - - MITK_INFO << "Testing standard write to scene file/xml file."; - PersistenceTestClass testClass; - testClass.id = testClassId; - testClass.param1 = param1; - testClass.param2 = param2; - testClass.param3 = param3; - MITK_TEST_CONDITION_REQUIRED( testClass.Save(testTempFile.path()), "testClass.Save(testTempFile.path())"); - MITK_TEST_CONDITION_REQUIRED( testClass.Save(testXmlTempFile.path()), "testClass.Save(testTempFile.path())"); - - MITK_INFO << "Testing read from scene file."; - MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); - PersistenceTestClass testClass2; - testClass2.id = testClassId; - MITK_TEST_CONDITION_REQUIRED( testClass2.Load(testTempFile.path()), "testClass2.Load(testTempFile.path())"); - - testParams( testClass2, "testClass2" ); - - MITK_INFO << "Testing read from xml file."; - MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); - PersistenceTestClass testClass3; - testClass3.id = testClassId; - MITK_TEST_CONDITION_REQUIRED( testClass3.Load(testXmlTempFile.path()), "testClass3.Load(testXmlTempFile.path())"); - - testParams( testClass3, "testClass3" ); - - MITK_INFO << "Testing appendChanges functionality with scene load/write."; - MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); - MITK_TEST_CONDITION_REQUIRED( persistenceService->Save(testTempFile.path(), true), "persistenceService->Save(testTempFile.path())"); - MITK_TEST_CONDITION_REQUIRED( persistenceService->Load(testTempFile.path()), "persistenceService->Load(testTempFile.path())"); - - PersistenceTestClass testClass4; - testClass4.id = testClassId; - testClass4.FromPropertyList(); - testParams( testClass4, "testClass4" ); - - MITK_INFO << "Testing appendChanges functionality with xml load/write."; - MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); - MITK_TEST_CONDITION_REQUIRED( persistenceService->Save(testXmlTempFile.path(), true), "persistenceService->Save(testXmlTempFile.path())"); - MITK_TEST_CONDITION_REQUIRED( persistenceService->Load(testXmlTempFile.path()), "persistenceService->Load(testXmlTempFile.path())"); - - PersistenceTestClass testClass5; - testClass5.id = testClassId; - testClass5.FromPropertyList(); - testParams( testClass5, "testClass5" ); - - MITK_INFO << "Testing observer functionality."; - TestPropertyListReplacedObserver testObserver; - testObserver.m_Id = testClassId; - persistenceService->AddPropertyListReplacedObserver( &testObserver ); - persistenceService->Load(testTempFile.path()); - MITK_TEST_CONDITION( testObserver.counter == 2, "testObserver.counter == 2, testObserver.counter is " << testObserver.counter ); - - MITK_INFO << "Cleaning test files."; - if( testXmlTempFile.exists() ) - testXmlTempFile.remove(false); - if( testTempFile.exists() ) - testTempFile.remove(false); - - autoLoadTestClass.param1 = param1; - autoLoadTestClass.param2 = param2; - autoLoadTestClass.param3 = param3; - autoLoadTestClass.ToPropertyList(); - MITK_TEST_END() -} + Poco::File defaultPersistenceFile(persistenceService->GetDefaultPersistenceFile()); + PersistenceTestClass autoLoadTestClass; + autoLoadTestClass.id = testClassId; + if( defaultPersistenceFile.exists() && persistenceService->GetAutoLoadAndSave() ) + { + MITK_INFO << "Testing auto load/save of the PersistenceService."; + defaultPersistenceFile.remove(); + autoLoadTestClass.FromPropertyList(); + + testParams( autoLoadTestClass, "autoLoadTestClass" ); + } + + MITK_INFO << "Removing left-over test files."; + std::string testTempFile = mitk::IOUtil::CreateTemporaryFile("XXXXXX.mitk"); + std::string testXmlTempFile = mitk::IOUtil::CreateTemporaryFile("PersistenceTestFileXXXXXX.xml"); + + MITK_INFO << "Testing standard write to scene file/xml file."; + PersistenceTestClass testClass; + testClass.id = testClassId; + testClass.param1 = param1; + testClass.param2 = param2; + testClass.param3 = param3; + MITK_TEST_CONDITION_REQUIRED( testClass.Save(testTempFile), "Testing to save a scene file"); + MITK_TEST_CONDITION_REQUIRED( testClass.Save(testXmlTempFile), "testing to save an xml file"); + + MITK_INFO << "Testing read from scene file."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); + PersistenceTestClass testClass2; + testClass2.id = testClassId; + MITK_TEST_CONDITION_REQUIRED( testClass2.Load(testTempFile), "testClass2.Load(testTempFile.path())"); + + testParams( testClass2, "testClass2" ); + + MITK_INFO << "Testing read from xml file."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); + PersistenceTestClass testClass3; + testClass3.id = testClassId; + MITK_TEST_CONDITION_REQUIRED( testClass3.Load(testXmlTempFile), "testClass3.Load(testXmlTempFile.path())"); + + testParams( testClass3, "testClass3" ); + + MITK_INFO << "Testing appendChanges functionality with scene load/write."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Save(testTempFile, true), "persistenceService->Save(testTempFile.path())"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Load(testTempFile), "persistenceService->Load(testTempFile.path())"); + + PersistenceTestClass testClass4; + testClass4.id = testClassId; + testClass4.FromPropertyList(); + testParams( testClass4, "testClass4" ); + + MITK_INFO << "Testing appendChanges functionality with xml load/write."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Save(testXmlTempFile, true), "persistenceService->Save(testXmlTempFile.path())"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Load(testXmlTempFile), "persistenceService->Load(testXmlTempFile.path())"); + + PersistenceTestClass testClass5; + testClass5.id = testClassId; + testClass5.FromPropertyList(); + testParams( testClass5, "testClass5" ); + + MITK_INFO << "Testing observer functionality."; + TestPropertyListReplacedObserver testObserver; + testObserver.m_Id = testClassId; + persistenceService->AddPropertyListReplacedObserver( &testObserver ); + persistenceService->Load(testTempFile); + MITK_TEST_CONDITION( testObserver.counter == 2, "testObserver.counter == 2, testObserver.counter is " << testObserver.counter ); + + autoLoadTestClass.param1 = param1; + autoLoadTestClass.param2 = param2; + autoLoadTestClass.param3 = param3; + autoLoadTestClass.ToPropertyList(); + MITK_TEST_END() +} \ No newline at end of file diff --git a/Modules/SceneSerialization/mitkSceneIO.cpp b/Modules/SceneSerialization/mitkSceneIO.cpp index 5df2e1a6d3..a0a7348a9f 100644 --- a/Modules/SceneSerialization/mitkSceneIO.cpp +++ b/Modules/SceneSerialization/mitkSceneIO.cpp @@ -1,537 +1,531 @@ /*=================================================================== 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 #include #include #include "mitkSceneIO.h" #include "mitkBaseDataSerializer.h" #include "mitkPropertyListSerializer.h" #include "mitkSceneReader.h" #include "mitkProgressBar.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkStandaloneDataStorage.h" #include #include #include #include #include +#include #include "itksys/SystemTools.hxx" mitk::SceneIO::SceneIO() -:m_WorkingDirectory(""), - m_UnzipErrors(0) + :m_WorkingDirectory(""), + m_UnzipErrors(0) { } mitk::SceneIO::~SceneIO() { } std::string mitk::SceneIO::CreateEmptyTempDirectory() { - mitk::UIDGenerator uidGen("UID_",6); //std::string returnValue = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "SceneIOTemp" + uidGen.GetUID(); std::string returnValue = Poco::Path::temp() + "SceneIOTemp" + uidGen.GetUID(); std::string uniquename = returnValue + Poco::Path::separator(); Poco::File tempdir( uniquename ); try { bool existsNot = tempdir.createDirectory(); if (!existsNot) - { + { MITK_ERROR << "Warning: Directory already exitsts: " << uniquename << " (choosing another)"; returnValue = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "SceneIOTempDirectory" + uidGen.GetUID(); uniquename = returnValue + Poco::Path::separator(); Poco::File tempdir2( uniquename ); if (!tempdir2.createDirectory()) - { + { MITK_ERROR << "Warning: Second directory also already exitsts: " << uniquename; - } } + } } catch( std::exception& e ) { MITK_ERROR << "Could not create temporary directory " << uniquename << ":" << e.what(); return ""; } - return returnValue; } mitk::DataStorage::Pointer mitk::SceneIO::LoadScene( const std::string& filename, - DataStorage* pStorage, - bool clearStorageFirst ) + DataStorage* pStorage, + bool clearStorageFirst ) { // prepare data storage DataStorage::Pointer storage = pStorage; if ( storage.IsNull() ) { storage = StandaloneDataStorage::New().GetPointer(); } if ( clearStorageFirst ) { try { storage->Remove( storage->GetAll() ); } catch(...) { MITK_ERROR << "DataStorage cannot be cleared properly."; } } // test input filename if ( filename.empty() ) { MITK_ERROR << "No filename given. Not possible to load scene."; return storage; } // test if filename can be read std::ifstream file( filename.c_str(), std::ios::binary ); if (!file.good()) { MITK_ERROR << "Cannot open '" << filename << "' for reading"; return storage; } // get new temporary directory m_WorkingDirectory = CreateEmptyTempDirectory(); if (m_WorkingDirectory.empty()) { MITK_ERROR << "Could not create temporary directory. Cannot open scene files."; return storage; } // unzip all filenames contents to temp dir m_UnzipErrors = 0; Poco::Zip::Decompress unzipper( file, Poco::Path( m_WorkingDirectory ) ); unzipper.EError += Poco::Delegate >(this, &SceneIO::OnUnzipError); unzipper.EOk += Poco::Delegate >(this, &SceneIO::OnUnzipOk); unzipper.decompressAllFiles(); unzipper.EError -= Poco::Delegate >(this, &SceneIO::OnUnzipError); unzipper.EOk -= Poco::Delegate >(this, &SceneIO::OnUnzipOk); if ( m_UnzipErrors ) { MITK_ERROR << "There were " << m_UnzipErrors << " errors unzipping '" << filename << "'. Will attempt to read whatever could be unzipped."; } // test if index.xml exists // parse index.xml with TinyXML - TiXmlDocument document( m_WorkingDirectory + Poco::Path::separator() + "index.xml" ); + TiXmlDocument document( m_WorkingDirectory + mitk::IOUtil::GetDirectorySeparator() + "index.xml" ); if (!document.LoadFile()) { - MITK_ERROR << "Could not open/read/parse " << m_WorkingDirectory << "/index.xml\nTinyXML reports: " << document.ErrorDesc() << std::endl; + MITK_ERROR << "Could not open/read/parse " << m_WorkingDirectory << mitk::IOUtil::GetDirectorySeparator() << "index.xml\nTinyXML reports: " << document.ErrorDesc() << std::endl; return storage; } SceneReader::Pointer reader = SceneReader::New(); if ( !reader->LoadScene( document, m_WorkingDirectory, storage ) ) { MITK_ERROR << "There were errors while loading scene file " << filename << ". Your data may be corrupted"; } // delete temp directory try { Poco::File deleteDir( m_WorkingDirectory ); deleteDir.remove(true); // recursive } catch(...) { MITK_ERROR << "Could not delete temporary directory " << m_WorkingDirectory; } // return new data storage, even if empty or uncomplete (return as much as possible but notify calling method) return storage; - } bool mitk::SceneIO::SaveScene( DataStorage::SetOfObjects::ConstPointer sceneNodes, const DataStorage* storage, - const std::string& filename) + const std::string& filename) { if (!sceneNodes) { MITK_ERROR << "No set of nodes given. Not possible to save scene."; return false; } if (!storage) { MITK_ERROR << "No data storage given. Not possible to save scene."; // \TODO: Technically, it would be possible to save the nodes without their relation return false; } if ( filename.empty() ) { MITK_ERROR << "No filename given. Not possible to save scene."; return false; } try { - m_FailedNodes = DataStorage::SetOfObjects::New(); m_FailedProperties = PropertyList::New(); // start XML DOM TiXmlDocument document; TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "UTF-8", "" ); // TODO what to write here? encoding? standalone would mean that we provide a DTD somewhere... document.LinkEndChild( decl ); TiXmlElement* version = new TiXmlElement("Version"); version->SetAttribute("Writer", __FILE__ ); version->SetAttribute("Revision", "$Revision: 17055 $" ); version->SetAttribute("FileVersion", 1 ); document.LinkEndChild(version); //DataStorage::SetOfObjects::ConstPointer sceneNodes = storage->GetSubset( predicate ); if ( sceneNodes.IsNull() ) { MITK_WARN << "Saving empty scene to " << filename; } else { if ( sceneNodes->size() == 0 ) { MITK_WARN << "Saving empty scene to " << filename; } - MITK_INFO << "Storing scene with " << sceneNodes->size() << " objects to " << filename; + MITK_INFO << "Storing scene with " << sceneNodes->size() << " objects to " << filename; m_WorkingDirectory = CreateEmptyTempDirectory(); if (m_WorkingDirectory.empty()) { MITK_ERROR << "Could not create temporary directory. Cannot create scene files."; return false; } ProgressBar::GetInstance()->AddStepsToDo( sceneNodes->size() ); // find out about dependencies typedef std::map< DataNode*, std::string > UIDMapType; typedef std::map< DataNode*, std::list > SourcesMapType; UIDMapType nodeUIDs; // for dependencies: ID of each node SourcesMapType sourceUIDs; // for dependencies: IDs of a node's parent nodes UIDGenerator nodeUIDGen("OBJECT_"); for (DataStorage::SetOfObjects::const_iterator iter = sceneNodes->begin(); - iter != sceneNodes->end(); - ++iter) + iter != sceneNodes->end(); + ++iter) { DataNode* node = iter->GetPointer(); if (!node) continue; // unlikely event that we get a NULL pointer as an object for saving. just ignore // generate UIDs for all source objects DataStorage::SetOfObjects::ConstPointer sourceObjects = storage->GetSources( node ); for ( mitk::DataStorage::SetOfObjects::const_iterator sourceIter = sourceObjects->begin(); - sourceIter != sourceObjects->end(); - ++sourceIter ) + sourceIter != sourceObjects->end(); + ++sourceIter ) { if ( std::find( sceneNodes->begin(), sceneNodes->end(), *sourceIter ) == sceneNodes->end() ) continue; // source is not saved, so don't generate a UID for this source // create a uid for the parent object if ( nodeUIDs[ *sourceIter ].empty() ) { nodeUIDs[ *sourceIter ] = nodeUIDGen.GetUID(); } // store this dependency for writing sourceUIDs[ node ].push_back( nodeUIDs[*sourceIter] ); } if ( nodeUIDs[ node ].empty() ) { nodeUIDs[ node ] = nodeUIDGen.GetUID(); } } // write out objects, dependencies and properties for (DataStorage::SetOfObjects::const_iterator iter = sceneNodes->begin(); - iter != sceneNodes->end(); - ++iter) + iter != sceneNodes->end(); + ++iter) { DataNode* node = iter->GetPointer(); if (node) { TiXmlElement* nodeElement = new TiXmlElement("node"); std::string filenameHint( node->GetName() ); filenameHint = itksys::SystemTools::MakeCindentifier(filenameHint.c_str()); // escape filename <-- only allow [A-Za-z0-9_], replace everything else with _ // store dependencies UIDMapType::iterator searchUIDIter = nodeUIDs.find(node); if ( searchUIDIter != nodeUIDs.end() ) { // store this node's ID nodeElement->SetAttribute("UID", searchUIDIter->second.c_str() ); } SourcesMapType::iterator searchSourcesIter = sourceUIDs.find(node); if ( searchSourcesIter != sourceUIDs.end() ) { // store all source IDs for ( std::list::iterator sourceUIDIter = searchSourcesIter->second.begin(); - sourceUIDIter != searchSourcesIter->second.end(); - ++sourceUIDIter ) + sourceUIDIter != searchSourcesIter->second.end(); + ++sourceUIDIter ) { TiXmlElement* uidElement = new TiXmlElement("source"); uidElement->SetAttribute("UID", sourceUIDIter->c_str() ); nodeElement->LinkEndChild( uidElement ); } } // store basedata if ( BaseData* data = node->GetData() ) { //std::string filenameHint( node->GetName() ); bool error(false); TiXmlElement* dataElement( SaveBaseData( data, filenameHint, error ) ); // returns a reference to a file if (error) { m_FailedNodes->push_back( node ); } // store basedata properties PropertyList* propertyList = data->GetPropertyList(); if (propertyList && !propertyList->IsEmpty() ) { TiXmlElement* baseDataPropertiesElement( SavePropertyList( propertyList, filenameHint + "-data") ); // returns a reference to a file dataElement->LinkEndChild( baseDataPropertiesElement ); } nodeElement->LinkEndChild( dataElement ); } // store all renderwindow specific propertylists if (RenderingManager::IsInstantiated()) { const RenderingManager::RenderWindowVector& allRenderWindows( RenderingManager::GetInstance()->GetAllRegisteredRenderWindows() ); for ( RenderingManager::RenderWindowVector::const_iterator rw = allRenderWindows.begin(); - rw != allRenderWindows.end(); - ++rw) + rw != allRenderWindows.end(); + ++rw) { if (vtkRenderWindow* renderWindow = *rw) { std::string renderWindowName( mitk::BaseRenderer::GetInstance(renderWindow)->GetName() ); BaseRenderer* renderer = mitk::BaseRenderer::GetInstance(renderWindow); PropertyList* propertyList = node->GetPropertyList(renderer); if ( propertyList && !propertyList->IsEmpty() ) { TiXmlElement* renderWindowPropertiesElement( SavePropertyList( propertyList, filenameHint + "-" + renderWindowName) ); // returns a reference to a file renderWindowPropertiesElement->SetAttribute("renderwindow", renderWindowName); nodeElement->LinkEndChild( renderWindowPropertiesElement ); } } } } // don't forget the renderwindow independent list PropertyList* propertyList = node->GetPropertyList(); if ( propertyList && !propertyList->IsEmpty() ) { TiXmlElement* propertiesElement( SavePropertyList( propertyList, filenameHint + "-node") ); // returns a reference to a file nodeElement->LinkEndChild( propertiesElement ); } document.LinkEndChild( nodeElement ); } else { MITK_WARN << "Ignoring NULL node during scene serialization."; } ProgressBar::GetInstance()->Progress(); } // end for all nodes - } // end if sceneNodes if ( !document.SaveFile( m_WorkingDirectory + Poco::Path::separator() + "index.xml" ) ) { MITK_ERROR << "Could not write scene to " << m_WorkingDirectory << Poco::Path::separator() << "index.xml" << "\nTinyXML reports '" << document.ErrorDesc() << "'"; return false; } else { try { Poco::File deleteFile( filename.c_str() ); if (deleteFile.exists()) { deleteFile.remove(); } // create zip at filename std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out); if (!file.good()) { MITK_ERROR << "Could not open a zip file for writing: '" << filename << "'"; return false; } else { Poco::Zip::Compress zipper( file, true ); Poco::Path tmpdir( m_WorkingDirectory ); zipper.addRecursive( tmpdir ); zipper.close(); } try { Poco::File deleteDir( m_WorkingDirectory ); deleteDir.remove(true); // recursive } catch(...) { MITK_ERROR << "Could not delete temporary directory " << m_WorkingDirectory; return false; // ok? } } catch(std::exception& e) { MITK_ERROR << "Could not create ZIP file from " << m_WorkingDirectory << "\nReason: " << e.what(); return false; } return true; } } catch(std::exception& e) { MITK_ERROR << "Caught exception during saving temporary files to disk. Error description: '" << e.what() << "'"; return false; } } - TiXmlElement* mitk::SceneIO::SaveBaseData( BaseData* data, const std::string& filenamehint, bool& error ) { assert(data); error = true; // find correct serializer // the serializer must // - create a file containing all information to recreate the BaseData object --> needs to know where to put this file (and a filename?) // - TODO what to do about writers that creates one file per timestep? TiXmlElement* element = new TiXmlElement("data"); element->SetAttribute( "type", data->GetNameOfClass() ); // construct name of serializer class std::string serializername(data->GetNameOfClass()); serializername += "Serializer"; std::list thingsThatCanSerializeThis = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str()); if (thingsThatCanSerializeThis.size() < 1) { MITK_ERROR << "No serializer found for " << data->GetNameOfClass() << ". Skipping object"; } for ( std::list::iterator iter = thingsThatCanSerializeThis.begin(); - iter != thingsThatCanSerializeThis.end(); - ++iter ) + iter != thingsThatCanSerializeThis.end(); + ++iter ) { if (BaseDataSerializer* serializer = dynamic_cast( iter->GetPointer() ) ) { serializer->SetData(data); serializer->SetFilenameHint(filenamehint); serializer->SetWorkingDirectory( m_WorkingDirectory ); try { std::string writtenfilename = serializer->Serialize(); element->SetAttribute("file", writtenfilename); error = false; } catch (std::exception& e) { MITK_ERROR << "Serializer " << serializer->GetNameOfClass() << " failed: " << e.what(); } break; } } return element; } TiXmlElement* mitk::SceneIO::SavePropertyList( PropertyList* propertyList, const std::string& filenamehint) { assert(propertyList); // - TODO what to do about shared properties (same object in two lists or behind several keys)? TiXmlElement* element = new TiXmlElement("properties"); // construct name of serializer class PropertyListSerializer::Pointer serializer = PropertyListSerializer::New(); serializer->SetPropertyList(propertyList); serializer->SetFilenameHint(filenamehint); serializer->SetWorkingDirectory( m_WorkingDirectory ); try { std::string writtenfilename = serializer->Serialize(); element->SetAttribute("file", writtenfilename); PropertyList::Pointer failedProperties = serializer->GetFailedProperties(); if (failedProperties.IsNotNull()) { // move failed properties to global list m_FailedProperties->ConcatenatePropertyList( failedProperties, true ); } } catch (std::exception& e) { MITK_ERROR << "Serializer " << serializer->GetNameOfClass() << " failed: " << e.what(); } return element; } - const mitk::SceneIO::FailedBaseDataListType* mitk::SceneIO::GetFailedNodes() { return m_FailedNodes.GetPointer(); } const mitk::PropertyList* mitk::SceneIO::GetFailedProperties() { return m_FailedProperties; } void mitk::SceneIO::OnUnzipError(const void* /*pSender*/, std::pair& info) { ++m_UnzipErrors; MITK_ERROR << "Error while unzipping: " << info.second; } void mitk::SceneIO::OnUnzipOk(const void* /*pSender*/, std::pair& /*info*/) { // MITK_INFO << "Unzipped ok: " << info.second.toString(); -} +} \ No newline at end of file