1 // Copyright (C) 2013 James Turner - zakalawe@mac.com
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #include <simgear/package/Package.hxx>
21 #include <boost/foreach.hpp>
23 #include <simgear/debug/logstream.hxx>
24 #include <simgear/structure/exception.hxx>
26 #include <simgear/package/Catalog.hxx>
27 #include <simgear/package/Install.hxx>
28 #include <simgear/package/Root.hxx>
34 Package::Package(const SGPropertyNode* aProps, CatalogRef aCatalog) :
37 initWithProps(aProps);
40 void Package::initWithProps(const SGPropertyNode* aProps)
42 m_props = const_cast<SGPropertyNode*>(aProps);
44 BOOST_FOREACH(const SGPropertyNode* c, aProps->getChildren("tag")) {
45 m_tags.insert(c->getStringValue());
49 bool Package::matches(const SGPropertyNode* aFilter) const
51 int nChildren = aFilter->nChildren();
52 for (int i = 0; i < nChildren; i++) {
53 const SGPropertyNode* c = aFilter->getChild(i);
54 if (strutils::starts_with(c->getName(), "rating-")) {
55 int minRating = c->getIntValue();
56 std::string rname = c->getName() + 7;
57 int ourRating = m_props->getChild("rating")->getIntValue(rname, 0);
58 if (ourRating < minRating) {
63 if (strcmp(c->getName(), "tag") == 0) {
64 std::string tag(c->getStringValue());
65 if (m_tags.find(tag) == m_tags.end()) {
70 // substring search of name, description
71 if (strcmp(c->getName(), "name") == 0) {
72 std::string n(c->getStringValue());
73 size_t pos = name().find(n);
74 if (pos == std::string::npos) {
79 if (strcmp(c->getName(), "description") == 0) {
80 std::string n(c->getStringValue());
81 size_t pos = description().find(n);
82 if (pos == std::string::npos) {
87 SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << c->getName());
88 } // of filter props iteration
93 bool Package::isInstalled() const
95 SGPath p(m_catalog->installRoot());
99 // anything to check for? look for a valid revision file?
103 InstallRef Package::install()
105 SGPath p(m_catalog->installRoot());
106 p.append("Aircraft");
109 return Install::createFromPath(p, m_catalog);
112 InstallRef ins(new Install(this, p));
113 m_catalog->root()->scheduleToUpdate(ins);
117 std::string Package::id() const
119 return m_props->getStringValue("id");
122 std::string Package::md5() const
124 return m_props->getStringValue("md5");
127 unsigned int Package::revision() const
129 return m_props->getIntValue("revision");
132 std::string Package::name() const
134 return m_props->getStringValue("name");
137 std::string Package::description() const
139 return getLocalisedProp("decription");
142 SGPropertyNode* Package::properties() const
144 return m_props.ptr();
147 string_list Package::thumbnailUrls() const
150 BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
151 r.push_back(dl->getStringValue());
156 string_list Package::downloadUrls() const
159 BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("download")) {
160 r.push_back(dl->getStringValue());
165 std::string Package::getLocalisedProp(const std::string& aName) const
167 return getLocalisedString(m_props, aName.c_str());
170 std::string Package::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
172 std::string locale = m_catalog->root()->getLocale();
173 if (aRoot->hasChild(locale)) {
174 const SGPropertyNode* localeRoot = aRoot->getChild(locale.c_str());
175 if (localeRoot->hasChild(aName)) {
176 return localeRoot->getStringValue(aName);
180 return aRoot->getStringValue(aName);
183 PackageList Package::dependencies() const
187 BOOST_FOREACH(SGPropertyNode* dep, m_props->getChildren("depends")) {
188 std::string depName = dep->getStringValue("package");
189 unsigned int rev = dep->getIntValue("revision", 0);
191 // prefer local hangar package if possible, in case someone does something
192 // silly with naming. Of course flightgear's aircraft search doesn't know
193 // about hanagrs, so names still need to be unique.
194 PackageRef depPkg = m_catalog->getPackageById(depName);
196 Root* rt = m_catalog->root();
197 depPkg = rt->getPackageById(depName);
199 throw sg_exception("Couldn't satisfy dependency of " + id() + " : " + depName);
203 if (depPkg->revision() < rev) {
204 throw sg_range_exception("Couldn't find suitable revision of " + depName);
207 // forbid recursive dependency graphs, we don't need that level
208 // of complexity for aircraft resources
209 assert(depPkg->dependencies() == PackageList());
211 result.push_back(depPkg);
217 } // of namespace pkg
219 } // of namespace simgear