NIREP
|
00001 /*************************************************************************************** 00002 * Programmer: Gary E. Christensen 00003 * Date: 6/24/2010 00004 * Name: ResourceDescriptionList 00005 * Purpose: This class keeps a list of the data files available to be loaded into memory. 00006 * This class lists the data descriptions of images, object maps, landmark files, and 00007 * contour files. It does not list information about transformations. 00008 * This class creates a map of DataDescription objects by parsing a data resource file. 00009 * Required XML Tags: 00010 * database - main tag of resource description list, must contian an id. 00011 * resource - one tag for each resource in database, each resource can contain 00012 * multiple data descriptions, i.e., files 00013 * Optional XML Tags: 00014 * database_attributes - contains non-required user defined XML tags and values 00015 ******************************************************************************************/ 00016 #include "ResourceDescriptionList.h" 00017 #include "BasicDescription.h" 00018 #include "NIREPDefinitions.h" 00019 #include <wx/log.h> 00020 00021 #include <iostream> 00022 #include <fstream> 00023 00026 void ResourceDescriptionList::Clear(){ 00027 m_filename.clear(); 00028 m_namespace.clear(); 00029 00030 ClearNameSpaceDescrips(); 00031 ClearCSDescrips(); 00032 ClearAlgorithmDescrips(); 00033 ClearDataDescrips(); 00034 ClearTransformDescrips(); 00035 ClearRDLs(); 00036 ClearLabelDescrips(); 00037 } 00038 00043 //JAH changed so that we now use a FILE pointer as the main 00044 //function 00045 bool ResourceDescriptionList::Save(const std::string & filename){ 00046 FILE *tempFile = fopen(filename.c_str(),"w"); 00047 bool returnValue = Save(tempFile); 00048 fclose(tempFile); 00049 00050 return returnValue; 00051 } 00052 00053 00058 //JAH added 00059 bool ResourceDescriptionList::Save(FILE * file){ 00060 TiXmlDocument doc; 00061 00062 // Add XML declaration to resource description list 00063 TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" ); 00064 if (decl){ 00065 doc.LinkEndChild( decl ); 00066 } else { 00067 wxString msg(wxT("Error: Failed to allocate memory for Tiny XML declaration tag.")); 00068 msg += wxT("\nFile: "); 00069 //msg.Append(file->_tmpfname); 00070 wxLogError(msg); // Show a dialog box with error message 00071 00072 return false; // Failed to allocate memory 00073 } 00074 00075 // Add the database tag to resource description list 00076 TiXmlElement * root = new TiXmlElement("ResourceDescriptionList"); 00077 if (root){ 00078 root->SetAttribute("namespace", m_namespace.c_str()); 00079 doc.LinkEndChild( root ); 00080 } else { 00081 wxString msg(wxT("Error: Failed to allocate memory for Tiny XML ResourceDescriptionList tag.")); 00082 msg += wxT("\nFile: "); 00083 //msg.Append(file->_tmpfname); 00084 wxLogError(msg); // Show a dialog box with error message 00085 00086 return false; // Failed to allocate memory 00087 } 00088 00089 // Cycle through included filenames. The filenames are the keys to the m_RDL map. 00090 RDLList::iterator RDL_iter; 00091 for (RDL_iter=m_RDL.begin(); RDL_iter != m_RDL.end(); RDL_iter++) { 00092 const std::string & key= RDL_iter->first; 00093 00094 TiXmlElement * includeRDL = new TiXmlElement( "includeRDL" ); 00095 if (includeRDL != NULL){ 00096 includeRDL->LinkEndChild( new TiXmlText(key.c_str())); 00097 root->LinkEndChild( includeRDL ); 00098 }else{ 00099 wxString msg(wxT("Error: Failed to allocate memory for Tiny XML includeRDL tag.")); 00100 msg += wxT("\nFile: "); 00101 //msg.Append(file->_tmpfname); 00102 wxLogError(msg); // Show a dialog box with error message 00103 00104 return false; // Failed to allocate memory 00105 } 00106 } 00107 00108 // Add namespace description to resource description list DOM 00109 if (!m_namespace_descrip.empty()){ 00110 BasicList::iterator ns_iter; 00111 for (ns_iter=m_namespace_descrip.begin(); ns_iter != m_namespace_descrip.end(); ns_iter++) { 00112 BasicDescription * value= ns_iter->second; 00113 root->LinkEndChild(value->CreateDOM("namespace_description")); 00114 } 00115 } 00116 00117 // Add algorithm description to resource description list DOM 00118 if (!m_algorithm_descrip.empty()){ 00119 BasicList::iterator a_iter; 00120 for (a_iter=m_algorithm_descrip.begin(); a_iter != m_algorithm_descrip.end(); a_iter++) { 00121 BasicDescription * value= a_iter->second; 00122 root->LinkEndChild(value->CreateDOM("algorithm_description")); 00123 } 00124 } 00125 00126 // Add label descriptions to resource description list DOM 00127 if (!m_label_descrip.empty()){ 00128 std::string buf; 00129 BasicList::iterator label_iter; 00130 for (label_iter=m_label_descrip.begin(); label_iter != m_label_descrip.end(); label_iter++) { 00131 BasicDescription * value= label_iter->second; 00132 root->LinkEndChild(value->CreateDOM("label_description")); 00133 } 00134 } 00135 00136 // Add coordinate system description to resource description list DOM 00137 if (!m_cs_descrip.empty()){ 00138 std::string buf; 00139 BasicList::iterator cs_iter; 00140 for (cs_iter=m_cs_descrip.begin(); cs_iter != m_cs_descrip.end(); cs_iter++) { 00141 BasicDescription * value= cs_iter->second; 00142 TiXmlElement * cs_description = value->CreateDOM("cs_description"); 00143 00144 // If there was no namespace in description, set the namespace to the 00145 // file default namespace. 00146 buf.clear(); 00147 int readOkay = cs_description->QueryStringAttribute("ns", &buf); 00148 if (!readOkay || buf.empty()){ 00149 cs_description->SetAttribute("ns", m_namespace.c_str()); 00150 } 00151 root->LinkEndChild(cs_description); 00152 } 00153 } 00154 00155 // Add data description to resource description list DOM 00156 if (!m_data_descrip.empty()){ 00157 ResourceList::iterator dd_iter; 00158 for (dd_iter=m_data_descrip.begin(); dd_iter != m_data_descrip.end(); dd_iter++) { 00159 ResourceDescription * value= dd_iter->second; 00160 root->LinkEndChild(value->CreateDOM("data_description")); 00161 } 00162 } 00163 00164 // Add resources to resource description list 00165 if (!m_transform_descrip.empty()){ 00166 ResourceList::iterator td_iter; 00167 for (td_iter=m_transform_descrip.begin(); td_iter != m_transform_descrip.end(); td_iter++) { 00168 ResourceDescription * value= td_iter->second; 00169 root->LinkEndChild(value->CreateDOM("transform_description")); 00170 } 00171 } 00172 00173 bool saveOkay = doc.SaveFile(file); 00174 00175 if (saveOkay){ 00176 return true; 00177 } else { 00178 wxString msg(doc.ErrorDesc(), wxConvUTF8); // Get the error message from the tiny xml document 00179 msg += wxT("\nFile: "); 00180 //msg.Append(file->_tmpfname); 00181 wxLogError(msg); // Show a dialog box with error message 00182 00183 return false; // Failed to save file 00184 } 00185 } 00186 00190 bool ResourceDescriptionList::Load(const std::string & filename){ 00191 // Open fileName, parse file, and construct spatial data resource list 00192 TiXmlDocument doc(filename.c_str()); 00193 bool loadOkay = doc.LoadFile(); 00194 00195 if ( !loadOkay ) { 00196 wxString msg(doc.ErrorDesc(), wxConvUTF8); // Get the error message from the tiny xml document 00197 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00198 wxLogError(msg); // Show a dialog box with error message 00199 00200 return false; 00201 } 00202 00203 00204 // Set the filename of this object to filename if successfully able to load and parse it. 00205 this->SetFilename(filename); 00206 00207 TiXmlHandle hDoc(&doc); 00208 TiXmlElement* pElem; 00209 TiXmlHandle hRoot(NULL); 00210 00211 pElem=hDoc.FirstChildElement().Element(); 00212 // should always have a valid root but handle gracefully if it does 00213 if (!pElem){ 00214 wxString msg(wxT("Error: no root tag")); 00215 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00216 wxLogError(msg); // Show a dialog box with error message 00217 00218 return false; 00219 } 00220 00221 //Root should be ResourceDescriptionList and have a namespace 00222 if (pElem->ValueStr().compare("ResourceDescriptionList") == 0){ 00223 if (pElem->QueryStringAttribute("namespace", &m_namespace)==TIXML_NO_ATTRIBUTE){ 00224 wxString msg(wxT("Error: Missing default namespace (i.e., na=\"\") in ResourceDescriptionList tag.")); 00225 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00226 wxLogError(msg); // Show a dialog box with error message 00227 00228 return false; // error: namespace missing 00229 } 00230 }else{ 00231 wxString msg(wxT("Error: Missing ResourceDescriptionList tag.")); 00232 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00233 wxLogError(msg); // Show a dialog box with error message 00234 00235 return false; // error: no ResourceDescriptionList tag in document 00236 } 00237 00238 // save this for later 00239 hRoot=TiXmlHandle(pElem); 00240 00241 // Get directory of current RDL file 00242 wxFileName dir(wxString(m_filename.c_str(), wxConvUTF8)); 00243 wxString defaultDirectory = dir.GetPath(); 00244 00245 //Go to first attribute child of description and set attributes 00246 //Use hRoot to ensure that pElem is set to NULL if database_attributes is missing 00247 pElem=hRoot.FirstChildElement().Element(); 00248 for( pElem; pElem; pElem=pElem->NextSiblingElement()) { 00249 const std::string pKey = std::string(pElem->Value()); 00250 00251 00252 if (pKey.compare("namespace_description") == 0){ 00253 BasicDescription * bdescrip = new BasicDescription(pElem); 00254 if(bdescrip){ 00255 // Use namespace as key for adding namespace description 00256 AddNameSpaceDescrip(bdescrip->GetID(), bdescrip); 00257 } else { 00258 wxString msg(wxT("Error: Failed to allocate memory for namespace description.")); 00259 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00260 wxLogError(msg); // Show a dialog box with error message 00261 00262 return false; // Failed to allocate memory 00263 } 00264 } 00265 00266 if (pKey.compare("cs_description") == 0){ 00267 BasicDescription * bdescrip = new BasicDescription(pElem,m_namespace); 00268 if(bdescrip){ 00269 // Use coordinate system namespace & id as key for adding coordinate system description 00270 AddCSDescrip(bdescrip->CreateNSID(), bdescrip); 00271 } else { 00272 wxString msg(wxT("Error: Failed to allocate memory for coordinate system description.")); 00273 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00274 wxLogError(msg); // Show a dialog box with error message 00275 00276 return false; // Failed to allocate memory 00277 } 00278 } 00279 00280 if (pKey.compare("algorithm_description") == 0){ 00281 BasicDescription * bdescrip = new BasicDescription(pElem); 00282 if(bdescrip){ 00283 // Use algorithm id as key for adding aglorithm description 00284 AddAlgorithmDescrip(bdescrip->GetID(), bdescrip); 00285 } else { 00286 wxString msg(wxT("Error: Failed to allocate memory for algorithm description.")); 00287 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00288 wxLogError(msg); // Show a dialog box with error message 00289 00290 return false; // Failed to allocate memory 00291 } 00292 } 00293 00294 if (pKey.compare("label_description") == 0){ 00295 BasicDescription * bdescrip = new BasicDescription(pElem); 00296 if(bdescrip){ 00297 // Use label id as key for adding label description 00298 AddLabelDescrip(bdescrip->GetID(), bdescrip); 00299 } else { 00300 wxString msg(wxT("Error: Failed to allocate memory for label description.")); 00301 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00302 wxLogError(msg); // Show a dialog box with error message 00303 00304 return false; // Failed to allocate memory 00305 } 00306 } 00307 00308 if (pKey.compare("data_description") == 0){ 00309 ResourceDescription * rdescrip = new ResourceDescription(pElem,m_namespace); 00310 if(rdescrip){ 00311 // Use dmid as key to add data description 00312 if (rdescrip->GetDMID().empty()){ 00313 std::string dmid = rdescrip->CreateLabelDMID(); 00314 if (dmid.empty()){ 00315 wxString msg(wxT("Error: Failed to create data manager id.")); 00316 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00317 wxLogError(msg); // Show a dialog box with error message 00318 00319 return false; // Failed to create dmid 00320 } 00321 rdescrip->SetDMID( dmid ); 00322 } 00323 // Set default directory for data description 00324 rdescrip->SetDirectory( std::string(defaultDirectory.mb_str()) ); 00325 AddDataDescrip(rdescrip->GetDMID(), rdescrip); 00326 } else { 00327 wxString msg(wxT("Error: Failed to allocate memory for data description.")); 00328 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00329 wxLogError(msg); // Show a dialog box with error message 00330 00331 return false; // Failed to allocate memory 00332 } 00333 } 00334 00335 if (pKey.compare("transform_description") == 0){ 00336 ResourceDescription * rdescrip = new ResourceDescription(pElem,m_namespace); 00337 if(rdescrip){ 00338 // Use dmid as key to add transformation description 00339 if (rdescrip->GetDMID().empty()){ 00340 std::string dmid = rdescrip->CreateTransformDMID(); 00341 if (dmid.empty()){ 00342 wxString msg(wxT("Error: Failed to create transform data manager id.")); 00343 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00344 wxLogError(msg); // Show a dialog box with error message 00345 00346 return false; // Failed to create dmid 00347 } 00348 rdescrip->SetDMID( dmid ); 00349 } 00350 // Set default directory for transform description 00351 rdescrip->SetDirectory( std::string(defaultDirectory.mb_str()) ); 00352 AddTransformDescrip(rdescrip->GetDMID(), rdescrip); 00353 } else { 00354 wxString msg(wxT("Error: Failed to allocate memory for transform description.")); 00355 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00356 wxLogError(msg); // Show a dialog box with error message 00357 00358 return false; // Failed to allocate memory 00359 } 00360 } 00361 00362 if (pKey.compare("includeRDL") == 0){ 00363 const wxString fn = wxString(pElem->GetText(), wxConvUTF8); 00364 wxFileName fName(fn); 00365 00366 // Set directory to defaultDirectory if fname is short form. 00367 // Assume fname is relative to directory containing filename. 00368 // Use current working directory if defaultDirectory is an empty string. 00369 fName.Normalize(wxPATH_NORM_LONG|wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|wxPATH_NORM_ABSOLUTE,defaultDirectory); 00370 std::string fullFileName = std::string(fName.GetFullPath().mb_str()); 00371 00372 ResourceDescriptionList * rdl = new ResourceDescriptionList(fullFileName,this); 00373 if (rdl){ 00374 // Use filename of RDL as key to add RDL. Add RDL to root RDL list 00375 // RDL is passed from parent to parent until added to root RDL list 00376 AddRDL(fullFileName, rdl); 00377 } else { 00378 wxString msg(wxT("Error: Failed to allocate memory for included resource description list.")); 00379 msg += wxT("\nFile: ") + wxString(filename.c_str(), wxConvUTF8); 00380 wxLogError(msg); // Show a dialog box with error message 00381 00382 return false; // Failed to allocate memory 00383 } 00384 } 00385 00386 } 00387 00388 return true; 00389 } 00390 00397 bool ResourceDescriptionList::LoadFromDisplayDescription(const std::string & displayDescriptionFilename){ 00398 wxString temp_str; // Used to remove spaces from left and right of a string 00399 std::string compare_string; // used to compare lower case string to display description tag 00400 00401 std::ifstream dd_file(displayDescriptionFilename.c_str()); 00402 00403 if (dd_file.is_open()){ 00404 00405 // loop through the file one line at a time to find begin resource descirption list 00406 std::string line; 00407 bool found_begin = false; 00408 while (!dd_file.eof() && (!found_begin)){ 00409 getline(dd_file,line); 00410 found_begin = CaseInsensitiveFind(line,"Begin ResourcedescriptionList"); 00411 } 00412 00413 // Report Error if did not find Begin ResourceDescriptionList 00414 if (dd_file.eof()){ 00415 wxString msg(wxT("Error: ")); 00416 msg += wxString(displayDescriptionFilename.c_str(), wxConvUTF8); 00417 msg += wxT(" does not contain Begin ResourceDescriptionList statement."); 00418 wxLogError(msg); 00419 00420 dd_file.close(); 00421 return false; 00422 } 00423 00424 00425 getline(dd_file,line); 00426 bool found_end = CaseInsensitiveFind(line,"End ResourceDescriptionList"); 00427 00428 while (!dd_file.eof() && (!found_end)){ 00429 00430 if(!line.empty()){ 00431 // Get directory of Display Description file 00432 wxFileName dir(wxString(displayDescriptionFilename.c_str(), wxConvUTF8)); 00433 wxString defaultDirectory = dir.GetPath(); 00434 00435 wxString fn = wxString(line.c_str(), wxConvUTF8); 00436 fn.Trim(false); // remove spaces from left side of filename 00437 fn.Trim(true); 00438 wxFileName fName(fn); 00439 00440 // Set directory to defaultDirectory if fname is a short form of a filename. 00441 // Assume that fname is relative to directory containing Display Description file. 00442 // Use current working directory if defaultDirectory is an empty string. 00443 fName.Normalize(wxPATH_NORM_LONG|wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|wxPATH_NORM_ABSOLUTE,defaultDirectory); 00444 std::string rdl_filename = std::string(fName.GetFullPath().mb_str()); 00445 00446 if (!rdl_filename.empty()){ 00447 if (GetFilename().empty()){ 00448 this->Load(rdl_filename); 00449 } else { 00450 this->AddRDL(rdl_filename,new ResourceDescriptionList(rdl_filename)); 00451 } 00452 } 00453 } 00454 00455 getline(dd_file,line); 00456 found_end = CaseInsensitiveFind(line,"End ResourceDescriptionList"); 00457 } 00458 00459 // Check if we did not find End ResourceDescriptionList filename 00460 if (dd_file.eof()){ 00461 wxString msg(wxT("Error: ")); 00462 msg += wxString(displayDescriptionFilename.c_str(), wxConvUTF8); 00463 msg += wxT(" does not contain End ResourceDescriptionList"); 00464 wxLogError(msg); 00465 00466 dd_file.close(); 00467 return false; 00468 } 00469 00470 dd_file.close(); 00471 return true; 00472 00473 }else{ 00474 wxString msg(wxT("Error: ")); 00475 msg += wxT("Failed to open "); 00476 msg += wxString(displayDescriptionFilename.c_str(), wxConvUTF8); 00477 wxLogError(msg); 00478 00479 return false; 00480 } 00481 } 00482