packagewxp.cpp

00001 
00002 // Name:        packagewxp.cpp
00003 // Purpose:     wxPackageXMLDescriptor
00004 // Author:      Francesco Montorsi
00005 // Modified by:
00006 // Created:     2006-06-29
00007 // RCS-ID:      $Id: packagewxp.cpp,v 1.15 2007/01/28 15:56:11 frm Exp $
00008 // Copyright:   (c) Francesco Montorsi
00009 // Licence:     wxWidgets licence
00011 
00012 
00013 // For compilers that support precompilation, includes "wx/wx.h".
00014 #include "wx/wxprec.h"
00015 
00016 #ifdef __BORLANDC__
00017 #pragma hdrstop
00018 #endif
00019 
00020 #ifndef WX_PRECOMP
00021 #include "wx/wx.h"
00022 #endif
00023 
00024 // includes
00025 #include <wx/fileconf.h>
00026 #include <wx/mstream.h>
00027 #include <wx/apptrait.h>
00028 
00029 #include "wxp/packagewxp.h"
00030 
00031 // RTTI
00032 IMPLEMENT_DYNAMIC_CLASS(wxPackageXMLDescriptor, wxPackageXML)
00033 
00034 // global objects
00035 wxPackageXMLDescriptor wxEmptyPackageXMLDescriptor;
00036 
00037 
00038 // ----------------------------------------------------------------------------
00039 // helper save functions for wxPackageXMLDescriptor::ResetEnumeration
00040 // ----------------------------------------------------------------------------
00041 
00042 void FormatAuthor(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00043 {
00044     n->AddProperty(wxT("name"), pkg.GetAuthors().Item(i));
00045     if (!pkg.GetAuthorsHref().Item(i).IsEmpty())
00046         n->AddProperty(wxT("href"), pkg.GetAuthorsHref().Item(i));
00047 }
00048 
00049 void FormatMaintainer(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00050 {
00051     n->AddProperty(wxT("name"), pkg.GetMaintainers().Item(i));
00052     if (!pkg.GetMaintainersHref().Item(i).IsEmpty())
00053         n->AddProperty(wxT("href"), pkg.GetMaintainersHref().Item(i));
00054 }
00055 
00056 void FormatMirror(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00057 {
00058     n->AddProperty(wxT("href"), pkg.GetDownloadHref(i));
00059 }
00060 
00061 void FormatRef(wxXmlNode *n, const wxPackageDataWithRef &ref)
00062 {
00063     n->AddProperty(wxT("href"), ref.GetHref());
00064     n->AddProperty(wxT("localref"), ref.GetLocalRef());
00065 }
00066 
00067 void FormatDoc(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00068 {
00069     FormatRef(n, pkg.GetDocumentation(i));
00070 }
00071 
00072 void FormatScreenshot(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00073 {
00074     FormatRef(n, pkg.GetScreenshot(i));
00075 }
00076 
00077 void FormatSupportedPort(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00078 {
00079     wxPortId id = (wxPortId)pkg.GetSupportedPorts().Item(i);
00080     n->AddProperty(wxT("name"), wxPlatformInfo::GetPortIdName(id, false));
00081     n->AddProperty(wxT("versions"), pkg.GetSupportedVersions().Item(i));
00082 }
00083 
00084 void FormatTestedPort(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00085 {
00086     wxPortId id = (wxPortId)pkg.GetTestedPorts().Item(i);
00087     n->AddProperty(wxT("name"), wxPlatformInfo::GetPortIdName(id, false));
00088     n->AddProperty(wxT("versions"), pkg.GetTestedVersions().Item(i));
00089 }
00090 
00091 void FormatRequiredDependency(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00092 {
00093     static wxPackageDependencyArray arr;
00094 
00095     if (i == 0)
00096         arr = pkg.GetDependencies().GetDependenciesOfType(wxPDT_REQUIRED);
00097 
00098     n->AddProperty(wxT("name"), arr[i].GetName());
00099     n->AddProperty(wxT("versions"), arr[i].GetVersion().GetAsString());
00100 }
00101 
00102 void FormatSuggestedDependency(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00103 {
00104     static wxPackageDependencyArray arr;
00105 
00106     if (i == 0)
00107         arr = pkg.GetDependencies().GetDependenciesOfType(wxPDT_SUGGESTED);
00108 
00109     n->AddProperty(wxT("name"), arr[i].GetName());
00110     n->AddProperty(wxT("versions"), arr[i].GetVersion().GetAsString());
00111 }
00112 
00113 void FormatExclude(wxXmlNode *n, size_t i, const wxPackageInfo &pkg)
00114 {
00115     static size_t files, dirs, patterns;
00116     
00117     if (i == 0)
00118     {
00119         files = pkg.GetExcluded(wxPEM_FILE).GetCount();
00120         dirs = pkg.GetExcluded(wxPEM_DIRECTORY).GetCount();
00121         patterns = pkg.GetExcluded(wxPEM_PATTERN).GetCount();
00122     }
00123 
00124     // create first the excluded FILE list
00125     if (i < files)
00126     {
00127         wxString f = pkg.GetExcluded(wxPEM_FILE).Item(i);
00128         n->AddProperty(wxT("file"), wxT("file:///") + f);
00129     }
00130     else if (i < files+dirs)    // then the DIRECTORY list
00131     {
00132         wxString d = pkg.GetExcluded(wxPEM_DIRECTORY).Item(i-files);
00133         n->AddProperty(wxT("directory"), wxT("file:///") + d);
00134     }
00135     else        // last the PATTERN list
00136     {
00137         wxString p = pkg.GetExcluded(wxPEM_PATTERN).Item(i-files-dirs);
00138         n->AddProperty(wxT("pattern"), p);
00139     }
00140 }
00141 
00142 
00143 
00144 
00145 // ----------------------------------------------------------------------------
00146 // wxPackageXMLDescriptor - save API
00147 // ----------------------------------------------------------------------------
00148 
00149 void SetProp(wxXmlNode *node, const wxString &name, const wxString &val)
00150 {
00151     /*wxXmlProperty *p = node->GetProperties();
00152     while (p)
00153     {
00154         if (p->GetName() == name)
00155         {
00156             p->SetValue(val);
00157             return;
00158         }
00159 
00160         p = p->GetNext();
00161     }
00162     
00163     NOT NECESSARY SINCE REMOVEPROPS WAS USED ON THE TREE
00164     */
00165 
00166     if (val.IsEmpty())
00167         return;     // do not add empty properties
00168 
00169     // the property is missing - create it !
00170     node->AddProperty(name, val);
00171 }
00172 
00173 void wxPackageXMLDescriptor::SetRefProp(wxXmlNode *node, const wxPackageDataWithRef &ref)
00174 {
00175     SetProp(node, wxT("href"), ref.GetHref());
00176     SetProp(node, wxT("localref"), ref.GetLocalRef());
00177 }
00178 
00179 void wxPackageXMLDescriptor::SetNodeContent(wxXmlNode *node, const wxString &text)
00180 {
00181     wxXmlNode *p = node->GetChildren();
00182     bool found = false;
00183 
00184     while (p)
00185     {
00186         if (p->GetType() == wxXML_TEXT_NODE ||
00187             p->GetType() == wxXML_CDATA_SECTION_NODE)
00188         {
00189             if (!found)
00190             {
00191                 p->SetContent(text);
00192                 found = true;
00193             }
00194             else
00195             {
00196                 // remove all other TEXT & CDATA nodes
00197                 wxXmlNode *next = p->GetNext();
00198                 node->RemoveChild(p);
00199                 p = next;
00200 
00201                 if (!p)
00202                     return;
00203             }
00204         }
00205 
00206         p = p->GetNext();
00207     }
00208 
00209     if (found) return;
00210 
00211     // no text/cdata child found?
00212     // create it ourselves
00213     if (!text.IsEmpty())
00214     {
00215         wxXmlNode *content = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, text);
00216         node->AddChild(content);
00217     }
00218 }
00219 
00220 void wxPackageXMLDescriptor::RemoveAllChildrenFrom(wxXmlNode *node, const wxString &name)
00221 {
00222     wxXmlNode *p = node->GetChildren();
00223     while (p)
00224     {
00225         if (name.IsEmpty() ||
00226             p->GetName() == name)
00227         {
00228             wxXmlNode *next = p->GetNext();
00229             node->RemoveChild(p);
00230             delete p;
00231             p = next;
00232         }
00233         else
00234             p = p->GetNext();
00235     }
00236 }
00237 
00238 void wxPackageXMLDescriptor::RemoveAllPropertiesFrom(wxXmlNode *node, const wxString &name)
00239 {
00240     wxXmlProperty *p = node->GetProperties();
00241     while (p)
00242     {
00243         if (name.IsEmpty() ||
00244             p->GetName() == name)
00245         {
00246             wxXmlProperty *next = p->GetNext();
00247             delete p;
00248             p = next;
00249         }
00250         else
00251             p = p->GetNext();
00252     }
00253     node->SetProperties(NULL);
00254 
00255     // recursively remove all properties
00256     wxXmlNode *pn = node->GetChildren();
00257     while (pn)
00258     {
00259         RemoveAllPropertiesFrom(pn);
00260         pn = pn->GetNext();
00261     }
00262 }
00263 
00264 void wxPackageXMLDescriptor::ResetEnumeration(wxXmlNode *parent,
00265                                               int parentIndentLevel,
00266                                               const wxString &nodename,
00267                                               size_t max,
00268                                               FormatNodeFnc f,
00269                                               const wxPackageInfo &pkg,
00270                                               bool eraseChildren)
00271 {
00272     if (eraseChildren)
00273         RemoveAllChildrenFrom(parent);
00274 
00275     for (size_t i=0; i < max; i++)
00276     {
00277         wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, nodename);
00278 
00279         f(n, i, pkg);
00280 
00281         AddChildIndentation(parent, parentIndentLevel+1);
00282         parent->AddChild(n);
00283     }
00284 
00285     if (max > 0)
00286         AddChildIndentation(parent, parentIndentLevel);
00287 }
00288 
00289 void wxPackageXMLDescriptor::CreateSiblingIfMissing(wxXmlNode *prev, wxXmlNode **node,
00290                                                     const wxString &name)
00291 {
00292     wxASSERT(node && prev);
00293 
00294     if (*node)
00295         return; // the sibling already exists
00296 
00297     // the sibling is missing, create it
00298     *node = new wxXmlNode(wxXML_ELEMENT_NODE, name);
00299     (*node)->SetParent(prev->GetParent());
00300 
00301     // add indentation for this child, before appending it to the sibling list
00302     int level = prev->GetDepth();
00303     wxXmlNode *indent = AddSiblingIndentation(prev, level);
00304     wxXmlNode *oldnext = indent->GetNext();
00305     indent->SetNext(*node);
00306     (*node)->SetNext(oldnext);
00307 
00308     // add indentation inside the just-created node, if necessary
00309     if (level == 1)         // don't put e.g. a newline inside the <id> tag
00310         AddChildIndentation(*node, level);
00311 }
00312 
00313 void wxPackageXMLDescriptor::CreateChildIfMissing(wxXmlNode *parent, wxXmlNode *prev,
00314                                                   wxXmlNode **node, const wxString &name,
00315                                                   int level)
00316 {
00317     wxASSERT(node && parent);
00318 
00319     if (*node)
00320         return; // the child already exists
00321 
00322     // the child is missing, create it
00323     *node = new wxXmlNode(wxXML_ELEMENT_NODE, name);
00324     (*node)->SetParent(parent);
00325     parent->InsertChild(*node, prev);
00326 
00327     // add indentation both inside the new node (if necessary) and just before it
00328     if (level == 1)             // don't put e.g. a newline inside the <id> tag
00329         AddChildIndentation(*node, level);
00330     InsertChildIndentation(parent, *node, level);
00331 }
00332 
00333 void wxPackageXMLDescriptor::CreateMissingNodes()
00334 {
00335     if (!GetRoot())
00336     {
00337         // create root first
00338         SetRoot(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("wxpackage")));
00339         AddChildIndentation(GetRoot(), 0);
00340     }
00341 
00342     // create main section nodes if missing
00343     CreateChildIfMissing(GetRoot(), NULL, &m_pBasics, wxT("basics"), 1);
00344     CreateSiblingIfMissing(m_pBasics, &m_pPackaging, wxT("packaging"));
00345     CreateSiblingIfMissing(m_pPackaging, &m_pLicensing, wxT("licensing"));
00346     CreateSiblingIfMissing(m_pLicensing, &m_pDetails, wxT("details"));
00347     CreateSiblingIfMissing(m_pDetails, &m_pDep, wxT("dependencies"));
00348     CreateSiblingIfMissing(m_pDep, &m_pBuildSystem, wxT("build-system"));
00349 
00350     // BASIC data
00351     CreateChildIfMissing(m_pBasics, NULL, &m_pId, wxT("id"), 2);
00352     CreateSiblingIfMissing(m_pId, &m_pDescription, wxT("description"));
00353     CreateSiblingIfMissing(m_pDescription, &m_pKeywords, wxT("keywords"));
00354     CreateSiblingIfMissing(m_pKeywords, &m_pCategory, wxT("category"));
00355     CreateSiblingIfMissing(m_pCategory, &m_pWebsite, wxT("website"));
00356     CreateSiblingIfMissing(m_pWebsite, &m_pCreationDate, wxT("creation-date"));
00357 
00358     // PACKAGING data
00359     CreateChildIfMissing(m_pPackaging, NULL, &m_pRoot, wxT("root"), 2);
00360     CreateSiblingIfMissing(m_pRoot, &m_pFileName, wxT("filename"));
00361     CreateSiblingIfMissing(m_pFileName, &m_pContents, wxT("contents"));
00362     CreateSiblingIfMissing(m_pContents, &m_pCompress, wxT("compress"));
00363     CreateSiblingIfMissing(m_pCompress, &m_pUpload, wxT("upload"));
00364 
00365     // LICENSING data
00366     CreateChildIfMissing(m_pLicensing, NULL, &m_pLicense, wxT("license"), 2);
00367     CreateSiblingIfMissing(m_pLicense, &m_pOrganization, wxT("organization"));
00368     CreateSiblingIfMissing(m_pOrganization, &m_pCost, wxT("cost"));
00369     CreateSiblingIfMissing(m_pCost, &m_pCredits, wxT("credits"));
00370     CreateSiblingIfMissing(m_pCredits, &m_pCopyright, wxT("copyright"));
00371     CreateSiblingIfMissing(m_pCopyright, &m_pAuthors, wxT("authors"));
00372     CreateSiblingIfMissing(m_pAuthors, &m_pMaintainers, wxT("maintainers"));
00373 
00374     // DETAILS data
00375     CreateChildIfMissing(m_pDetails, NULL, &m_pStatus, wxT("status"), 2);
00376     CreateSiblingIfMissing(m_pStatus, &m_pProgLanguage, wxT("proglanguage"));
00377     CreateSiblingIfMissing(m_pProgLanguage, &m_pSamples, wxT("samples"));
00378     CreateSiblingIfMissing(m_pSamples, &m_pDownloads, wxT("download"));
00379     CreateSiblingIfMissing(m_pDownloads, &m_pLogo, wxT("logo"));
00380     CreateSiblingIfMissing(m_pLogo, &m_pRSS, wxT("rss"));
00381     CreateSiblingIfMissing(m_pRSS, &m_pScreenshots, wxT("screenshots"));
00382     CreateSiblingIfMissing(m_pScreenshots, &m_pDocs, wxT("documentation"));
00383 
00384     // DEPENDENCIES data
00385     CreateChildIfMissing(m_pDep, NULL, &m_pSupportedPorts, wxT("supported-ports"), 2);
00386     CreateSiblingIfMissing(m_pSupportedPorts, &m_pTestedPorts, wxT("tested-ports"));
00387     CreateSiblingIfMissing(m_pTestedPorts, &m_pDependencies[wxPDT_REQUIRED],
00388                            wxT("dependency"));
00389     CreateSiblingIfMissing(m_pDependencies[wxPDT_REQUIRED],
00390                            &m_pDependencies[wxPDT_SUGGESTED], wxT("dependency"));
00391 
00392     // BUILD SYSTEM data
00393     CreateChildIfMissing(m_pBuildSystem, NULL, &m_pFormats, wxT("formats"), 2);
00394     CreateSiblingIfMissing(m_pFormats, &m_pOptions, wxT("options"));
00395     CreateSiblingIfMissing(m_pOptions, &m_pStages, wxT("stages"));
00396 }
00397 
00398 void wxPackageXMLDescriptor::SetPackageInfo(const wxPackageInfo &pkg)
00399 {
00400     // NOTE: we don't want a
00401     //          wxASSERT(pkg.IsOk());
00402     //       here as we want to allow the user to save also invalid wxPackageInfo
00403     //       object (this is useful when e.g. the user wants to stop working on
00404     //       a WXP file and resume later)...
00405 
00406     CreateMissingNodes();
00407 
00408     // recursively remove all properties from the nodes of this document:
00409     // this way properties which have not been recognized when loading the
00410     // document are removed; SetProp() will regenerate the valid ones.
00411     RemoveAllPropertiesFrom(GetRoot());
00412 
00413     // the version of this WXP file
00414     SetProp(GetRoot(), wxT("version"), WXP_VERSION_STRING);
00415 
00416     // BASIC data
00417     SetProp(m_pId, wxT("name"), pkg.GetName());
00418     SetProp(m_pId, wxT("version"), pkg.GetVersion());
00419     SetNodeContent(m_pDescription, pkg.GetDescription());
00420     SetNodeContent(m_pKeywords, pkg.GetKeywordsStr());
00421     SetProp(m_pCategory, wxT("primary"), 
00422             pkg.GetPrimaryCategory() == wxPC_INVALID ? 
00423                 wxT("invalid") : pkg.GetPrimaryCategoryStr());
00424     SetProp(m_pCategory, wxT("secondary"), 
00425             pkg.GetSecondaryCategory() == wxPC_INVALID ? 
00426                 wxT("invalid") : pkg.GetSecondaryCategoryStr());
00427     SetProp(m_pWebsite, wxT("href"), pkg.GetWebsite());
00428     SetNodeContent(m_pCreationDate, pkg.GetCreationDate().Format(wxT("%d %B %Y")));
00429 
00430     // PACKAGING data
00431     SetNodeContent(m_pRoot, pkg.GetRelativeRoot());
00432     SetNodeContent(m_pUpload, pkg.GetUploadDestination());
00433     SetNodeContent(m_pCompress, pkg.GetCompressionModeStr());
00434     SetNodeContent(m_pFileName, pkg.GetOutputFileName());
00435 
00436     size_t total = 0;
00437     total += pkg.GetExcluded(wxPEM_FILE).GetCount();
00438     total += pkg.GetExcluded(wxPEM_DIRECTORY).GetCount();
00439     total += pkg.GetExcluded(wxPEM_PATTERN).GetCount();
00440     ResetEnumeration(m_pContents, 2, wxT("exclude"),
00441                      total, FormatExclude, pkg);
00442 
00443     // LICENSING data
00444     SetProp(m_pLicense, wxT("name"), pkg.GetLicenseRef().GetData());
00445     SetProp(m_pLicense, wxT("type"),
00446                 pkg.GetLicenseType() == wxPLT_INVALID ? 
00447                     wxT("invalid") : pkg.GetLicenseTypeStr());
00448     SetRefProp(m_pLicense, pkg.GetLicenseRef());
00449     SetProp(m_pOrganization, wxT("name"), pkg.GetOrganization());
00450     SetProp(m_pOrganization, wxT("href"), pkg.GetOrganizationHref());
00451     SetNodeContent(m_pCost, pkg.GetCost());
00452     SetNodeContent(m_pCredits, pkg.GetCredits());
00453     SetNodeContent(m_pCopyright, pkg.GetCopyright());
00454 
00455     ResetEnumeration(m_pAuthors, 2, wxT("author"), pkg.GetAuthors().GetCount(),
00456                      FormatAuthor, pkg);
00457     ResetEnumeration(m_pMaintainers, 2, wxT("maintainer"), pkg.GetMaintainers().GetCount(),
00458                      FormatMaintainer, pkg);
00459 
00460     // DETAILS data
00461     SetNodeContent(m_pStatus,
00462                     pkg.GetDevelopmentStatus() == wxPDS_INVALID ? 
00463                         wxT("invalid") : pkg.GetDevelopmentStatusStr());
00464     SetNodeContent(m_pProgLanguage, 
00465                     pkg.GetProgLanguage() == wxPPL_INVALID ? 
00466                         wxT("invalid") : pkg.GetProgLanguageStr());
00467     SetProp(m_pRSS, wxT("href"), pkg.GetRSSHref());
00468     SetRefProp(m_pLogo, pkg.GetLogoRef());
00469     SetProp(m_pSamples, wxT("number"),
00470             wxString::Format(wxT("%d"), pkg.GetNumberOfSamples()));
00471 
00472     ResetEnumeration(m_pDownloads, 2, wxT("mirror"), pkg.GetDownloadHref().GetCount(),
00473                      FormatMirror, pkg);
00474     ResetEnumeration(m_pScreenshots, 2, wxT("image"), pkg.GetScreenshots().GetCount(),
00475                      FormatScreenshot, pkg);
00476     ResetEnumeration(m_pDocs, 2, wxT("doc"), pkg.GetDocumentation().GetCount(),
00477                      FormatDoc, pkg);
00478 
00479     // DEPENDENCIES data
00480     if (pkg.GetSupportedPortFlag() == wxGetFullPortIdList() &&
00481         pkg.HasSameSupportedPortVersions())
00482     {
00483         // it's easier to write a <wxport name="any" /> tag
00484         RemoveAllChildrenFrom(m_pSupportedPorts);
00485 
00486         wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("wxport"));
00487         n->AddProperty(wxT("name"), wxT("any"));
00488         n->AddProperty(wxT("versions"), pkg.GetSupportedVersions().Item(0));
00489 
00490         AddChildIndentation(m_pSupportedPorts, 3);
00491         m_pSupportedPorts->AddChild(n);
00492         AddChildIndentation(m_pSupportedPorts, 2);
00493     }
00494     else
00495     {
00496         ResetEnumeration(m_pSupportedPorts, 2, wxT("wxport"), 
00497                          pkg.GetSupportedPorts().GetCount(), FormatSupportedPort, pkg);
00498     }
00499 
00500     if (pkg.GetTestedPortFlag() == wxGetFullPortIdList() &&
00501         pkg.HasSameTestedPortVersions())
00502     {
00503         // it's easier to write a <wxport name="any" /> tag
00504         RemoveAllChildrenFrom(m_pTestedPorts);
00505 
00506         wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("wxport"));
00507         n->AddProperty(wxT("name"), wxT("any"));
00508         n->AddProperty(wxT("versions"), pkg.GetSupportedVersions().Item(0));
00509 
00510         AddChildIndentation(m_pTestedPorts, 3);
00511         m_pTestedPorts->AddChild(n);
00512         AddChildIndentation(m_pTestedPorts, 2);
00513     }
00514     else
00515     {
00516         ResetEnumeration(m_pTestedPorts, 2, wxT("wxport"), 
00517                          pkg.GetTestedPorts().GetCount(), FormatTestedPort, pkg);
00518     }
00519 
00520     SetProp(m_pDependencies[wxPDT_REQUIRED], wxT("type"), wxT("required"));
00521     ResetEnumeration(m_pDependencies[wxPDT_REQUIRED], 2, wxT("id"),
00522                      pkg.GetDependencies().GetDependenciesOfType(wxPDT_REQUIRED).GetCount(),
00523                      FormatRequiredDependency, pkg);
00524 
00525     SetProp(m_pDependencies[wxPDT_SUGGESTED], wxT("type"), wxT("suggested"));
00526     ResetEnumeration(m_pDependencies[wxPDT_SUGGESTED], 2, wxT("id"),
00527                      pkg.GetDependencies().GetDependenciesOfType(wxPDT_SUGGESTED).GetCount(),
00528                      FormatSuggestedDependency, pkg);
00529 
00530     // BUILD SYSTEM data
00531 
00532     SetProp(m_pBuildSystem, wxT("type"), 
00533                 pkg.GetBuildSystemType() == wxPBST_INVALID ? 
00534                     wxT("invalid") : pkg.GetBuildSystemTypeStr().Lower());
00535     SetProp(m_pBuildSystem, wxT("localref"), pkg.GetBuildSystemHref());
00536     SetNodeContent(m_pFormats,
00537             wxPackageCompilerFormatList2String(pkg.GetSupportedBuildSysFormats()));
00538 
00539     // remove from the option array all option presets in use
00540         wxArrayString usedpresets = pkg.GetUsedOptionPresets();
00541     wxPackageCommandOptionArray opt = pkg.GetBuildSysOptions();
00542     for (size_t i=0; i < usedpresets.GetCount(); i++)
00543         opt.Remove(wxPresetXMLDescriptor::s_hashmapOptions[usedpresets[i]]);
00544 
00545     // save build system options
00546     SetProp(m_pOptions, wxT("presets"), wxArray2String(usedpresets));
00547     RemoveAllChildrenFrom(m_pOptions);
00548 
00549     // write the new if+option list
00550     //AddChildIndentation(m_pOptions, 3);
00551     wxIfNodeListManager mngr(this, m_pOptions);
00552     mngr.SaveOptions(opt, 3);
00553     AddChildIndentation(m_pOptions, 2);
00554 
00555     // save stages
00556     RemoveAllChildrenFrom(m_pStages);
00557 
00558     // recreate target lists
00559     for (size_t i=0; i < wxPBSS_MAX; i++)
00560     {
00561         wxPackageBuildSystemStage s = wxIdx2PackageBuildSystemStage(i);
00562 
00563         wxXmlNode *p = new wxXmlNode(wxXML_ELEMENT_NODE,
00564                                      wxPackageBuildSystemStage2String(s).Lower());
00565         p->AddProperty(wxT("targets"), pkg.GetCmdForStage(s).GetTargetsStr());
00566 
00567         AddChildIndentation(m_pStages, 3);
00568         m_pStages->AddChild(p);
00569     }
00570 
00571     AddChildIndentation(m_pStages, 2);
00572 
00573     // save commands
00574     wxStringHashMap vars;
00575     wxString preset = pkg.GetUsedCommandPreset(vars);
00576     if (!preset.IsEmpty())
00577     {
00578         // use the command preset
00579         wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, preset);
00580 
00581         wxStringHashMap::iterator it;
00582         for( it = vars.begin(); it != vars.end(); ++it )
00583             n->AddProperty(it->first, it->second);
00584 
00585         AddChildIndentation(m_pStages, 3);
00586         m_pStages->AddChild(n);
00587         AddChildIndentation(m_pStages, 2);
00588     }
00589     else
00590     {
00591         // write our list of commands for each stage
00592         for (size_t i=0; i < wxPBSS_MAX; i++)
00593         {
00594             wxPackageBuildSystemStage s = wxIdx2PackageBuildSystemStage(i);
00595             wxPackageCommandArray cmd = pkg.GetCmdForStage(s);
00596             wxString name = wxPackageBuildSystemStage2String(s).Lower();
00597 
00598             if (cmd.GetCount() == 0)
00599                 continue;
00600 
00601             AddChildIndentation(m_pStages, 3);
00602             m_pStages->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, wxEmptyString,
00603                                 wxString::Format(wxT(" %s stage commands "), name.c_str())));
00604 
00605             for (size_t j=0; j<cmd.GetCount(); j++)
00606                 cmd[j].GetCondition().SetStages(s);
00607 
00608             wxIfNodeListManager mngr(this, m_pStages);
00609             mngr.SaveCommands(cmd, 3);
00610             AddChildIndentation(m_pStages, 2);
00611         }
00612     }
00613 }
00614 
00615 
00616 
00617 // ----------------------------------------------------------------------------
00618 // wxPackageXMLDescriptor - load API
00619 // ----------------------------------------------------------------------------
00620 
00621 wxString wxPackageXMLDescriptor::GetHrefProp(const wxXmlNode *p) const
00622 {
00623     wxString ref = p->GetPropVal(wxT("href"), wxEmptyString);
00624 
00625     // for security reasons, avoid loading of files with unknown protocols
00626     if (!ref.StartsWith(wxT("http://")))
00627         return wxEmptyString;
00628     return ref;
00629 }
00630 
00631 wxString wxPackageXMLDescriptor::GetLocalRefProp(const wxXmlNode *p) const
00632 {
00633     wxString ref = p->GetPropVal(wxT("localref"), wxEmptyString);
00634 
00635     // for security reasons, avoid loading of files with unknown protocols
00636     // or that do not refer to the root of the package (i.e. using only file://).
00637     if (!ref.StartsWith(wxT("file:///")))
00638         return wxEmptyString;
00639     return ref;
00640 }
00641 
00642 bool wxPackageXMLDescriptor::Parse()
00643 { 
00644     // parse this package
00645     if (!GetRoot() ||
00646         GetRoot()->GetName() != wxT("wxpackage"))
00647         return false;
00648 
00649     // is the version ok?
00650     wxVersion ver = GetRoot()->GetPropVal(wxT("version"), WXP_VERSION_STRING);
00651     if (ver != wxVersion(WXP_VERSION_STRING))
00652     {
00653         wxLogError(wxT("Invalid package version '%s'; cannot load it."), 
00654                    ver.GetAsString().c_str());
00655         return false;
00656     }
00657 
00658     // DON'T DO VALIDITY CHECK ON LOADED STUFF FROM NOW ON
00659     // IT'S THE TASK OF wxPackageInfo::IsOk() !!
00660     //
00661     // In fact, we want to be able to load also invalid WXP files
00662     // (just think to e.g. incomplete package descriptors saved by the user 
00663     //  using the Packager to complete them later).
00664 
00665     wxXmlNode *child = GetRoot()->GetChildren();
00666     while (child)
00667     {
00668         if (child->GetName() == wxT("basics"))
00669         {
00670             m_pBasics = child;
00671             if (!LoadBasics(child, m_info))
00672                 return false;
00673 
00674             // say the name of the package we are loading now that we know it
00675             wxLogDebug(wxT("Parsing %s package..."), m_info.GetName().c_str());
00676         }
00677         else if (child->GetName() == wxT("packaging"))
00678         {
00679             m_pPackaging = child;
00680             if (!LoadPackaging(child, m_info))
00681                 return false;
00682         }
00683         else if (child->GetName() == wxT("licensing"))
00684         {
00685             m_pLicensing = child;
00686             if (!LoadLicensing(child, m_info))
00687                 return false;
00688         }
00689         else if (child->GetName() == wxT("details"))
00690         {
00691             m_pDetails = child;
00692             if (!LoadDetails(child, m_info))
00693                 return false;
00694         }
00695         else if (child->GetName() == wxT("dependencies"))
00696         {
00697             m_pDep = child;
00698             if (!LoadDependencies(child, m_info))
00699                 return false;
00700         }
00701         else if (child->GetName() == wxT("build-system"))
00702         {
00703             m_pBuildSystem = child;
00704             if (!LoadBuildSystem(child, m_info))
00705                 return false;
00706         }
00707         else
00708             HandleUnknownTag(child);
00709 
00710         // proceed
00711         child = child->GetNext();
00712     }
00713 
00714     // NB: do NOT execute any substitution here: we want to remember
00715     //     all the $(key) values to eventually save them later back
00716     //     in the WXP !
00717 
00718     return true;
00719 }
00720 
00721 bool wxPackageXMLDescriptor::LoadBasics(const wxXmlNode *n, wxPackageInfo &p)
00722 {
00723     wxXmlNode *child = n->GetChildren();
00724     while (child)
00725     {
00726         if (child->GetName() == wxT("id"))
00727         {
00728             p.SetName(child->GetPropVal(wxT("name"), wxEmptyString));
00729             p.SetVersion(child->GetPropVal(wxT("version"), wxEmptyString));
00730 
00731             m_pId = child;
00732         }
00733         else if (child->GetName() == wxT("description"))
00734         {
00735             p.SetDescription(GetStrippedNodeContent(child));
00736             m_pDescription = child;
00737         }
00738         else if (child->GetName() == wxT("keywords"))
00739         {
00740             p.SetKeywords(GetStrippedNodeContent(child));
00741             m_pKeywords = child;
00742         }
00743         else if (child->GetName() == wxT("category"))
00744         {
00745             p.SetPrimaryCategoryStr(
00746                 child->GetPropVal(wxT("primary"), wxEmptyString));
00747             p.SetSecondaryCategoryStr(
00748                 child->GetPropVal(wxT("secondary"), wxEmptyString));
00749             m_pCategory = child;
00750         }
00751         else if (child->GetName() == wxT("website"))
00752         {
00753             p.SetWebsite(GetHrefProp(child));
00754             m_pWebsite = child;
00755         }
00756         else if (child->GetName() == wxT("creation-date"))
00757         {
00758             p.SetCreationDate(GetStrippedNodeContent(child));
00759             m_pCreationDate = child;
00760         }
00761         else
00762             HandleUnknownTag(child);
00763 
00764         // proceed
00765         child = child->GetNext();
00766     }
00767 
00768     return true;
00769 }
00770 
00771 bool wxPackageXMLDescriptor::LoadContentsTag(const wxXmlNode *tag,
00772                                              wxArrayString *dirs,
00773                                              wxArrayString *files,
00774                                              wxArrayString *patterns)
00775 {
00776     while (tag)
00777     {
00778         if (tag->GetName() == wxT("exclude"))
00779         {
00780             wxArrayString *arr = NULL;
00781             wxString str;
00782 
00783             if (tag->HasProp(wxT("directory")))
00784             {
00785                 str = tag->GetPropVal(wxT("directory"), wxEmptyString);
00786                 arr = dirs;
00787             }
00788             else if (tag->HasProp(wxT("file")))
00789             {
00790                 str = tag->GetPropVal(wxT("file"), wxEmptyString);
00791                 arr = files;
00792             }
00793             else if (tag->HasProp(wxT("pattern")))
00794             {
00795                 str = tag->GetPropVal(wxT("pattern"), wxEmptyString);
00796                 arr = patterns;
00797             }        
00798 
00799             const wxString prefix = wxT("file:///");
00800             if (str.StartsWith(prefix))
00801                 str.Remove(0, prefix.Len());
00802 
00803             if (arr) arr->Add(str);
00804         }
00805         else
00806             HandleUnknownTag((wxXmlNode*)tag);
00807 
00808         tag = tag->GetNext();
00809     }
00810 
00811     return true;
00812 }
00813 
00814 bool wxPackageXMLDescriptor::LoadPackaging(const wxXmlNode *n, wxPackageInfo &p)
00815 {
00816     wxArrayString dirs, files, patterns;
00817 
00818     wxXmlNode *child = n->GetChildren();
00819     while (child)
00820     {
00821         if (child->GetName() == wxT("root"))
00822         {
00823             wxString root = GetStrippedNodeContent(child);
00824 
00825             // only the '.' and the '/' characters should be part of the relative root!
00826             bool isok = true;
00827             for (size_t i=0; i<root.Len(); i++)
00828                 if (root[i] != wxT('.') && root[i] != wxT('/'))
00829                     isok = false;
00830 
00831             if (isok)
00832                 p.SetRoot(root);
00833             m_pRoot = child;
00834         }
00835         else if (child->GetName() == wxT("contents"))
00836         {
00837             if (LoadContentsTag(child->GetChildren(), &dirs, &files, &patterns))
00838             {
00839                 p.SetExcluded(wxPEM_DIRECTORY, dirs);
00840                 p.SetExcluded(wxPEM_FILE, files);
00841                 p.SetExcluded(wxPEM_PATTERN, patterns);
00842             }
00843             m_pContents = child;
00844         }
00845         else if (child->GetName() == wxT("compress"))
00846         {
00847             p.SetCompressModeStr(GetStrippedNodeContent(child));
00848             m_pCompress = child;
00849         }
00850         else if (child->GetName() == wxT("filename"))
00851         {
00852             p.SetFileName(GetStrippedNodeContent(child));
00853             m_pFileName = child;
00854         }
00855         else if (child->GetName() == wxT("upload"))
00856         {
00857             p.SetUploadDestination(GetStrippedNodeContent(child));
00858             m_pUpload = child;
00859         }
00860         else
00861             HandleUnknownTag(child);
00862 
00863         // proceed
00864         child = child->GetNext();
00865     }
00866 
00867     return true;
00868 }
00869 
00870 bool wxPackageXMLDescriptor::LoadLicensing(const wxXmlNode *n, wxPackageInfo &p)
00871 {
00872     wxXmlNode *child = n->GetChildren();
00873     while (child)
00874     {
00875         if (child->GetName() == wxT("license"))
00876         {
00877             wxPackageDataWithRef license(
00878                     child->GetPropVal(wxT("name"), wxT("wxWidgets license")),
00879                     GetHrefProp(child),
00880                     GetLocalRefProp(child));
00881 
00882             p.SetLicenseRef(license);
00883             p.SetLicenseTypeStr(child->GetPropVal(wxT("type"), wxT("Open Source")));
00884 
00885             m_pLicense = child;
00886         }
00887         else if (child->GetName() == wxT("organization"))
00888         {
00889             p.SetOrganization(child->GetPropVal(wxT("name"), wxEmptyString),
00890                               GetHrefProp(child));
00891 
00892             m_pOrganization = child;
00893         }
00894         else if (child->GetName() == wxT("cost"))
00895         {
00896             p.SetCost(GetStrippedNodeContent(child));
00897             m_pCost = child;
00898         }
00899         else if (child->GetName() == wxT("credits"))
00900         {
00901             p.SetCredits(GetStrippedNodeContent(child));
00902             m_pCredits = child;
00903         }
00904         else if (child->GetName() == wxT("copyright"))
00905         {
00906             p.SetCopyright(GetStrippedNodeContent(child));
00907             m_pCopyright = child;
00908         }
00909         else if (child->GetName() == wxT("authors"))
00910         {
00911             wxXmlNode *author = child->GetChildren();
00912             while (author)
00913             {
00914                 if (author->GetName() == wxT("author") && author->HasProp(wxT("name")))
00915                 {
00916                     // NB: do not use GetHrefProp() here since it would discard
00917                     //     email addresses !
00918                     p.AddAuthor(author->GetPropVal(wxT("name"), wxEmptyString),
00919                                 author->GetPropVal(wxT("href"), wxEmptyString));
00920                 }
00921 
00922                 author = author->GetNext();
00923             }
00924 
00925             m_pAuthors = child;
00926         }
00927         else if (child->GetName() == wxT("maintainers"))
00928         {
00929             wxXmlNode *maint = child->GetChildren();
00930             while (maint)
00931             {
00932                 if (maint->GetName() == wxT("maintainer") && maint->HasProp(wxT("name")))
00933                 {
00934                     // NB: do not use GetHrefProp() here since it would discard
00935                     //     email addresses !
00936                     p.AddMaintainer(maint->GetPropVal(wxT("name"), wxEmptyString),
00937                                     maint->GetPropVal(wxT("href"), wxEmptyString));
00938                 }
00939 
00940                 maint = maint->GetNext();
00941             }
00942 
00943             m_pMaintainers = child;
00944         }
00945         else
00946             HandleUnknownTag(child);
00947 
00948         // proceed
00949         child = child->GetNext();
00950     }
00951 
00952     return true;
00953 }
00954 
00955 bool wxPackageXMLDescriptor::LoadDetails(const wxXmlNode *n, wxPackageInfo &p)
00956 {
00957     wxXmlNode *child = n->GetChildren();
00958     while (child)
00959     {
00960         if (child->GetName() == wxT("status"))
00961         {
00962             p.SetDevelopmentStatusStr(GetStrippedNodeContent(child));
00963             m_pStatus = child;
00964         }
00965         else if (child->GetName() == wxT("proglanguage"))
00966         {
00967             p.SetProgLanguageStr(GetStrippedNodeContent(child));
00968             m_pProgLanguage = child;
00969         }
00970         else if (child->GetName() == wxT("rss"))
00971         {
00972             p.SetRSSHref(GetHrefProp(child));
00973             m_pRSS = child;
00974         }
00975         else if (child->GetName() == wxT("logo"))
00976         {
00977             p.SetLogo(GetHrefProp(child),
00978                     GetLocalRefProp(child));
00979             m_pLogo = child;
00980         }
00981         else if (child->GetName() == wxT("samples"))
00982         {
00983             wxString str = child->GetPropVal(wxT("number"), wxT("0"));
00984             unsigned long n;
00985             if (str.ToULong(&n))
00986                 p.SetNumberOfSamples(n);
00987 
00988             m_pSamples = child;
00989         }
00990         else if (child->GetName() == wxT("download"))
00991         {
00992             wxXmlNode *mirror = child->GetChildren();
00993             while (mirror)
00994             {
00995                 if (mirror->GetName() == wxT("mirror") && mirror->HasProp(wxT("href")))
00996                     p.AddMirror(GetHrefProp(mirror));
00997 
00998                 mirror = mirror->GetNext();
00999             }
01000 
01001             m_pDownloads = child;
01002         }
01003         else if (child->GetName() == wxT("documentation"))
01004         {
01005             wxXmlNode *doc = child->GetChildren();
01006             while (doc)
01007             {
01008                 if (doc->GetName() == wxT("doc"))
01009                 {
01010                     p.AddDoc(doc->GetPropVal(wxT("type"), wxEmptyString),
01011                             GetHrefProp(doc),
01012                             GetLocalRefProp(doc));
01013                 }
01014                 else
01015                     HandleUnknownTag(doc);
01016 
01017                 doc = doc->GetNext();
01018             }
01019 
01020             m_pDocs = child;
01021         }
01022         else if (child->GetName() == wxT("screenshots"))
01023         {
01024             wxXmlNode *screen = child->GetChildren();
01025             while (screen)
01026             {
01027                 if (screen->GetName() == wxT("image") &&
01028                     screen->HasProp(wxT("href")))
01029                 {
01030                     p.AddScreenshot(GetHrefProp(screen),
01031                                     GetLocalRefProp(screen));
01032                 }
01033                 else
01034                     HandleUnknownTag(screen);
01035 
01036                 screen = screen->GetNext();
01037             }
01038 
01039             m_pScreenshots = child;
01040         }
01041         else
01042             HandleUnknownTag(child);
01043 
01044         // proceed
01045         child = child->GetNext();
01046     }
01047 
01048     return true;
01049 }
01050 
01051 bool wxPackageXMLDescriptor::LoadWxportTags(const wxXmlNode *port,
01052                                             const wxVersionRange &defrange,
01053                                             wxArrayInt *ports,
01054                                             wxVersionRangeArray *ver)
01055 {
01056     while (port)
01057     {
01058         if (port->GetName() == wxT("wxport") && port->HasProp(wxT("name")))
01059         {
01060             wxString verstr = port->GetPropVal(wxT("versions"), wxEmptyString);
01061             wxString portname = port->GetPropVal(wxT("name"), wxEmptyString);
01062 
01063             wxVersionRange v;
01064             if (port->HasProp(wxT("versions")))
01065                 v.Set(verstr);
01066             else
01067                 v = defrange;
01068 
01069             if (!v.IsOk())
01070             {
01071                 wxLogWarning(wxT("Found a <wxport> tag with an invalid version string: %s"),
01072                            verstr.c_str());
01073                 // continue nonetheless (remember we want to be able to load invalid WXP too!)
01074             }
01075 
01076             if (portname == wxT("any"))
01077             {
01078                 // allow the use of "any" as name
01079                 for (size_t i=0; i<wxPORT_MAX; i++)
01080                 {
01081                     wxPortId id = (wxPortId)(1 << i);
01082 
01083                     if (ver) ver->Add(v);
01084                     if (ports) ports->Add(id);
01085                 }
01086             }
01087             else
01088             {
01089                 wxPortId id(wxPlatformInfo::GetPortId(portname));
01090                 if (id != wxPORT_UNKNOWN)
01091                 {
01092                     if (ver) ver->Add(v);
01093                     if (ports) ports->Add(id);
01094                 }
01095             }
01096         }
01097         else
01098             HandleUnknownTag((wxXmlNode*)port);
01099 
01100         port = port->GetNext();
01101     }
01102 
01103     return true;
01104 }
01105 
01106 bool wxPackageXMLDescriptor::LoadDependencies(const wxXmlNode *n, wxPackageInfo &p)
01107 {
01108     wxXmlNode *child = n->GetChildren();
01109     while (child)
01110     {
01111         if (child->GetName() == wxT("supported-ports"))
01112         {
01113             wxArrayInt ports;
01114             wxVersionRangeArray vers;
01115 
01116             wxString versions = child->GetPropVal(wxT("versions"), wxEmptyString);
01117             if (LoadWxportTags(child->GetChildren(), versions, &ports, &vers))
01118                 p.SetSupportedPorts(ports, vers);
01119 
01120             m_pSupportedPorts = child;
01121         }
01122         else if (child->GetName() == wxT("tested-ports"))
01123         {
01124             wxArrayInt ports;
01125             wxVersionRangeArray vers;
01126 
01127             wxString versions = child->GetPropVal(wxT("versions"), wxEmptyString);
01128             if (LoadWxportTags(child->GetChildren(), versions, &ports, &vers))
01129                 p.SetTestedPorts(ports, vers);
01130 
01131             m_pTestedPorts = child;
01132         }
01133         else if (child->GetName() == wxT("dependency"))
01134         {
01135             wxString deptypename = child->GetPropVal(wxT("type"), wxT("required"));
01136             wxPackageDependencyType deptype = wxString2PackageDependencyType(deptypename);
01137 
01138             wxXmlNode *dep = child->GetChildren();
01139             while (dep)
01140             {
01141                 if (dep->GetName() == wxT("id") &&
01142                     dep->HasProp(wxT("name")))
01143                 {
01144                     wxVersionRange ver(dep->GetPropVal(wxT("versions"), wxEmptyString));
01145                     wxPackageDependency pd(dep->GetPropVal(wxT("name"), wxEmptyString),
01146                                            ver, GetHrefProp(dep), deptype);
01147 
01148                     if (!pd.IsOk())
01149                     {                        
01150                         wxLogWarning(wxT("Found invalid dependency named '%s'"),
01151                                      pd.GetName().c_str());
01152                         // continue nonetheless (remember we want to be able to load invalid WXP too!)
01153                     }
01154 
01155                     p.AddDependency(pd);
01156                 }
01157                 else
01158                     HandleUnknownTag(dep);
01159 
01160                 dep = dep->GetNext();
01161             }
01162 
01163             if (m_pDependencies[deptype] != NULL)
01164             {
01165                 // the dependencies of these type are divided in two blocks...
01166                 // while we can load them without problems we cannot save them
01167                 // keeping the two blocks separed... so we remove this tag from the
01168                 // tree keeping only the first parsed <dependency>
01169                 ((wxXmlNode*)n)->RemoveChild(child);
01170             }
01171             else
01172                 m_pDependencies[deptype] = child;
01173         }
01174         else
01175             HandleUnknownTag(child);
01176 
01177         // proceed
01178         child = child->GetNext();
01179     }
01180 
01181     return true;
01182 }
01183 
01184 bool wxPackageXMLDescriptor::LoadBuildSystem(const wxXmlNode *n, wxPackageInfo &p)
01185 {
01186     p.SetBuildSystemTypeStr(n->GetPropVal(wxT("type"), wxT("bakefile")));
01187     p.SetBuildSysHref(GetLocalRefProp(n));
01188 
01189     wxXmlNode *child = n->GetChildren();
01190     while (child)
01191     {
01192         if (child->GetName() == wxT("formats"))
01193         {
01194             wxString str = GetStrippedNodeContent(child);
01195             p.SetSupportedFormats(wxString2PackageCompilerFormatList(str));
01196 
01197             m_pFormats = child;
01198         }
01199         else if (child->GetName() == wxT("options"))
01200         {
01201             wxArrayString presets =
01202                                 wxString2Array(child->GetPropVal(wxT("presets"), wxEmptyString));
01203 
01204             // add preset options, if specified
01205             for (size_t i=0; i<presets.GetCount(); i++)
01206                 if (wxPresetXMLDescriptor::s_hashmapOptions.count(presets[i]) > 0)
01207                     p.AddBuildSysOptions(wxPresetXMLDescriptor::s_hashmapOptions[presets[i]]);
01208                 else
01209                     wxLogWarning(wxT("Ignoring unknown option preset '%s'"), 
01210                                  presets[i].c_str());
01211 
01212             // add any other option...
01213             wxPackageCommandOptionArray arr(LoadOptions(child));
01214             if (!arr.IsOk())
01215             {
01216                 wxLogWarning(wxT("Found an invalid set of %d options"), arr.GetCount());
01217                 // continue nonetheless (remember we want to be able to load invalid WXP too!)
01218             }
01219 
01220             p.AddBuildSysOptions(arr);
01221             m_pOptions = child;
01222         }
01223         else if (child->GetName() == wxT("stages"))
01224         {
01225             if (!LoadStages(child, p))
01226                 return false;
01227 
01228             m_pStages = child;
01229         }
01230         else
01231             HandleUnknownTag(child);
01232 
01233         // proceed
01234         child = child->GetNext();
01235     }
01236 
01237     if (p.GetSupportedBuildSysFormats() == 0)
01238         p.SetSupportedFormats(wxGetFullPackageCompilerFormatList());
01239 
01240     return true;
01241 }
01242 
01243 bool wxPackageXMLDescriptor::LoadStages(const wxXmlNode *n, wxPackageInfo &p)
01244 {
01245     wxXmlNode *child = n->GetChildren();
01246     while (child)
01247     {
01248         if (child->GetName() == wxT("cmd"))
01249         {
01250             wxPackageCommand command(LoadCommand(child));
01251 
01252             // add a non-conditional command to all stages
01253             if (!command.IsOk())
01254             {
01255                 wxLogWarning(wxT("Found invalid <cmd> '%s'"), 
01256                              command.GetCommand().c_str());
01257                 // continue nonetheless (remember we want to be able to load invalid WXP too!)
01258             }
01259 
01260             p.AddBuildSysCommand(wxGetFullPackageBuildSystemStageList(), command);
01261         }
01262         else if (child->GetName() == wxT("if"))
01263         {
01264             wxPackageCondition cnd(LoadCondition(child));
01265 
01266             // add conditional commands
01267             wxXmlNode *cmd = child->GetChildren();
01268             while (cmd)
01269             {
01270                 if (cmd->GetName() == wxT("cmd"))
01271                 {
01272                     wxPackageCommand command(LoadCommand(cmd));
01273                     command.SetCondition(cnd);
01274 
01275                     if (!command.IsOk())
01276                     {                        
01277                         wxLogWarning(wxT("Found invalid <cmd> '%s'"), 
01278                                      command.GetCommand().c_str());
01279                         // continue nonetheless (remember we want to be able to load invalid WXP too!)
01280                     }
01281 
01282                     p.AddBuildSysCommand(cnd.GetStages(), command);
01283                 }
01284                 else
01285                     HandleUnknownTag(cmd);
01286 
01287                 cmd = cmd->GetNext();
01288             }
01289         }
01290         else
01291         {
01292             bool valid = false;
01293 
01294             // is this the name of a build system stage ?
01295             wxPackageBuildSystemStage stage =
01296                 wxString2PackageBuildSystemStage(child->GetName());
01297             if (stage != wxPBSS_INVALID)
01298             {
01299                 if (child->HasProp(wxT("targets")))
01300                 {
01301                     // this is the list of targets supported for this stage
01302                     p.GetCmdForStage(stage).
01303                         SetTargets(child->GetPropVal(wxT("targets"), wxEmptyString));
01304 
01305                     valid = true;
01306                 }
01307                 else
01308                 {
01309                     wxLogWarning(wxT("Ignoring tag '%s' which has no 'targets' attribute!"),
01310                                child->GetName().c_str());
01311                 }
01312             }
01313 
01314             // is this the name of a command preset ?
01315             wxPackageCommandSetHashMap::iterator it;
01316             for( it = wxPresetXMLDescriptor::s_hashmapCommands.begin();
01317                 it != wxPresetXMLDescriptor::s_hashmapCommands.end(); ++it )
01318             {
01319                 if (it->first == child->GetName())
01320                 {
01321                     if (it->second.GetBuildSystemType()!=p.GetBuildSystemType())
01322                     {
01323                         wxLogWarning(wxT("The command preset '%s' is not valid for '%s' build system!"),
01324                                      child->GetName().c_str(), p.GetBuildSystemTypeStr().c_str());
01325                         break;
01326                     }
01327 
01328                     // get the variable substitutions for this command preset
01329                     wxXmlProperty *prop = child->GetProperties();
01330                     wxArrayString names, values;
01331                     while (prop)
01332                     {
01333                         names.Add(prop->GetName());
01334                         values.Add(prop->GetValue());
01335                         prop = prop->GetNext();
01336                     }
01337 
01338                     // did the user specified a value for each variable supported
01339                     // by this command preset ?
01340                     valid = true;
01341                     for (size_t i=0; i<it->second.GetVars().GetCount(); i++)
01342                     {
01343                         wxString varname = it->second.GetVars().Item(i);
01344                         if (names.Index(varname) == wxNOT_FOUND)
01345                         {
01346                             valid = false;
01347                             wxLogWarning(wxT("The command preset '%s' needs a value for its '%s' variable"),
01348                                          child->GetName().c_str(), varname.c_str());
01349                             break;
01350                         }
01351                     }
01352 
01353                     if (!valid)
01354                         break;
01355 
01356                     // set the commandset vars as keywords to be substituted in
01357                     // *all* the commands which belong to the commandset
01358                     wxPackageCommandSet copy(it->second);
01359                     copy.AddKeywords(names, values);
01360 
01361                     // finally, add the commands to the package commands
01362                     p.AddBuildSysCommands(copy);
01363                 }
01364             }
01365 
01366             if (!valid)
01367                 HandleUnknownTag(child);
01368         }
01369 
01370         child = child->GetNext();
01371     }
01372 
01373     // add the default 'all' target if no other targets are available
01374     // FIXME: this is a sort of auto-repair which should be removed
01375     for (size_t i=0; i < wxPBST_MAX; i++)
01376     {
01377         wxPackageCommandArray &arr = p.GetCmdForStage(wxIdx2PackageBuildSystemStage(i));
01378         if (arr.GetTargets().GetCount() == 0)
01379             arr.SetTargets(wxT("all"));
01380     }
01381 
01382     return true;
01383 }
01384 

Generated on Thu Feb 1 22:14:31 2007 for wxWidgets Package Manager by  doxygen 1.5.1-p1