]> git.mxchange.org Git - simgear.git/commitdiff
Package: support for variants
authorJames Turner <zakalawe@mac.com>
Sun, 15 Jun 2014 17:55:50 +0000 (19:55 +0200)
committerJames Turner <zakalawe@mac.com>
Sun, 15 Jun 2014 17:55:50 +0000 (19:55 +0200)
- Catalog keeps a map from variant IDs to packages
- Package caches its ID
- Refreshing a catalog updates existing Package instances

Dropping a package from a Catalog will now warn, need to decide
a real policy for this scenario.

simgear/package/Catalog.cxx
simgear/package/Catalog.hxx
simgear/package/Package.cxx
simgear/package/Package.hxx

index 9d5f4ac78f2c368e73a252d24d8e1f90843e86ea..9c36d2aabfd7a2ed3b49d2569098de0143ed63d3 100644 (file)
@@ -244,19 +244,47 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
 {
     // copy everything except package children?
     m_props = new SGPropertyNode;
-    
+
+    m_variantDict.clear(); // will rebuild during parse
+    std::set<PackageRef> orphans;
+    orphans.insert(m_packages.begin(), m_packages.end());
+
     int nChildren = aProps->nChildren();
     for (int i = 0; i < nChildren; i++) {
         const SGPropertyNode* pkgProps = aProps->getChild(i);
         if (strcmp(pkgProps->getName(), "package") == 0) {
-            PackageRef p = new Package(pkgProps, this);
-            m_packages.push_back(p);   
+            PackageRef p = getPackageById(pkgProps->getStringValue("id"));
+            if (p) {
+                // existing package
+                p->updateFromProps(pkgProps);
+                orphans.erase(p); // not an orphan
+            } else {
+                // new package
+                p = new Package(pkgProps, this);
+                m_packages.push_back(p);
+            }
+
+            string_list vars(p->variants());
+            for (string_list::iterator it = vars.begin(); it != vars.end(); ++it) {
+                m_variantDict[*it] = p.ptr();
+            }
         } else {
             SGPropertyNode* c = m_props->getChild(pkgProps->getName(), pkgProps->getIndex(), true);
             copyProperties(pkgProps, c);
         }
     } // of children iteration
-  
+
+    if (!orphans.empty()) {
+        SG_LOG(SG_GENERAL, SG_WARN, "have orphan packages: will become inaccesible");
+        std::set<PackageRef>::iterator it;
+        for (it = orphans.begin(); it != orphans.end(); ++it) {
+            SG_LOG(SG_GENERAL, SG_WARN, "\torphan package:" << (*it)->qualifiedId());
+            PackageList::iterator pit = std::find(m_packages.begin(), m_packages.end(), *it);
+            assert(pit != m_packages.end());
+            m_packages.erase(pit);
+        }
+    }
+
     if (!m_url.empty()) {
         if (m_url != m_props->getStringValue("url")) {
             // this effectively allows packages to migrate to new locations,
@@ -280,13 +308,13 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
 
 PackageRef Catalog::getPackageById(const std::string& aId) const
 {
-    BOOST_FOREACH(PackageRef p, m_packages) {
-        if (p->id() == aId) {
-            return p;
-        }
-    }
-    
-    return NULL; // not found
+    // search the variant dict here, so looking up aircraft variants
+    // works as expected.
+    PackageWeakMap::const_iterator it = m_variantDict.find(aId);
+    if (it == m_variantDict.end())
+        return NULL;
+
+    return it->second;
 }
 
 std::string Catalog::id() const
index 1d06b9bea60485642b33684da3faa5fe8f94e640..bae9c04a1d789a3f7083e3d533b0af009fe09021 100644 (file)
@@ -51,7 +51,7 @@ typedef SGSharedPtr<Install> InstallRef;
 typedef std::vector<PackageRef> PackageList;
 typedef std::vector<CatalogRef> CatalogList;
 
-  class Catalog : public SGReferenced
+class Catalog : public SGReferenced
 {
 public:
     virtual ~Catalog();
@@ -140,9 +140,12 @@ private:
     SGPropertyNode_ptr m_props;
     SGPath m_installRoot;
     std::string m_url;
-  
+
     PackageList m_packages;
     time_t m_retrievedTime;
+
+    typedef std::map<std::string, Package*> PackageWeakMap;
+    PackageWeakMap m_variantDict;
   
   // important that this is a weak-ref to Installs,
   // since it is only cleaned up in the Install destructor
index 9c8a0b805dfa0e3d7f34631fbbad66fe9872944d..a5c8d34150c8f6ba4c226d2e9a9da1cb0307cbed 100644 (file)
@@ -46,6 +46,14 @@ void Package::initWithProps(const SGPropertyNode* aProps)
       std::string t(c->getStringValue());
       m_tags.insert(boost::to_lower_copy(t));
     }
+
+    m_id = m_props->getStringValue("id");
+}
+
+void Package::updateFromProps(const SGPropertyNode* aProps)
+{
+    m_tags.clear();
+    initWithProps(aProps);
 }
 
 bool Package::matches(const SGPropertyNode* aFilter) const
@@ -133,7 +141,7 @@ InstallRef Package::existingInstall() const
 
 std::string Package::id() const
 {
-    return m_props->getStringValue("id");
+    return m_id;
 }
 
 std::string Package::qualifiedId() const
@@ -241,6 +249,34 @@ PackageList Package::dependencies() const
     return result;
 }
 
+string_list Package::variants() const
+{
+    string_list result;
+    result.push_back(id());
+
+    BOOST_FOREACH(SGPropertyNode* var, m_props->getChildren("variant")) {
+        result.push_back(var->getStringValue("id"));
+    }
+
+    return result;
+}
+
+std::string Package::nameForVariant(const std::string& vid) const
+{
+    if (vid == id()) {
+        return name();
+    }
+
+    BOOST_FOREACH(SGPropertyNode* var, m_props->getChildren("variant")) {
+        if (vid == var->getStringValue("id")) {
+            return var->getStringValue("name");
+        }
+    }
+
+
+    throw sg_exception("Unknow variant +" + vid + " in package " + id());
+}
+
 } // of namespace pkg
 
 } // of namespace simgear
index 56edabc423f152b787811062360ac88cb64a6013..2c2ce556c350ddf45688852e20b72a4de4a75a16 100644 (file)
@@ -60,6 +60,12 @@ public:
     
     std::string id() const;
 
+    /**
+     * Variant IDs. Note the primary ID will always be included as 
+     * variants()[0], to simplify enumerating all variants
+     */
+    string_list variants() const;
+
     /**
      * Fully-qualified ID, including our catalog'd ID
      */
@@ -70,7 +76,12 @@ public:
      * although this is not ruled out for the future.
      */
     std::string name() const;
-    
+
+    /**
+     * Human readable name of a variant
+     */
+    std::string nameForVariant(const std::string& vid) const;
+
     /**
      * syntactic sugar to get the localised description
      */
@@ -118,10 +129,13 @@ private:
     Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
     
     void initWithProps(const SGPropertyNode* aProps);
-    
+
+    void updateFromProps(const SGPropertyNode* aProps);
+
     std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
     
     SGPropertyNode_ptr m_props;
+    std::string m_id;
     string_set m_tags;
     CatalogRef m_catalog;
 };