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