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