Back to index

nordugrid-arc-nox  1.1.0~rc6
ARCJSDLParser.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #include <string>
00008 #include <glibmm.h>
00009 
00010 #include <arc/DateTime.h>
00011 #include <arc/Logger.h>
00012 #include <arc/StringConv.h>
00013 #include <arc/URL.h>
00014 #include <arc/XMLNode.h>
00015 #include <arc/client/JobDescription.h>
00016 
00017 #include "ARCJSDLParser.h"
00018 
00019 namespace Arc {
00020 
00021   ARCJSDLParser::ARCJSDLParser()
00022     : JobDescriptionParser() {}
00023 
00024   ARCJSDLParser::~ARCJSDLParser() {}
00025 
00026   static void XmlErrorHandler(void* ctx, const char* msg) {
00027     return;
00028   }
00029 
00030   bool ARCJSDLParser::parseSoftware(XMLNode xmlSoftware, SoftwareRequirement& sr) const {
00031     for (int i = 0; (bool)(xmlSoftware["Software"][i]); i++) {
00032       Software::ComparisonOperator comOp = &Software::operator==;
00033       if (bool(xmlSoftware["Software"][i]["Version"].Attribute("require"))) {
00034         const std::string comOpStr = (std::string)xmlSoftware["Software"][i]["Version"].Attribute("require");
00035         if (comOpStr == "!=" || lower(comOpStr) == "ne")
00036           comOp = &Software::operator!=;
00037         else if (comOpStr == ">" || lower(comOpStr) == "gt")
00038           comOp = &Software::operator>;
00039         else if (comOpStr == "<" || lower(comOpStr) == "lt")
00040           comOp = &Software::operator<;
00041         else if (comOpStr == ">=" || lower(comOpStr) == "ge")
00042           comOp = &Software::operator>=;
00043         else if (comOpStr == "<=" || lower(comOpStr) == "le")
00044           comOp = &Software::operator<=;
00045         else if (comOpStr != "=" && comOpStr != "==" && lower(comOpStr) != "eq") {
00046           logger.msg(ERROR, "Unknown operator '%s' in attribute require in Version element", comOpStr);
00047           return false;
00048         }
00049       }
00050 
00051       sr.add(Software(trim((std::string)xmlSoftware["Software"][i]["Name"]),
00052                       trim((std::string)xmlSoftware["Software"][i]["Version"])),
00053              comOp);
00054     }
00055 
00056     return true;
00057   }
00058 
00059   void ARCJSDLParser::outputSoftware(const SoftwareRequirement& sr, XMLNode& arcJSDL) const {
00060     std::list<Software>::const_iterator itSW = sr.getSoftwareList().begin();
00061     std::list<Software::ComparisonOperator>::const_iterator itCO = sr.getComparisonOperatorList().begin();
00062     for (; itSW != sr.getSoftwareList().end(); itSW++, itCO++) {
00063       if (itSW->empty()) continue;
00064 
00065       XMLNode xmlSoftware = arcJSDL.NewChild("Software");
00066       if (!itSW->getFamily().empty()) xmlSoftware.NewChild("Family") = itSW->getFamily();
00067       xmlSoftware.NewChild("Name") = itSW->getName();
00068       if (!itSW->getVersion().empty()) {
00069         XMLNode xmlVersion = xmlSoftware.NewChild("Version");
00070         xmlVersion = itSW->getVersion();
00071         if (*itCO != &Software::operator ==)
00072           xmlVersion.NewAttribute("require") = Software::toString(*itCO);
00073       }
00074     }
00075 
00076     if (bool(arcJSDL["Software"]) && sr.isRequiringAll())
00077       arcJSDL.NewAttribute("require") = "all";
00078   }
00079 
00080   template<typename T>
00081   void ARCJSDLParser::parseRange(XMLNode xmlRange, Range<T>& range, const T& undefValue) const {
00082     if (!xmlRange) return;
00083 
00084     if (bool(xmlRange["Min"])) {
00085       if (!stringto<T>((std::string)xmlRange["Min"], range.min))
00086         range.min = undefValue;
00087     }
00088     else if (bool(xmlRange["LowerBoundedRange"])) {
00089       if (!stringto<T>((std::string)xmlRange["LowerBoundedRange"], range.min))
00090         range.min = undefValue;
00091     }
00092 
00093     if (bool(xmlRange["Max"])) {
00094       if (!stringto<T>((std::string)xmlRange["Max"], range.max))
00095         range.max = undefValue;
00096     }
00097     else if (bool(xmlRange["UpperBoundedRange"])) {
00098       if (!stringto<T>((std::string)xmlRange["UpperBoundedRange"]), range.max)
00099         range.max = undefValue;
00100     }
00101   }
00102 
00103   template<typename T>
00104   Range<T> ARCJSDLParser::parseRange(XMLNode xmlRange, const T& undefValue) const {
00105     Range<T> range;
00106     parseRange(xmlRange, range, undefValue);
00107     return range;
00108   }
00109 
00110   template<typename T>
00111   void ARCJSDLParser::outputARCJSDLRange(const Range<T>& range, XMLNode& arcJSDL, const T& undefValue) const {
00112     if (range.min != undefValue) {
00113       const std::string min = tostring(range.min);
00114       if (!min.empty()) arcJSDL.NewChild("Min") = min;
00115     }
00116 
00117     if (range.max != undefValue) {
00118       const std::string max = tostring(range.max);
00119       if (!max.empty()) arcJSDL.NewChild("Max") = max;
00120     }
00121   }
00122 
00123   template<typename T>
00124   void ARCJSDLParser::outputJSDLRange(const Range<T>& range, XMLNode& jsdl, const T& undefValue) const {
00125     if (range.min != undefValue) {
00126       const std::string lower = tostring(range.min);
00127       if (!lower.empty()) jsdl.NewChild("LowerBoundedRange") = lower;
00128     }
00129 
00130     if (range.max != undefValue) {
00131       const std::string upper = tostring(range.max);
00132       if (!upper.empty()) jsdl.NewChild("UpperBoundedRange") = upper;
00133     }
00134   }
00135 
00136   void ARCJSDLParser::parseBenchmark(XMLNode xmlBenchmark, std::pair<std::string, double>& benchmark) const {
00137     int value;
00138     if (bool(xmlBenchmark["BenchmarkType"]) &&
00139         bool(xmlBenchmark["BenchmarkValue"]) &&
00140         stringto(xmlBenchmark["BenchmarkValue"], value))
00141       benchmark = std::make_pair<std::string, int>((std::string)xmlBenchmark["BenchmarkType"], value);
00142   }
00143 
00144   void ARCJSDLParser::outputBenchmark(const std::pair<std::string, double>& benchmark, XMLNode& arcJSDL) const {
00145     if (!benchmark.first.empty()) {
00146       arcJSDL.NewChild("BenchmarkType") = benchmark.first;
00147       arcJSDL.NewChild("BenchmarkValue") = tostring(benchmark.second);
00148     }
00149   }
00150 
00151   JobDescription ARCJSDLParser::Parse(const std::string& source) const {
00152     JobDescription job;
00153 
00154     xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
00155 
00156     if (ctxt == NULL) {
00157         logger.msg(VERBOSE, "[ARCJSDLParser] Failed to create parser context");
00158     }
00159     xmlSetGenericErrorFunc(NULL, (xmlGenericErrorFunc)XmlErrorHandler);
00160     XMLNode node(source);
00161     xmlSetGenericErrorFunc(NULL, NULL);
00162 
00163     if (!node) {
00164         logger.msg(VERBOSE, "[ARCJSDLParser] Parsing error: %s\n", (xmlGetLastError())->message);
00165     }
00166     else if (ctxt->valid == 0) {
00167         logger.msg(VERBOSE, "[ARCJSDLParser] Validating error");
00168     }
00169 
00170     xmlFreeParserCtxt(ctxt);
00171 
00172     if (node.Size() == 0) {
00173       logger.msg(VERBOSE, "[ARCJSDLParser] Wrong XML structure! ");
00174       return JobDescription();
00175     }
00176 
00177     // The source parsing start now.
00178     XMLNode jobdescription = node["JobDescription"];
00179 
00180     // JobIdentification
00181     XMLNode jobidentification = node["JobDescription"]["JobIdentification"];
00182 
00183     // std::string JobName;
00184     if (bool(jobidentification["JobName"]))
00185       job.Identification.JobName = (std::string)jobidentification["JobName"];
00186 
00187     // std::string Description;
00188     if (bool(jobidentification["Description"]))
00189       job.Identification.Description = (std::string)jobidentification["Description"];
00190 
00191     // std::string JobVOName;
00192     if (bool(jobidentification["JobVOName"]))
00193       job.Identification.JobVOName = (std::string)jobidentification["JobVOName"];
00194 
00195     // ComputingActivityType JobType;
00196     if (!bool(jobidentification["JobType"]) || lower((std::string)jobidentification["JobType"]) == "single")
00197       job.Identification.JobType = SINGLE;
00198     else if (lower((std::string)jobidentification["JobType"]) == "collectionelement")
00199       job.Identification.JobType = COLLECTIONELEMENT;
00200     else if (lower((std::string)jobidentification["JobType"]) == "parallelelement")
00201       job.Identification.JobType = PARALLELELEMENT;
00202     else if (lower((std::string)jobidentification["JobType"]) == "workflownode")
00203       job.Identification.JobType = WORKFLOWNODE;
00204 
00205     // std::list<std::string> UserTag;
00206     for (int i = 0; (bool)(jobidentification["UserTag"][i]); i++)
00207       job.Identification.UserTag.push_back((std::string)jobidentification["UserTag"][i]);
00208 
00209     // std::list<std::string> ActivityOldId;
00210     for (int i = 0; (bool)(jobidentification["ActivityOldId"][i]); i++)
00211       job.Identification.ActivityOldId.push_back((std::string)jobidentification["ActivityOldId"][i]);
00212     // end of JobIdentification
00213 
00214 
00215     // Application
00216     XMLNode xmlApplication = node["JobDescription"]["Application"];
00217 
00218     // Look for extended application element. First look for POSIX and then HPCProfile.
00219     XMLNode xmlXApplication = xmlApplication["POSIXApplication"];
00220     if (!xmlXApplication)
00221       xmlXApplication = xmlApplication["HPCProfileApplication"];
00222     if (!xmlXApplication) {
00223       logger.msg(ERROR, "[ARCJSDLParser] An extended application element (POSIXApplication or HPCProfileApplication) was not found in the job description.");
00224       return JobDescription();
00225     }
00226 
00227 
00228     // ExecutableType Executable;
00229     if (bool(xmlApplication["Executable"]["Path"])) {
00230       job.Application.Executable.Name = (std::string)xmlApplication["Executable"]["Path"];
00231       for (int i = 0; (bool)(xmlApplication["Executable"]["Argument"][i]); i++)
00232         job.Application.Executable.Argument.push_back((std::string)xmlApplication["Executable"]["Argument"]);
00233     }
00234     else if (bool(xmlXApplication["Executable"])) {
00235       job.Application.Executable.Name = (std::string)xmlXApplication["Executable"];
00236       for (int i = 0; (bool)(xmlXApplication["Argument"][i]); i++)
00237         job.Application.Executable.Argument.push_back((std::string)xmlXApplication["Argument"][i]);
00238     }
00239 
00240     // std::string Input;
00241     if (bool(xmlApplication["Input"]))
00242       job.Application.Input = (std::string)xmlApplication["Input"];
00243     else if (bool(xmlXApplication["Input"]))
00244       job.Application.Input = (std::string)xmlXApplication["Input"];
00245 
00246     // std::string Output;
00247     if (bool(xmlApplication["Output"]))
00248       job.Application.Output = (std::string)xmlApplication["Output"];
00249     else if (bool(xmlXApplication["Output"]))
00250       job.Application.Output = (std::string)xmlXApplication["Output"];
00251 
00252     // std::string Error;
00253     if (bool(xmlApplication["Error"]))
00254       job.Application.Error = (std::string)xmlApplication["Error"];
00255     else if (bool(xmlXApplication["Error"]))
00256       job.Application.Error = (std::string)xmlXApplication["Error"];
00257 
00258     // bool Join;
00259     job.Application.Join = (lower((std::string)xmlApplication["Join"]) == "true");
00260 
00261     // std::list< std::pair<std::string, std::string> > Environment;
00262     if (bool(xmlApplication["Environment"]["Name"])) {
00263       for (int i = 0; (bool)(xmlApplication["Environment"][i]); i++) {
00264         if (!((std::string)xmlApplication["Environment"][i]["Name"]).empty() && bool(xmlApplication["Environment"][i]["Value"]))
00265           job.Application.Environment.push_back(std::pair<std::string, std::string>((std::string)xmlApplication["Environment"][i]["Name"],
00266                                                                                     (std::string)xmlApplication["Environment"][i]["Value"]));
00267       }
00268     }
00269     else if (bool(xmlXApplication["Environment"])) {
00270       for (int i = 0; (bool)(xmlXApplication["Environment"][i]); i++) {
00271         XMLNode env = xmlXApplication["Environment"][i];
00272         XMLNode name = env.Attribute("name");
00273         if (!name || ((std::string)name).empty()) {
00274           logger.msg(VERBOSE, "[ARCJSDLParser] Error during the parsing: missed the name attributes of the \"%s\" Environment", (std::string)env);
00275           return JobDescription();
00276         }
00277         job.Application.Environment.push_back(std::pair<std::string, std::string>(name, env));
00278       }
00279     }
00280 
00281     // ExecutableType Prologue;
00282     if (bool(xmlApplication["Prologue"]["Path"]))
00283       job.Application.Prologue.Name = (std::string)xmlApplication["Prologue"]["Path"];
00284     for (int i = 0; (bool)(xmlApplication["Prologue"]["Argument"][i]); i++)
00285       job.Application.Prologue.Argument.push_back((std::string)xmlApplication["Prologue"]["Argument"][i]);
00286 
00287     // ExecutableType Epilogue;
00288     if (bool(xmlApplication["Epilogue"]["Path"]))
00289       job.Application.Epilogue.Name = (std::string)xmlApplication["Epilogue"]["Path"];
00290     for (int i = 0; (bool)(xmlApplication["Epilogue"]["Argument"][i]); i++)
00291       job.Application.Epilogue.Argument.push_back((std::string)xmlApplication["Epilogue"]["Argument"][i]);
00292 
00293     // std::string LogDir;
00294     if (bool(xmlApplication["LogDir"]))
00295       job.Application.LogDir = (std::string)xmlApplication["LogDir"];
00296 
00297     // std::list<URL> RemoteLogging;
00298     for (int i = 0; (bool)(xmlApplication["RemoteLogging"][i]); i++) {
00299       URL url((std::string)xmlApplication["RemoteLogging"][i]);
00300       if (!url) {
00301         logger.msg(VERBOSE, "[ARCJSDLParser] RemoteLogging URL is wrongly formatted.");
00302         return JobDescription();
00303       }
00304       job.Application.RemoteLogging.push_back(url);
00305     }
00306 
00307     // int Rerun;
00308     if (bool(xmlApplication["Rerun"]))
00309       job.Application.Rerun = stringtoi((std::string)xmlApplication["Rerun"]);
00310 
00311     // Time ExpiryTime;
00312     if (bool(xmlApplication["ExpiryTime"]))
00313       job.Application.ExpiryTime = Time((std::string)xmlApplication["ExpiryTime"]);
00314 
00315     // Time ProcessingStartTime;
00316     if (bool(xmlApplication["ProcessingStartTime"]))
00317       job.Application.ProcessingStartTime = Time((std::string)xmlApplication["ProcessingStartTime"]);
00318 
00319     // XMLNode Notification;
00320     for (int i = 0; bool(jobdescription["Notification"][i]); i++) {
00321       XMLNode n = jobdescription["Notification"][i];
00322       // Accepting only supported notification types
00323       if(((bool)n["Type"]) && (n["Type"] != "Email")) continue;
00324       NotificationType notification;
00325       notification.Email = (std::string)n["Endpoint"];
00326       for (int j = 0; bool(n["State"][j]); j++) {
00327         notification.States.push_back((std::string)n["State"][j]);
00328       }
00329       job.Application.Notification.push_back(notification);
00330     }
00331 
00332     // std::list<URL> CredentialService;
00333     for (int i = 0; (bool)(xmlApplication["CredentialService"][i]); i++)
00334       job.Application.CredentialService.push_back(URL((std::string)xmlApplication["CredentialService"][i]));
00335 
00336     // XMLNode AccessControl;
00337     if (bool(xmlApplication["AccessControl"]))
00338       xmlApplication["AccessControl"][0].New(job.Application.AccessControl);
00339 
00340     // End of Application
00341 
00342     // Resources
00343     XMLNode resource = node["JobDescription"]["Resources"];
00344 
00345     // SoftwareRequirement OperatingSystem;
00346     if (bool(resource["OperatingSystem"])) {
00347       if (!parseSoftware(resource["OperatingSystem"], job.Resources.OperatingSystem))
00348         return JobDescription();
00349       if (!resource["OperatingSystem"]["Software"] &&
00350           resource["OperatingSystem"]["OperatingSystemType"]["OperatingSystemName"] &&
00351           resource["OperatingSystem"]["OperatingSystemVersion"])
00352         job.Resources.OperatingSystem = Software((std::string)resource["OperatingSystem"]["OperatingSystemType"]["OperatingSystemName"],
00353                                                  (std::string)resource["OperatingSystem"]["OperatingSystemVersion"]);
00354     }
00355 
00356     // std::string Platform;
00357     if (bool(resource["Platform"]))
00358       job.Resources.Platform = (std::string)resource["Platform"];
00359     else if (bool(resource["CPUArchitecture"]["CPUArchitectureName"]))
00360       job.Resources.Platform = (std::string)resource["CPUArchitecture"]["CPUArchitectureName"];
00361 
00362     // std::string NetworkInfo;
00363     if (bool(resource["NetworkInfo"]))
00364       job.Resources.NetworkInfo = (std::string)resource["NetworkInfo"];
00365     else if (bool(resource["IndividualNetworkBandwidth"])) {
00366       Range<long long> bits_per_sec;
00367       parseRange<long long>(resource["IndividualNetworkBandwidth"], bits_per_sec, -1);
00368       const long long network = 1024 * 1024;
00369       if (bits_per_sec < 100 * network)
00370         job.Resources.NetworkInfo = "100megabitethernet";
00371       else if (bits_per_sec < 1024 * network)
00372         job.Resources.NetworkInfo = "gigabitethernet";
00373       else if (bits_per_sec < 10 * 1024 * network)
00374         job.Resources.NetworkInfo = "myrinet";
00375       else
00376         job.Resources.NetworkInfo = "infiniband";
00377     }
00378 
00379     // Range<int64_t> IndividualPhysicalMemory;
00380     // If the consolidated element exist parse it, else try to parse the POSIX one.
00381     if (bool(resource["IndividualPhysicalMemory"]))
00382       parseRange<int64_t>(resource["IndividualPhysicalMemory"], job.Resources.IndividualPhysicalMemory, -1);
00383     else if (bool(xmlXApplication["MemoryLimit"])) {
00384       if (!stringto<int64_t>((std::string)xmlXApplication["MemoryLimit"], job.Resources.IndividualPhysicalMemory.max))
00385         job.Resources.IndividualPhysicalMemory = Range<int64_t>(-1);
00386     }
00387 
00388     // Range<int64_t> IndividualVirtualMemory;
00389     // If the consolidated element exist parse it, else try to parse the POSIX one.
00390     if (bool(resource["IndividualVirtualMemory"])) {
00391       parseRange<int64_t>(resource["IndividualVirtualMemory"], job.Resources.IndividualVirtualMemory, -1);
00392     }
00393     else if (bool(xmlXApplication["VirtualMemoryLimit"])) {
00394       if (!stringto<int64_t>((std::string)xmlXApplication["VirtualMemoryLimit"], job.Resources.IndividualVirtualMemory.max))
00395         job.Resources.IndividualVirtualMemory = Range<int64_t>(-1);
00396     }
00397 
00398     // Range<int> IndividualCPUTime;
00399     if (bool(resource["IndividualCPUTime"]["Value"])) {
00400       parseRange<int>(resource["IndividualCPUTime"]["Value"], job.Resources.IndividualCPUTime.range, -1);
00401       parseBenchmark(resource["IndividualCPUTime"], job.Resources.IndividualCPUTime.benchmark);
00402     }
00403     else if (bool(resource["IndividualCPUTime"])) // JSDL compliance...
00404       parseRange<int>(resource["IndividualCPUTime"], job.Resources.IndividualCPUTime.range, -1);
00405 
00406     // Range<int> TotalCPUTime;
00407     // If the consolidated element exist parse it, else try to parse the POSIX one.
00408     if (bool(resource["TotalCPUTime"]["Value"])) {
00409       parseRange<int>(resource["TotalCPUTime"]["Value"], job.Resources.TotalCPUTime.range, -1);
00410       parseBenchmark(resource["TotalCPUTime"], job.Resources.TotalCPUTime.benchmark);
00411     }
00412     else if (bool(resource["TotalCPUTime"])) // JSDL compliance...
00413       parseRange<int>(resource["TotalCPUTime"], job.Resources.TotalCPUTime.range, -1);
00414     else if (bool(xmlXApplication["CPUTimeLimit"])) { // POSIX compliance...
00415       if (!stringto<int>((std::string)xmlXApplication["CPUTimeLimit"], job.Resources.TotalCPUTime.range.max))
00416         job.Resources.TotalCPUTime.range = Range<int>(-1);
00417     }
00418 
00419     // Range<int> IndividualWallTime;
00420     if (bool(resource["IndividualWallTime"]["Value"])) {
00421       parseRange<int>(resource["IndividualWallTime"]["Value"], job.Resources.IndividualWallTime.range, -1);
00422       parseBenchmark(resource["IndividualCPUTime"], job.Resources.IndividualWallTime.benchmark);
00423     }
00424 
00425     // Range<int> TotalWallTime;
00426     // If the consolidated element exist parse it, else try to parse the POSIX one.
00427     if (bool(resource["TotalWallTime"]["Value"])) {
00428       parseRange<int>(resource["TotalWallTime"]["Value"], job.Resources.TotalWallTime.range, -1);
00429       parseBenchmark(resource["TotalWallTime"], job.Resources.TotalWallTime.benchmark);
00430     }
00431     else if (bool(xmlXApplication["WallTimeLimit"])) {
00432       if (!stringto<int>((std::string)xmlXApplication["WallTimeLimit"], job.Resources.TotalWallTime.range.max))
00433         job.Resources.TotalWallTime.range = Range<int>(-1);
00434     }
00435 
00436     // Range<int64_t> DiskSpace;
00437     // If the consolidated element exist parse it, else try to parse the JSDL one.
00438     if (bool(resource["DiskSpaceRequirement"]["DiskSpace"]))
00439       parseRange<int64_t>(resource["DiskSpaceRequirement"]["DiskSpace"], job.Resources.DiskSpaceRequirement.DiskSpace, -1);
00440     else if (bool(resource["FileSystem"]["DiskSpace"]))
00441       parseRange<int64_t>(resource["FileSystem"]["DiskSpace"], job.Resources.DiskSpaceRequirement.DiskSpace, -1);
00442 
00443     // int64_t CacheDiskSpace;
00444     if (bool(resource["DiskSpaceRequirement"]["CacheDiskSpace"])) {
00445       if (!stringto<int64_t>((std::string)resource["DiskSpaceRequirement"]["CacheDiskSpace"], job.Resources.DiskSpaceRequirement.CacheDiskSpace))
00446          job.Resources.DiskSpaceRequirement.CacheDiskSpace = -1;
00447     }
00448 
00449     // int64_t SessionDiskSpace;
00450     if (bool(resource["DiskSpaceRequirement"]["SessionDiskSpace"])) {
00451       if (!stringto<int64_t>((std::string)resource["DiskSpaceRequirement"]["SessionDiskSpace"], job.Resources.DiskSpaceRequirement.SessionDiskSpace))
00452         job.Resources.DiskSpaceRequirement.SessionDiskSpace = -1;
00453     }
00454 
00455     // Period SessionLifeTime;
00456     if (bool(resource["SessionLifeTime"]))
00457       job.Resources.SessionLifeTime = Period((std::string)resource["SessionLifeTime"]);
00458 
00459     // SoftwareRequirement CEType;
00460     if (bool(resource["CEType"]))
00461       if (!parseSoftware(resource["CEType"], job.Resources.CEType))
00462         return JobDescription();
00463 
00464     // NodeAccessType NodeAccess;
00465     if (lower((std::string)resource["NodeAccess"]) == "inbound")
00466       job.Resources.NodeAccess = NAT_INBOUND;
00467     else if (lower((std::string)resource["NodeAccess"]) == "outbound")
00468       job.Resources.NodeAccess = NAT_OUTBOUND;
00469     else if (lower((std::string)resource["NodeAccess"]) == "inoutbound")
00470       job.Resources.NodeAccess = NAT_INOUTBOUND;
00471 
00472     // ResourceSlotType Slots;
00473     if (bool(resource["SlotRequirement"]["NumberOfSlots"]))
00474       parseRange<int>(resource["SlotRequirement"]["NumberOfSlots"], job.Resources.SlotRequirement.NumberOfSlots, -1);
00475     else if (bool(xmlXApplication["ProcessCountLimit"])) {
00476       if (!stringto<int>((std::string)xmlXApplication["ProcessCountLimit"], job.Resources.SlotRequirement.NumberOfSlots.max))
00477         job.Resources.SlotRequirement.NumberOfSlots = Range<int>(-1);
00478     }
00479     if (bool(resource["SlotRequirement"]["ThreadsPerProcesses"]))
00480       parseRange<int>(resource["SlotRequirement"]["ThreadsPerProcesses"], job.Resources.SlotRequirement.ThreadsPerProcesses, -1);
00481     else if (bool(xmlXApplication["ThreadCountLimit"])) {
00482       if (!stringto<int>((std::string)xmlXApplication["ThreadCountLimit"], job.Resources.SlotRequirement.ThreadsPerProcesses.max))
00483         job.Resources.SlotRequirement.ThreadsPerProcesses = Range<int>(-1);
00484     }
00485     if (bool(resource["SlotRequirement"]["ProcessPerHost"]))
00486       parseRange<int>(resource["SlotRequirement"]["ProcessPerHost"], job.Resources.SlotRequirement.ProcessPerHost, -1);
00487     else if (bool(resource["TotalCPUCount"]))
00488       parseRange<int>(resource["TotalCPUCount"], job.Resources.SlotRequirement.ProcessPerHost, -1);
00489 
00490     // std::string SPMDVariation;
00491     if (bool(resource["SlotRequirement"]["SPMDVariation"]))
00492       job.Resources.SlotRequirement.SPMDVariation = (std::string)resource["Slots"]["SPMDVariation"];
00493 
00494 
00495     // std::list<ResourceTargetType> CandidateTarget;
00496     if (bool(resource["CandidateTarget"])) {
00497       for (int i = 0; (bool)(resource["CandidateTarget"][i]); i++)
00498         if (bool(resource["CandidateTarget"][i]["HostName"]) || bool(resource["CandidateTarget"][i]["QueueName"])) {
00499           ResourceTargetType candidateTarget;
00500           candidateTarget.EndPointURL = URL((std::string)resource["CandidateTarget"][i]["HostName"]);
00501           candidateTarget.QueueName = (std::string)resource["CandidateTarget"][i]["QueueName"];
00502           job.Resources.CandidateTarget.push_back(candidateTarget);
00503       }
00504     }
00505     else if (bool(resource["CandidateHosts"]))
00506       for (int i = 0; (bool)(resource["CandidateHosts"]["HostName"][i]); i++) {
00507         ResourceTargetType candidateTarget;
00508         candidateTarget.EndPointURL = URL((std::string)resource["CandidateHosts"]["HostName"][i]);
00509         job.Resources.CandidateTarget.push_back(candidateTarget);
00510       }
00511 
00512     // SoftwareRequirement RunTimeEnvironment;
00513     if (bool(resource["RunTimeEnvironment"])) {
00514       if (bool(resource["RunTimeEnvironment"].Attribute("require")))
00515         job.Resources.RunTimeEnvironment.setRequirement(lower((std::string)resource["RunTimeEnvironment"].Attribute("require")) == "all");
00516       if (!parseSoftware(resource["RunTimeEnvironment"], job.Resources.RunTimeEnvironment))
00517         return JobDescription();
00518     }
00519     // end of Resources
00520 
00521     // Datastaging
00522     XMLNode datastaging = node["JobDescription"]["DataStaging"];
00523 
00524     for (int i = 0; datastaging[i]; i++) {
00525       XMLNode ds = datastaging[i];
00526       XMLNode source = ds["Source"];
00527       XMLNode source_uri = source["URI"];
00528       XMLNode target = ds["Target"];
00529       XMLNode target_uri = target["URI"];
00530       XMLNode filenameNode = ds["FileName"];
00531 
00532       if (filenameNode) {
00533         FileType file;
00534         file.Name = (std::string)filenameNode;
00535         if (bool(source)) {
00536           DataSourceType source;
00537           if (bool(source_uri))
00538             source.URI = (std::string)source_uri;
00539           else
00540             source.URI = file.Name;
00541           source.Threads = -1;
00542           file.Source.push_back(source);
00543         }
00544         if (bool(target)) {
00545           DataTargetType target;
00546           if (bool(target_uri)) {
00547             target.URI = (std::string)target_uri;
00548           }
00549           target.Threads = -1;
00550           file.Target.push_back(target);
00551         }
00552 
00553         // If DeteleOnTermination is not set do not keep data. Only keep data if explicitly specified.
00554         file.KeepData = ds["DeleteOnTermination"] && lower(((std::string)ds["DeleteOnTermination"])) == "false";
00555         file.IsExecutable = ds["IsExecutable"] && lower(((std::string)ds["IsExecutable"])) == "true";
00556         // Default is to put file in cache. DownloadToCache does not make sense for output files.
00557         file.DownloadToCache = !file.Source.empty() && (!ds["DownloadToCache"] || lower(((std::string)ds["DownloadToCache"])) != "false");
00558         job.DataStaging.File.push_back(file);
00559       }
00560     }
00561     // end of Datastaging
00562 
00563     return job;
00564   }
00565 
00566   std::string ARCJSDLParser::UnParse(const JobDescription& job) const {
00567     XMLNode jobdefinition(NS("", "http://schemas.ggf.org/jsdl/2005/11/jsdl"), "JobDefinition");
00568 
00569     XMLNode jobdescription = jobdefinition.NewChild("JobDescription");
00570 
00571     // JobIdentification
00572 
00573     // std::string JobName;
00574     XMLNode xmlIdentification("<JobIdentification/>");
00575     if (!job.Identification.JobName.empty())
00576       xmlIdentification.NewChild("JobName") = job.Identification.JobName;
00577 
00578     // std::string Description;
00579     if (!job.Identification.Description.empty())
00580       xmlIdentification.NewChild("Description") = job.Identification.Description;
00581 
00582     // std::string JobVOName;
00583     if (!job.Identification.JobVOName.empty())
00584       xmlIdentification.NewChild("JobVOName") = job.Identification.JobVOName;
00585 
00586     // ComputingActivityType JobType;
00587     switch (job.Identification.JobType) {
00588     case COLLECTIONELEMENT:
00589       xmlIdentification.NewChild("JobType") = "collectionelement";
00590       break;
00591     case PARALLELELEMENT:
00592       xmlIdentification.NewChild("JobType") = "parallelelement";
00593       break;
00594     case WORKFLOWNODE:
00595       xmlIdentification.NewChild("JobType") = "workflownode";
00596       break;
00597     default:
00598       xmlIdentification.NewChild("JobType") = "single";
00599       break;
00600     }
00601 
00602     // std::list<std::string> UserTag;
00603     for (std::list<std::string>::const_iterator it = job.Identification.UserTag.begin();
00604          it != job.Identification.UserTag.end(); it++)
00605       xmlIdentification.NewChild("UserTag") = *it;
00606 
00607     // std::list<std::string> ActivityOldId;
00608     for (std::list<std::string>::const_iterator it = job.Identification.ActivityOldId.begin();
00609          it != job.Identification.ActivityOldId.end(); it++)
00610       xmlIdentification.NewChild("ActivityOldId") = *it;
00611 
00612     if (xmlIdentification.Size() > 0)
00613       jobdescription.NewChild(xmlIdentification);
00614     // end of JobIdentification
00615 
00616     // Application
00617     XMLNode xmlApplication("<Application/>");
00618     XMLNode xmlPApplication(NS("posix-jsdl", "http://schemas.ggf.org/jsdl/2005/11/jsdl-posix"), "posix-jsdl:POSIXApplication");
00619     XMLNode xmlHApplication(NS("hpcp-jsdl", "http://schemas.ggf.org/jsdl/2006/07/jsdl-hpcpa"), "hpcp-jsdl:HPCProfileApplication");
00620 
00621     // ExecutableType Executable;
00622     if (!job.Application.Executable.Name.empty()) {
00623       xmlPApplication.NewChild("posix-jsdl:Executable") = job.Application.Executable.Name;
00624       xmlHApplication.NewChild("hpcp-jsdl:Executable") = job.Application.Executable.Name;
00625       for (std::list<std::string>::const_iterator it = job.Application.Executable.Argument.begin();
00626            it != job.Application.Executable.Argument.end(); it++) {
00627         xmlPApplication.NewChild("posix-jsdl:Argument") = *it;
00628         xmlHApplication.NewChild("hpcp-jsdl:Argument") = *it;
00629       }
00630     }
00631 
00632     // std::string Input;
00633     if (!job.Application.Input.empty()) {
00634       xmlPApplication.NewChild("posix-jsdl:Input") = job.Application.Input;
00635       xmlHApplication.NewChild("hpcp-jsdl:Input") = job.Application.Input;
00636     }
00637 
00638     // std::string Output;
00639     if (!job.Application.Output.empty()) {
00640       xmlPApplication.NewChild("posix-jsdl:Output") = job.Application.Output;
00641       xmlHApplication.NewChild("hpcp-jsdl:Output") = job.Application.Output;
00642     }
00643 
00644     // std::string Error;
00645     if (!job.Application.Error.empty()) {
00646       xmlPApplication.NewChild("posix-jsdl:Error") = job.Application.Error;
00647       xmlHApplication.NewChild("hpcp-jsdl:Error") = job.Application.Error;
00648     }
00649 
00650     // bool Join;
00651     if (job.Application.Join)
00652       xmlApplication.NewChild("Join") = "true";
00653 
00654     // std::list< std::pair<std::string, std::string> > Environment;
00655     for (std::list< std::pair<std::string, std::string> >::const_iterator it = job.Application.Environment.begin();
00656          it != job.Application.Environment.end(); it++) {
00657       XMLNode pEnvironment = xmlPApplication.NewChild("posix-jsdl:Environment");
00658       XMLNode hEnvironment = xmlHApplication.NewChild("hpcp-jsdl:Environment");
00659       pEnvironment.NewAttribute("name") = it->first;
00660       pEnvironment = it->second;
00661       hEnvironment.NewAttribute("name") = it->first;
00662       hEnvironment = it->second;
00663     }
00664 
00665     // ExecutableType Prologue;
00666     if (!job.Application.Prologue.Name.empty()) {
00667       xmlApplication.NewChild("Prologue");
00668       xmlApplication["Prologue"].NewChild("Path") = job.Application.Prologue.Name;
00669       for (std::list<std::string>::const_iterator it = job.Application.Prologue.Argument.begin();
00670            it != job.Application.Prologue.Argument.end(); it++)
00671         xmlApplication["Prologue"].NewChild("Argument") = *it;
00672     }
00673 
00674     // ExecutableType Epilogue;
00675     if (!job.Application.Epilogue.Name.empty()) {
00676       xmlApplication.NewChild("Epilogue");
00677       xmlApplication["Epilogue"].NewChild("Path") = job.Application.Epilogue.Name;
00678       for (std::list<std::string>::const_iterator it = job.Application.Epilogue.Argument.begin();
00679            it != job.Application.Epilogue.Argument.end(); it++)
00680         xmlApplication["Epilogue"].NewChild("Argument") = *it;
00681     }
00682 
00683     // std::string LogDir;
00684     if (!job.Application.LogDir.empty())
00685       xmlApplication.NewChild("LogDir") = job.Application.LogDir;
00686 
00687     // std::list<URL> RemoteLogging;
00688     for (std::list<URL>::const_iterator it = job.Application.RemoteLogging.begin();
00689          it != job.Application.RemoteLogging.end(); it++)
00690       xmlApplication.NewChild("RemoteLogging") = it->str();
00691 
00692     // int Rerun;
00693     if (job.Application.Rerun > -1)
00694       xmlApplication.NewChild("Rerun") = tostring(job.Application.Rerun);
00695 
00696     // Time ExpiryTime;
00697     if (job.Application.ExpiryTime > -1)
00698       xmlApplication.NewChild("ExpiryTime") = job.Application.ExpiryTime.str();
00699 
00700 
00701     // Time ProcessingStartTime;
00702     if (job.Application.ProcessingStartTime > -1)
00703       xmlApplication.NewChild("ProcessingStartTime") = job.Application.ProcessingStartTime.str();
00704 
00705     // XMLNode Notification;
00706     for (std::list<NotificationType>::const_iterator it = job.Application.Notification.begin();
00707          it != job.Application.Notification.end(); it++) {
00708       XMLNode n = xmlApplication.NewChild("Notification");
00709       n.NewChild("Type") = "Email";
00710       n.NewChild("Endpoint") = it->Email;
00711       for (std::list<std::string>::const_iterator s = it->States.begin();
00712                   s != it->States.end(); s++) {
00713         n.NewChild("State") = *s;
00714       }
00715     }
00716 
00717     // XMLNode AccessControl;
00718     if (bool(job.Application.AccessControl))
00719       xmlApplication.NewChild("AccessControl").NewChild(job.Application.AccessControl);
00720 
00721     // std::list<URL> CredentialService;
00722     for (std::list<URL>::const_iterator it = job.Application.CredentialService.begin();
00723          it != job.Application.CredentialService.end(); it++)
00724       xmlApplication.NewChild("CredentialService") = it->fullstr();
00725 
00726     // POSIX compliance...
00727     if (job.Resources.TotalWallTime.range.max != -1)
00728       xmlPApplication.NewChild("posix-jsdl:WallTimeLimit") = tostring(job.Resources.TotalWallTime.range.max);
00729     if (job.Resources.IndividualPhysicalMemory.max != -1)
00730       xmlPApplication.NewChild("posix-jsdl:MemoryLimit") = tostring(job.Resources.IndividualPhysicalMemory.max);
00731     if (job.Resources.TotalCPUTime.range.max != -1)
00732       xmlPApplication.NewChild("posix-jsdl:CPUTimeLimit") = tostring(job.Resources.TotalCPUTime.range.max);
00733     if (job.Resources.SlotRequirement.NumberOfSlots.max != -1)
00734       xmlPApplication.NewChild("posix-jsdl:ProcessCountLimit") = tostring(job.Resources.SlotRequirement.NumberOfSlots.max);
00735     if (job.Resources.IndividualVirtualMemory.max != -1)
00736       xmlPApplication.NewChild("posix-jsdl:VirtualMemoryLimit") = tostring(job.Resources.IndividualVirtualMemory.max);
00737     if (job.Resources.SlotRequirement.ThreadsPerProcesses.max != -1)
00738       xmlPApplication.NewChild("posix-jsdl:ThreadCountLimit") = tostring(job.Resources.SlotRequirement.ThreadsPerProcesses.max);
00739 
00740     if (xmlPApplication.Size() > 0)
00741       xmlApplication.NewChild(xmlPApplication);
00742     if (xmlHApplication.Size() > 0)
00743       xmlApplication.NewChild(xmlHApplication);
00744     if (xmlApplication.Size() > 0)
00745       jobdescription.NewChild(xmlApplication);
00746     // end of Application
00747 
00748     // Resources
00749     XMLNode xmlResources("<Resources/>");
00750 
00751     // SoftwareRequirement OperatingSystem
00752     if (!job.Resources.OperatingSystem.empty()) {
00753       XMLNode xmlOS = xmlResources.NewChild("OperatingSystem");
00754 
00755       outputSoftware(job.Resources.OperatingSystem, xmlOS);
00756 
00757       // JSDL compliance. Only the first element in the OperatingSystem object is printed.
00758       xmlOS.NewChild("jsdl:OperatingSystemType").NewChild("OperatingSystemName") = job.Resources.OperatingSystem.getSoftwareList().front().getName();
00759       if (!job.Resources.OperatingSystem.getSoftwareList().front().getVersion().empty())
00760         xmlOS.NewChild("jsdl:OperatingSystemVersion") = job.Resources.OperatingSystem.getSoftwareList().front().getVersion();
00761     }
00762 
00763     // std::string Platform;
00764     if (!job.Resources.Platform.empty()) {
00765       xmlResources.NewChild("Platform") = job.Resources.Platform;
00766       // JSDL compliance
00767       xmlResources.NewChild("CPUArchitecture").NewChild("CPUArchitectureName") = job.Resources.Platform;
00768     }
00769 
00770     // std::string NetworkInfo;
00771     if (!job.Resources.NetworkInfo.empty()) {
00772       xmlResources.NewChild("NetworkInfo") = job.Resources.NetworkInfo;
00773 
00774       std::string value = "";
00775       if (job.Resources.NetworkInfo == "100megabitethernet")
00776         value = "104857600.0";
00777       else if (job.Resources.NetworkInfo == "gigabitethernet")
00778         value = "1073741824.0";
00779       else if (job.Resources.NetworkInfo == "myrinet")
00780         value = "2147483648.0";
00781       else if (job.Resources.NetworkInfo == "infiniband")
00782         value = "10737418240.0";
00783 
00784       if (value != "")
00785         xmlResources.NewChild("IndividualNetworkBandwidth").NewChild("LowerBoundedRange") = value;
00786     }
00787 
00788     // NodeAccessType NodeAccess;
00789     switch (job.Resources.NodeAccess) {
00790     case NAT_INBOUND:
00791       xmlResources.NewChild("NodeAccess") = "inbound";
00792       break;
00793     case NAT_OUTBOUND:
00794       xmlResources.NewChild("NodeAccess") = "outbound";
00795       break;
00796     case NAT_INOUTBOUND:
00797       xmlResources.NewChild("NodeAccess") = "inoutbound";
00798       break;
00799     }
00800 
00801     // Range<int64_t> IndividualPhysicalMemory;
00802     {
00803       XMLNode xmlIPM("<IndividualPhysicalMemory/>");
00804       outputARCJSDLRange(job.Resources.IndividualPhysicalMemory, xmlIPM, (int64_t)-1);
00805       // JSDL compliance...
00806       outputJSDLRange(job.Resources.IndividualPhysicalMemory, xmlIPM, (int64_t)-1);
00807       if (xmlIPM.Size() > 0)
00808         xmlResources.NewChild(xmlIPM);
00809     }
00810 
00811     // Range<int64_t> IndividualVirtualMemory;
00812     {
00813       XMLNode xmlIVM("<IndividualVirtualMemory/>");
00814       outputARCJSDLRange(job.Resources.IndividualVirtualMemory, xmlIVM, (int64_t)-1);
00815       outputJSDLRange(job.Resources.IndividualVirtualMemory, xmlIVM, (int64_t)-1);
00816       if (xmlIVM.Size() > 0)
00817         xmlResources.NewChild(xmlIVM);
00818     }
00819 
00820     {
00821       // Range<int64_t> DiskSpace;
00822       XMLNode xmlDiskSpace("<DiskSpace/>");
00823       outputARCJSDLRange(job.Resources.DiskSpaceRequirement.DiskSpace, xmlDiskSpace, (int64_t)-1);
00824 
00825       if (xmlDiskSpace.Size() > 0) {
00826         xmlResources.NewChild("DiskSpaceRequirement").NewChild(xmlDiskSpace);
00827 
00828         // int64_t CacheDiskSpace;
00829         if (job.Resources.DiskSpaceRequirement.CacheDiskSpace != -1)
00830           xmlResources["DiskSpaceRequirement"].NewChild("CacheDiskSpace") = tostring(job.Resources.DiskSpaceRequirement.CacheDiskSpace);
00831 
00832         // int64_t SessionDiskSpace;
00833         if (job.Resources.DiskSpaceRequirement.SessionDiskSpace != -1)
00834           xmlResources["DiskSpaceRequirement"].NewChild("SessionDiskSpace") = tostring(job.Resources.DiskSpaceRequirement.SessionDiskSpace);
00835       }
00836     }
00837 
00838     {
00839       // JSDL Compliance...
00840       XMLNode xmlDiskSpace("<FileSystem/>");
00841       outputJSDLRange(job.Resources.DiskSpaceRequirement.DiskSpace, xmlDiskSpace, (int64_t)-1);
00842       if (xmlDiskSpace.Size() > 0)
00843         xmlResources.NewChild("FileSystem").NewChild(xmlDiskSpace);
00844     }
00845 
00846     // Period SessionLifeTime;
00847     if (job.Resources.SessionLifeTime > -1)
00848       xmlResources.NewChild("SessionLifeTime") = tostring(job.Resources.SessionLifeTime);
00849 
00850     // ScalableTime<int> IndividualCPUTime;
00851     {
00852       XMLNode xmlICPUT("<IndividualCPUTime><Value/></IndividualCPUTime>");
00853       XMLNode xmlValue = xmlICPUT["Value"];
00854       outputARCJSDLRange(job.Resources.IndividualCPUTime.range, xmlValue, -1);
00855       if (xmlICPUT["Value"].Size() > 0) {
00856         outputBenchmark(job.Resources.IndividualCPUTime.benchmark, xmlICPUT);
00857         xmlResources.NewChild(xmlICPUT);
00858 
00859         // JSDL compliance...
00860         outputJSDLRange(job.Resources.IndividualCPUTime.range, xmlICPUT, -1);
00861       }
00862     }
00863 
00864     // ScalableTime<int> TotalCPUTime;
00865     {
00866       XMLNode xmlTCPUT("<TotalCPUTime><Value/></TotalCPUTime>");
00867       XMLNode xmlValue = xmlTCPUT["Value"];
00868       outputARCJSDLRange(job.Resources.TotalCPUTime.range, xmlValue, -1);
00869       if (xmlTCPUT["Value"].Size() > 0) {
00870         outputBenchmark(job.Resources.TotalCPUTime.benchmark, xmlTCPUT);
00871         xmlResources.NewChild(xmlTCPUT);
00872 
00873         // JSDL compliance...
00874         outputJSDLRange(job.Resources.TotalCPUTime.range, xmlTCPUT, -1);
00875       }
00876     }
00877 
00878     // ScalableTime<int> IndividualWallTime;
00879     {
00880      XMLNode xmlIWT("<IndividualWallTime><Value/></IndividualWallTime>");
00881       XMLNode xmlValue = xmlIWT["Value"];
00882       outputARCJSDLRange(job.Resources.IndividualWallTime.range, xmlValue, -1);
00883       if (xmlIWT["Value"].Size() > 0) {
00884         outputBenchmark(job.Resources.IndividualWallTime.benchmark, xmlIWT);
00885         xmlResources.NewChild(xmlIWT);
00886       }
00887     }
00888 
00889     // ScalableTime<int> TotalWallTime;
00890     {
00891      XMLNode xmlTWT("<TotalWallTime><Value/></TotalWallTime>");
00892       XMLNode xmlValue = xmlTWT["Value"];
00893       outputARCJSDLRange(job.Resources.TotalWallTime.range, xmlValue, -1);
00894       if (xmlTWT["Value"].Size() > 0) {
00895         outputBenchmark(job.Resources.TotalWallTime.benchmark, xmlTWT);
00896         xmlResources.NewChild(xmlTWT);
00897       }
00898     }
00899 
00900     // SoftwareRequirement CEType;
00901     if (!job.Resources.CEType.empty()) {
00902       XMLNode xmlCEType = xmlResources.NewChild("CEType");
00903       outputSoftware(job.Resources.CEType, xmlCEType);
00904     }
00905 
00906     // ResourceSlotType Slots;
00907     {
00908       XMLNode xmlSlotRequirement("<SlotRequirement/>");
00909 
00910       // Range<int> NumberOfProcesses;
00911       XMLNode xmlNOP("<NumberOfProcesses/>");
00912       outputARCJSDLRange(job.Resources.SlotRequirement.NumberOfSlots, xmlNOP, -1);
00913       if (xmlNOP.Size() > 0)
00914         xmlSlotRequirement.NewChild(xmlNOP);
00915 
00916       // Range<int> ProcessPerHost;
00917       XMLNode xmlPPH("<ProcessPerHost/>");
00918       outputARCJSDLRange(job.Resources.SlotRequirement.ProcessPerHost, xmlPPH, -1);
00919       if (xmlPPH.Size() > 0) {
00920         xmlSlotRequirement.NewChild(xmlPPH);
00921         XMLNode xmlTCC("<TotalCPUCount/>");
00922         outputJSDLRange(job.Resources.SlotRequirement.ProcessPerHost, xmlTCC, -1);
00923         xmlResources.NewChild(xmlTCC);
00924       }
00925 
00926       // Range<int> ThreadsPerProcesses;
00927       XMLNode xmlTPP("<ThreadsPerProcesses/>");
00928       outputARCJSDLRange(job.Resources.SlotRequirement.ThreadsPerProcesses, xmlTPP, -1);
00929       if (xmlTPP.Size() > 0)
00930         xmlSlotRequirement.NewChild(xmlTPP);
00931 
00932       // std::string SPMDVariation;
00933       if (!job.Resources.SlotRequirement.SPMDVariation.empty())
00934         xmlSlotRequirement.NewChild("SPMDVariation") = job.Resources.SlotRequirement.SPMDVariation;
00935 
00936       if (xmlSlotRequirement.Size() > 0)
00937         xmlResources.NewChild(xmlSlotRequirement);
00938     }
00939 
00940     // std::list<ResourceTargetType> CandidateTarget;
00941     for (std::list<ResourceTargetType>::const_iterator it = job.Resources.CandidateTarget.begin();
00942          it != job.Resources.CandidateTarget.end(); it++) {
00943       XMLNode xmlCandidateTarget = xmlResources.NewChild("CandidateTarget");
00944       if (it->EndPointURL)
00945         xmlCandidateTarget.NewChild("HostName") = it->EndPointURL.str();
00946       if (!it->QueueName.empty())
00947         xmlCandidateTarget.NewChild("QueueName") = it->QueueName;
00948       if (xmlCandidateTarget.Size() > 0)
00949         xmlResources.NewChild(xmlCandidateTarget);
00950     }
00951 
00952     // SoftwareRequirement RunTimeEnvironment;
00953     if (!job.Resources.RunTimeEnvironment.empty()) {
00954       XMLNode xmlRTE = xmlResources.NewChild("RunTimeEnvironment");
00955       outputSoftware(job.Resources.RunTimeEnvironment, xmlRTE);
00956     }
00957 
00958     if (xmlResources.Size() > 0)
00959       jobdescription.NewChild(xmlResources);
00960 
00961     // end of Resources
00962 
00963     // DataStaging
00964     for (std::list<FileType>::const_iterator it = job.DataStaging.File.begin();
00965          it != job.DataStaging.File.end(); it++) {
00966       XMLNode datastaging = jobdescription.NewChild("DataStaging");
00967       if (!it->Name.empty())
00968         datastaging.NewChild("FileName") = it->Name;
00969       if (it->Source.size() != 0 &&
00970           it->Source.begin()->URI &&
00971           trim(it->Source.begin()->URI.fullstr()) != "") {
00972         if (it->Source.begin()->URI.Protocol() == "file")
00973           datastaging.NewChild("Source");
00974         else
00975           datastaging.NewChild("Source").NewChild("URI") = it->Source.begin()->URI.fullstr();
00976       }
00977       if (it->Target.size() != 0 &&
00978           it->Target.begin()->URI &&
00979           trim(it->Target.begin()->URI.fullstr()) != "")
00980         datastaging.NewChild("Target").NewChild("URI") = it->Target.begin()->URI.fullstr();
00981       if (it->IsExecutable || it->Name == job.Application.Executable.Name)
00982         datastaging.NewChild("IsExecutable") = "true";
00983       datastaging.NewChild("DeleteOnTermination") = (it->KeepData ? "false" : "true");
00984       if (!it->DownloadToCache)
00985         datastaging.NewChild("DownloadToCache") = "false";
00986     }
00987     // End of DataStaging
00988 
00989     std::string product;
00990     jobdefinition.GetDoc(product, true);
00991 
00992     return product;
00993   }
00994 
00995 } // namespace Arc