]> git.mxchange.org Git - simgear.git/blob - simgear/package/Package.cxx
Pkg: qualified ID accessor.
[simgear.git] / simgear / package / Package.cxx
1 // Copyright (C) 2013  James Turner - zakalawe@mac.com
2 //
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.
7 //
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.
12 //
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.
16 //
17
18 #include <simgear/package/Package.hxx>
19
20 #include <cassert>
21 #include <boost/foreach.hpp>
22 #include <boost/algorithm/string/case_conv.hpp>
23
24 #include <simgear/debug/logstream.hxx> 
25 #include <simgear/structure/exception.hxx>
26
27 #include <simgear/package/Catalog.hxx>
28 #include <simgear/package/Install.hxx>
29 #include <simgear/package/Root.hxx>
30
31 namespace simgear {
32     
33 namespace pkg {
34
35 Package::Package(const SGPropertyNode* aProps, CatalogRef aCatalog) :
36     m_catalog(aCatalog)
37 {
38     initWithProps(aProps);
39 }
40
41 void Package::initWithProps(const SGPropertyNode* aProps)
42 {
43     m_props = const_cast<SGPropertyNode*>(aProps);
44 // cache tag values
45     BOOST_FOREACH(const SGPropertyNode* c, aProps->getChildren("tag")) {
46       std::string t(c->getStringValue());
47       m_tags.insert(boost::to_lower_copy(t));
48     }
49 }
50
51 bool Package::matches(const SGPropertyNode* aFilter) const
52 {
53     int nChildren = aFilter->nChildren();
54     for (int i = 0; i < nChildren; i++) {
55         const SGPropertyNode* c = aFilter->getChild(i);
56         const std::string& filter_name = c->getNameString();
57
58         if (strutils::starts_with(filter_name, "rating-")) {
59             int minRating = c->getIntValue();
60             std::string rname = c->getName() + 7;
61             int ourRating = m_props->getChild("rating")->getIntValue(rname, 0);
62             if (ourRating < minRating) {
63                 return false;
64             }
65         }
66         else if (filter_name == "tag") {
67             std::string tag(c->getStringValue());
68             boost::to_lower(tag);
69             if (m_tags.find(tag) == m_tags.end()) {
70                 return false;
71             }
72         }
73         // substring search of name, description
74         else if (filter_name == "name") {
75           std::string n(c->getStringValue());
76           boost::to_lower(n);
77           size_t pos = boost::to_lower_copy(name()).find(n);
78           if (pos == std::string::npos) {
79             return false;
80           }
81         }
82         else if (filter_name == "description") {
83           std::string n(c->getStringValue());
84           boost::to_lower(n);
85           size_t pos = boost::to_lower_copy(description()).find(n);
86           if (pos == std::string::npos) {
87             return false;
88           }
89         }
90         else
91           SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << filter_name);
92     } // of filter props iteration
93     
94     return true;
95 }
96
97 bool Package::isInstalled() const
98 {
99     // anything to check for? look for a valid revision file?
100     return pathOnDisk().exists();
101 }
102
103 SGPath Package::pathOnDisk() const
104 {
105     SGPath p(m_catalog->installRoot());
106     p.append("Aircraft");
107     p.append(id());
108     return p;
109 }
110
111 InstallRef Package::install()
112 {
113     SGPath p(pathOnDisk());
114     if (p.exists()) {
115         return Install::createFromPath(p, m_catalog);
116     }
117     
118     InstallRef ins(new Install(this, p));
119     m_catalog->root()->scheduleToUpdate(ins);
120     return ins;
121 }
122
123 InstallRef Package::existingInstall() const
124 {
125     SGPath p(pathOnDisk());
126     if (p.exists()) {
127         return Install::createFromPath(p, m_catalog);
128     }
129
130     return NULL;
131 }
132
133 std::string Package::id() const
134 {
135     return m_props->getStringValue("id");
136 }
137
138 std::string Package::qualifiedId() const
139 {
140     return m_catalog->id() + "." + id();
141 }
142
143 std::string Package::md5() const
144 {
145     return m_props->getStringValue("md5");
146 }
147
148 unsigned int Package::revision() const
149 {
150     return m_props->getIntValue("revision");
151 }
152     
153 std::string Package::name() const
154 {
155     return m_props->getStringValue("name");
156 }
157
158 std::string Package::description() const
159 {
160     return getLocalisedProp("decription");
161 }
162     
163 SGPropertyNode* Package::properties() const
164 {
165     return m_props.ptr();
166 }
167
168 string_list Package::thumbnailUrls() const
169 {
170     string_list r;
171     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
172         r.push_back(dl->getStringValue());
173     }
174     return r;
175 }
176
177 string_list Package::downloadUrls() const
178 {
179     string_list r;
180     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("url")) {
181         r.push_back(dl->getStringValue());
182     }
183     return r;
184 }
185
186 std::string Package::getLocalisedProp(const std::string& aName) const
187 {
188     return getLocalisedString(m_props, aName.c_str());
189 }
190
191 std::string Package::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
192 {
193     std::string locale = m_catalog->root()->getLocale();
194     if (aRoot->hasChild(locale)) {
195         const SGPropertyNode* localeRoot = aRoot->getChild(locale.c_str());
196         if (localeRoot->hasChild(aName)) {
197             return localeRoot->getStringValue(aName);
198         }
199     }
200     
201     return aRoot->getStringValue(aName);
202 }
203
204 PackageList Package::dependencies() const
205 {
206     PackageList result;
207     
208     BOOST_FOREACH(SGPropertyNode* dep, m_props->getChildren("depends")) {
209         std::string depName = dep->getStringValue("package");
210         unsigned int rev = dep->getIntValue("revision", 0);
211         
212     // prefer local hangar package if possible, in case someone does something
213     // silly with naming. Of course flightgear's aircraft search doesn't know
214     // about hanagrs, so names still need to be unique.
215         PackageRef depPkg = m_catalog->getPackageById(depName);
216         if (!depPkg) {   
217             Root* rt = m_catalog->root();
218             depPkg = rt->getPackageById(depName);
219             if (!depPkg) {
220                 throw sg_exception("Couldn't satisfy dependency of " + id() + " : " + depName);
221             }
222         }
223         
224         if (depPkg->revision() < rev) {
225             throw sg_range_exception("Couldn't find suitable revision of " + depName);
226         }
227     
228     // forbid recursive dependency graphs, we don't need that level
229     // of complexity for aircraft resources
230         assert(depPkg->dependencies() == PackageList());
231         
232         result.push_back(depPkg);
233     }
234     
235     return result;
236 }
237
238 } // of namespace pkg
239
240 } // of namespace simgear