]> git.mxchange.org Git - simgear.git/blob - simgear/package/Package.cxx
Substring search of package name/description.
[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, CatalogRef 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         // 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) {
75             return false;
76           }
77         }
78       
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) {
83             return false;
84           }
85         }
86
87         SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << c->getName());
88     } // of filter props iteration
89     
90     return true;
91 }
92
93 bool Package::isInstalled() const
94 {
95     SGPath p(m_catalog->installRoot());
96     p.append("Aircraft");
97     p.append(id());
98     
99     // anything to check for? look for a valid revision file?
100     return p.exists();
101 }
102
103 InstallRef Package::install()
104 {
105     SGPath p(m_catalog->installRoot());
106     p.append("Aircraft");
107     p.append(id());
108     if (p.exists()) {
109         return Install::createFromPath(p, m_catalog);
110     }
111     
112     InstallRef ins(new Install(this, p));
113     m_catalog->root()->scheduleToUpdate(ins);
114     return ins;
115 }
116
117 std::string Package::id() const
118 {
119     return m_props->getStringValue("id");
120 }
121
122 std::string Package::md5() const
123 {
124     return m_props->getStringValue("md5");
125 }
126
127 unsigned int Package::revision() const
128 {
129     return m_props->getIntValue("revision");
130 }
131     
132 std::string Package::name() const
133 {
134     return m_props->getStringValue("name");
135 }
136
137 std::string Package::description() const
138 {
139     return getLocalisedProp("decription");
140 }
141     
142 SGPropertyNode* Package::properties() const
143 {
144     return m_props.ptr();
145 }
146
147 string_list Package::thumbnailUrls() const
148 {
149     string_list r;
150     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
151         r.push_back(dl->getStringValue());
152     }
153     return r;
154 }
155
156 string_list Package::downloadUrls() const
157 {
158     string_list r;
159     BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("download")) {
160         r.push_back(dl->getStringValue());
161     }
162     return r;
163 }
164
165 std::string Package::getLocalisedProp(const std::string& aName) const
166 {
167     return getLocalisedString(m_props, aName.c_str());
168 }
169
170 std::string Package::getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const
171 {
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);
177         }
178     }
179     
180     return aRoot->getStringValue(aName);
181 }
182
183 PackageList Package::dependencies() const
184 {
185     PackageList result;
186     
187     BOOST_FOREACH(SGPropertyNode* dep, m_props->getChildren("depends")) {
188         std::string depName = dep->getStringValue("package");
189         unsigned int rev = dep->getIntValue("revision", 0);
190         
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);
195         if (!depPkg) {   
196             Root* rt = m_catalog->root();
197             depPkg = rt->getPackageById(depName);
198             if (!depPkg) {
199                 throw sg_exception("Couldn't satisfy dependency of " + id() + " : " + depName);
200             }
201         }
202         
203         if (depPkg->revision() < rev) {
204             throw sg_range_exception("Couldn't find suitable revision of " + depName);
205         }
206     
207     // forbid recursive dependency graphs, we don't need that level
208     // of complexity for aircraft resources
209         assert(depPkg->dependencies() == PackageList());
210         
211         result.push_back(depPkg);
212     }
213     
214     return result;
215 }
216
217 } // of namespace pkg
218
219 } // of namespace simgear