Medical Imaging Interaction Toolkit  2018.4.99-f51274ea
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>
17 
19 #include <mitkVersion.h>
21 
22 #include <usGetModuleContext.h>
23 #include <usModuleContext.h>
25 
26 #include <itksys/SystemTools.hxx>
27 
28 #include <fstream>
29 
30 namespace mitk
31 {
32  AbstractFileReader::InputStream::InputStream(IFileReader *reader, std::ios_base::openmode mode)
33  : std::istream(nullptr), m_Stream(nullptr)
34  {
35  std::istream *stream = reader->GetInputStream();
36  if (stream)
37  {
38  this->init(stream->rdbuf());
39  }
40  else
41  {
42  m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode);
43  this->init(m_Stream->rdbuf());
44  }
45  }
46 
48  class AbstractFileReader::Impl : public FileReaderWriterBase
49  {
50  public:
51  Impl() : FileReaderWriterBase(), m_Stream(nullptr), m_PrototypeFactory(nullptr) {}
52  Impl(const Impl &other) : FileReaderWriterBase(other), m_Stream(nullptr), m_PrototypeFactory(nullptr) {}
53  std::string m_Location;
54  std::string m_TmpFile;
55  std::istream *m_Stream;
56 
57  us::PrototypeServiceFactory *m_PrototypeFactory;
59  };
60 
63  {
65 
66  delete d->m_PrototypeFactory;
67 
68  if (!d->m_TmpFile.empty())
69  {
70  std::remove(d->m_TmpFile.c_str());
71  }
72  }
73 
74  AbstractFileReader::AbstractFileReader(const AbstractFileReader &other) : IFileReader(), d(new Impl(*other.d.get()))
75  {
76  }
77 
78  AbstractFileReader::AbstractFileReader(const CustomMimeType &mimeType, const std::string &description) : d(new Impl)
79  {
80  d->SetMimeType(mimeType);
81  d->SetDescription(description);
82  }
83 
85 
86  std::vector<BaseData::Pointer> AbstractFileReader::Read()
87  {
88  std::vector<BaseData::Pointer> result = this->DoRead();
89 
90  const auto options = this->GetOptions();
91 
92  for (auto& data : result)
93  {
98  if (this->GetInputStream() == nullptr)
99  {
101  }
102 
103  for (const auto& option : options)
104  {
105  auto optionpath = IOMetaInformationPropertyConstants::READER_OPTION_ROOT().AddElement(option.first);
106  data->SetProperty(PropertyKeyPathToPropertyName(optionpath), StringProperty::New(option.second.ToString()));
107  }
108  }
109 
110  return result;
111  }
112 
113  DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage &ds)
114  {
115  DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New();
116  std::vector<BaseData::Pointer> data = this->Read();
117  for (auto iter = data.begin(); iter != data.end(); ++iter)
118  {
120  node->SetData(*iter);
121  this->SetDefaultDataNodeProperties(node, this->GetInputLocation());
122  ds.Add(node);
123  result->InsertElement(result->Size(), node);
124  }
125  return result;
126  }
127 
129  {
130  if (d->m_Stream)
131  {
132  if (*d->m_Stream)
133  return Supported;
134  }
135  else
136  {
137  if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true))
138  {
139  return Supported;
140  }
141  }
142  return Unsupported;
143  }
144 
146 
148  {
149  if (d->m_PrototypeFactory)
151 
152  if (context == nullptr)
153  {
154  context = us::GetModuleContext();
155  }
156 
157  d->RegisterMimeType(context);
158 
159  if (this->GetMimeType()->GetName().empty())
160  {
161  MITK_WARN << "Not registering reader due to empty MIME type.";
163  }
164 
165  struct PrototypeFactory : public us::PrototypeServiceFactory
166  {
167  AbstractFileReader *const m_Prototype;
168 
169  PrototypeFactory(AbstractFileReader *prototype) : m_Prototype(prototype) {}
170  us::InterfaceMap GetService(us::Module * /*module*/,
171  const us::ServiceRegistrationBase & /*registration*/) override
172  {
173  return us::MakeInterfaceMap<IFileReader>(m_Prototype->Clone());
174  }
175 
176  void UngetService(us::Module * /*module*/,
177  const us::ServiceRegistrationBase & /*registration*/,
178  const us::InterfaceMap &service) override
179  {
180  delete us::ExtractInterface<IFileReader>(service);
181  }
182  };
183 
184  d->m_PrototypeFactory = new PrototypeFactory(this);
186  d->m_Reg = context->RegisterService<IFileReader>(d->m_PrototypeFactory, props);
187  return d->m_Reg;
188  }
189 
191  {
192  try
193  {
194  d->m_Reg.Unregister();
195  }
196  catch (const std::exception &)
197  {
198  }
199  }
200 
202  {
203  us::ServiceProperties result;
204 
205  result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription();
206  result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName();
208  return result;
209  }
210 
212  {
213  return d->RegisterMimeType(context);
214  }
215 
216  std::vector< std::string > AbstractFileReader::GetReadFiles(){ return m_ReadFiles; }
217 
218  void AbstractFileReader::SetMimeType(const CustomMimeType &mimeType) { d->SetMimeType(mimeType); }
219  void AbstractFileReader::SetDescription(const std::string &description) { d->SetDescription(description); }
220  void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); }
221  int AbstractFileReader::GetRanking() const { return d->GetRanking(); }
223  {
224  std::string localFileName;
225  if (d->m_Stream)
226  {
227  if (d->m_TmpFile.empty())
228  {
229  // write the stream contents to temporary file
230  std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation());
231  std::ofstream tmpStream;
232  localFileName = mitk::IOUtil::CreateTemporaryFile(
233  tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext);
234  tmpStream << d->m_Stream->rdbuf();
235  d->m_TmpFile = localFileName;
236  }
237  else
238  {
239  localFileName = d->m_TmpFile;
240  }
241  }
242  else
243  {
244  localFileName = d->m_Location;
245  }
246  return localFileName;
247  }
248 
250 
252  {
253  d->SetDefaultOptions(defaultOptions);
254  }
255 
256  IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); }
257  void AbstractFileReader::SetInput(const std::string &location)
258  {
259  d->m_Location = location;
260  d->m_Stream = nullptr;
261  }
262 
263  void AbstractFileReader::SetInput(const std::string &location, std::istream *is)
264  {
265  if (d->m_Stream != is && !d->m_TmpFile.empty())
266  {
267  std::remove(d->m_TmpFile.c_str());
268  d->m_TmpFile.clear();
269  }
270  d->m_Location = location;
271  d->m_Stream = is;
272  }
273 
274  std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; }
275  std::istream *AbstractFileReader::GetInputStream() const { return d->m_Stream; }
276  MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); }
277  IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); }
278  us::Any AbstractFileReader::GetOption(const std::string &name) const { return d->GetOption(name); }
279  void AbstractFileReader::SetOptions(const Options &options) { d->SetOptions(options); }
280  void AbstractFileReader::SetOption(const std::string &name, const us::Any &value) { d->SetOption(name, value); }
282 
283  void AbstractFileReader::AddProgressCallback(const ProgressCallback &callback) { d->AddProgressCallback(callback); }
285  {
286  d->RemoveProgressCallback(callback);
287  }
288 
290 
291  const CustomMimeType *AbstractFileReader::GetMimeType() const { return d->GetMimeType(); }
292  void AbstractFileReader::SetMimeTypePrefix(const std::string &prefix) { d->SetMimeTypePrefix(prefix); }
293  std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); }
294  std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); }
295  void AbstractFileReader::SetDefaultDataNodeProperties(DataNode *node, const std::string &filePath)
296  {
297  // path
298  if (!filePath.empty())
299  {
301  mitk::StringProperty::New(itksys::SystemTools::GetFilenamePath(filePath));
302  node->SetProperty(StringProperty::PATH, pathProp);
303  }
304 
305  // name already defined?
306  mitk::StringProperty::Pointer nameProp = dynamic_cast<mitk::StringProperty *>(node->GetProperty("name"));
307  if (nameProp.IsNull() || nameProp->GetValue() == DataNode::NO_NAME_VALUE())
308  {
309  // name already defined in BaseData
310  mitk::StringProperty::Pointer baseDataNameProp =
311  dynamic_cast<mitk::StringProperty *>(node->GetData()->GetProperty("name").GetPointer());
312  if (baseDataNameProp.IsNull() || baseDataNameProp->GetValue() == DataNode::NO_NAME_VALUE())
313  {
314  // name neither defined in node, nor in BaseData -> name = filebasename;
315  nameProp = mitk::StringProperty::New(this->GetRegisteredMimeType().GetFilenameWithoutExtension(filePath));
316  node->SetProperty("name", nameProp);
317  }
318  else
319  {
320  // name defined in BaseData!
321  nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue());
322  node->SetProperty("name", nameProp);
323  }
324  }
325 
326  // visibility
327  if (!node->GetProperty("visible"))
328  {
329  node->SetVisibility(true);
330  }
331  }
332 }
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...
#define MITK_VERSION_STRING
Definition: mitkVersion.h:9
Data management class that handles &#39;was created by&#39; relations.
us::Any GetOption(const std::string &name) const override
MITKCORE_EXPORT std::string PropertyKeyPathToPropertyName(const PropertyKeyPath &tagPath)
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.
PropertyKeyPath & AddElement(const ElementNameType &name)
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
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:393
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)
virtual std::vector< itk::SmartPointer< BaseData > > DoRead()=0
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.
std::vector< itk::SmartPointer< BaseData > > Read() override
Reads a path or stream and creates a list of BaseData objects.
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:57