1 /*
2 * Copyright 2013-2014, Stephan Aßmus <superstippi@gmx.de>.
3 * Copyright 2014, Axel Dörfler <axeld@pinc-software.de>.
4 * Copyright 2016-2024, Andrew Lindesay <apl@lindesay.co.nz>.
5 * All rights reserved. Distributed under the terms of the MIT License.
6 *
7 * Note that this file included code earlier from `Model.cpp` and
8 * copyrights have been latterly been carried across in 2024.
9 */
10
11
12 #include "PackageFilter.h"
13 #include "PackageUtils.h"
14
15
~PackageFilter()16 PackageFilter::~PackageFilter()
17 {
18 }
19
20
21 void
AddFilter(PackageFilterRef filter)22 AndFilter::AddFilter(PackageFilterRef filter)
23 {
24 fFilters.push_back(filter);
25 }
26
27
NotFilter(PackageFilterRef filter)28 NotFilter::NotFilter(PackageFilterRef filter)
29 :
30 fFilter(filter)
31 {
32 }
33
34
35 bool
AcceptsPackage(const PackageInfoRef & package) const36 NotFilter::AcceptsPackage(const PackageInfoRef& package) const
37 {
38 return !(fFilter.IsSet() && fFilter->AcceptsPackage(package));
39 }
40
41
42 bool
AcceptsPackage(const PackageInfoRef & package) const43 AndFilter::AcceptsPackage(const PackageInfoRef& package) const
44 {
45 std::vector<PackageFilterRef>::const_iterator it;
46 for (it = fFilters.begin(); it != fFilters.end(); it++) {
47 PackageFilterRef aFilter = *it;
48 if (!aFilter.IsSet() || !aFilter->AcceptsPackage(package))
49 return false;
50 }
51 return true;
52 }
53
54
55 class StateFilter : public PackageFilter
56 {
57 public:
StateFilter(PackageState state)58 StateFilter(PackageState state)
59 :
60 fState(state)
61 {
62 }
63
AcceptsPackage(const PackageInfoRef & package) const64 virtual bool AcceptsPackage(const PackageInfoRef& package) const
65 {
66 return PackageUtils::State(package) == fState;
67 }
68
69 private:
70 PackageState fState;
71 };
72
73
74 class CategoryFilter : public PackageFilter {
75 public:
CategoryFilter(const BString & categoryCode)76 CategoryFilter(const BString& categoryCode)
77 :
78 fCategoryCode(categoryCode)
79 {
80 }
81
AcceptsPackage(const PackageInfoRef & package) const82 virtual bool AcceptsPackage(const PackageInfoRef& package) const
83 {
84 if (!package.IsSet())
85 return false;
86
87 PackageClassificationInfoRef classificationInfo = package->PackageClassificationInfo();
88
89 if (!classificationInfo.IsSet())
90 return false;
91
92 return classificationInfo->HasCategoryByCode(CategoryCode());
93 }
94
CategoryCode() const95 const BString& CategoryCode() const
96 {
97 return fCategoryCode;
98 }
99
100 private:
101 BString fCategoryCode;
102 };
103
104
105 class DepotFilter : public PackageFilter {
106 public:
DepotFilter(const BString & name)107 DepotFilter(const BString& name)
108 :
109 fName(name)
110 {
111 }
112
AcceptsPackage(const PackageInfoRef & package) const113 virtual bool AcceptsPackage(const PackageInfoRef& package) const
114 {
115 if (!package.IsSet())
116 return false;
117 return package->DepotName() == fName;
118 }
119
Name() const120 const BString& Name() const
121 {
122 return fName;
123 }
124
125 private:
126 BString fName;
127 };
128
129
130 class SourceFilter : public PackageFilter {
131 public:
AcceptsPackage(const PackageInfoRef & package) const132 virtual bool AcceptsPackage(const PackageInfoRef& package) const
133 {
134 if (!package.IsSet())
135 return false;
136 const BString& packageName = package->Name();
137 return packageName.EndsWith("_source");
138 }
139 };
140
141
142 class DevelopmentFilter : public PackageFilter
143 {
144 public:
AcceptsPackage(const PackageInfoRef & package) const145 virtual bool AcceptsPackage(const PackageInfoRef& package) const
146 {
147 if (!package.IsSet())
148 return false;
149 const BString& packageName = package->Name();
150 return packageName.EndsWith("_devel")
151 || packageName.EndsWith("_debuginfo");
152 }
153 };
154
155
156 class SearchTermsFilter : public PackageFilter {
157 public:
SearchTermsFilter(const BString & searchTerms)158 SearchTermsFilter(const BString& searchTerms)
159 {
160 // Separate the string into terms at spaces
161 int32 index = 0;
162 while (index < searchTerms.Length()) {
163 int32 nextSpace = searchTerms.FindFirst(" ", index);
164 if (nextSpace < 0)
165 nextSpace = searchTerms.Length();
166 if (nextSpace > index) {
167 BString term;
168 searchTerms.CopyInto(term, index, nextSpace - index);
169 term.ToLower();
170 fSearchTerms.Add(term);
171 }
172 index = nextSpace + 1;
173 }
174 }
175
AcceptsPackage(const PackageInfoRef & package) const176 virtual bool AcceptsPackage(const PackageInfoRef& package) const
177 {
178 if (!package.IsSet())
179 return false;
180 // Every search term must be found in one of the package texts
181 for (int32 i = fSearchTerms.CountStrings() - 1; i >= 0; i--) {
182 const BString& term = fSearchTerms.StringAt(i);
183 if (!_TextContains(package->Name(), term)
184 && !_TextContains(package->Publisher().Name(), term)
185 && !_AcceptsPackageFromLocalizedText(package, term)) {
186 return false;
187 }
188 }
189 return true;
190 }
191
SearchTerms() const192 BString SearchTerms() const
193 {
194 BString searchTerms;
195 for (int32 i = 0; i < fSearchTerms.CountStrings(); i++) {
196 const BString& term = fSearchTerms.StringAt(i);
197 if (term.IsEmpty())
198 continue;
199 if (!searchTerms.IsEmpty())
200 searchTerms.Append(" ");
201 searchTerms.Append(term);
202 }
203 return searchTerms;
204 }
205
206 private:
_TextContains(BString text,const BString & string) const207 bool _TextContains(BString text, const BString& string) const
208 {
209 text.ToLower();
210 int32 index = text.FindFirst(string);
211 return index >= 0;
212 }
213
_AcceptsPackageFromLocalizedText(const PackageInfoRef & package,const BString & searchTerm) const214 bool _AcceptsPackageFromLocalizedText(const PackageInfoRef& package,
215 const BString& searchTerm) const
216 {
217 if (!package.IsSet())
218 return false;
219
220 PackageLocalizedTextRef localizedText = package->LocalizedText();
221
222 if (!localizedText.IsSet())
223 return false;
224
225 return _TextContains(localizedText->Title(), searchTerm)
226 || _TextContains(localizedText->Summary(), searchTerm)
227 || _TextContains(localizedText->Description(), searchTerm);
228 }
229
230 private:
231 BStringList fSearchTerms;
232 };
233
234
235 // #pragma mark - factory
236
237
238 /*static*/ PackageFilterRef
CreateCategoryFilter(const BString & category)239 PackageFilterFactory::CreateCategoryFilter(const BString& category)
240 {
241 return PackageFilterRef(new CategoryFilter(category), true);
242 }
243
244
245 /*static*/ PackageFilterRef
CreateSearchTermsFilter(const BString & searchTerms)246 PackageFilterFactory::CreateSearchTermsFilter(const BString& searchTerms)
247 {
248 return PackageFilterRef(new SearchTermsFilter(searchTerms), true);
249 }
250
251
252 /*static*/ PackageFilterRef
CreateDepotFilter(const BString & depotName)253 PackageFilterFactory::CreateDepotFilter(const BString& depotName)
254 {
255 return PackageFilterRef(new DepotFilter(depotName), true);
256 }
257
258
259 /*static*/ PackageFilterRef
CreateStateFilter(PackageState state)260 PackageFilterFactory::CreateStateFilter(PackageState state)
261 {
262 return PackageFilterRef(new StateFilter(state), true);
263 }
264
265
266 /*static*/ PackageFilterRef
CreateSourceFilter()267 PackageFilterFactory::CreateSourceFilter()
268 {
269 return PackageFilterRef(new SourceFilter(), true);
270 }
271
272
273 /*static*/ PackageFilterRef
CreateDevelopmentFilter()274 PackageFilterFactory::CreateDevelopmentFilter()
275 {
276 return PackageFilterRef(new DevelopmentFilter(), true);
277 }
278