1 /*
2 * Copyright 2019-2020, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6
7 #include "ServerReferenceDataUpdateProcess.h"
8
9 #include <stdio.h>
10 #include <sys/stat.h>
11 #include <time.h>
12
13 #include <AutoDeleter.h>
14 #include <AutoLocker.h>
15 #include <Catalog.h>
16 #include <FileIO.h>
17 #include <Url.h>
18
19 #include "DumpExportReference.h"
20 #include "DumpExportReferenceCountry.h"
21 #include "DumpExportReferenceJsonListener.h"
22 #include "DumpExportReferenceNaturalLanguage.h"
23 #include "DumpExportReferencePkgCategory.h"
24 #include "DumpExportReferenceUserRatingStability.h"
25 #include "LocaleUtils.h"
26 #include "Logger.h"
27 #include "ServerSettings.h"
28 #include "StorageUtils.h"
29
30
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "ServerReferenceDataUpdateProcess"
33
34
ServerReferenceDataUpdateProcess(Model * model,uint32 serverProcessOptions)35 ServerReferenceDataUpdateProcess::ServerReferenceDataUpdateProcess(
36 Model* model,
37 uint32 serverProcessOptions)
38 :
39 AbstractSingleFileServerProcess(serverProcessOptions),
40 fModel(model)
41 {
42 }
43
44
~ServerReferenceDataUpdateProcess()45 ServerReferenceDataUpdateProcess::~ServerReferenceDataUpdateProcess()
46 {
47 }
48
49
50 const char*
Name() const51 ServerReferenceDataUpdateProcess::Name() const
52 {
53 return "ServerReferenceDataUpdateProcess";
54 }
55
56
57 const char*
Description() const58 ServerReferenceDataUpdateProcess::Description() const
59 {
60 return B_TRANSLATE("Synchronizing reference data from server");
61 }
62
63
64 BString
UrlPathComponent()65 ServerReferenceDataUpdateProcess::UrlPathComponent()
66 {
67 BString result;
68 AutoLocker<BLocker> locker(fModel->Lock());
69 result.SetToFormat("/__reference/all-%s.json.gz", fModel->PreferredLanguage()->ID());
70 return result;
71 }
72
73
74 status_t
GetLocalPath(BPath & path) const75 ServerReferenceDataUpdateProcess::GetLocalPath(BPath& path) const
76 {
77 AutoLocker<BLocker> locker(fModel->Lock());
78 return StorageUtils::DumpExportReferenceDataPath(path, fModel->PreferredLanguage());
79 }
80
81
82 status_t
ProcessLocalData()83 ServerReferenceDataUpdateProcess::ProcessLocalData()
84 {
85 SingleDumpExportReferenceJsonListener* listener =
86 new SingleDumpExportReferenceJsonListener();
87
88 BPath localPath;
89 status_t result = GetLocalPath(localPath);
90
91 if (result != B_OK)
92 return result;
93
94 result = ParseJsonFromFileWithListener(listener, localPath);
95
96 if (result != B_OK)
97 return result;
98
99 result = listener->ErrorStatus();
100
101 if (result != B_OK)
102 return result;
103
104 return _ProcessData(listener->Target());
105 }
106
107
108 status_t
_ProcessData(DumpExportReference * data)109 ServerReferenceDataUpdateProcess::_ProcessData(DumpExportReference* data)
110 {
111 status_t result = B_OK;
112 if (result == B_OK)
113 result = _ProcessNaturalLanguages(data);
114 if (result == B_OK)
115 result = _ProcessPkgCategories(data);
116 if (result == B_OK)
117 result = _ProcessRatingStabilities(data);
118 return result;
119 }
120
121
122 status_t
_ProcessNaturalLanguages(DumpExportReference * data)123 ServerReferenceDataUpdateProcess::_ProcessNaturalLanguages(
124 DumpExportReference* data)
125 {
126 HDINFO("[%s] will populate from %" B_PRId32 " possible natural languages",
127 Name(), data->CountNaturalLanguages());
128 AutoLocker<BLocker> locker(fModel->Lock());
129
130 LanguageRepository* languageRepository = fModel->Languages();
131 languageRepository->Clear();
132 int32 count = 0;
133
134 for (int32 i = 0; i < data->CountNaturalLanguages(); i++) {
135 DumpExportReferenceNaturalLanguage* naturalLanguage =
136 data->NaturalLanguagesItemAt(i);
137 languageRepository->AddLanguage(
138 LanguageRef(new Language(*(naturalLanguage->Code()), *(naturalLanguage->Name()),
139 naturalLanguage->IsPopular()),
140 true));
141 count++;
142 }
143
144 // it could be that the preferred language does not exist in the
145 // list. In this case it is necessary to choose one from the list.
146 fModel->SetPreferredLanguage(LocaleUtils::DeriveDefaultLanguage(fModel->Languages()));
147
148 HDINFO("[%s] did add %" B_PRId32 " supported languages", Name(), count);
149
150 return B_OK;
151 }
152
153
154 status_t
_ProcessPkgCategories(DumpExportReference * data)155 ServerReferenceDataUpdateProcess::_ProcessPkgCategories(
156 DumpExportReference* data)
157 {
158 HDINFO("[%s] will populate %" B_PRId32 " pkg categories",
159 Name(), data->CountPkgCategories());
160
161 std::vector<CategoryRef> assembledCategories;
162
163 for (int32 i = 0; i < data->CountPkgCategories(); i++) {
164 DumpExportReferencePkgCategory* pkgCategory =
165 data->PkgCategoriesItemAt(i);
166 assembledCategories.push_back(CategoryRef(
167 new PackageCategory(
168 *(pkgCategory->Code()),
169 *(pkgCategory->Name())
170 ),
171 true));
172 }
173
174 {
175 AutoLocker<BLocker> locker(fModel->Lock());
176 fModel->AddCategories(assembledCategories);
177 }
178
179 return B_OK;
180 }
181
182
183 status_t
_ProcessRatingStabilities(DumpExportReference * data)184 ServerReferenceDataUpdateProcess::_ProcessRatingStabilities(
185 DumpExportReference* data)
186 {
187 HDINFO("[%s] will populate %" B_PRId32 " rating stabilities",
188 Name(), data->CountUserRatingStabilities());
189
190 std::vector<RatingStabilityRef> assembledRatingStabilities;
191
192 for (int32 i = 0; i < data->CountUserRatingStabilities(); i++) {
193 DumpExportReferenceUserRatingStability* ratingStability =
194 data->UserRatingStabilitiesItemAt(i);
195 assembledRatingStabilities.push_back(RatingStabilityRef(
196 new RatingStability(
197 *(ratingStability->Code()),
198 *(ratingStability->Name()),
199 ratingStability->Ordering()
200 ),
201 true));
202 }
203
204 {
205 AutoLocker<BLocker> locker(fModel->Lock());
206 fModel->AddRatingStabilities(assembledRatingStabilities);
207 }
208
209 return B_OK;
210 }
211
212
213 status_t
GetStandardMetaDataPath(BPath & path) const214 ServerReferenceDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
215 {
216 return GetLocalPath(path);
217 }
218
219
220 void
GetStandardMetaDataJsonPath(BString & jsonPath) const221 ServerReferenceDataUpdateProcess::GetStandardMetaDataJsonPath(
222 BString& jsonPath) const
223 {
224 jsonPath.SetTo("$.info");
225 }
226