]> git.mxchange.org Git - simgear.git/blobdiff - simgear/package/Package.cxx
HTTP request cancellation
[simgear.git] / simgear / package / Package.cxx
index cf156195e295f3d1e43e9311f22dc56c112e3cfc..b32e2fc3137a132997d95136005046b1e2043cc0 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <cassert>
 #include <boost/foreach.hpp>
+#include <boost/algorithm/string/case_conv.hpp>
 
 #include <simgear/debug/logstream.hxx> 
 #include <simgear/structure/exception.hxx>
@@ -31,7 +32,7 @@ namespace simgear {
     
 namespace pkg {
 
-Package::Package(const SGPropertyNode* aProps, Catalog* aCatalog) :
+Package::Package(const SGPropertyNode* aProps, CatalogRef aCatalog) :
     m_catalog(aCatalog)
 {
     initWithProps(aProps);
@@ -42,8 +43,17 @@ void Package::initWithProps(const SGPropertyNode* aProps)
     m_props = const_cast<SGPropertyNode*>(aProps);
 // cache tag values
     BOOST_FOREACH(const SGPropertyNode* c, aProps->getChildren("tag")) {
-        m_tags.insert(c->getStringValue());
+      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
@@ -51,7 +61,9 @@ bool Package::matches(const SGPropertyNode* aFilter) const
     int nChildren = aFilter->nChildren();
     for (int i = 0; i < nChildren; i++) {
         const SGPropertyNode* c = aFilter->getChild(i);
-        if (strutils::starts_with(c->getName(), "rating-")) {
+        const std::string& filter_name = c->getNameString();
+
+        if (strutils::starts_with(filter_name, "rating-")) {
             int minRating = c->getIntValue();
             std::string rname = c->getName() + 7;
             int ourRating = m_props->getChild("rating")->getIntValue(rname, 0);
@@ -59,15 +71,37 @@ bool Package::matches(const SGPropertyNode* aFilter) const
                 return false;
             }
         }
-        
-        if (strcmp(c->getName(), "tag") == 0) {
+        else if (filter_name == "tag") {
             std::string tag(c->getStringValue());
+            boost::to_lower(tag);
             if (m_tags.find(tag) == m_tags.end()) {
                 return false;
             }
         }
-        
-        SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << c->getName());
+        // substring search of name, description
+        else if (filter_name == "name") {
+          std::string n(c->getStringValue());
+          boost::to_lower(n);
+          size_t pos = boost::to_lower_copy(name()).find(n);
+          if (pos == std::string::npos) {
+            return false;
+          }
+        }
+        else if (filter_name == "description") {
+          std::string n(c->getStringValue());
+          boost::to_lower(n);
+          size_t pos = boost::to_lower_copy(description()).find(n);
+          if (pos == std::string::npos) {
+            return false;
+          }
+        }
+        else if (filter_name == "installed") {
+          if (isInstalled() != c->getBoolValue()) {
+            return false;
+          }
+        }
+        else
+          SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << filter_name);
     } // of filter props iteration
     
     return true;
@@ -75,31 +109,67 @@ bool Package::matches(const SGPropertyNode* aFilter) const
 
 bool Package::isInstalled() const
 {
-    SGPath p(m_catalog->installRoot());
-    p.append("Aircraft");
-    p.append(id());
-    
     // anything to check for? look for a valid revision file?
-    return p.exists();
+    return pathOnDisk().exists();
 }
 
-Install* Package::install()
+SGPath Package::pathOnDisk() const
 {
     SGPath p(m_catalog->installRoot());
     p.append("Aircraft");
-    p.append(id());
-    if (p.exists()) {
-        return Install::createFromPath(p, m_catalog);
+    p.append(dirName());
+    return p;
+}
+
+InstallRef Package::install()
+{
+    InstallRef ins = existingInstall();
+    if (ins) {
+        return ins;
     }
-    
-    Install* ins = new Install(this, p);
+  
+  // start a new install
+    ins = new Install(this, pathOnDisk());
     m_catalog->root()->scheduleToUpdate(ins);
+
+    _install_cb(this, ins);
+
     return ins;
 }
 
+InstallRef Package::existingInstall(const InstallCallback& cb) const
+{
+    InstallRef install;
+    try {
+        install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
+    } catch (std::exception& e) {
+        return InstallRef();
+    }
+
+  if( cb )
+  {
+    _install_cb.push_back(cb);
+
+    if( install )
+      cb(const_cast<Package*>(this), install);
+  }
+
+  return install;
+}
+
 std::string Package::id() const
 {
-    return m_props->getStringValue("id");
+    return m_id;
+}
+
+std::string Package::qualifiedId() const
+{
+    return m_catalog->id() + "." + id();
+}
+
+std::string Package::qualifiedVariantId(const unsigned int variantIndex) const
+{
+    return m_catalog->id() + "." + variants()[variantIndex];
 }
 
 std::string Package::md5() const
@@ -107,11 +177,43 @@ std::string Package::md5() const
     return m_props->getStringValue("md5");
 }
 
+std::string Package::dirName() const
+{
+    std::string r(m_props->getStringValue("dir"));
+    if (r.empty())
+        throw sg_exception("missing dir property on catalog package entry for " + m_id);
+    return r;
+}
+
 unsigned int Package::revision() const
 {
+    if (!m_props) {
+        return 0;
+    }
+    
     return m_props->getIntValue("revision");
 }
     
+std::string Package::name() const
+{
+    return m_props->getStringValue("name");
+}
+
+size_t Package::fileSizeBytes() const
+{
+    return m_props->getIntValue("file-size-bytes");
+}
+  
+std::string Package::description() const
+{
+    return getLocalisedProp("description");
+}
+
+string_set Package::tags() const
+{
+    return m_tags;
+}
+    
 SGPropertyNode* Package::properties() const
 {
     return m_props.ptr();
@@ -120,16 +222,37 @@ SGPropertyNode* Package::properties() const
 string_list Package::thumbnailUrls() const
 {
     string_list r;
+    if (!m_props) {
+        return r;
+    }
+    
     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
         r.push_back(dl->getStringValue());
     }
     return r;
 }
 
+string_list Package::thumbnails() const
+{
+    string_list r;
+    if (!m_props) {
+        return r;
+    }
+    
+    BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail-path")) {
+        r.push_back(dl->getStringValue());
+    }
+    return r;
+}
+    
 string_list Package::downloadUrls() const
 {
     string_list r;
-    BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("download")) {
+    if (!m_props) {
+        return r;
+    }
+    
+    BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("url")) {
         r.push_back(dl->getStringValue());
     }
     return r;
@@ -163,8 +286,8 @@ PackageList Package::dependencies() const
         
     // prefer local hangar package if possible, in case someone does something
     // silly with naming. Of course flightgear's aircraft search doesn't know
-    // about hanagrs, so names still need to be unique.
-        Package* depPkg = m_catalog->getPackageById(depName);
+    // about hangars, so names still need to be unique.
+        PackageRef depPkg = m_catalog->getPackageById(depName);
         if (!depPkg) {   
             Root* rt = m_catalog->root();
             depPkg = rt->getPackageById(depName);
@@ -187,6 +310,48 @@ 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());
+}
+
+std::string Package::nameForVariant(const unsigned int vIndex) const
+{
+    if (vIndex == 0)
+        return name();
+
+    // offset by minus one to allow for index 0 being the primary
+    SGPropertyNode_ptr var = m_props->getChild("variant", vIndex - 1);
+    if (var)
+        return var->getStringValue("name");
+
+    throw sg_exception("Unknow variant in package " + id());
+}
+
+
 } // of namespace pkg
 
 } // of namespace simgear