Medical Imaging Interaction Toolkit  2018.4.99-87d68d9f
Medical Imaging Interaction Toolkit
mitkAbstractFileWriter.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 <mitkAbstractFileWriter.h>
14 
15 #include <mitkBaseData.h>
16 #include <mitkCustomMimeType.h>
17 #include <mitkExceptionMacro.h>
18 #include <mitkIOUtil.h>
19 
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  struct AbstractFileWriter::LocalFile::Impl
33  {
34  Impl(const std::string &location, std::ostream *os) : m_Location(location), m_Stream(os) {}
35  std::string m_Location;
36  std::string m_TmpFileName;
37  std::ostream *m_Stream;
38  };
39 
40  AbstractFileWriter::LocalFile::LocalFile(IFileWriter *writer)
41  : d(new Impl(writer->GetOutputLocation(), writer->GetOutputStream()))
42  {
43  }
44 
46  {
47  if (d->m_Stream && !d->m_TmpFileName.empty())
48  {
49  std::ifstream ifs(d->m_TmpFileName.c_str(), std::ios_base::binary);
50  *d->m_Stream << ifs.rdbuf();
51  d->m_Stream->flush();
52  ifs.close();
53  std::remove(d->m_TmpFileName.c_str());
54  }
55  }
56 
58  {
59  if (d->m_Stream == nullptr)
60  {
61  return d->m_Location;
62  }
63  else if (d->m_TmpFileName.empty())
64  {
65  std::string ext = itksys::SystemTools::GetFilenameExtension(d->m_Location);
66  d->m_TmpFileName = IOUtil::CreateTemporaryFile("XXXXXX" + ext);
67  }
68  return d->m_TmpFileName;
69  }
70 
71  AbstractFileWriter::OutputStream::OutputStream(IFileWriter *writer, std::ios_base::openmode mode)
72  : std::ostream(nullptr), m_Stream(nullptr)
73  {
74  std::ostream *stream = writer->GetOutputStream();
75  if (stream)
76  {
77  this->init(stream->rdbuf());
78  }
79  else
80  {
81  m_Stream = new std::ofstream(writer->GetOutputLocation().c_str(), mode);
82  this->init(m_Stream->rdbuf());
83  }
84  }
85 
87  class AbstractFileWriter::Impl : public FileReaderWriterBase
88  {
89  public:
90  Impl() : FileReaderWriterBase(), m_BaseData(nullptr), m_Stream(nullptr), m_PrototypeFactory(nullptr) {}
91  Impl(const Impl &other)
92  : FileReaderWriterBase(other),
93  m_BaseDataType(other.m_BaseDataType),
94  m_BaseData(nullptr),
95  m_Stream(nullptr),
96  m_PrototypeFactory(nullptr)
97  {
98  }
99 
100  std::string m_BaseDataType;
101  const BaseData *m_BaseData;
102  std::string m_Location;
103  std::ostream *m_Stream;
104 
105  us::PrototypeServiceFactory *m_PrototypeFactory;
107  };
108 
109  void AbstractFileWriter::SetInput(const BaseData *data) { d->m_BaseData = data; }
110  const BaseData *AbstractFileWriter::GetInput() const { return d->m_BaseData; }
111  void AbstractFileWriter::SetOutputLocation(const std::string &location)
112  {
113  d->m_Location = location;
114  d->m_Stream = nullptr;
115  }
116 
117  std::string AbstractFileWriter::GetOutputLocation() const { return d->m_Location; }
118  void AbstractFileWriter::SetOutputStream(const std::string &location, std::ostream *os)
119  {
120  d->m_Location = location;
121  d->m_Stream = os;
122  }
123 
124  std::ostream *AbstractFileWriter::GetOutputStream() const { return d->m_Stream; }
126  {
128 
129  delete d->m_PrototypeFactory;
130  }
131 
132  AbstractFileWriter::AbstractFileWriter(const AbstractFileWriter &other) : IFileWriter(), d(new Impl(*other.d.get()))
133  {
134  }
135 
136  AbstractFileWriter::AbstractFileWriter(const std::string &baseDataType) : d(new Impl)
137  {
138  d->m_BaseDataType = baseDataType;
139  }
140 
141  AbstractFileWriter::AbstractFileWriter(const std::string &baseDataType,
142  const CustomMimeType &mimeType,
143  const std::string &description)
144  : d(new Impl)
145  {
146  d->m_BaseDataType = baseDataType;
147  d->SetMimeType(mimeType);
148  d->SetDescription(description);
149  }
150 
152 
154  {
155  if (d->m_BaseData == nullptr)
156  return Unsupported;
157 
158  std::vector<std::string> classHierarchy = d->m_BaseData->GetClassHierarchy();
159  if (std::find(classHierarchy.begin(), classHierarchy.end(), d->m_BaseDataType) == classHierarchy.end())
160  {
161  return Unsupported;
162  }
163  return Supported;
164  }
165 
166  MimeType AbstractFileWriter::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); }
168 
170  {
171  if (d->m_PrototypeFactory)
173 
174  if (context == nullptr)
175  {
176  context = us::GetModuleContext();
177  }
178 
179  d->RegisterMimeType(context);
180 
181  if (this->GetMimeType()->GetName().empty())
182  {
183  MITK_WARN << "Not registering writer due to empty MIME type.";
185  }
186 
187  struct PrototypeFactory : public us::PrototypeServiceFactory
188  {
189  AbstractFileWriter *const m_Prototype;
190 
191  PrototypeFactory(AbstractFileWriter *prototype) : m_Prototype(prototype) {}
192  us::InterfaceMap GetService(us::Module * /*module*/,
193  const us::ServiceRegistrationBase & /*registration*/) override
194  {
195  return us::MakeInterfaceMap<IFileWriter>(m_Prototype->Clone());
196  }
197 
198  void UngetService(us::Module * /*module*/,
199  const us::ServiceRegistrationBase & /*registration*/,
200  const us::InterfaceMap &service) override
201  {
202  delete us::ExtractInterface<IFileWriter>(service);
203  }
204  };
205 
206  d->m_PrototypeFactory = new PrototypeFactory(this);
208  d->m_Reg = context->RegisterService<IFileWriter>(d->m_PrototypeFactory, props);
209  return d->m_Reg;
210  }
211 
213  {
214  try
215  {
216  d->m_Reg.Unregister();
217  }
218  catch (const std::exception &)
219  {
220  }
221  }
222 
224  {
225  us::ServiceProperties result;
226  result[IFileWriter::PROP_DESCRIPTION()] = this->GetDescription();
227  result[IFileWriter::PROP_MIMETYPE()] = this->GetMimeType()->GetName();
228  result[IFileWriter::PROP_BASEDATA_TYPE()] = d->m_BaseDataType;
230 
231  // for (IFileWriter::OptionList::const_iterator it = d->m_Options.begin(); it != d->m_Options.end(); ++it)
232  // {
233  // result[it->first] = std::string("true");
234  // }
235  return result;
236  }
237 
238  const CustomMimeType *AbstractFileWriter::GetMimeType() const { return d->GetMimeType(); }
239  void AbstractFileWriter::SetMimeTypePrefix(const std::string &prefix) { d->SetMimeTypePrefix(prefix); }
240  std::string AbstractFileWriter::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); }
242  {
243  return d->RegisterMimeType(context);
244  }
245 
246  void AbstractFileWriter::SetMimeType(const CustomMimeType &mimeType) { d->SetMimeType(mimeType); }
247  void AbstractFileWriter::SetRanking(int ranking) { d->SetRanking(ranking); }
249 
251  {
252  d->SetDefaultOptions(defaultOptions);
253  }
254 
255  IFileWriter::Options AbstractFileWriter::GetDefaultOptions() const { return d->GetDefaultOptions(); }
256  IFileWriter::Options AbstractFileWriter::GetOptions() const { return d->GetOptions(); }
257  us::Any AbstractFileWriter::GetOption(const std::string &name) const { return d->GetOption(name); }
258  void AbstractFileWriter::SetOption(const std::string &name, const us::Any &value) { d->SetOption(name, value); }
259  void AbstractFileWriter::SetOptions(const Options &options) { d->SetOptions(options); }
261 
262  void AbstractFileWriter::AddProgressCallback(const ProgressCallback &callback) { d->AddProgressCallback(callback); }
264  {
265  d->RemoveProgressCallback(callback);
266  }
267 
269 
270  int AbstractFileWriter::GetRanking() const { return d->GetRanking(); }
271  void AbstractFileWriter::SetBaseDataType(const std::string &baseDataType) { d->m_BaseDataType = baseDataType; }
272  std::string AbstractFileWriter::GetDescription() const { return d->GetDescription(); }
273  std::string AbstractFileWriter::GetBaseDataType() const { return d->m_BaseDataType; }
275  {
276  if (this->GetOutputStream() == nullptr)
277  {
278  // check if a file name is set and if we can write to it
279  const std::string fileName = this->GetOutputLocation();
280  if (fileName.empty())
281  {
282  mitkThrow() << "No output location or stream specified";
283  }
284  }
285  }
286 
287  void AbstractFileWriter::SetDescription(const std::string &description) { d->SetDescription(description); }
288 }
AbstractFileWriter(const AbstractFileWriter &other)
void SetInput(const BaseData *data) override
Set the input data for writing.
virtual us::ServiceProperties GetServiceProperties() const
US_Core_EXPORT const std::string & SERVICE_RANKING()
Base of all data objects.
Definition: mitkBaseData.h:37
const CustomMimeType * GetMimeType() const
virtual std::string GetBaseDataType() const
Options GetOptions() const override
returns a list of the supported options
std::map< std::string, void * > InterfaceMap
static std::string PROP_DESCRIPTION()
Service property name for a description.
Definition: mitkIFileIO.cpp:18
std::string GetName() const
Returns the unique name for the MimeType.
STL namespace.
DataCollection - Class to facilitate loading/accessing structured data.
virtual std::string GetOutputLocation() const =0
Get the current output location.
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
void SetDefaultOptions(const Options &defaultOptions)
ConfidenceLevel GetConfidenceLevel() const override
The confidence level of the reader or writer implementation.
The CustomMimeType class represents a custom mime-type which may be registered as a service object...
void SetRanking(int ranking)
Set the service ranking for this file writer.
#define MITK_WARN
Definition: mitkLogMacros.h:19
void SetOutputStream(const std::string &location, std::ostream *os) override
Set an output stream for writing.
ConfidenceLevel
A confidence level describing the confidence of the reader or writer in handling the given data...
Definition: mitkIFileIO.h:45
#define mitkThrow()
const BaseData * GetInput() const override
Get the input data set via SetInput().
Definition: usAny.h:163
void SetBaseDataType(const std::string &baseDataType)
Sets the name of the mitk::Basedata that this writer is able to handle.
std::string GetMimeTypePrefix() const
void SetOutputLocation(const std::string &location) override
Set the output location.
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
virtual std::ostream * GetOutputStream() const =0
Get the output stream.
std::ostream * GetOutputStream() const override
Get the output stream.
void SetOption(const std::string &name, const us::Any &value) override
static std::string PROP_BASEDATA_TYPE()
Service property name for the supported mitk::BaseData sub-class.
static std::string CreateTemporaryFile(std::ofstream &tmpStream, const std::string &templateName="XXXXXX", std::string path=std::string())
Definition: mitkIOUtil.cpp:413
us::ServiceRegistration< IFileWriter > RegisterService(us::ModuleContext *context=us::GetModuleContext())
void SetMimeType(const CustomMimeType &mimeType)
static std::string GetName(std::string fileName, std::string suffix)
OutputStream(IFileWriter *writer, std::ios_base::openmode mode=std::ios_base::trunc|std::ios_base::out)
void SetOptions(const Options &options) override
std::string GetOutputLocation() const override
Get the current output location.
void SetMimeTypePrefix(const std::string &prefix)
The common interface of all MITK file writers.
Base class for writing mitk::BaseData objects to files or streams.
void SetDescription(const std::string &description)
Sets a human readable description of this writer.
us::Any GetOption(const std::string &name) const override
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void AddProgressCallback(const ProgressCallback &callback) override
void RemoveProgressCallback(const ProgressCallback &callback) override