Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

omgmodellerwebservicesplugin.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Tim Sutton   *
00003  *   tim@linfiniti.com   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include <omgmodellerwebservicesplugin.h>
00021 #include <omgalgorithm.h>
00022 #include <omgalgorithmset.h>
00023 #include <omgui.h>
00024 //qt includes
00025 #include <QStringList>
00026 #include <QSettings>
00027 #include <QFile>
00028 #include <QUrl>
00029 #include <QDir>
00030 #include <QTimer>
00031 // needed for Q_EXPORT_PLUGIN macro at the end of this file
00032 #include <QtPlugin>
00033 
00034 //gsoap includes
00035 #include <openModeller.nsmap>
00036 //#include <soapH.h>
00037 typedef char *xsd__string;
00038 typedef int xsd__int; 
00039 
00040 //time in seconds between getProgress requests 
00041 const int SLEEP_INTERVAL=5;
00042 
00043 OmgModellerWebServicesPlugin::OmgModellerWebServicesPlugin( QObject * parent) : 
00044       QObject (parent), 
00045       OmgModellerPluginInterface() 
00046 {
00047   initialise();
00048 }
00049 
00050 OmgModellerWebServicesPlugin::~OmgModellerWebServicesPlugin()
00051 {
00052 }
00053 
00054 bool OmgModellerWebServicesPlugin::initialise()
00055 {
00056 
00057   return true;
00058 
00059 } //initialise
00060 
00061 QString OmgModellerWebServicesPlugin::createModel(OmgModel * thepModel)
00062 {
00063   mMessenger.emitModelMessage(thepModel->guid(),tr("WS: creating model"));
00064   mMessenger.emitModelCreationProgress(thepModel->guid(),0);
00065   thepModel->setError(false);
00066 
00067   //get the xml for the model creation process
00068   QString myXmlString = thepModel->toModelCreationXml().trimmed();
00069   //first write the model creation request xml to a file - I may remove this in future - its just for debug purposes
00070   QString myFileName = thepModel->taxonName();
00071   myFileName = myFileName.replace(" ","_");
00072   QString myWorkDir = QDir::convertSeparators(thepModel->workDir());
00073   if (!Omgui::createTextFile(myWorkDir + myFileName+"_create.xml",myXmlString))
00074   {
00075     QString myWarning(tr("Unable to open ") + myFileName.toLocal8Bit() + tr(" for writing!"));
00076     mMessenger.emitModelError(thepModel->guid(),myWarning);
00077   }
00078   //create a wchar array to hold the xml, using the size of the above xml
00079   wchar_t * myXml = convertToWideChar(myXmlString.toStdString().c_str()) ; 
00080   struct soap * mypSoap = getSoapConnection();
00081   xsd__string myWSResponse ; 
00082   QString myTicketQString;
00083   QSettings mySettings;
00084   QString myWSUrl=mySettings.value("openModeller/webServicesPlugin/url", "").toString();
00085   //send the model request and get teh ticket id back into myWSResponse
00086   if ( soap_call_omws__createModel(mypSoap, 
00087         myWSUrl.toLocal8Bit(),
00088         NULL, 
00089         myXml,
00090         myWSResponse) == 0 ) 
00091   {
00092     mMessenger.emitModelMessage(thepModel->guid(),tr("Create model job requested ok, getting job id... "));
00093     // myWSResponse is a char** and we need to convert it to a QString    
00094     std::string myTicketString (myWSResponse); 
00095     myTicketQString = QString::fromStdString(myTicketString);
00096     mMessenger.emitModelMessage(thepModel->guid(),tr("Create model job scheduled with job id: ") + myTicketQString);
00097   }
00098   else
00099   {
00100     soap_print_fault(mypSoap, stderr);
00101     thepModel->setError(true);
00102     return 0;
00103   }
00104   
00105   // poll the ws until the job is done
00106   mMessenger.emitModelMessage(thepModel->guid(),tr("Calling getProgress until job is done"));
00107   xsd__int myProgress=static_cast<xsd__int>(-999); //undefined state!
00108   
00109   //                            aborted                  completed
00110   while (myProgress!=-2 && myProgress!=100)
00111   {
00112     if ( soap_call_omws__getProgress(mypSoap, 
00113         myWSUrl.toLocal8Bit(),
00114         NULL,
00115         myWSResponse,
00116         myProgress) == 0 ) 
00117     {   
00118       mMessenger.emitModelMessage(thepModel->guid(),tr("Progress of Job ") + QString::number(myProgress) + "%");
00119       mMessenger.emitModelCreationProgress(thepModel->guid(),myProgress);
00120 #ifdef Q_WS_WIN
00121       //Sleep on windows takes milliseconds
00122       Sleep(SLEEP_INTERVAL*1000);
00123 #else
00124       //sleep on mac / linux takes seconds
00125       sleep(SLEEP_INTERVAL);
00126 #endif
00127     }
00128     else
00129     {
00130       soap_print_fault(mypSoap, stderr);
00131       thepModel->setError(true);
00132       return 0;
00133     }
00134   }
00135   //get the log messages for this job
00136   mMessenger.emitModelMessage(thepModel->guid(),tr("Calling getLog"));
00137   //wchar_t * myWSLog;
00138   xsd__string myWSLog; 
00139   std::string myLogString ;
00140   QString myLogQString;
00141   if ( soap_call_omws__getLog(mypSoap, 
00142        myWSUrl.toLocal8Bit(),
00143        NULL,
00144        myWSResponse,
00145        myWSLog
00146        ) == 0 ) 
00147   {   
00148     // myWSLogis a char** and we need to convert it to a QString          
00149     myLogString = myWSLog[0]; 
00150     myLogQString = QString::fromStdString(myLogString);
00151     mMessenger.emitModelMessage(thepModel->guid(),tr("Log of Job ") + myTicketQString + tr(" is: "));
00152     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00153     mMessenger.emitModelMessage(thepModel->guid(), myLogQString );
00154     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00155     thepModel->appendToLog(myLogQString);
00156   }
00157   else
00158   {
00159     soap_print_fault(mypSoap, stderr);
00160     thepModel->setError(true);
00161     return 0;
00162   }
00163   //check if the model failed / or aborted
00164   if (myProgress == -2)
00165   {
00166      //model was aborted, so bail out
00167      mMessenger.emitModelError(thepModel->guid(), tr("Model was aborted on server, quitting....." ));
00168      thepModel->setError(true);
00169      return 0;
00170   }
00171 
00172   // now that the model is done, we can get the model result
00173 
00174   mMessenger.emitModelMessage(thepModel->guid(),tr("Calling getModel"));
00175   struct omws__getModelResponse myModelEnvelope;
00176   //wchar_t * myModelEnvelope;
00177   QString myModelQString;
00178   if ( soap_call_omws__getModel(mypSoap, 
00179        myWSUrl.toLocal8Bit(),
00180        NULL,
00181        myWSResponse,
00182        &myModelEnvelope
00183        ) == 0 ) 
00184   {   
00185     // myWSLogis a char** and we need to convert it to a QString          
00186     QString myModelQString = QString::fromWCharArray(myModelEnvelope.om__ModelEnvelope);
00187     mMessenger.emitModelMessage(thepModel->guid(),tr("Model of Job ") + myTicketQString + tr(" is: "));
00188     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00189     mMessenger.emitModelMessage(thepModel->guid(), myModelQString );
00190     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00191     return myModelQString;
00192   }
00193   else
00194   {
00195     mMessenger.emitModelError(thepModel->guid(),"Get model failed!") ;
00196     soap_print_fault(mypSoap, stderr);
00197     thepModel->setError(true);
00198     return 0;
00199   }
00200 
00201   //
00202   //  @TODO delete pointers etc
00203   //
00204 
00205   return QString(tr("No model created!"));
00206 }//createModel
00207 
00208 void  OmgModellerWebServicesPlugin::projectModel(OmgModel * thepModel)
00209 {
00210 
00211   mMessenger.emitModelMessage(thepModel->guid(),"WS: projecting model");
00212   mMessenger.emitModelProjectionProgress(thepModel->guid(),0);
00213 
00214   //get the xml for the model creation process
00215   QString myXmlString = thepModel->toModelProjectionXml().trimmed();
00216   //first write the model projection request xml to a file - I may remove this in future - its just for debug purposes
00217   QString myFileName = thepModel->taxonName();
00218   myFileName = myFileName.replace(" ","_");
00219   QString myWorkDir = QDir::convertSeparators(thepModel->workDir());
00220   if (!Omgui::createTextFile(myWorkDir + myFileName+"_project.xml",myXmlString))
00221   {
00222     QString myWarning(tr("Unable to open ") + myFileName.toLocal8Bit() + tr(" for writing!"));
00223     mMessenger.emitModelError(thepModel->guid(),myWarning);
00224   }
00225   //create a wchar array to hold the xml, using the size of the above xml
00226   wchar_t * myXml = convertToWideChar(myXmlString.toStdString().c_str()) ; 
00227   struct soap * mypSoap = getSoapConnection();
00228   xsd__string myWSResponse ; 
00229   QString myTicketQString;
00230   QSettings mySettings;
00231   QString myWSUrl=mySettings.value("openModeller/webServicesPlugin/url", "").toString();
00232   //send the model request and get teh ticket id back into myWSResponse
00233   if ( soap_call_omws__projectModel(mypSoap, 
00234         myWSUrl.toLocal8Bit(),
00235         NULL, 
00236               myXml,
00237               myWSResponse) == 0 ) 
00238   {
00239     mMessenger.emitModelMessage(thepModel->guid(),tr("Project model job requested ok, getting job id... "));
00240     // myWSResponse is a char** and we need to convert it to a QString    
00241     std::string myTicketString (myWSResponse); 
00242     myTicketQString = QString::fromStdString(myTicketString);
00243     mMessenger.emitModelMessage(thepModel->guid(),tr("Project model job scheduled with job id: ") + myTicketQString);
00244   }
00245   else
00246   {
00247     soap_print_fault(mypSoap, stderr);
00248     thepModel->setError(true);
00249     return ;
00250   }
00251   
00252   // poll the ws until the job is done
00253   mMessenger.emitModelMessage(thepModel->guid(),tr("Calling getProgress until job is done"));
00254   xsd__int myProgress=static_cast<xsd__int>(-999); //undefined state!
00255   
00256   //                            aborted                  completed
00257   while (myProgress!=-2 && myProgress!=100)
00258   {
00259     if ( soap_call_omws__getProgress(mypSoap, 
00260         myWSUrl.toLocal8Bit(),
00261         NULL,
00262         myWSResponse,
00263         myProgress) == 0 ) 
00264     {   
00265       mMessenger.emitModelMessage(thepModel->guid(),tr("Progress of Job ") + QString::number(myProgress) + "%");
00266       mMessenger.emitModelProjectionProgress(thepModel->guid(),myProgress);
00267 #ifdef Q_WS_WIN
00268       //Sleep on windows takes milliseconds
00269       Sleep(SLEEP_INTERVAL*1000);
00270 #else
00271       //sleep on mac / linux takes seconds
00272       sleep(SLEEP_INTERVAL);
00273 #endif
00274     }
00275     else
00276     {
00277       soap_print_fault(mypSoap, stderr);
00278       thepModel->setError(true);
00279       return ;
00280     }
00281   }
00282   //get the log messages for this job
00283   mMessenger.emitModelMessage(thepModel->guid(),"Calling getLog");
00284   //wchar_t * myWSLog;
00285   xsd__string myWSLog; 
00286   std::string myLogString ;
00287   QString myLogQString;
00288   if ( soap_call_omws__getLog(mypSoap, 
00289        myWSUrl.toLocal8Bit(),
00290        NULL,
00291        myWSResponse,
00292        myWSLog
00293        ) == 0 ) 
00294   {   
00295     // myWSLogis a char** and we need to convert it to a QString          
00296     myLogString = myWSLog[0]; 
00297     myLogQString = QString::fromStdString(myLogString);
00298     mMessenger.emitModelMessage(thepModel->guid(),tr("Log of Job ") + myTicketQString + tr(" is: "));
00299     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00300     mMessenger.emitModelMessage(thepModel->guid(), myLogQString );
00301     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00302     thepModel->appendToLog(myLogQString);
00303   }
00304   else
00305   {
00306     soap_print_fault(mypSoap, stderr);
00307     thepModel->setError(true);
00308     return ;
00309   }
00310   //check if the model failed / or aborted
00311   if (myProgress == -2)
00312   {
00313      //model was aborted, so bail out
00314      mMessenger.emitModelError(thepModel->guid(), tr("Model was aborted on server, quitting....." ));
00315      return ;
00316   }
00317 
00318   // now that the model is done, we can get the model result
00319 
00320   mMessenger.emitModelMessage(thepModel->guid(),tr("Calling getLayerAsUrl"));
00321   xsd__string myModelUrl ;
00322   QString myModelUrlString;
00323   if ( soap_call_omws__getLayerAsUrl(mypSoap, 
00324        myWSUrl.toLocal8Bit(),
00325        NULL,
00326        myWSResponse,
00327        myModelUrl
00328        ) == 0 ) 
00329   {   
00330     // myWSLogis a char** and we need to convert it to a QString          
00331     myModelUrlString = QString::fromStdString(myModelUrl);
00332     mMessenger.emitModelMessage(thepModel->guid(),tr("Model Url of Job ") + myTicketQString + tr(" is: "));
00333     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00334     mMessenger.emitModelMessage(thepModel->guid(), myModelUrlString );
00335     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00336   }
00337   else
00338   {
00339     soap_print_fault(mypSoap, stderr);
00340     thepModel->setError(true);
00341     return ;
00342   }
00343 
00344   //
00345   // Now fetch the actual image using QHttp stuff
00346   //
00347   mMessenger.emitModelMessage(thepModel->guid(),tr("Calling getLayerAsAttachment"));
00348   xsd__base64Binary myProjectionFile ;
00349   if ( soap_call_omws__getLayerAsAttachment(mypSoap, 
00350        myWSUrl.toLocal8Bit(),
00351        NULL,
00352        myWSResponse,
00353        myProjectionFile
00354        ) == 0 ) 
00355   {   
00356     // myWSLogis a char** and we need to convert it to a QString          
00357     mMessenger.emitModelMessage(thepModel->guid(),tr("Model Projection for Job ") + myTicketQString + tr(" downloaded: "));
00358     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00359     //mMessenger.emitModelMessage(thepModel->guid(), myModelUrlString );
00360     mMessenger.emitModelMessage(thepModel->guid(),"-----------------------------------------------") ;
00361   }
00362   else
00363   {
00364     soap_print_fault(mypSoap, stderr);
00365     //char * myReason = mypSoap->fault->SOAP_ENV__Reason->SOAP_ENV__Text;
00366     //std::string myReasonString ( myReason );
00367     //mMessenger.emitModelError(thepModel->guid(),tr("A soap error occurred in getLayerAsAttachment call:\n") + myReasonString.c_str());
00368     mMessenger.emitModelError(thepModel->guid(),tr("A soap error occurred in getLayerAsAttachment call:\nMap was probably unavailable") );
00369     thepModel->setError(true);
00370     return ;
00371   }
00372 
00373   QString myRawImageFileName =  myWorkDir + myFileName+"_projection." + Omgui::getOutputFormatExtension();
00374   mMessenger.emitModelMessage(thepModel->guid(),tr("Downloading model image file to : ") + myRawImageFileName);
00375   QFile myFile(myRawImageFileName);
00376   if (!myFile.open(QFile::WriteOnly)) 
00377   {
00378     mMessenger.emitModelError(thepModel->guid(),
00379         tr("Cannot write file %1:\n%2")
00380         .arg(myFile.fileName())
00381         .arg(myFile.errorString()));
00382     return;
00383   }
00384   QDataStream myStream(&myFile);   // we will serialize the data into the file
00385   int i;
00386   for ( i = 0; i < myProjectionFile.__size; i++ ) 
00387   {
00388     unsigned char myValue;
00389     myValue = myProjectionFile.__ptr[i];
00390     myStream  << myValue ;   
00391   }
00392   myFile.close();
00393   //store the model image file name in the model object
00394   thepModel->setRawImageFileName(myRawImageFileName);
00395   mMessenger.emitModelProjectionProgress(thepModel->guid(),100);
00396 
00397 
00398   //
00399   //  @TODO delete pointers etc
00400   //
00401 
00402 }//projectModel
00403 
00404 
00405 const QStringList OmgModellerWebServicesPlugin::getAlgorithmList()
00406 { 
00407   //qDebug("WS: Getting om Algorithm List");
00408   QStringList myAlgList;
00409   OmgAlgorithmSet myAlgorithmSet = getAlgorithmSet();
00410   myAlgList = myAlgorithmSet.nameList();
00411   return myAlgList;
00412 }//getAlgorithmList
00413 
00414 const OmgAlgorithmSet OmgModellerWebServicesPlugin::getAlgorithmSet()
00415 {
00416   //qDebug("WS: Getting om Algorithm Set");
00417   struct soap * mypSoap = getSoapConnection();
00418   QSettings mySettings;
00419   QString myWSUrl=mySettings.value("openModeller/webServicesPlugin/url", "").toString();
00420   if (myWSUrl.isEmpty())
00421   {
00422     mMessenger.emitError("Web Service URL not set in getAlgorithmSet!");
00423   }
00424   OmgAlgorithmSet myAlgorithmSet;
00425   //omws__getAlgorithmsResponse* myWSResponse;
00426   struct omws__getAlgorithmsResponse myWSResponse; 
00427   if ( soap_call_omws__getAlgorithms(mypSoap, 
00428         myWSUrl.toLocal8Bit(),
00429         NULL, NULL, &myWSResponse) == 0 ) 
00430   {
00431     wchar_t * myXmlLiteral = myWSResponse.om__AvailableAlgorithms;
00432     QString myXml = QString::fromWCharArray(myXmlLiteral);
00433     myXml = Omgui::xmlEncodeAmpersands(myXml);
00434     Omgui::createTextFile("/tmp/getAlgorithmSet.xml", myXml);
00435     myAlgorithmSet.fromXml(myXml.trimmed());
00436     myAlgorithmSet.setName("WebService Plugin Algorithms");
00437     myAlgorithmSet.setDescription("These are the algorithms available on " + myWSUrl);
00438   }
00439   else 
00440   {
00441     soap_print_fault(mypSoap, stderr);
00442   }
00443   soap_destroy(mypSoap); // delete deserialized class instances (for C++ only)
00444   soap_end(mypSoap);     // remove deserialized data and clean up
00445   soap_done(mypSoap);    // detach the gSOAP environment 
00446   return myAlgorithmSet; 
00447 }//getAlgorithmSet
00448  
00449 const QString OmgModellerWebServicesPlugin::getLayers(QString theBaseDir)
00450 {
00451   //qDebug("WS: getLayers called");
00452   //emit regular refresh events
00453   QTimer *mypTimer = new QTimer(this);
00454   connect(mypTimer, SIGNAL(timeout()), &mMessenger, SLOT(refresh()));
00455   mypTimer->start(1000);
00456 
00457   //now go ahead and call getLayers on WS
00458   struct soap * mypSoap = getSoapConnection();
00459   struct omws__getLayersResponse myWSResponse;
00460   //wchar_t * myWSResponse;
00461   QSettings mySettings;
00462   QString myWSUrl=mySettings.value("openModeller/webServicesPlugin/url", "").toString();
00463   QString myXml;
00464   
00465   if ( soap_call_omws__getLayers(mypSoap, 
00466         myWSUrl.toLocal8Bit(),
00467         NULL, NULL,&myWSResponse) == 0 ) 
00468   {
00469     //myXml = "<AvailableLayers>" + QString::fromWCharArray(myWSResponse) + "</AvailableLayers>";
00470     myXml = QString::fromWCharArray(myWSResponse.om__AvailableLayers); 
00471   }
00472   else 
00473   {
00474     soap_print_fault(mypSoap, stderr);
00475   }
00476   soap_destroy(mypSoap); // delete deserialized class instances (for C++ only)
00477   soap_end(mypSoap);     // remove deserialized data and clean up
00478   soap_done(mypSoap);    // detach the gSOAP environment 
00479   mypTimer->stop();
00480   delete mypTimer;
00481   return myXml; 
00482 }//getLayers
00483 
00484 struct soap * OmgModellerWebServicesPlugin::getSoapConnection()
00485 {
00486   QSettings mySettings;
00487   struct soap * mypSoap = soap_new();
00488   
00489   if (mySettings.value("proxy/proxyEnabled","0").toBool())
00490   {
00491     mypSoap->proxy_host=mySettings.value("proxy/proxyHost").toString().toLocal8Bit();
00492     mypSoap->proxy_port=mySettings.value("proxy/proxyPort").toInt();
00493     mypSoap->proxy_userid=mySettings.value("proxy/proxyUser").toString().toLocal8Bit();
00494     mypSoap->proxy_passwd=mySettings.value("proxy/proxyPassword").toString().toLocal8Bit();
00495   }
00496   soap_set_omode(mypSoap, SOAP_XML_TREE);
00497   bool myWSLoggingFlag=mySettings.value("openModeller/webServicesPlugin/doLoggingFlag", false).toBool();
00498   if (!myWSLoggingFlag)
00499   {
00500     //using NULL instead of "/path/to/file/" will create no logs
00501     soap_set_recv_logfile(mypSoap, NULL); 
00502     soap_set_sent_logfile(mypSoap, NULL);
00503     soap_set_test_logfile(mypSoap, NULL);
00504   }
00505   else
00506   {
00507     //gSoap will automatically log to RECV.log, SEND.log and ERROR.log
00508     //unless we have disabled them above
00509   }
00510   return mypSoap;
00511 }//getSoapConnection
00512 
00513 wchar_t* OmgModellerWebServicesPlugin::convertToWideChar( const char* p )
00514 {
00515   wchar_t *r;
00516   r = new wchar_t[strlen(p)+1];
00517   const char *tempsource = p;
00518   wchar_t *tempdest = r;
00519   while ( (*tempdest++ = *tempsource++) );
00520   return r;
00521 }
00522 
00523 // Entry point for the Qt plugin:
00524 Q_EXPORT_PLUGIN2(webservices_modeller_plugin, OmgModellerWebServicesPlugin);
00525  

Generated on Mon Apr 28 15:09:27 2008 for openModellerDesktop by  doxygen 1.4.1-20050210