Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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