+#include <stdexcept>
+#include <msp/fs/utils.h>
+#include <msp/strings/format.h>
+#include "builder.h"
+#include "component.h"
+#include "datacollection.h"
+#include "datapack.h"
+#include "datatool.h"
+#include "datatransform.h"
+#include "externaltask.h"
+#include "sourcepackage.h"
+
+using namespace std;
+using namespace Msp;
+
+DataTool::DataTool(Builder &b):
+ Tool(b, "DATA")
+{
+ executable = builder.get_vfs().find_binary("mspdatatool");
+ if(!executable)
+ builder.problem(string(), format("Can't find executable mspdatatool for tool %s", tag));
+
+ input_suffixes.push_back(".mdt");
+}
+
+Target *DataTool::create_source(const Component &comp, const FS::Path &path) const
+{
+ return new DataTransform(builder, comp, path);
+}
+
+Target *DataTool::create_target(const list<Target *> &sources, const string &arg) const
+{
+ if(arg=="collection")
+ {
+ if(sources.size()!=1)
+ throw invalid_argument("DataTool::create_target");
+ DataTransform &source = dynamic_cast<DataTransform &>(*sources.front());
+ DataCollection *coll = new DataCollection(builder, *source.get_component(), source);
+ coll->set_tool(*this);
+ return coll;
+ }
+ else if(arg=="pack")
+ {
+ list<FileTarget *> files;
+ for(list<Target *>::const_iterator i=sources.begin(); i!=sources.end(); ++i)
+ files.push_back(&dynamic_cast<FileTarget &>(**i));
+ DataPack *pack = new DataPack(builder, *files.front()->get_component(), files);
+ pack->set_tool(*this);
+ return pack;
+ }
+ else
+ throw invalid_argument("DataTool::create_target");
+}
+
+Task *DataTool::run(const Target &tgt) const
+{
+ const Component &comp = *tgt.get_component();
+ FS::Path work_dir = comp.get_package().get_source_directory();
+
+ vector<string> argv;
+ argv.push_back(executable->get_path().str());
+
+ argv.push_back("-o");
+ argv.push_back(FS::relative(dynamic_cast<const FileTarget &>(tgt).get_path(), work_dir).str());
+
+ const BuildInfo &binfo = comp.get_build_info();
+ if(binfo.debug)
+ argv.push_back("-g");
+ if(binfo.optimize>0)
+ {
+ argv.push_back("-b");
+ if(binfo.optimize>1)
+ argv.push_back("-z");
+ }
+
+ if(const DataCollection *coll = dynamic_cast<const DataCollection *>(&tgt))
+ {
+ argv.push_back("-c");
+ argv.push_back(FS::relative(coll->get_source().get_path(), work_dir).str());
+ }
+ else if(const DataPack *pack = dynamic_cast<const DataPack *>(&tgt))
+ {
+ argv.push_back("-p");
+ const DataPack::FileList &files = pack->get_files();
+ for(DataPack::FileList::const_iterator i=files.begin(); i!=files.end(); ++i)
+ argv.push_back(FS::relative((*i)->get_path(), work_dir).str());
+ }
+
+ return new ExternalTask(argv, work_dir);
+}