Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkAbstractFileReader.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include <mitkAbstractFileReader.h>
14 
15 #include <mitkCustomMimeType.h>
16 #include <mitkIOUtil.h>
18 
20 
21 #include <usGetModuleContext.h>
22 #include <usModuleContext.h>
24 
25 #include <itksys/SystemTools.hxx>
26 
27 #include <fstream>
28 
29 namespace mitk
30 {
31  AbstractFileReader::InputStream::InputStream(IFileReader *reader, std::ios_base::openmode mode)
32  : std::istream(nullptr), m_Stream(nullptr)
33  {
34  std::istream *stream = reader->GetInputStream();
35  if (stream)
36  {
37  this->init(stream->rdbuf());
38  }
39  else
40  {
41  m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode);
42  this->init(m_Stream->rdbuf());
43  }
44  }
45 
47  class AbstractFileReader::Impl : public FileReaderWriterBase
48  {
49  public:
50  Impl() : FileReaderWriterBase(), m_Stream(nullptr), m_PrototypeFactory(nullptr) {}
51  Impl(const Impl &other) : FileReaderWriterBase(other), m_Stream(nullptr), m_PrototypeFactory(nullptr) {}
52  std::string m_Location;
53  std::string m_TmpFile;
54  std::istream *m_Stream;
55 
56  us::PrototypeServiceFactory *m_PrototypeFactory;
58  };
59 
62  {
64 
65  delete d->m_PrototypeFactory;
66 
67  if (!d->m_TmpFile.empty())
68  {
69  std::remove(d->m_TmpFile.c_str());
70  }
71  }
72 
73  AbstractFileReader::AbstractFileReader(const AbstractFileReader &other) : IFileReader(), d(new Impl(*other.d.get()))
74  {
75  }
76 
77  AbstractFileReader::AbstractFileReader(const CustomMimeType &mimeType, const std::string &description) : d(new Impl)
78  {
79  d->SetMimeType(mimeType);
80  d->SetDescription(description);
81  }
82 
84 
85  std::vector<BaseData::Pointer> AbstractFileReader::Read()
86  {
87  std::vector<BaseData::Pointer> result;
88 
90  this->Read(*ds);
91  DataStorage::SetOfObjects::ConstPointer dataNodes = ds->GetAll();
92  for (DataStorage::SetOfObjects::ConstIterator iter = dataNodes->Begin(), iterEnd = dataNodes->End();
93  iter != iterEnd;
94  ++iter)
95  {
96  result.push_back(iter.Value()->GetData());
97  }
98  return result;
99  }
100 
101  DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage &ds)
102  {
103  DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New();
104  std::vector<BaseData::Pointer> data = this->Read();
105  for (auto iter = data.begin(); iter != data.end(); ++iter)
106  {
108  node->SetData(*iter);
109  this->SetDefaultDataNodeProperties(node, this->GetInputLocation());
110  ds.Add(node);
111  result->InsertElement(result->Size(), node);
112  }
113  return result;
114  }
115 
117  {
118  if (d->m_Stream)
119  {
120  if (*d->m_Stream)
121  return Supported;
122  }
123  else
124  {
125  if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true))
126  {
127  return Supported;
128  }
129  }
130  return Unsupported;
131  }
132 
134 
136  {
137  if (d->m_PrototypeFactory)
139 
140  if (context == nullptr)
141  {
142  context = us::GetModuleContext();
143  }
144 
145  d->RegisterMimeType(context);
146 
147  if (this->GetMimeType()->GetName().empty())
148  {
149  MITK_WARN << "Not registering reader due to empty MIME type.";
151  }
152 
153  struct PrototypeFactory : public us::PrototypeServiceFactory
154  {
155  AbstractFileReader *const m_Prototype;
156 
157  PrototypeFactory(AbstractFileReader *prototype) : m_Prototype(prototype) {}
158  us::InterfaceMap GetService(us::Module * /*module*/,
159  const us::ServiceRegistrationBase & /*registration*/) override
160  {
161  return us::MakeInterfaceMap<IFileReader>(m_Prototype->Clone());
162  }
163 
164  void UngetService(us::Module * /*module*/,
165  const us::ServiceRegistrationBase & /*registration*/,
166  const us::InterfaceMap &service) override
167  {
168  delete us::ExtractInterface<IFileReader>(service);
169  }
170  };
171 
172  d->m_PrototypeFactory = new PrototypeFactory(this);
174  d->m_Reg = context->RegisterService<IFileReader>(d->m_PrototypeFactory, props);
175  return d->m_Reg;
176  }
177 
179  {
180  try
181  {
182  d->m_Reg.Unregister();
183  }
184  catch (const std::exception &)
185  {
186  }
187  }
188 
190  {
191  us::ServiceProperties result;
192 
193  result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription();
194  result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName();
196  return result;
197  }
198 
200  {
201  return d->RegisterMimeType(context);
202  }
203 
204  std::vector< std::string > AbstractFileReader::GetReadFiles(){ return m_ReadFiles; }
205 
206  void AbstractFileReader::SetMimeType(const CustomMimeType &mimeType) { d->SetMimeType(mimeType); }
207  void AbstractFileReader::SetDescription(const std::string &description) { d->SetDescription(description); }
208  void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); }
209  int AbstractFileReader::GetRanking() const { return d->GetRanking(); }
211  {
212  std::string localFileName;
213  if (d->m_Stream)
214  {
215  if (d->m_TmpFile.empty())
216  {
217  // write the stream contents to temporary file
218  std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation());
219  std::ofstream tmpStream;
220  localFileName = mitk::IOUtil::CreateTemporaryFile(
221  tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext);
222  tmpStream << d->m_Stream->rdbuf();
223  d->m_TmpFile = localFileName;
224  }
225  else
226  {
227  localFileName = d->m_TmpFile;
228  }
229  }
230  else
231  {
232  localFileName = d->m_Location;
233  }
234  return localFileName;
235  }
236 
238 
240  {
241  d->SetDefaultOptions(defaultOptions);
242  }
243 
244  IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); }
245  void AbstractFileReader::SetInput(const std::string &location)
246  {
247  d->m_Location = location;
248  d->m_Stream = nullptr;
249  }
250 
251  void AbstractFileReader::SetInput(const std::string &location, std::istream *is)
252  {
253  if (d->m_Stream != is && !d->m_TmpFile.empty())
254  {
255  std::remove(d->m_TmpFile.c_str());
256  d->m_TmpFile.clear();
257  }
258  d->m_Location = location;
259  d->m_Stream = is;
260  }
261 
262  std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; }
263  std::istream *AbstractFileReader::GetInputStream() const { return d->m_Stream; }
264  MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); }
265  IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); }
266  us::Any AbstractFileReader::GetOption(const std::string &name) const { return d->GetOption(name); }
267  void AbstractFileReader::SetOptions(const Options &options) { d->SetOptions(options); }
268  void AbstractFileReader::SetOption(const std::string &name, const us::Any &value) { d->SetOption(name, value); }
270 
271  void AbstractFileReader::AddProgressCallback(const ProgressCallback &callback) { d->AddProgressCallback(callback); }
273  {
274  d->RemoveProgressCallback(callback);
275  }
276 
278 
279  const CustomMimeType *AbstractFileReader::GetMimeType() const { return d->GetMimeType(); }
280  void AbstractFileReader::SetMimeTypePrefix(const std::string &prefix) { d->SetMimeTypePrefix(prefix); }
281  std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); }
282  std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); }
283  void AbstractFileReader::SetDefaultDataNodeProperties(DataNode *node, const std::string &filePath)
284  {
285  // path
286  if (!filePath.empty())
287  {
289  mitk::StringProperty::New(itksys::SystemTools::GetFilenamePath(filePath));
290  node->SetProperty(StringProperty::PATH, pathProp);
291  }
292 
293  // name already defined?
294  mitk::StringProperty::Pointer nameProp = dynamic_cast<mitk::StringProperty *>(node->GetProperty("name"));
295  if (nameProp.IsNull() || nameProp->GetValue() == DataNode::NO_NAME_VALUE())
296  {
297  // name already defined in BaseData
298  mitk::StringProperty::Pointer baseDataNameProp =
299  dynamic_cast<mitk::StringProperty *>(node->GetData()->GetProperty("name").GetPointer());
300  if (baseDataNameProp.IsNull() || baseDataNameProp->GetValue() == DataNode::NO_NAME_VALUE())
301  {
302  // name neither defined in node, nor in BaseData -> name = filebasename;
303  nameProp = mitk::StringProperty::New(this->GetRegisteredMimeType().GetFilenameWithoutExtension(filePath));
304  node->SetProperty("name", nameProp);
305  }
306  else
307  {
308  // name defined in BaseData!
309  nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue());
310  node->SetProperty("name", nameProp);
311  }
312  }
313 
314  // visibility
315  if (!node->GetProperty("visible"))
316  {
317  node->SetVisibility(true);
318  }
319  }
320 }
const CustomMimeType * GetMimeType() const
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr, bool fallBackOnDataProperties=true) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
Data management class that handles &#39;was created by&#39; relations.
us::Any GetOption(const std::string &name) const override
virtual us::ServiceProperties GetServiceProperties() const
void SetVisibility(bool visible, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="visible")
Convenience method for setting visibility properties (instances of BoolProperty)
US_Core_EXPORT const std::string & SERVICE_RANKING()
void SetOption(const std::string &name, const us::Any &value) override
ConfidenceLevel GetConfidenceLevel() const override
The confidence level of the reader or writer implementation.
std::map< std::string, void * > InterfaceMap
static std::string PROP_DESCRIPTION()
Service property name for a description.
Definition: mitkIFileIO.cpp:18
std::istream * GetInputStream() const override
Get the input stream.
std::string GetName() const
Returns the unique name for the MimeType.
void SetOptions(const Options &options) override
STL namespace.
DataCollection - Class to facilitate loading/accessing structured data.
std::map< std::string, us::Any > Options
Options for reading or writing data.
Definition: mitkIFileIO.h:69
virtual us::ServiceRegistration< CustomMimeType > RegisterMimeType(us::ModuleContext *context)
static std::string PROP_MIMETYPE()
Service property name for the mime-type associated with this file writer.
Definition: mitkIFileIO.cpp:24
std::vector< itk::SmartPointer< BaseData > > Read() override=0
Reads a path or stream and creates a list of BaseData objects.
virtual void Add(DataNode *node, const DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
std::vector< std::string > m_ReadFiles
virtual void SetDefaultDataNodeProperties(DataNode *node, const std::string &filePath)
static std::string NO_NAME_VALUE()
Definition: mitkDataNode.h:401
void SetMimeType(const CustomMimeType &mimeType)
The CustomMimeType class represents a custom mime-type which may be registered as a service object...
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
std::string GetLocalFileName() const
Get a local file name for reading.
void SetMimeTypePrefix(const std::string &prefix)
InputStream(IFileReader *writer, std::ios_base::openmode mode=std::ios_base::in)
void SetDefaultOptions(const Options &defaultOptions)
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
us::ServiceRegistration< IFileReader > RegisterService(us::ModuleContext *context=us::GetModuleContext())
#define MITK_WARN
Definition: mitkLogMacros.h:19
ConfidenceLevel
A confidence level describing the confidence of the reader or writer in handling the given data...
Definition: mitkIFileIO.h:45
static Pointer New()
void SetDescription(const std::string &description)
Definition: usAny.h:163
Options GetOptions() const override
returns a list of the supported options
void AddProgressCallback(const ProgressCallback &callback) override
static const char * PATH
virtual std::istream * GetInputStream() const =0
Get the input stream.
The MimeType class represens a registered mime-type. It is an immutable wrapper for mitk::CustomMimeT...
Definition: mitkMimeType.h:36
US_UNORDERED_MAP_TYPE< std::string, Any > ServiceProperties
void SetRanking(int ranking)
Set the service ranking for this file reader.
mitk::BaseProperty::Pointer GetProperty(const char *propertyKey) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList, and set it to this, respectively;.
std::vector< std::string > GetReadFiles() override
Base class for creating mitk::BaseData objects from files or streams.
static std::string CreateTemporaryFile(std::ofstream &tmpStream, const std::string &templateName="XXXXXX", std::string path=std::string())
Definition: mitkIOUtil.cpp:413
virtual std::string GetInputLocation() const =0
Get the current input location.
static std::string GetName(std::string fileName, std::string suffix)
Property for strings.
std::string GetInputLocation() const override
Get the current input location.
The common interface for all MITK file readers.
void SetInput(const std::string &location) override
Set the input location.
std::string GetMimeTypePrefix() const
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
static Pointer New()
void RemoveProgressCallback(const ProgressCallback &callback) override
Class for nodes of the DataTree.
Definition: mitkDataNode.h:64