Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkFileWriterSelector.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkFileWriterSelector.h"
18 
19 #include <mitkBaseData.h>
20 #include <mitkCoreServices.h>
21 #include <mitkFileWriterRegistry.h>
22 #include <mitkIMimeTypeProvider.h>
23 
24 #include <usAny.h>
25 #include <usServiceProperties.h>
26 #include <usServiceReference.h>
27 
28 #include <itksys/SystemTools.hxx>
29 
30 #include <iterator>
31 #include <limits>
32 #include <set>
33 
34 namespace mitk
35 {
36  struct FileWriterSelector::Item::Impl : us::SharedData
37  {
38  Impl() : m_FileWriter(NULL), m_ConfidenceLevel(IFileWriter::Unsupported), m_BaseDataIndex(0), m_Id(-1) {}
39  us::ServiceReference<IFileWriter> m_FileWriterRef;
40  IFileWriter *m_FileWriter;
41  IFileWriter::ConfidenceLevel m_ConfidenceLevel;
42  std::size_t m_BaseDataIndex;
43  MimeType m_MimeType;
44  long m_Id;
45  };
46 
47  struct FileWriterSelector::Impl : us::SharedData
48  {
49  Impl() : m_BestId(-1), m_SelectedId(m_BestId) {}
50  Impl(const Impl &other) : us::SharedData(other), m_BestId(-1), m_SelectedId(m_BestId) {}
51  FileWriterRegistry m_WriterRegistry;
52  std::map<long, FileWriterSelector::Item> m_Items;
53  std::set<MimeType> m_MimeTypes;
54  long m_BestId;
55  long m_SelectedId;
56  };
57 
58  FileWriterSelector::FileWriterSelector(const FileWriterSelector &other) : m_Data(other.m_Data) {}
59  FileWriterSelector::FileWriterSelector(const BaseData *baseData, const std::string &mimeType, const std::string &path)
60  : m_Data(new Impl)
61  {
63 
64  std::vector<FileWriterRegistry::WriterReference> refs;
65 
66  std::string destMimeType = mimeType;
67  if (destMimeType.empty() && !path.empty())
68  {
69  // try to derive a mime-type from the file
70  std::vector<MimeType> mimeTypes = mimeTypeProvider->GetMimeTypesForFile(path);
71  if (!mimeTypes.empty())
72  {
73  for (unsigned int index = 0; index < mimeTypes.size(); index++)
74  {
75  std::vector<FileWriterRegistry::WriterReference> tempRefs =
76  m_Data->m_WriterRegistry.GetReferences(baseData, mimeTypes.at(index).GetName());
77  for (unsigned int innerIndex = 0; innerIndex < tempRefs.size(); innerIndex++)
78  {
79  refs.push_back(tempRefs.at(innerIndex));
80  }
81  }
82  }
83  else if (!itksys::SystemTools::GetFilenameExtension(path).empty())
84  {
85  // If there are no suitable mime-type for the file AND an extension
86  // was supplied, we stop here.
87  return;
88  }
89  else
90  {
91  refs = m_Data->m_WriterRegistry.GetReferences(baseData, destMimeType);
92  }
93  }
94  else
95  {
96  refs = m_Data->m_WriterRegistry.GetReferences(baseData, destMimeType);
97  }
98 
99  std::vector<std::string> classHierarchy = baseData->GetClassHierarchy();
100 
101  // Get all writers and their mime types for the given base data type
102  Item bestItem;
103  for (std::vector<FileWriterRegistry::WriterReference>::const_iterator iter = refs.begin(), iterEnd = refs.end();
104  iter != iterEnd;
105  ++iter)
106  {
107  std::string mimeTypeName = iter->GetProperty(IFileWriter::PROP_MIMETYPE()).ToString();
108  if (!mimeTypeName.empty())
109  {
110  MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName);
111  if (mimeType.IsValid())
112  {
113  // There is a registered mime-type for this writer. Now get the confidence level
114  // of this writer for writing the given base data object.
115 
116  IFileWriter *writer = m_Data->m_WriterRegistry.GetWriter(*iter);
117  if (writer == NULL)
118  continue;
119  try
120  {
121  writer->SetInput(baseData);
122  IFileWriter::ConfidenceLevel confidenceLevel = writer->GetConfidenceLevel();
123  if (confidenceLevel == IFileWriter::Unsupported)
124  {
125  continue;
126  }
127 
128  std::string baseDataType = iter->GetProperty(IFileWriter::PROP_BASEDATA_TYPE()).ToString();
129  std::vector<std::string>::iterator idxIter =
130  std::find(classHierarchy.begin(), classHierarchy.end(), baseDataType);
131  std::size_t baseDataIndex = std::numeric_limits<std::size_t>::max();
132  if (idxIter != classHierarchy.end())
133  {
134  baseDataIndex = std::distance(classHierarchy.begin(), idxIter);
135  }
136 
137  Item item;
138  item.d->m_FileWriterRef = *iter;
139  item.d->m_FileWriter = writer;
140  item.d->m_ConfidenceLevel = confidenceLevel;
141  item.d->m_BaseDataIndex = baseDataIndex;
142  item.d->m_MimeType = mimeType;
143  item.d->m_Id = us::any_cast<long>(iter->GetProperty(us::ServiceConstants::SERVICE_ID()));
144  m_Data->m_Items.insert(std::make_pair(item.d->m_Id, item));
145  m_Data->m_MimeTypes.insert(mimeType);
146  if (!bestItem.GetReference() || bestItem < item)
147  {
148  bestItem = item;
149  }
150  }
151  catch (const us::BadAnyCastException &e)
152  {
153  MITK_WARN << "Unexpected: " << e.what();
154  }
155  catch (const std::exception &e)
156  {
157  // Log the error but continue
158  MITK_WARN << "IFileWriter::GetConfidenceLevel exception: " << e.what();
159  }
160  }
161  }
162  }
163 
164  if (bestItem.GetReference())
165  {
166  m_Data->m_BestId = bestItem.GetServiceId();
167  m_Data->m_SelectedId = m_Data->m_BestId;
168  }
169  }
170 
173  {
174  m_Data = other.m_Data;
175  return *this;
176  }
177 
178  bool FileWriterSelector::IsEmpty() const { return m_Data->m_Items.empty(); }
179  std::vector<FileWriterSelector::Item> FileWriterSelector::Get(const std::string &mimeType) const
180  {
181  std::vector<Item> result;
182  for (std::map<long, Item>::const_iterator iter = m_Data->m_Items.begin(), iterEnd = m_Data->m_Items.end();
183  iter != iterEnd;
184  ++iter)
185  {
186  if (mimeType.empty() || iter->second.GetMimeType().GetName() == mimeType)
187  {
188  result.push_back(iter->second);
189  }
190  }
191  std::sort(result.begin(), result.end());
192  return result;
193  }
194 
195  std::vector<FileWriterSelector::Item> FileWriterSelector::Get() const
196  {
197  return Get(this->GetSelected().d->m_MimeType.GetName());
198  }
199 
201  {
202  std::map<long, Item>::const_iterator iter = m_Data->m_Items.find(id);
203  if (iter != m_Data->m_Items.end())
204  {
205  return iter->second;
206  }
207  return Item();
208  }
209 
210  FileWriterSelector::Item FileWriterSelector::GetDefault() const { return Get(m_Data->m_BestId); }
211  long FileWriterSelector::GetDefaultId() const { return m_Data->m_BestId; }
212  FileWriterSelector::Item FileWriterSelector::GetSelected() const { return Get(m_Data->m_SelectedId); }
213  long FileWriterSelector::GetSelectedId() const { return m_Data->m_SelectedId; }
214  bool FileWriterSelector::Select(const std::string &mimeType)
215  {
216  std::vector<Item> items = Get(mimeType);
217  if (items.empty())
218  return false;
219  return Select(items.back());
220  }
221 
222  bool FileWriterSelector::Select(const FileWriterSelector::Item &item) { return Select(item.d->m_Id); }
224  {
225  if (id > -1)
226  {
227  if (m_Data->m_Items.find(id) == m_Data->m_Items.end())
228  {
229  return false;
230  }
231  m_Data->m_SelectedId = id;
232  return true;
233  }
234  return false;
235  }
236 
237  std::vector<MimeType> FileWriterSelector::GetMimeTypes() const
238  {
239  std::vector<MimeType> result;
240  result.reserve(m_Data->m_MimeTypes.size());
241  result.assign(m_Data->m_MimeTypes.begin(), m_Data->m_MimeTypes.end());
242  return result;
243  }
244 
245  void FileWriterSelector::Swap(FileWriterSelector &fws) { m_Data.Swap(fws.m_Data); }
246  FileWriterSelector::Item::Item(const FileWriterSelector::Item &other) : d(other.d) {}
249  {
250  d = other.d;
251  return *this;
252  }
253 
254  IFileWriter *FileWriterSelector::Item::GetWriter() const { return d->m_FileWriter; }
256  {
257  us::Any descr = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_DESCRIPTION());
258  if (descr.Empty())
259  return std::string();
260  return descr.ToString();
261  }
262 
264  MimeType FileWriterSelector::Item::GetMimeType() const { return d->m_MimeType; }
266  {
267  us::Any any = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_BASEDATA_TYPE());
268  if (any.Empty())
269  return std::string();
270  return any.ToString();
271  }
272 
274  long FileWriterSelector::Item::GetServiceId() const { return d->m_Id; }
276  {
277  // sort by confidence level first (ascending)
278  if (d->m_ConfidenceLevel == other.d->m_ConfidenceLevel)
279  {
280  // sort by class hierarchy index (writers for more derived
281  // based data types are considered a better match)
282  if (d->m_BaseDataIndex == other.d->m_BaseDataIndex)
283  {
284  // sort by file writer service ranking
285  return d->m_FileWriterRef < other.d->m_FileWriterRef;
286  }
287  return other.d->m_BaseDataIndex < d->m_BaseDataIndex;
288  }
289  return d->m_ConfidenceLevel < other.d->m_ConfidenceLevel;
290  }
291 
292  FileWriterSelector::Item::Item() : d(new Impl()) {}
293  void swap(FileWriterSelector &fws1, FileWriterSelector &fws2) { fws1.Swap(fws2); }
294 }
bool operator<(const Item &other) const
virtual ConfidenceLevel GetConfidenceLevel() const =0
The confidence level of the reader or writer implementation.
us::ServiceReference< IFileWriter > GetReference() const
static IMimeTypeProvider * GetMimeTypeProvider(us::ModuleContext *context=us::GetModuleContext())
Get an IMimeTypeProvider instance.
virtual const char * what() const override
Definition: usAny.h:352
Base of all data objects.
Definition: mitkBaseData.h:39
virtual MimeType GetMimeTypeForName(const std::string &name) const =0
bool IsValid() const
static std::string PROP_DESCRIPTION()
Service property name for a description.
Definition: mitkIFileIO.cpp:22
bool Select(const std::string &mimeType)
DataCollection - Class to facilitate loading/accessing structured data.
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
std::vector< Item > Get() const
Get a sorted list of file writer info objects.
static std::string PROP_MIMETYPE()
Service property name for the mime-type associated with this file writer.
Definition: mitkIFileIO.cpp:28
virtual std::vector< std::string > GetClassHierarchy() const
Definition: mitkBaseData.h:42
void Swap(ExplicitlySharedDataPointer &other)
Definition: usSharedData.h:207
#define MITK_WARN
Definition: mitkLogMacros.h:23
Definition: usAny.h:163
void swap(CustomMimeType &l, CustomMimeType &r)
std::vector< MimeType > GetMimeTypes() const
static T max(T x, T y)
Definition: svm.cpp:70
virtual void SetInput(const BaseData *data)=0
Set the input data for writing.
std::string ToString() const
Definition: usAny.h:257
The MimeType class represens a registered mime-type. It is an immutable wrapper for mitk::CustomMimeT...
Definition: mitkMimeType.h:45
FileWriterSelector & operator=(const FileWriterSelector &other)
static std::string PROP_BASEDATA_TYPE()
Service property name for the supported mitk::BaseData sub-class.
FileWriterSelector(const FileWriterSelector &other)
ConfidenceLevel
A confidence level describing the confidence of the reader or writer in handling the given data...
Definition: mitkIFileIO.h:49
A RAII helper class for core service objects.
IFileWriter::ConfidenceLevel GetConfidenceLevel() const
US_Core_EXPORT const std::string & SERVICE_ID()
The common interface of all MITK file writers.
bool Empty() const
Definition: usAny.h:246
void Swap(FileWriterSelector &fws)
virtual std::vector< MimeType > GetMimeTypesForFile(const std::string &filePath) const =0