xref: /haiku/src/apps/haikudepot/server/ServerReferenceDataUpdateProcess.cpp (revision 909af08f4328301fbdef1ffb41f566c3b5bec0c7)
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 
35 ServerReferenceDataUpdateProcess::ServerReferenceDataUpdateProcess(
36 	Model* model,
37 	uint32 serverProcessOptions)
38 	:
39 	AbstractSingleFileServerProcess(serverProcessOptions),
40 	fModel(model)
41 {
42 }
43 
44 
45 ServerReferenceDataUpdateProcess::~ServerReferenceDataUpdateProcess()
46 {
47 }
48 
49 
50 const char*
51 ServerReferenceDataUpdateProcess::Name() const
52 {
53 	return "ServerReferenceDataUpdateProcess";
54 }
55 
56 
57 const char*
58 ServerReferenceDataUpdateProcess::Description() const
59 {
60 	return B_TRANSLATE("Synchronizing reference data from server");
61 }
62 
63 
64 BString
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
75 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
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
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
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
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
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
214 ServerReferenceDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
215 {
216 	return GetLocalPath(path);
217 }
218 
219 
220 void
221 ServerReferenceDataUpdateProcess::GetStandardMetaDataJsonPath(
222 	BString& jsonPath) const
223 {
224 	jsonPath.SetTo("$.info");
225 }
226