USGS

Isis 3.0 Object Programmers' Reference

Home

Pipeline.cpp

00001 #include <iostream>
00002 
00003 #include <QFile>
00004 
00005 #include "Pipeline.h"
00006 #include "PipelineApplication.h"
00007 #include "ProgramLauncher.h"
00008 #include "IException.h"
00009 #include "Application.h"
00010 #include "Preference.h"
00011 #include "Progress.h"
00012 #include "TextFile.h"
00013 #include "FileName.h"
00014 
00015 using namespace Isis;
00016 using namespace std;
00017 
00018 namespace Isis {
00019 
00020 
00030   Pipeline::Pipeline(const QString &procAppName) {
00031     p_pausePosition = -1;
00032     p_procAppName = procAppName;
00033     p_addedCubeatt = false;
00034     p_outputListNeedsModifiers = false;
00035     p_continue = false;
00036   }
00037 
00038 
00043   Pipeline::~Pipeline() {
00044     for (int i = 0; i < (int)p_apps.size(); i++) {
00045       delete p_apps[i];
00046     }
00047 
00048     p_apps.clear();
00049   }
00050 
00051 
00063   void Pipeline::Prepare() {
00064     // Nothing in the pipeline? quit
00065     if (p_apps.size() == 0) return;
00066 
00067     // We might have to modify the pipeline and try again, so keep track of if this is necessary
00068     bool successfulPrepare = false;
00069 
00070     while (!successfulPrepare) {
00071       // Assume we'll be successful
00072       successfulPrepare = true;
00073       bool foundFirst = false;
00074 
00075       // Keep track of whether or not we must remove virtual bands
00076       bool mustElimBands = false;
00077 
00078       // Look to see if we need to eliminate virtual bands...
00079       for (unsigned int i = 0; i < p_virtualBands.size(); i++) {
00080         mustElimBands |= !p_virtualBands[i].isEmpty();
00081       }
00082 
00083       // Keep track of temp files for conflicts
00084       vector<QString> tmpFiles;
00085 
00086       // Loop through all the pipeline apps, look for a good place to remove virtual
00087       //   bands and tell the apps the prepare themselves. Double check the first program
00088       //   is not branched (expecting multiple inputs).
00089       for (int i = 0; i < (int)p_apps.size() && successfulPrepare; i++) {
00090         if (p_apps[i] == NULL) continue;
00091         if (mustElimBands && p_apps[i]->SupportsVirtualBands()) {
00092           if (i != 0 && p_virtualBands.size() != 1) {
00093             QString message = "If multiple original inputs were set in the pipeline, the first application must support virtual bands.";
00094             throw IException(IException::Programmer, message, _FILEINFO_);
00095           }
00096 
00097           p_apps[i]->SetVirtualBands(p_virtualBands);
00098           mustElimBands = false;
00099 
00100           // We might have added the "cubeatt" program to eliminate bands,
00101           //   remove it if we found something else to do the virtual bands.
00102           // **This causes a failure in our calculations, start over.
00103           if (p_addedCubeatt && i != (int)p_apps.size() - 1) {
00104             delete p_apps[p_apps.size() - 1];
00105             p_apps.resize(p_apps.size() - 1);
00106             p_appIdentifiers.resize(p_appIdentifiers.size() - 1);
00107             p_apps[p_apps.size() - 1]->SetNext(NULL);
00108             p_addedCubeatt = false;
00109             successfulPrepare = false;
00110             continue;
00111           }
00112         }
00113         else {
00114           // Pipeline is responsible for the virtual bands, reset any apps
00115           //   who have an old virtual bands setting.
00116           vector<QString> empty;
00117           p_apps[i]->SetVirtualBands(empty);
00118         }
00119 
00120         // This instructs the pipeline app to prepare itself; all previous pipeline apps must
00121         //   be already prepared. Future pipeline apps do not have to be.
00122         p_apps[i]->BuildParamString();
00123 
00124         // keep track of tmp files
00125         vector<QString> theseTempFiles = p_apps[i]->TemporaryFiles();
00126         for (int tmpFile = 0; tmpFile < (int)theseTempFiles.size(); tmpFile++) {
00127           // no need to delete blank files
00128           if (theseTempFiles[tmpFile].contains("blank")) {
00129             tmpFiles.push_back(theseTempFiles[tmpFile]);
00130           }
00131         }
00132 
00133         if (!foundFirst && p_apps[i]->Enabled()) {
00134           foundFirst = true;
00135 
00136           if (p_apps[i]->InputBranches().size() != OriginalBranches().size()) {
00137             QString msg = "The program [" + p_apps[i]->Name() + "] can not be the first in the pipeline";
00138             msg += " because it must be run multiple times with unspecified varying inputs";
00139             throw IException(IException::Programmer, msg, _FILEINFO_);
00140           }
00141         }
00142       }
00143 
00144       // Make sure we found an app!
00145       if (!foundFirst) {
00146         string msg = "No applications are enabled in the pipeline";
00147         throw IException(IException::Programmer, msg, _FILEINFO_);
00148       }
00149 
00150       // Make sure all tmp files are unique!
00151       for (int i = 0; successfulPrepare && i < (int)tmpFiles.size(); i++) {
00152         for (int j = i + 1; j < (int)tmpFiles.size(); j++) {
00153           if (tmpFiles[i] == tmpFiles[j]) {
00154             QString msg = "There is a conflict with the temporary file naming. The temporary file [";
00155             msg += tmpFiles[i] + "] is created twice.";
00156             throw IException(IException::Programmer, msg, _FILEINFO_);
00157           }
00158         }
00159       }
00160 
00161       // We failed at eliminating bands, add stretch to our programs and try again
00162       if (successfulPrepare && mustElimBands) {
00163         AddToPipeline("cubeatt", "~PIPELINE_RESERVED_FOR_BANDS~");
00164         Application("~PIPELINE_RESERVED_FOR_BANDS~").SetInputParameter("FROM", true);
00165         Application("~PIPELINE_RESERVED_FOR_BANDS~").SetOutputParameter("TO", "final");
00166         p_addedCubeatt = true;
00167         successfulPrepare = false;
00168       }
00169 
00170       int lastApp = p_apps.size()-1;
00171       if (p_apps[p_apps.size()-1] == NULL)
00172         lastApp = p_apps.size() - 2;
00173 
00174       if (p_apps[lastApp]->GetOutputs().size() == 0) {
00175         string msg = "There are no outputted files in the pipeline. At least one program must generate an output file.";
00176         throw IException(IException::Programmer, msg, _FILEINFO_);
00177       }
00178     }
00179   }
00180 
00181 
00193   void Pipeline::Run() {
00194     // Prepare the pipeline programs
00195     Prepare();
00196 
00197     // Get the starting point
00198     p_pausePosition++;
00199 
00200     Progress pipelineProg;
00201     pipelineProg.SetText(p_procAppName);
00202     pipelineProg.SetMaximumSteps(1);
00203     pipelineProg.CheckStatus();
00204 
00205     // Go through these programs, executing them
00206     for (int i = p_pausePosition; i < Size(); i++) {
00207 
00208       // Return to caller for a pause
00209       if (p_apps[i] == NULL) {
00210         p_pausePosition = i;
00211         return;
00212       }
00213 
00214       if (Application(i).Enabled()) {
00215         Progress appName;
00216         appName.SetText("Running " + Application(i).Name());
00217         appName.SetMaximumSteps(1);
00218         appName.CheckStatus();
00219          
00220         // grab the sets of parameters this program needs to be run with
00221         const vector<QString> &params = Application(i).ParamString();
00222         for (int j = 0; j < (int)params.size(); j++) {
00223 
00224           // check for non-program run special strings
00225           QString special(params[j].mid(0, 7));
00226 
00227           // If ">>LIST", then we need to make a list file
00228           if (special == ">>LIST ") {
00229             QString cmd = params[j].mid(7);
00230 
00231             QStringList listData = cmd.split(" ");
00232             QString listFileName = listData.takeFirst();
00233             TextFile listFile(listFileName, "overwrite");
00234 
00235             while (!listData.isEmpty()) {
00236               listFile.PutLine(listData.takeFirst());
00237             }
00238 
00239             listFile.Close();
00240           }
00241           else {
00242             // Nothing special is happening, just execute the program
00243             try {
00244               ProgramLauncher::RunIsisProgram(Application(i).Name(), params[j]);
00245             }
00246             catch (IException &e) {
00247               if (!p_continue && !Application(i).Continue()) {
00248                 throw;
00249               }
00250               else {
00251                 e.print();
00252                 cerr << "Continuing ......" << endl;
00253               }
00254             }
00255           }
00256         }
00257       }
00258     }
00259 
00260     // Remove temporary files now
00261     if (!KeepTemporaryFiles()) {
00262       for (int i = 0; i < Size(); i++) {
00263         if (p_apps[i] == NULL) continue;
00264         if (Application(i).Enabled()) {
00265           vector<QString> tmpFiles = Application(i).TemporaryFiles();
00266           for (int file = 0; file < (int)tmpFiles.size(); file++) {
00267             QFile::remove(tmpFiles[file]);
00268           }
00269         }
00270       }
00271     }
00272 
00273     // Reset pause position
00274     p_pausePosition = -1;
00275   }
00276 
00277 
00286   void Pipeline::SetInputFile(const char *inputParam) {
00287     SetInputFile(QString(inputParam));
00288   }
00289 
00290 
00301   void Pipeline::SetInputFile(const QString &inputParam) {
00302     UserInterface &ui = Application::GetUserInterface();
00303     p_originalInput.push_back(ui.GetFileName(inputParam));
00304     p_inputBranches.push_back(inputParam);
00305     p_virtualBands.push_back(ui.GetInputAttribute(inputParam).toString());
00306   }
00307 
00308 
00318   void Pipeline::SetInputFile(const FileName &inputFile) {
00319     p_originalInput.push_back(inputFile.original());
00320     p_inputBranches.push_back(inputFile.original());
00321     p_virtualBands.push_back("");
00322   }
00323 
00324 
00333   void Pipeline::SetInputListFile(const char *inputParam) {
00334     SetInputListFile(QString(inputParam));
00335   }
00336 
00337 
00348   void Pipeline::SetInputListFile(const QString &inputParam) {
00349     UserInterface &ui = Application::GetUserInterface();
00350 
00351     TextFile filelist(FileName(ui.GetFileName(inputParam)).expanded());
00352     QString filename;
00353     int branch = 1;
00354 
00355     while (filelist.GetLineNoFilter(filename)) {
00356       p_originalInput.push_back(filename);
00357       p_inputBranches.push_back(inputParam + toString(branch));
00358       p_virtualBands.push_back("");
00359       p_finalOutput.push_back(FileName(filename).name());
00360 
00361       branch ++;
00362     }
00363 
00364     p_outputListNeedsModifiers = true;
00365   }
00366 
00367 
00376   void Pipeline::SetInputListFile(const FileName &inputFileName) {
00377     TextFile filelist(inputFileName.expanded());
00378     QString filename;
00379     int branch = 1;
00380 
00381     while (filelist.GetLineNoFilter(filename)) {
00382       p_originalInput.push_back(filename);
00383       p_inputBranches.push_back(FileName(inputFileName).expanded() + " " + QString(branch));
00384       p_finalOutput.push_back(FileName(filename).name());
00385       p_virtualBands.push_back("");
00386 
00387       branch ++;
00388     }
00389 
00390     p_outputListNeedsModifiers = true;
00391   }
00392 
00393 
00405   void Pipeline::SetInputFile(const char *inputParam, const char *virtualBandsParam) {
00406     SetInputFile(QString(inputParam), QString(virtualBandsParam));
00407   }
00408 
00409 
00423   void Pipeline::SetInputFile(const QString &inputParam, const QString &virtualBandsParam) {
00424     UserInterface &ui = Application::GetUserInterface();
00425     p_originalInput.push_back(ui.GetAsString(inputParam));
00426     p_inputBranches.push_back(inputParam);
00427 
00428     if (!virtualBandsParam.isEmpty() && ui.WasEntered(virtualBandsParam)) {
00429       p_virtualBands.push_back(ui.GetAsString(virtualBandsParam));
00430     }
00431     else {
00432       p_virtualBands.push_back("");
00433     }
00434   }
00435 
00436 
00446   void Pipeline::SetOutputFile(const char *outputParam) {
00447     SetOutputFile(QString(outputParam));
00448   }
00449 
00450 
00460   void Pipeline::SetOutputFile(const QString &outputParam) {
00461     UserInterface &ui = Application::GetUserInterface();
00462     p_finalOutput.clear();
00463 
00464     if (ui.WasEntered(outputParam)) {
00465       p_finalOutput.push_back(ui.GetAsString(outputParam));
00466     }
00467   }
00468 
00469 
00478   void Pipeline::SetOutputFile(const FileName &outputFile) {
00479     p_finalOutput.clear();
00480     p_finalOutput.push_back(outputFile.expanded());
00481   }
00482 
00483 
00492   void Pipeline::SetOutputListFile(const char *outputFileNameParam) {
00493     SetOutputListFile(QString(outputFileNameParam));
00494   }
00495 
00496 
00505   void Pipeline::SetOutputListFile(const QString &outputFileNameParam) {
00506     UserInterface &ui = Application::GetUserInterface();
00507 
00508     if (ui.WasEntered(outputFileNameParam)) {
00509       SetOutputListFile(FileName(ui.GetFileName(outputFileNameParam)));
00510     }
00511     else {
00512       p_finalOutput.clear();
00513 
00514       // Calculate output files
00515       for (unsigned int i = 0; i < p_originalInput.size(); i++) {
00516         p_finalOutput.push_back(FileName(p_originalInput[i]).name());
00517       }
00518 
00519       p_outputListNeedsModifiers = true;
00520     }
00521   }
00522 
00523 
00530   void Pipeline::SetOutputListFile(const FileName &outputFileNameList) {
00531     p_finalOutput.clear();
00532 
00533     TextFile filelist(outputFileNameList.expanded());
00534     QString filename;
00535 
00536     while (filelist.GetLineNoFilter(filename)) {
00537       p_finalOutput.push_back(filename);
00538     }
00539 
00540     p_outputListNeedsModifiers = false;
00541   }
00542 
00543 
00550   void Pipeline::KeepTemporaryFiles(bool keep) {
00551     p_keepTemporary = keep;
00552   }
00553 
00554 
00562   void Pipeline::AddPause() {
00563     // Add the pause
00564     QString pauseAppId = "";
00565     PipelineApplication *pauseApp = NULL;
00566 
00567     p_apps.push_back(pauseApp);
00568     p_appIdentifiers.push_back(pauseAppId);
00569   }
00570 
00571 
00585   void Pipeline::AddToPipeline(const QString &appname, const QString &identifier) {
00586     // Check uniqueness first
00587     for (unsigned int appIdentifier = 0; appIdentifier < p_appIdentifiers.size(); appIdentifier++) {
00588       if (p_appIdentifiers[appIdentifier] == identifier) {
00589         QString message = "The application identifier [" + identifier + "] is not unique. " +
00590                           "Please providing a unique identifier";
00591         throw IException(IException::Programmer, message, _FILEINFO_);
00592       }
00593     }
00594 
00595     // If we've got cubeatt on our list of applications for band eliminating, take it away temporarily
00596     PipelineApplication *cubeAtt = NULL;
00597     QString cubeAttId = "";
00598     if (p_addedCubeatt) {
00599       cubeAtt = p_apps[p_apps.size()-1];
00600       cubeAttId = p_appIdentifiers[p_appIdentifiers.size()-1];
00601       p_apps.resize(p_apps.size() - 1);
00602       p_appIdentifiers.resize(p_appIdentifiers.size() - 1);
00603       p_apps[p_apps.size()-1]->SetNext(NULL);
00604     }
00605 
00606     //Check for non nulls instead of size ie. find last non null or use this
00607     int appsSize = 0;
00608     QString pauseAppId = "";
00609 
00610     for (int iapp = 0; iapp < (int) p_apps.size(); iapp++)
00611       if (p_apps[iapp] != NULL) appsSize++;
00612 
00613     // Add the new application
00614     if (p_apps.size() == 0) {
00615       p_apps.push_back(new PipelineApplication(appname, this));
00616     }
00617     else {
00618       if (p_apps[p_apps.size()-1] != NULL)
00619         p_apps.push_back(new PipelineApplication(appname, p_apps[p_apps.size()-1]));
00620       else // We know we have app NULL before this new app
00621         p_apps.push_back(new PipelineApplication(appname, p_apps[p_apps.size()-2]));
00622     }
00623 
00624     p_appIdentifiers.push_back(identifier);
00625 
00626     // If we have stretch, put it back where it belongs
00627     if (cubeAtt) {
00628       p_apps[p_apps.size()-1]->SetNext(cubeAtt);
00629       cubeAtt->SetPrevious(p_apps[p_apps.size()-1]);
00630       p_apps.push_back(cubeAtt);
00631       p_appIdentifiers.push_back(cubeAttId);
00632     }
00633   }
00634 
00635 
00647   void Pipeline::AddToPipeline(const QString &appname) {
00648     // Check uniqueness first
00649     for (unsigned int appIdentifier = 0; appIdentifier < p_appIdentifiers.size(); appIdentifier++) {
00650       if (p_appIdentifiers[appIdentifier] == appname) {
00651         QString message = "The application identifier [" + appname + "] is not unique. Please use " +
00652                           "the other AddToPipeline method providing a unique identifier";
00653         throw IException(IException::Programmer, message, _FILEINFO_);
00654       }
00655     }
00656 
00657     // If we've got cubeatt on our list of applications for band eliminating, take it away temporarily
00658     PipelineApplication *cubeAtt = NULL;
00659     QString cubeAttId = "";
00660     if (p_addedCubeatt) {
00661       cubeAtt = p_apps[p_apps.size()-1];
00662       cubeAttId = p_appIdentifiers[p_appIdentifiers.size()-1];
00663       p_apps.resize(p_apps.size() - 1);
00664       p_appIdentifiers.resize(p_appIdentifiers.size() - 1);
00665       p_apps[p_apps.size()-1]->SetNext(NULL);
00666     }
00667 
00668     // Add the new application
00669     if (p_apps.size() == 0) {
00670       p_apps.push_back(new PipelineApplication(appname, this));
00671     }
00672     else {
00673       if (p_apps[p_apps.size()-1] != NULL)
00674         p_apps.push_back(new PipelineApplication(appname, p_apps[p_apps.size()-1]));
00675       else // We know we have app NULL before this new app
00676         p_apps.push_back(new PipelineApplication(appname, p_apps[p_apps.size()-2]));
00677     }
00678 
00679     p_appIdentifiers.push_back(appname);
00680 
00681     // If we have stretch, put it back where it belongs
00682     if (cubeAtt) {
00683       p_apps[p_apps.size()-1]->SetNext(cubeAtt);
00684       cubeAtt->SetPrevious(p_apps[p_apps.size()-1]);
00685       p_apps.push_back(cubeAtt);
00686       p_appIdentifiers.push_back(cubeAttId);
00687     }
00688   }
00689 
00690 
00700   PipelineApplication &Pipeline::Application(const QString &identifier) {
00701     int index = 0;
00702     bool found = false;
00703 
00704     while (!found && index < Size()) {
00705       if (p_appIdentifiers[index] == identifier) {
00706         found = true;
00707       }
00708       else {
00709         index ++;
00710       }
00711     }
00712 
00713     if (!found) {
00714       QString msg = "Application identified by [" + identifier + "] has not been added to the pipeline";
00715       throw IException(IException::Programmer, msg, _FILEINFO_);
00716     }
00717 
00718     return *p_apps[index];
00719   }
00720 
00721 
00730   PipelineApplication &Pipeline::Application(const int &index) {
00731     if (index > Size()) {
00732       QString msg = "Index [" + QString(index) + "] out of bounds";
00733       throw IException(IException::Programmer, msg, _FILEINFO_);
00734     }
00735 
00736     return *p_apps[index];
00737   }
00738 
00739 
00752   void Pipeline::SetFirstApplication(const QString &appname) {
00753     int appIndex = 0;
00754     for (appIndex = 0; appIndex < (int)p_apps.size() &&
00755                       p_apps[appIndex]->Name() != appname; appIndex++) {
00756       if (p_apps[appIndex] == NULL) continue;
00757       p_apps[appIndex]->Disable();
00758     }
00759     // for (appIndex = 0; appIndex < (int)p_apps.size() && p_apps[appIndex]->Name() != appname; appIndex++) {
00760     //   p_apps[appIndex]->Disable();
00761     // }
00762 
00763     if (appIndex >= (int)p_apps.size()) {
00764       QString msg = "Pipeline could not find application [" + appname + "]";
00765       throw IException(IException::Programmer, msg, _FILEINFO_);
00766     }
00767   }
00768 
00769 
00782   void Pipeline::SetLastApplication(const QString &appname) {
00783     int appIndex = p_apps.size() - 1;
00784     for (appIndex = p_apps.size() - 1; appIndex >= 0 && p_apps[appIndex]->Name() != appname; appIndex --) {
00785       if (p_apps[appIndex] == NULL) continue;
00786       p_apps[appIndex]->Disable();
00787     }
00788 
00789     if (appIndex < 0) {
00790       QString msg = "Pipeline could not find application [" + appname + "]";
00791       throw IException(IException::Programmer, msg, _FILEINFO_);
00792     }
00793   }
00794 
00795 
00809   QString Pipeline::FinalOutput(int branch, bool addModifiers) {
00810     QString output = ((p_finalOutput.size() != 0) ? p_finalOutput[0] : "");
00811 
00812     if (p_apps.size() == 0) return output;
00813 
00814     if (p_finalOutput.size() > 1) {
00815       if ((unsigned int)branch >= p_finalOutput.size()) {
00816         QString msg = "Output not set for branch [" + QString(branch) + "]";
00817         throw IException(IException::Programmer, msg, _FILEINFO_);
00818       }
00819 
00820       if (!p_outputListNeedsModifiers) {
00821         return p_finalOutput[branch];
00822       }
00823       else {
00824         output = p_finalOutput[branch];
00825         addModifiers = true;
00826       }
00827     }
00828 
00829     PipelineApplication *last = p_apps[p_apps.size()-1];
00830     if (last == NULL) last = p_apps[p_apps.size()-2];
00831     if (!last->Enabled()) last = last->Previous();
00832 
00833     if (output == "" || p_finalOutput.size() > 1) {
00834       if (output == "") {
00835         output = "./" + FileName(p_originalInput[0]).baseName();
00836       }
00837       else {
00838         output = "./" + FileName(p_originalInput[branch]).baseName();
00839       }
00840 
00841       // Base filename off of first input file
00842       if (!addModifiers || last->OutputBranches().size() == 1) {
00843         if (addModifiers && p_finalOutput.size() > 1)
00844           output += "." + last->OutputNameModifier();
00845 
00846         output += "." + last->OutputExtension();
00847       }
00848       else {
00849         // If we have multiple final outputs, rely on them to
00850         //   differentiate the branches
00851         if (p_finalOutput.size() <= 1) {
00852           output += "." + last->OutputBranches()[branch];
00853         }
00854 
00855         if (addModifiers && p_finalOutput.size() > 1)
00856           output += "." + last->OutputNameModifier();
00857 
00858         output += "." + last->OutputExtension();
00859       }
00860     }
00861     else if (addModifiers) {
00862       PipelineApplication *last = p_apps[p_apps.size()-1];
00863       if (!last->Enabled()) last = last->Previous();
00864 
00865       output = FileName(p_finalOutput[0]).path() + "/" +
00866                FileName(p_finalOutput[0]).baseName() + "." +
00867                last->OutputBranches()[branch] + ".";
00868 
00869       if (p_finalOutput.size() > 1) {
00870         output += last->OutputNameModifier() + ".";
00871       }
00872 
00873       output += last->OutputExtension();
00874     }
00875 
00876     return output;
00877   }
00878 
00879 
00886   QString Pipeline::TemporaryFolder() {
00887     Pvl &pref = Preference::Preferences();
00888     return pref.FindGroup("DataDirectory")["Temporary"];
00889   }
00890 
00891 
00900   void Pipeline::EnableAllApplications() {
00901     for (int i = 0; i < Size(); i++) {
00902       if (p_apps[i] != NULL) p_apps[i]->Enable();
00903     }
00904   }
00905 
00906 
00923   ostream &operator<<(ostream &os, Pipeline &pipeline) {
00924     pipeline.Prepare();
00925 
00926     if (!pipeline.Name().isEmpty()) {
00927       os << "PIPELINE -------> " << pipeline.Name() << " <------- PIPELINE" << endl;
00928     }
00929 
00930     for (int i = 0; i < pipeline.Size(); i++) {
00931       if (&(pipeline.Application(i)) == NULL) continue;
00932       if (pipeline.Application(i).Enabled()) {
00933         const vector<QString> &params = pipeline.Application(i).ParamString();
00934         for (int j = 0; j < (int)params.size(); j++) {
00935           QString special(params[j].mid(0, 7));
00936           if (special == ">>LIST ") {
00937             QString cmd = params[j].mid(7);
00938 
00939             QStringList listFileData = cmd.split(" ");
00940             QString file = listFileData.takeFirst();
00941             os << "echo -e \"" << listFileData.join("\\n") << "\" > " << file << endl;
00942           }
00943           else {
00944             os << pipeline.Application(i).Name() << " " << params[j] << endl;
00945           }
00946         }
00947       }
00948     }
00949 
00950     if (!pipeline.KeepTemporaryFiles()) {
00951       for (int i = 0; i < pipeline.Size(); i++) {
00952         if (&(pipeline.Application(i)) == NULL) continue;
00953         if (pipeline.Application(i).Enabled()) {
00954           vector<QString> tmpFiles = pipeline.Application(i).TemporaryFiles();
00955           for (int file = 0; file < (int)tmpFiles.size(); file++) {
00956             if (!tmpFiles[file].contains("blank")) {
00957               os << "rm " << tmpFiles[file] << endl;
00958             }
00959           }
00960         }
00961       }
00962     }
00963 
00964     if (!pipeline.Name().isEmpty()) {
00965       os << "PIPELINE -------> " << pipeline.Name() << " <------- PIPELINE" << endl;
00966     }
00967 
00968     return os;
00969   }
00970 }