Fraxinus  17.12-rc1
An IGT application
cxToolConfigurationParser.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
34 
35 #include <QFile>
36 #include <QDir>
37 #include <QFileInfo>
38 #include <QTextStream>
39 #include "cxLogger.h"
40 #include "cxTypeConversions.h"
41 #include "cxEnumConverter.h"
42 #include "cxDataLocations.h"
43 #include "cxProfile.h"
44 #include "cxFrame3D.h"
45 #include "cxTransformFile.h"
46 
47 namespace cx
48 {
49 
50 ConfigurationFileParser::ConfigurationFileParser(QString absoluteConfigFilePath, QString loggingFolder) :
51  mConfigurationFilePath(absoluteConfigFilePath), mLoggingFolder(loggingFolder), mConfigTag(
52  "configuration"), mConfigTrackerTag("tracker"), mConfigTrackerToolFile("toolfile"), mTypeAttribute(
53  "type"), mClinicalAppAttribute("clinical_app"), mReferenceAttribute("reference")
54 {
55  this->setConfigDocument(mConfigurationFilePath);
56 }
57 
59 {
60 }
61 
63 {
64  if (!this->isConfigFileValid())
65  return "";
66 
67  QDomNode configNode = mConfigureDoc.elementsByTagName(mConfigTag).at(0);
68  QString retval = configNode.toElement().attribute(mClinicalAppAttribute);
69  return retval;
70 }
71 
72 std::vector<ToolFileParser::TrackerInternalStructure> ConfigurationFileParser::getTrackers()
73 {
74  std::vector<ToolFileParser::TrackerInternalStructure> retval;
75 
76  if (!this->isConfigFileValid())
77  return retval;
78 
79  QDomNodeList trackerNodes = mConfigureDoc.elementsByTagName(mConfigTrackerTag);
80  for (int i = 0; i < trackerNodes.count(); ++i)
81  {
83  QString trackerType = trackerNodes.at(i).toElement().attribute(mTypeAttribute);
84  internalStructure.mType = string2enum<TRACKING_SYSTEM>(trackerType);
85  internalStructure.mLoggingFolderName = mLoggingFolder;
86 
87  retval.push_back(internalStructure);
88  }
89 
90  if (retval.size() > 1)
92  "Config file " + mConfigurationFilePath
93  + " has a invalid number of tracking systems, we only support 1 tracking system atm!");
94 
95  return retval;
96 }
97 
99 {
100  std::vector<QString> retval;
101 
102  if (!this->isConfigFileValid())
103  return retval;
104 
105  QDomNodeList toolFileNodes = mConfigureDoc.elementsByTagName(mConfigTrackerToolFile);
106  for (int i = 0; i < toolFileNodes.count(); ++i)
107  {
108  QString absoluteToolFilePath = this->getAbsoluteToolFilePath(toolFileNodes.at(i).toElement());
109  if (absoluteToolFilePath.isEmpty())
110  continue;
111 
112  retval.push_back(absoluteToolFilePath);
113  }
114 
115  return retval;
116 }
117 
119 {
120  QString retval;
121 
122  if (!this->isConfigFileValid())
123  return retval;
124 
125 // QFile configFile(mConfigurationFilePath);
126 // QString configFolderAbsolutePath = QFileInfo(configFile).dir().absolutePath()+"/";
127 // std::cout << "configFolderAbsolutePath " << configFolderAbsolutePath << std::endl;
128 
129  QDomNodeList toolFileNodes = mConfigureDoc.elementsByTagName(mConfigTrackerToolFile);
130  for (int i = 0; i < toolFileNodes.count(); ++i)
131  {
132  QString reference = toolFileNodes.at(i).toElement().attribute(mReferenceAttribute);
133  if (reference.contains("yes", Qt::CaseInsensitive))
134  {
135 // std::cout << "Found yes..." << std::endl;
136  retval = this->getAbsoluteToolFilePath(toolFileNodes.at(i).toElement());
137  }
138  }
139  return retval;
140 }
141 
143 {
144  QString retval = DataLocations::getRootConfigPath() + "/tool/TEMPLATE_configuration.xml";
145  return retval;
146 }
147 
148 QString ConfigurationFileParser::convertToRelativeToolFilePath(QString configFilename, QString absoluteToolFilePath)
149 {
150  foreach (QString root, profile()->getAllRootConfigPaths())
151  {
152  QString configPath = getToolPathFromRoot(root);
153  if (!absoluteToolFilePath.contains(configPath))
154  continue;
155  absoluteToolFilePath.replace(configPath, "");
156  if (absoluteToolFilePath.startsWith("/"))
157  absoluteToolFilePath.remove(0, 1);
158  return absoluteToolFilePath;
159  }
160 
161  // file not in any of the standard locations: return absolute
162  return absoluteToolFilePath;
163 }
164 
165 QString ConfigurationFileParser::getToolPathFromRoot(QString root)
166 {
167  return root + "/tool/Tools/";
168 }
169 
171 {
172  QDomDocument doc;
173  doc.appendChild(doc.createProcessingInstruction("xml version =", "\"1.0\""));
174 
175  QDomElement configNode = doc.createElement("configuration");
176  configNode.setAttribute("clinical_app", config.mClinical_app);
177 
178  TrackersAndToolsMap::iterator it1 = config.mTrackersAndTools.begin();
179  for (; it1 != config.mTrackersAndTools.end(); ++it1)
180  {
181  QString trackerType = enum2string(it1->first);
182  QDomElement trackerTagNode = doc.createElement("tracker");
183  trackerTagNode.setAttribute("type", trackerType);
184 
185  ToolFilesAndReferenceVector::iterator it2 = it1->second.begin();
186  for (; it2 != it1->second.end(); ++it2)
187  {
188  QString absoluteToolFilePath = it2->first;
189  QString relativeToolFilePath = convertToRelativeToolFilePath(config.mFileName, absoluteToolFilePath);
190 
191  ToolFileParser toolparser(absoluteToolFilePath);
192  QString toolTrackerType = enum2string(toolparser.getTool().mTrackerType);
193  if (!trackerType.contains(enum2string(toolparser.getTool().mTrackerType), Qt::CaseInsensitive))
194  {
195  reportWarning("When saving configuration, skipping tool " + relativeToolFilePath + " of type "
196  + toolTrackerType + " because tracker is set to " + trackerType);
197  continue;
198  }
199 
200  QDomElement toolFileNode = doc.createElement("toolfile");
201  toolFileNode.appendChild(doc.createTextNode(relativeToolFilePath));
202  toolFileNode.setAttribute("reference", (it2->second ? "yes" : "no"));
203  trackerTagNode.appendChild(toolFileNode);
204  }
205  configNode.appendChild(trackerTagNode);
206  }
207 
208  doc.appendChild(configNode);
209 
210  //write to file
211  QFile file(config.mFileName);
212  QDir().mkpath(QFileInfo(config.mFileName).absolutePath());
213 
214  if (!file.open(QIODevice::WriteOnly))
215  {
216  reportWarning("Could not open file " + file.fileName() + ", aborting writing of config.");
217  return;
218  }
219  QTextStream stream(&file);
220  doc.save(stream, 4);
221  reportSuccess("Configuration file " + file.fileName() + " is written.");
222 }
223 
224 void ConfigurationFileParser::setConfigDocument(QString configAbsoluteFilePath)
225 {
226  QFile configFile(configAbsoluteFilePath);
227  if (!configFile.exists())
228  {
229 // reportDebug("Configfile "+configAbsoluteFilePath+" does not exist.");
230  return;
231  }
232 
233  if (!mConfigureDoc.setContent(&configFile))
234  {
235  reportError("Could not set the xml content of the config file " + configAbsoluteFilePath);
236  return;
237  }
238 }
239 
240 bool ConfigurationFileParser::isConfigFileValid()
241 {
242  //there can only be one config defined in every config.xml-file, that's why we say ...item(0)
243  QDomNode configNode = mConfigureDoc.elementsByTagName(mConfigTag).item(0);
244  if (configNode.isNull())
245  {
246  //reportDebug("Configuration file \""+mConfigurationFilePath+"\" does not contain the tag <"+mConfigTag+">.");
247  return false;
248  }
249  return true;
250 }
251 
252 QString ConfigurationFileParser::findXmlFileWithDirNameInPath(QString path)
253 {
254  QDir dir(path);
255  QStringList filter;
256  filter << dir.dirName() + ".xml";
257  QStringList filepaths = dir.entryList(filter);
258  if (!filepaths.isEmpty())
259  return dir.absoluteFilePath(filter[0]);
260  return "";
261 }
262 
263 QString ConfigurationFileParser::searchForExistingToolFilePath(QString relativeToolFilePath)
264 {
265  // remove old-style paths (<= v3.7.0)
266  relativeToolFilePath.replace("../Tools/", "");
267 
268  foreach (QString root, profile()->getAllRootConfigPaths())
269  {
270  QString configPath = this->getToolPathFromRoot(root);
271  QFileInfo guess(configPath + "/" + relativeToolFilePath);
272  if (guess.exists())
273  return guess.canonicalFilePath();
274  }
275  return "";
276 }
277 
278 QString ConfigurationFileParser::getAbsoluteToolFilePath(QDomElement toolfileelement)
279 {
280  QString relativeToolFilePath = toolfileelement.text();
281  if (relativeToolFilePath.isEmpty())
282  return "";
283 
284  QString absoluteToolFilePath = this->searchForExistingToolFilePath(relativeToolFilePath);
285 
286  QFileInfo info(absoluteToolFilePath);
287  if (!info.exists())
288  reportError(QString("Tool file %1 in configuration %2 not found. Skipping.")
289  .arg(relativeToolFilePath)
290  .arg(mConfigurationFilePath));
291 
292  if (info.isDir())
293  absoluteToolFilePath = this->findXmlFileWithDirNameInPath(absoluteToolFilePath);
294  return absoluteToolFilePath;
295 }
296 //----------------------------------------------------------------------------------------------------------------------
297 
298 
299 //----------------------------------------------------------------------------------------------------------------------
300 
301 }//namespace cx
TrackersAndToolsMap mTrackersAndTools
the trackers and tools (relative path) that should be used in the config
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:181
QString mLoggingFolderName
path to where log should be saved
void reportError(QString msg)
Definition: cxLogger.cpp:92
TRACKING_SYSTEM mType
the trackers type
QString mFileName
absolute path and filename for the new config file
ConfigurationFileParser(QString absoluteConfigFilePath, QString loggingFolder="")
static void saveConfiguration(Configuration &config)
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
TRACKING_SYSTEM mTrackerType
what product the tool belongs to
void reportSuccess(QString msg)
Definition: cxLogger.cpp:93
static QString getRootConfigPath()
return path to root config folder. May be replaced with getExistingConfigPath()
std::vector< QString > getAbsoluteToolFilePaths()
QString mClinical_app
the clinical application this config is made for
virtual ToolInternalStructure getTool()
std::vector< ToolFileParser::TrackerInternalStructure > getTrackers()
Class for reading the files defining a CustusX tool.
QString enum2string(const ENUM &val)
Namespace for all CustusX production code.