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 "ServerSettings.h"
20#include "StorageUtils.h"
21#include "Logger.h"
22#include "DumpExportReference.h"
23#include "DumpExportReferenceNaturalLanguage.h"
24#include "DumpExportReferencePkgCategory.h"
25#include "DumpExportReferenceUserRatingStability.h"
26#include "DumpExportReferenceCountry.h"
27#include "DumpExportReferenceJsonListener.h"
28
29
30#undef B_TRANSLATION_CONTEXT
31#define B_TRANSLATION_CONTEXT "ServerReferenceDataUpdateProcess"
32
33
34ServerReferenceDataUpdateProcess::ServerReferenceDataUpdateProcess(
35	Model* model,
36	uint32 serverProcessOptions)
37	:
38	AbstractSingleFileServerProcess(serverProcessOptions),
39	fModel(model)
40{
41}
42
43
44ServerReferenceDataUpdateProcess::~ServerReferenceDataUpdateProcess()
45{
46}
47
48
49const char*
50ServerReferenceDataUpdateProcess::Name() const
51{
52	return "ServerReferenceDataUpdateProcess";
53}
54
55
56const char*
57ServerReferenceDataUpdateProcess::Description() const
58{
59	return B_TRANSLATE("Synchronizing reference data from server");
60}
61
62
63BString
64ServerReferenceDataUpdateProcess::UrlPathComponent()
65{
66	BString result;
67	AutoLocker<BLocker> locker(fModel->Lock());
68	result.SetToFormat("/__reference/all-%s.json.gz",
69		fModel->Language()->PreferredLanguage()->ID());
70	return result;
71}
72
73
74status_t
75ServerReferenceDataUpdateProcess::GetLocalPath(BPath& path) const
76{
77	AutoLocker<BLocker> locker(fModel->Lock());
78	return fModel->DumpExportReferenceDataPath(path);
79}
80
81
82status_t
83ServerReferenceDataUpdateProcess::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
108status_t
109ServerReferenceDataUpdateProcess::_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
122status_t
123ServerReferenceDataUpdateProcess::_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	LanguageModel* languageModel = fModel->Language();
130	languageModel->ClearSupportedLanguages();
131	int32 count = 0;
132
133	for (int32 i = 0; i < data->CountNaturalLanguages(); i++) {
134		DumpExportReferenceNaturalLanguage* naturalLanguage =
135			data->NaturalLanguagesItemAt(i);
136		languageModel->AddSupportedLanguage(LanguageRef(
137			new Language(
138				*(naturalLanguage->Code()),
139				*(naturalLanguage->Name()),
140				naturalLanguage->IsPopular()
141			),
142			true)
143		);
144		count++;
145	}
146
147	languageModel->SetPreferredLanguageToSystemDefault();
148
149	HDINFO("[%s] did add %" B_PRId32 " supported languages",
150		Name(), count);
151
152	return B_OK;
153}
154
155
156status_t
157ServerReferenceDataUpdateProcess::_ProcessPkgCategories(
158	DumpExportReference* data)
159{
160	HDINFO("[%s] will populate %" B_PRId32 " pkg categories",
161		Name(), data->CountPkgCategories());
162
163	std::vector<CategoryRef> assembledCategories;
164
165	for (int32 i = 0; i < data->CountPkgCategories(); i++) {
166		DumpExportReferencePkgCategory* pkgCategory =
167			data->PkgCategoriesItemAt(i);
168		assembledCategories.push_back(CategoryRef(
169			new PackageCategory(
170				*(pkgCategory->Code()),
171				*(pkgCategory->Name())
172			),
173			true));
174	}
175
176	{
177		AutoLocker<BLocker> locker(fModel->Lock());
178		fModel->AddCategories(assembledCategories);
179	}
180
181	return B_OK;
182}
183
184
185status_t
186ServerReferenceDataUpdateProcess::_ProcessRatingStabilities(
187	DumpExportReference* data)
188{
189	HDINFO("[%s] will populate %" B_PRId32 " rating stabilities",
190		Name(), data->CountUserRatingStabilities());
191
192	std::vector<RatingStabilityRef> assembledRatingStabilities;
193
194	for (int32 i = 0; i < data->CountUserRatingStabilities(); i++) {
195		DumpExportReferenceUserRatingStability* ratingStability =
196			data->UserRatingStabilitiesItemAt(i);
197		assembledRatingStabilities.push_back(RatingStabilityRef(
198			new RatingStability(
199				*(ratingStability->Code()),
200				*(ratingStability->Name()),
201				ratingStability->Ordering()
202			),
203			true));
204	}
205
206	{
207		AutoLocker<BLocker> locker(fModel->Lock());
208		fModel->AddRatingStabilities(assembledRatingStabilities);
209	}
210
211	return B_OK;
212}
213
214
215status_t
216ServerReferenceDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
217{
218	return GetLocalPath(path);
219}
220
221
222void
223ServerReferenceDataUpdateProcess::GetStandardMetaDataJsonPath(
224	BString& jsonPath) const
225{
226	jsonPath.SetTo("$.info");
227}
228