diff --git a/docs/user/app/KeyStore.dox b/docs/user/app/KeyStore.dox index b2917a3f9e..2a0a7538ca 100644 --- a/docs/user/app/KeyStore.dox +++ b/docs/user/app/KeyStore.dox @@ -171,7 +171,7 @@ the key that you are looking for. \param[in] secondaryIdentifierOptional Use this query parameter to indicate if the secondary identifier has to match. When set to \a false, a - result will be returned, even if the \a secondaryIdentifer does not + result will be returned, even if the \a secondaryIdentifier does not match. \param[out] key A BKey object to copy the found data to. Any existing data in the key will be overwritten in case there is a match. diff --git a/docs/user/app/_app_keystore.dox b/docs/user/app/_app_keystore.dox index e6a2a7db3b..d046623b76 100644 --- a/docs/user/app/_app_keystore.dox +++ b/docs/user/app/_app_keystore.dox @@ -207,7 +207,7 @@ why in the \ref BApplication::ReadyToRun() hook we check for the availability of the key. If it is not available, or it does not work, the user will be redirected to the authentication tool. The key will be stored - as a password. It will be identified by the identifer "CoolWebService". + as a password. It will be identified by the identifier "CoolWebService". \code{.cpp} void diff --git a/src/apps/haikudepot/HaikuDepot.rdef b/src/apps/haikudepot/HaikuDepot.rdef index b2a05c5404..b587987ec1 100644 --- a/src/apps/haikudepot/HaikuDepot.rdef +++ b/src/apps/haikudepot/HaikuDepot.rdef @@ -8,13 +8,13 @@ resource app_flags B_SINGLE_LAUNCH; resource app_version { major = 0, middle = 0, - minor = 3, + minor = 4, variety = B_APPV_ALPHA, internal = 1, short_info = "HaikuDepot", - long_info = "HaikuDepot ©2013-2018 Haiku" + long_info = "HaikuDepot ©2013-2020 Haiku" }; resource file_types message { diff --git a/src/apps/haikudepot/build/scripts/hdsjsonschemacommon.py b/src/apps/haikudepot/build/scripts/hdsjsonschemacommon.py index e951ff484f..32443954a1 100644 --- a/src/apps/haikudepot/build/scripts/hdsjsonschemacommon.py +++ b/src/apps/haikudepot/build/scripts/hdsjsonschemacommon.py @@ -1,6 +1,6 @@ # ===================================== -# Copyright 2017-2019, Andrew Lindesay +# Copyright 2017-2020, Andrew Lindesay # Distributed under the terms of the MIT License. # ===================================== @@ -70,12 +70,21 @@ def propmetadatatocpptypename(propmetadata): if type == JSON_TYPE_ARRAY: itemsmetadata = propmetadata['items'] - itemsjavatype = itemsmetadata['javaType'] + itemstype = itemsmetadata['type'] - if not itemsjavatype or 0 == len(itemsjavatype): - raise Exception('missing "javaType" field') + if not itemstype or 0 == len(itemstype): + raise Exception('missing "type" field') - return "%s <%s>" % (CPP_TYPE_ARRAY, javatypetocppname(itemsjavatype)) + if itemstype == JSON_TYPE_OBJECT: + itemsjavatype = itemsmetadata['javaType'] + if not itemsjavatype or 0 == len(itemsjavatype): + raise Exception('missing "javaType" field') + return "%s<%s>" % (CPP_TYPE_ARRAY, javatypetocppname(itemsjavatype)) + + if itemstype == JSON_TYPE_STRING: + return "%s<%s>" % (CPP_TYPE_ARRAY, CPP_TYPE_STRING) + + raise Exception('unsupported type [%s]' % itemstype) raise Exception('unknown json-schema type [' + type + ']') diff --git a/src/apps/haikudepot/build/scripts/jsonschema2cppmodel.py b/src/apps/haikudepot/build/scripts/jsonschema2cppmodel.py index be671729ab..0bc9a42700 100644 --- a/src/apps/haikudepot/build/scripts/jsonschema2cppmodel.py +++ b/src/apps/haikudepot/build/scripts/jsonschema2cppmodel.py @@ -1,7 +1,7 @@ #!/usr/bin/python # ===================================== -# Copyright 2017-2019, Andrew Lindesay +# Copyright 2017-2020, Andrew Lindesay # Distributed under the terms of the MIT License. # ===================================== @@ -18,7 +18,7 @@ import string def hasanylistproperties(schema): for propname, propmetadata in schema['properties'].items(): - if propmetadata['type'] == 'array': + if propmetadata['type'] == jscom.JSON_TYPE_ARRAY: return True return False @@ -217,12 +217,12 @@ def writescalaraccessorsheader(outputfile, cppname, cpptype): def writeaccessors(outputfile, cppclassname, propname, propmetadata): type = propmetadata['type'] - if type == 'array': + if type == jscom.JSON_TYPE_ARRAY: writelistaccessors(outputfile, cppclassname, jscom.propnametocppname(propname), jscom.propnametocppmembername(propname), - jscom.javatypetocppname(propmetadata['items']['javaType'])) + jscom.propmetadatatocpptypename(propmetadata['items'])) elif jscom.propmetadatatypeisscalar(propmetadata): writescalaraccessors(outputfile, cppclassname, @@ -240,10 +240,10 @@ def writeaccessors(outputfile, cppclassname, propname, propmetadata): def writeaccessorsheader(outputfile, propname, propmetadata): type = propmetadata['type'] - if type == 'array': + if type == jscom.JSON_TYPE_ARRAY: writelistaccessorsheader(outputfile, jscom.propnametocppname(propname), - jscom.javatypetocppname(propmetadata['items']['javaType'])) + jscom.propmetadatatocpptypename(propmetadata['items'])) elif jscom.propmetadatatypeisscalar(propmetadata): writescalaraccessorsheader(outputfile, jscom.propnametocppname(propname), @@ -278,7 +278,7 @@ def writedestructor(outputfile, cppname, schema): outputfile.write(' if (%s != NULL) {\n' % propmembername) - if propmetadata['type'] == 'array': + if propmetadata['type'] == jscom.JSON_TYPE_ARRAY: writedestructorlogicforlist(outputfile, propname, propmetadata) outputfile.write(( @@ -304,10 +304,10 @@ def writeheaderincludes(outputfile, properties): jsontype = propmetadata['type'] javatype = None - if jsontype == 'object': + if jsontype == jscom.JSON_TYPE_OBJECT: javatype = propmetadata['javaType'] - if jsontype == 'array': + if jsontype == jscom.JSON_TYPE_ARRAY: javatype = propmetadata['items']['javaType'] if javatype is not None: @@ -315,8 +315,9 @@ def writeheaderincludes(outputfile, properties): def schematocppmodels(inputfile, schema, outputdirectory): - if schema['type'] != 'object': - raise Exception('expecting object') + type = schema['type'] + if type != jscom.JSON_TYPE_OBJECT: + raise Exception('expecting object, but was [' + type + ']') javatype = schema['javaType'] @@ -337,7 +338,7 @@ def schematocppmodels(inputfile, schema, outputdirectory): #define ${guarddefname} #include -#include "String.h" +#include """).substitute({'guarddefname': guarddefname})) @@ -388,10 +389,12 @@ public: for propname, propmetadata in schema['properties'].items(): jsontype = propmetadata['type'] - if jsontype == 'array': - schematocppmodels(inputfile, propmetadata['items'], outputdirectory) + if jsontype == jscom.JSON_TYPE_ARRAY: + arraySchema = propmetadata['items'] + if arraySchema['type'] == jscom.JSON_TYPE_OBJECT: + schematocppmodels(inputfile, arraySchema, outputdirectory) - if jsontype == 'object': + if jsontype == jscom.JSON_TYPE_OBJECT: schematocppmodels(inputfile, propmetadata, outputdirectory) diff --git a/src/apps/haikudepot/build/scripts/jsonschema2cppparser.py b/src/apps/haikudepot/build/scripts/jsonschema2cppparser.py index 78d555ad3b..ff8b813d91 100644 --- a/src/apps/haikudepot/build/scripts/jsonschema2cppparser.py +++ b/src/apps/haikudepot/build/scripts/jsonschema2cppparser.py @@ -1,7 +1,7 @@ #!/usr/bin/python # ===================================== -# Copyright 2017-2019, Andrew Lindesay +# Copyright 2017-2020, Andrew Lindesay # Distributed under the terms of the MIT License. # ===================================== @@ -23,12 +23,22 @@ class CppParserSubTypeNaming: _naming = None def __init__(self, schema, naming): - javatype = schema['javaType'] + type = schema['type'] - if not javatype or 0 == len(javatype): - raise Exception('missing "javaType" field') + if not type or 0 == len(type): + raise Exception('missing "type" field') - self._cppmodelclassname = jscom.javatypetocppname(javatype) + def derivecppmodelclassname(): + if type == jscom.JSON_TYPE_OBJECT: + javatype = schema['javaType'] + if not javatype or 0 == len(javatype): + raise Exception('missing "javaType" field') + return jscom.javatypetocppname(javatype) + if type == jscom.JSON_TYPE_STRING: + return jscom.CPP_TYPE_STRING + raise Exception('unsupported "type" of "%s"' % type) + + self._cppmodelclassname = derivecppmodelclassname() self._naming = naming def cppmodelclassname(self): @@ -38,6 +48,8 @@ class CppParserSubTypeNaming: return self._cppmodelclassname + '_' + self._naming.generatejsonlistenername('Stacked') def cppstackedlistlistenerclassname(self): + if self._cppmodelclassname == jscom.CPP_TYPE_STRING: + return self._naming.cppstringliststackedlistenerclassname() return self._cppmodelclassname + '_List_' + self._naming.generatejsonlistenername('Stacked') def todict(self): @@ -48,7 +60,8 @@ class CppParserSubTypeNaming: } -# This naming relates to the whole schema. It's point of reference is the top level. +# This naming relates to the whole schema. It's point of +# reference is the top level. class CppParserNaming: _schemaroot = None @@ -57,8 +70,9 @@ class CppParserNaming: self._schemaroot = schemaroot def cpprootmodelclassname(self): - if self._schemaroot['type'] != 'object': - raise Exception('expecting object') + type = self._schemaroot['type'] + if type != 'object': + raise Exception('expecting object, but was [' + type + "]") javatype = self._schemaroot['javaType'] @@ -82,6 +96,9 @@ class CppParserNaming: def cppsuperstackedlistenerclassname(self): return self.generatejsonlistenername('AbstractStacked') + def cppstringliststackedlistenerclassname(self): + return self.generatejsonlistenername('StringList') + def cppbulkcontainerstackedlistenerclassname(self): return self.generatejsonlistenername('BulkContainerStacked') @@ -113,6 +130,7 @@ class CppParserNaming: 'cppbulkcontaineritemliststackedlistenerclassname': self.cppbulkcontaineritemliststackedlistenerclassname(), 'cppsuperstackedlistenerclassname': self.cppsuperstackedlistenerclassname(), 'cppitemlistenerstackedlistenerclassname': self.cppitemlistenerstackedlistenerclassname(), + 'cppstringliststackedlistenerclassname': self.cppstringliststackedlistenerclassname(), 'cppgeneralobjectstackedlistenerclassname': self.cppgeneralobjectstackedlistenerclassname(), 'cppgeneralarraystackedlistenerclassname': self.cppgeneralarraystackedlistenerclassname(), 'cppitemlistenerclassname': self.cppitemlistenerclassname() @@ -246,6 +264,81 @@ ${cppsuperstackedlistenerclassname}::Pop() """).substitute(istate.naming().todict())) +def writestringliststackedlistenerinterface(istate): + istate.outputfile().write( + string.Template(""" + +/*! Sometimes attributes of objects are able to be arrays of strings. This + listener will parse and return the array of strings. +*/ + +class ${cppstringliststackedlistenerclassname} : public ${cppsuperstackedlistenerclassname} { +public: + ${cppstringliststackedlistenerclassname}( + ${cppsupermainlistenerclassname}* mainListener, + ${cppsuperstackedlistenerclassname}* parent); + ~${cppstringliststackedlistenerclassname}(); + + bool Handle(const BJsonEvent& event); + BObjectList* Target(); + +protected: + BObjectList* fTarget; +}; +""").substitute(istate.naming().todict())) + + +def writestringliststackedlistenerimplementation(istate): + istate.outputfile().write( + string.Template(""" +${cppstringliststackedlistenerclassname}::${cppstringliststackedlistenerclassname}( + ${cppsupermainlistenerclassname}* mainListener, + ${cppsuperstackedlistenerclassname}* parent) + : + ${cppsuperstackedlistenerclassname}(mainListener, parent) +{ + fTarget = new BObjectList(); +} + + +${cppstringliststackedlistenerclassname}::~${cppstringliststackedlistenerclassname}() +{ +} + + +BObjectList* +${cppstringliststackedlistenerclassname}::Target() +{ + return fTarget; +} + + +bool +${cppstringliststackedlistenerclassname}::Handle(const BJsonEvent& event) +{ + switch (event.EventType()) { + case B_JSON_ARRAY_END: + { + bool status = Pop() && (ErrorStatus() == B_OK); + delete this; + return status; + } + case B_JSON_STRING: + { + fTarget->AddItem(new BString(event.Content())); + break; + } + default: + HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, + "illegal state - unexpected json event parsing a string array"); + break; + } + + return ErrorStatus() == B_OK; +} +""").substitute(istate.naming().todict())) + + def writeageneralstackedlistenerinterface(istate, alistenerclassname): istate.outputfile().write( string.Template(""" @@ -310,7 +403,6 @@ bool ${generalobjectclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { - case B_JSON_OBJECT_NAME: case B_JSON_NUMBER: case B_JSON_STRING: @@ -319,34 +411,23 @@ ${generalobjectclassname}::Handle(const BJsonEvent& event) case B_JSON_NULL: // ignore break; - - case B_JSON_OBJECT_START: Push(new ${generalobjectclassname}(fMainListener, this)); break; - - case B_JSON_ARRAY_START: Push(new ${generalarrayclassname}(fMainListener, this)); break; - - case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of array"); break; - - case B_JSON_OBJECT_END: { bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - - } - return ErrorStatus() == B_OK; } """).substitute(substitutedict)) @@ -361,7 +442,6 @@ bool ${generalarrayclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { - case B_JSON_OBJECT_NAME: case B_JSON_NUMBER: case B_JSON_STRING: @@ -370,31 +450,21 @@ ${generalarrayclassname}::Handle(const BJsonEvent& event) case B_JSON_NULL: // ignore break; - - case B_JSON_OBJECT_START: Push(new ${generalobjectclassname}(fMainListener, this)); break; - - case B_JSON_ARRAY_START: Push(new ${generalarrayclassname}(fMainListener, this)); break; - - case B_JSON_OBJECT_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected end of object"); break; - - case B_JSON_ARRAY_END: { bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - - } @@ -438,23 +508,24 @@ public: ${cppsuperstackedlistenerclassname}* parent); ~${subtype_cppstackedlistlistenerclassname}(); - bool Handle(const BJsonEvent& event); - - BObjectList<${subtype_cppmodelclassname}>* Target(); // list of %s pointers - + BObjectList<${subtype_cppmodelclassname}>* Target(); + // list of ${subtype_cppmodelclassname} pointers private: BObjectList<${subtype_cppmodelclassname}>* fTarget; }; """).substitute(jscom.uniondicts(naming.todict(), subtypenaming.todict()))) - for propname, propmetadata in subschema['properties'].items(): - if propmetadata['type'] == 'array': - writestackedlistenerinterface(istate, propmetadata['items']) - elif propmetadata['type'] == 'object': - writestackedlistenerinterface(istate, propmetadata) + if 'properties' in subschema: + + for propname, propmetadata in subschema['properties'].items(): + if propmetadata['type'] == jscom.JSON_TYPE_ARRAY: + if propmetadata['items']['type'] == jscom.JSON_TYPE_OBJECT: + writestackedlistenerinterface(istate, propmetadata['items']) + elif propmetadata['type'] == jscom.JSON_TYPE_OBJECT: + writestackedlistenerinterface(istate, propmetadata) def writebulkcontainerstackedlistenerinterface(istate, schema): @@ -605,18 +676,12 @@ bool ${subtype_cppstackedlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { - - case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - - case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - - case B_JSON_OBJECT_END: { bool status = Pop() && (ErrorStatus() == B_OK); @@ -778,16 +843,12 @@ bool ${subtype_cppstackedlistlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { - - case B_JSON_ARRAY_END: { bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - - case B_JSON_OBJECT_START: { ${subtype_cppstackedlistenerclassname}* nextListener = @@ -796,15 +857,12 @@ ${subtype_cppstackedlistlistenerclassname}::Handle(const BJsonEvent& event) Push(nextListener); break; } - - default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing an array of ${subtype_cppmodelclassname}"); break; } - return ErrorStatus() == B_OK; } """).substitute(jscom.uniondicts(naming.todict(), subtypenaming.todict()))) @@ -861,45 +919,32 @@ bool ${cppbulkcontainerstackedlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { - - case B_JSON_ARRAY_END: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected start of array"); break; - - case B_JSON_OBJECT_NAME: fNextItemName = event.Content(); break; - - case B_JSON_OBJECT_START: Push(new ${cppgeneralobjectstackedlistenerclassname}(fMainListener, this)); break; - - case B_JSON_ARRAY_START: if (fNextItemName == "items") Push(new ${cppbulkcontaineritemliststackedlistenerclassname}(fMainListener, this, fItemListener)); else Push(new ${cppgeneralarraystackedlistenerclassname}(fMainListener, this)); break; - - case B_JSON_OBJECT_END: { bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - - default: // ignore break; } - return ErrorStatus() == B_OK; } @@ -923,27 +968,20 @@ bool ${cppbulkcontaineritemliststackedlistenerclassname}::Handle(const BJsonEvent& event) { switch (event.EventType()) { - - case B_JSON_OBJECT_START: Push(new ${cppitemlistenerstackedlistenerclassname}(fMainListener, this, fItemListener)); break; - - case B_JSON_ARRAY_END: { bool status = Pop() && (ErrorStatus() == B_OK); delete this; return status; } - - default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event"); break; } - return ErrorStatus() == B_OK; } @@ -972,7 +1010,9 @@ def writestackedlistenerimplementation(istate, schema): for propname, propmetadata in schema['properties'].items(): if propmetadata['type'] == 'array': - writestackedlistenerimplementation(istate, propmetadata['items']) + items = propmetadata['items'] + if items['type'] == jscom.JSON_TYPE_OBJECT: + writestackedlistenerimplementation(istate, items) elif propmetadata['type'] == 'object': writestackedlistenerimplementation(istate, propmetadata) @@ -1054,14 +1094,10 @@ ${cppsinglemainlistenerclassname}::Handle(const BJsonEvent& event) if (fErrorStatus != B_OK) return false; - if (fStackedListener != NULL) return fStackedListener->Handle(event); - switch (event.EventType()) { - - case B_JSON_OBJECT_START: { ${subtype_cppstackedlistenerclassname}* nextListener = new ${subtype_cppstackedlistenerclassname}( @@ -1070,8 +1106,6 @@ ${cppsinglemainlistenerclassname}::Handle(const BJsonEvent& event) SetStackedListener(nextListener); break; } - - default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for ${cpprootmodelclassname}"); @@ -1115,14 +1149,10 @@ ${cppbulkcontainermainlistenerclassname}::Handle(const BJsonEvent& event) if (fErrorStatus != B_OK) return false; - if (fStackedListener != NULL) return fStackedListener->Handle(event); - switch (event.EventType()) { - - case B_JSON_OBJECT_START: { ${cppbulkcontainerstackedlistenerclassname}* nextListener = @@ -1132,8 +1162,6 @@ ${cppbulkcontainermainlistenerclassname}::Handle(const BJsonEvent& event) return true; break; } - - default: HandleError(B_NOT_ALLOWED, JSON_EVENT_LISTENER_ANY_LINE, "illegal state - unexpected json event parsing top level for ${cppbulkcontainermainlistenerclassname}"); @@ -1178,12 +1206,10 @@ public: ${cppsupermainlistenerclassname}(); virtual ~${cppsupermainlistenerclassname}(); - void HandleError(status_t status, int32 line, const char* message); void Complete(); status_t ErrorStatus(); - protected: void SetStackedListener( ${cppsuperstackedlistenerclassname}* listener); @@ -1202,11 +1228,9 @@ public: ${cppsinglemainlistenerclassname}(); virtual ~${cppsinglemainlistenerclassname}(); - bool Handle(const BJsonEvent& event); ${cpprootmodelclassname}* Target(); - private: ${cpprootmodelclassname}* fTarget; }; @@ -1227,7 +1251,6 @@ private: it is parsed from the bulk container. When the stream is finished, the Complete() method is invoked. - Note that the item object will be deleted after the Handle method is invoked. The Handle method need not take responsibility for deleting the item itself. @@ -1258,10 +1281,8 @@ public: ${cppitemlistenerclassname}* itemListener); ~${cppbulkcontainermainlistenerclassname}(); - bool Handle(const BJsonEvent& event); - private: ${cppitemlistenerclassname}* fItemListener; }; @@ -1280,6 +1301,7 @@ private: writerootstackedlistenerinterface(istate) writegeneralstackedlistenerinterface(istate) + writestringliststackedlistenerinterface(istate) writestackedlistenerinterface(istate, schema) if supportbulkcontainer: @@ -1289,6 +1311,7 @@ private: writerootstackedlistenerimplementation(istate) writegeneralstackedlistenerimplementation(istate) + writestringliststackedlistenerimplementation(istate) writestackedlistenerimplementation(istate, schema) if supportbulkcontainer: diff --git a/src/apps/haikudepot/model/Model.cpp b/src/apps/haikudepot/model/Model.cpp index 110817c1ab..cf97979277 100644 --- a/src/apps/haikudepot/model/Model.cpp +++ b/src/apps/haikudepot/model/Model.cpp @@ -1041,19 +1041,19 @@ Model::_NotifyCategoryListChanged() /*! This method will find the stored 'DepotInfo' that correlates to the - supplied 'url' and will invoke the mapper function in order to get a - replacement for the 'DepotInfo'. The 'url' is a unique identifier - for the repository that holds across mirrors. + supplied 'identifier' and will invoke the mapper function in order + to get a replacement for the 'DepotInfo'. The 'identifier' holds + across mirrors. */ void -Model::ReplaceDepotByUrl(const BString& URL, DepotMapper* depotMapper, - void* context) +Model::ReplaceDepotByIdentifier(const BString& identifier, + DepotMapper* depotMapper, void* context) { for (int32 i = 0; i < fDepots.CountItems(); i++) { DepotInfo depotInfo = fDepots.ItemAtFast(i); - if (RepositoryUrlUtils::EqualsNormalized(URL, depotInfo.URL())) { + if (identifier == depotInfo.URL()) { BAutolock locker(&fLock); fDepots.Replace(i, depotMapper->MapDepot(depotInfo, context)); } diff --git a/src/apps/haikudepot/model/Model.h b/src/apps/haikudepot/model/Model.h index 1aa57cca83..7612cf98ca 100644 --- a/src/apps/haikudepot/model/Model.h +++ b/src/apps/haikudepot/model/Model.h @@ -147,8 +147,8 @@ public: GetWebAppInterface() const { return fWebAppInterface; } - void ReplaceDepotByUrl( - const BString& URL, + void ReplaceDepotByIdentifier( + const BString& identifier, DepotMapper* depotMapper, void* context); diff --git a/src/apps/haikudepot/server/ServerRepositoryDataUpdateProcess.cpp b/src/apps/haikudepot/server/ServerRepositoryDataUpdateProcess.cpp index b4923860a7..c18eb7902f 100644 --- a/src/apps/haikudepot/server/ServerRepositoryDataUpdateProcess.cpp +++ b/src/apps/haikudepot/server/ServerRepositoryDataUpdateProcess.cpp @@ -28,6 +28,12 @@ #define B_TRANSLATION_CONTEXT "ServerRepositoryDataUpdateProcess" +struct repository_and_repository_source { + DumpExportRepository* repository; + DumpExportRepositorySource* repositorySource; +}; + + /*! This repository listener (not at the JSON level) is feeding in the repositories as they are parsed and processing them. Processing includes finding the matching depot record and coupling the data @@ -43,6 +49,9 @@ public: virtual DepotInfo MapDepot(const DepotInfo& depot, void *context); virtual bool Handle(DumpExportRepository* item); + void Handle(repository_and_repository_source& pair); + void Handle(const BString& identifier, + repository_and_repository_source& pair); virtual void Complete(); private: @@ -73,12 +82,6 @@ DepotMatchingRepositoryListener::~DepotMatchingRepositoryListener() } -struct repository_and_repository_source { - DumpExportRepository* repository; - DumpExportRepositorySource* repositorySource; -}; - - /*! This is invoked as a result of logic in 'Handle(..)' that requests that the model call this method with the requested DepotInfo instance. */ @@ -104,7 +107,8 @@ DepotMatchingRepositoryListener::MapDepot(const DepotInfo& depot, void *context) modifiedDepotInfo.Name().String(), modifiedDepotInfo.URL().String(), repositorySourceCode->String(), - repositoryAndRepositorySource->repositorySource->Url()->String()); + repositoryAndRepositorySource + ->repositorySource->Identifier()->String()); } else { printf("[DepotMatchingRepositoryListener] associated depot [%s] with " "server repository source [%s]\n", @@ -116,6 +120,33 @@ DepotMatchingRepositoryListener::MapDepot(const DepotInfo& depot, void *context) } +void +DepotMatchingRepositoryListener::Handle(const BString& identifier, + repository_and_repository_source& pair) +{ + if (!identifier.IsEmpty()) { + fModel->ReplaceDepotByIdentifier(identifier, this, &pair); + } +} + + +void +DepotMatchingRepositoryListener::Handle(repository_and_repository_source& pair) +{ + Handle(*(pair.repositorySource->Identifier()), pair); + + // there may be additional identifiers for the remote repository and + // these should also be taken into consideration. + + for(int32 i = 0; + i < pair.repositorySource->CountExtraIdentifiers(); + i++) + { + Handle(*(pair.repositorySource->ExtraIdentifiersItemAt(i)), pair); + } +} + + bool DepotMatchingRepositoryListener::Handle(DumpExportRepository* repository) { @@ -126,14 +157,7 @@ DepotMatchingRepositoryListener::Handle(DumpExportRepository* repository) repositoryAndRepositorySource.repository = repository; repositoryAndRepositorySource.repositorySource = repository->RepositorySourcesItemAt(i); - - BString* repoInfoURL = repositoryAndRepositorySource - .repositorySource->RepoInfoUrl(); - - if (!repoInfoURL->IsEmpty()) { - fModel->ReplaceDepotByUrl(*repoInfoURL, this, - &repositoryAndRepositorySource); - } + Handle(repositoryAndRepositorySource); } return !fStoppable->WasStopped(); diff --git a/src/apps/haikudepot/server/schema/dumpexportrepository.json b/src/apps/haikudepot/server/schema/dumpexportrepository.json index d4676aefae..d6276c716a 100644 --- a/src/apps/haikudepot/server/schema/dumpexportrepository.json +++ b/src/apps/haikudepot/server/schema/dumpexportrepository.json @@ -26,11 +26,16 @@ "code": { "type": "string" }, - "url": { - "type": "string" + "identifier": { + "type": "string", + "javaType": "java.lang.String" }, - "repoInfoUrl": { - "type": "string" + "extraIdentifiers": { + "type": "array", + "items": { + "type": "string", + "javaType": "java.lang.String" + } }, "repositorySourceMirrors": { "type": "array", diff --git a/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp b/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp index bdbcc24fd0..f8c6fbac74 100644 --- a/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp +++ b/src/tests/apps/haikudepot/DumpExportRepositoryJsonListenerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2017, Andrew Lindesay . + * Copyright 2017-2020, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. */ @@ -37,11 +37,12 @@ " \"repositorySources\": [\n" \ " {\n" \ " \"code\": \"haikuports_x86_64\",\n" \ - " \"url\": \"http://example.com/0\"\n" \ + " \"identifier\": \"haiku:hpkr:haikuports_x86_64\",\n" \ + " \"extraIdentifiers\":[\"zing\"]\n" \ " },\n" \ " {\n" \ " \"code\": \"haikuports_x86_gcc2\",\n" \ - " \"url\": \"http://example.com/1\"\n" \ + " \"identifier\": \"haiku:hpkr:haikuports_x86_gcc2\"\n" \ " }\n" \ " ]\n" \ "}\n" @@ -67,7 +68,8 @@ " \"repositorySources\": [\n" \ " {\n" \ " \"code\": \"fatelk_x86_gcc2\",\n" \ - " \"url\": \"http://coquillemartialarts.com/fatelk/repo\"\n" \ + " \"identifier\": \"can-be-anything\",\n" \ + " \"extraIdentifiers\":[\"zing\"]\n" \ " }\n" \ " ]\n" \ " },\n" \ @@ -78,7 +80,7 @@ " \"repositorySources\": [\n" \ " {\n" \ " \"code\": \"besly_x86_gcc2\",\n" \ - " \"url\": \"http://software.besly.de/repo\"\n" \ + " \"identifier\": \"haiku:hpkr:wojfqdi23e\"\n" \ " }\n" \ " ]\n" \ " },\n" \ @@ -89,11 +91,11 @@ " \"repositorySources\": [\n" \ " {\n" \ " \"code\": \"clasqm_x86_64\",\n" \ - " \"url\": \"http://8ABA\"\n" \ + " \"identifier\": \"haiku:hpkr:23r829rro\"\n" \ " },\n" \ " {\n" \ " \"code\": \"clasqm_x86_gcc2\",\n" \ - " \"url\": \"http://8D0B\"\n" \ + " \"identifier\": \"haiku:hpkr:joihir32r\"\n" \ " }\n" \ " ]\n" \ " },\n" \ @@ -105,11 +107,11 @@ " \"repositorySources\": [\n" \ " {\n" \ " \"code\": \"haikuports_x86_64\",\n" \ - " \"url\": \"http://B362\"\n" \ + " \"identifier\": \"haiku:hpkr:jqod2333r3r\"\n" \ " },\n" \ " {\n" \ " \"code\": \"haikuports_x86_gcc2\",\n" \ - " \"url\": \"http://8AF3\"\n" \ + " \"identifier\": \"haiku:hpkr:wyeuhfwiewe\"\n" \ " }\n" \ " ]\n" \ " }\n" \ @@ -172,10 +174,12 @@ DumpExportRepositoryJsonListenerTest::TestBulkContainer() BString("fatelk besly clasqm haikuports"), itemListener.ConcatenatedCodes()); CPPUNIT_ASSERT_EQUAL_MESSAGE("!ConcatenatedSourcesUrls", - BString("http://coquillemartialarts.com/fatelk/repo" - " http://software.besly.de/repo" - " http://8ABA http://8D0B" - " http://B362 http://8AF3"), + BString("can-be-anything" + " haiku:hpkr:wojfqdi23e" + " haiku:hpkr:23r829rro" + " haiku:hpkr:joihir32r" + " haiku:hpkr:jqod2333r3r" + " haiku:hpkr:wyeuhfwiewe"), itemListener.ConcatenatedSourcesUrls()); } @@ -219,10 +223,11 @@ DumpExportRepositoryJsonListenerTest::TestSingle() repository->RepositorySourcesItemAt(1); CPPUNIT_ASSERT_EQUAL(BString("haikuports_x86_64"), *(source0->Code())); - CPPUNIT_ASSERT_EQUAL(BString("http://example.com/0"), *(source0->Url())); + CPPUNIT_ASSERT_EQUAL(BString("haiku:hpkr:haikuports_x86_64"), *(source0->Identifier())); + CPPUNIT_ASSERT_EQUAL(BString("zing"), *(source0->ExtraIdentifiersItemAt(0))); CPPUNIT_ASSERT_EQUAL(BString("haikuports_x86_gcc2"), *(source1->Code())); - CPPUNIT_ASSERT_EQUAL(BString("http://example.com/1"), *(source1->Url())); + CPPUNIT_ASSERT_EQUAL(BString("haiku:hpkr:haikuports_x86_gcc2"), *(source1->Identifier())); } @@ -276,7 +281,7 @@ TestBulkContainerItemListener::Handle(DumpExportRepository* item) fConcatenatedSourcesUrl.Append(" "); fConcatenatedSourcesUrl.Append( - item->RepositorySourcesItemAt(i)->Url()->String()); + item->RepositorySourcesItemAt(i)->Identifier()->String()); } return true; @@ -308,4 +313,4 @@ bool TestBulkContainerItemListener::WasCompleteInvoked() { return fWasCompleteInvoked; -} \ No newline at end of file +}