]> git.mxchange.org Git - simgear.git/blob - simgear/package/Package.cxx
io: refactor and improve HTTP modules.
[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
23 #include <simgear/debug/logstream.hxx> 
24 #include <simgear/structure/exception.hxx>
25
26 #include <simgear/package/Catalog.hxx>
27 #include <simgear/package/Install.hxx>
28 #include <simgear/package/Root.hxx>
29
30 namespace simgear {
31     
32 namespace pkg {
33
34 Package::Package(const SGPropertyNode* aProps, Catalog* aCatalog) :
35     m_catalog(aCatalog)
36 {
37     initWithProps(aProps);
38 }
39
40 void Package::initWithProps(const SGPropertyNode* aProps)
41 {
42     m_props = const_cast<SGPropertyNode*>(aProps);
43 // cache tag values
44     BOOST_FOREACH(const SGPropertyNode* c, aProps->getChildren("tag")) {
45         m_tags.insert(c->getStringValue());
46     }
47 }
48
49 bool Package::matches(const SGPropertyNode* aFilter) const
50 {
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) {
59                 return false;
60             }
61         }
62         
63         if (strcmp(c->getName(), "tag") == 0) {
64             std::string tag(c->getStringValue());
65             if (m_tags.find(tag) == m_tags.end()) {
66                 return false;
67             }
68         }
69         
70         SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << c->getName());
71     } // of filter props iteration
72     
73     return true;
74 }
75
76 bool Package::isInstalled() const
77 {
78     SGPath p(m_catalog->installRoot());
79     p.append("Aircraft");
80     p.append(id());
81     
82     // anything to check for? look for a valid revision file?
83     return p.exists();
84 }
85
86 Install* Package::install()
87 {
88     SGPath p(m_catalog->installRoot());
89     p.append("Aircraft");
90     p.append(id());
91     if (p.exists()) {
92         return Install::createFromPath(p, m_catalog);
93     }
94     
95     Install* ins = new Install(this, p);
96     m_catalog->root()->scheduleToUpdate(ins);
97     return ins;
98 }
99
100 std::string Package::id() const
101 {
102     return m_props->getStringValue("id");
103 }
104
105 std::string Package::md5() const
106 {
107     return m_props->getStringValue("md5");
108 }
109
110 unsigned int Package::revision() const
111 {
112     return m_props->getIntValue("revision");
113 }
114     
115 std::string Package::name() const
116 {
117     return m_props->getStringValue("name");
118 }
119
120 std::string Package::description() const
121 {
122     return getLocalisedProp("decription");
123 }
124     
125 SGPropertyNode* Package::properties() const
126 {
127     return m_props.ptr();
128 }
129
130 string_list Package::thumbnailUrls() const
131 {
132     string_list r;
133     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
134         r.push_back(dl->getStringValue());
135     }
136     return r;
137 }
138
139 string_list Package::downloadUrls() const
140 {
141     string_list r;
142     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("download")) {
143         r.push_back(dl->getStringValue());
144     }
145     return r;
146 }
147
148 std::string Package::getLocalisedProp(const std::string& aName) const
149 {
150     return getLocalisedString(m_props, aName.c_str());
151 }
152
153 std::string Package::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
154 {
155     std::string locale = m_catalog->root()->getLocale();
156     if (aRoot->hasChild(locale)) {
157         const SGPropertyNode* localeRoot = aRoot->getChild(locale.c_str());
158         if (localeRoot->hasChild(aName)) {
159             return localeRoot->getStringValue(aName);
160         }
161     }
162     
163     return aRoot->getStringValue(aName);
164 }
165
166 PackageList Package::dependencies() const
167 {
168     PackageList result;
169     
170     BOOST_FOREACH(SGPropertyNode* dep, m_props->getChildren("depends")) {
171         std::string depName = dep->getStringValue("package");
172         unsigned int rev = dep->getIntValue("revision", 0);
173         
174     // prefer local hangar package if possible, in case someone does something
175     // silly with naming. Of course flightgear's aircraft search doesn't know
176     // about hanagrs, so names still need to be unique.
177         Package* depPkg = m_catalog->getPackageById(depName);
178         if (!depPkg) {   
179             Root* rt = m_catalog->root();
180             depPkg = rt->getPackageById(depName);
181             if (!depPkg) {
182                 throw sg_exception("Couldn't satisfy dependency of " + id() + " : " + depName);
183             }
184         }
185         
186         if (depPkg->revision() < rev) {
187             throw sg_range_exception("Couldn't find suitable revision of " + depName);
188         }
189     
190     // forbid recursive dependency graphs, we don't need that level
191     // of complexity for aircraft resources
192         assert(depPkg->dependencies() == PackageList());
193         
194         result.push_back(depPkg);
195     }
196     
197     return result;
198 }
199
200 } // of namespace pkg
201
202 } // of namespace simgear