diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-08-12 13:45:17 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-08-12 13:45:17 +0200 |
| commit | 8d0500b325d12b047797a60e3c13d4b473fae987 (patch) | |
| tree | 3537d416efd354bdfb7248034d912675d344ca9f | |
| parent | 0a1261781de96d2bb8c76fbd905ebf8b0121d3a6 (diff) | |
| download | PROJ-8d0500b325d12b047797a60e3c13d4b473fae987.tar.gz PROJ-8d0500b325d12b047797a60e3c13d4b473fae987.zip | |
PROJJSON: add support for importing 'ids'
| -rw-r--r-- | data/crsjson.schema.json | 144 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 63 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 25 |
3 files changed, 174 insertions, 58 deletions
diff --git a/data/crsjson.schema.json b/data/crsjson.schema.json index 10b17caa..726d8ece 100644 --- a/data/crsjson.schema.json +++ b/data/crsjson.schema.json @@ -25,9 +25,13 @@ "type": "array", "items": { "$ref": "#/definitions/parameter_value" } }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "method", "parameters" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -79,9 +83,13 @@ "past", "unspecified" ] }, "unit": { "$ref": "#/definitions/unit" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "abbreviation", "direction" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -125,7 +133,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "components" ], "additionalProperties": false @@ -148,7 +156,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "source_crs", "target_crs", "steps" ], "additionalProperties": false @@ -164,9 +172,13 @@ "type": "array", "items": { "$ref": "#/definitions/parameter_value" } }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "method" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -189,9 +201,13 @@ "type": "array", "items": { "$ref": "#/definitions/axis" } }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "subtype", "axis" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -237,17 +253,25 @@ "type": "object", "properties": { "name": { "type": "string" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false } }, "ellipsoid": { "$ref": "#/definitions/ellipsoid" }, "accuracy": { "type": "string" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "members", "accuracy" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -266,7 +290,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -288,7 +312,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -309,7 +333,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -330,7 +354,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -351,7 +375,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -372,7 +396,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -394,7 +418,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "ellipsoid", "frame_reference_epoch" ], "additionalProperties": false @@ -414,7 +438,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "frame_reference_epoch" ], "additionalProperties": false @@ -429,7 +453,8 @@ "name": { "type": "string" }, "semi_major_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, "semi_minor_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "semi_major_axis", "semi_minor_axis" ], "additionalProperties": false @@ -440,7 +465,8 @@ "name": { "type": "string" }, "semi_major_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, "inverse_flattening": { "type": "number" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "semi_major_axis", "inverse_flattening" ], "additionalProperties": false @@ -450,11 +476,15 @@ "type": { "type": "string", "enum": ["Ellipsoid"] }, "name": { "type": "string" }, "radius": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "radius" ], "additionalProperties": false } + ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } ] }, @@ -471,7 +501,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "datum" ], "additionalProperties": false @@ -489,7 +519,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name" ], "additionalProperties": false @@ -513,7 +543,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name" ], "description": "One and only one of datum and datum_ensemble must be provided", @@ -538,7 +568,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "ellipsoid" ], "additionalProperties": false @@ -556,17 +586,33 @@ "additionalProperties": false }, + "ids": { + "type": "array", + "items": { "$ref": "#/definitions/id" } + }, + "method": { "type": "object", "properties": { "type": { "type": "string", "enum": ["OperationMethod"]}, "name": { "type": "string" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, + "id_ids_mutually_exclusive": { + "not": { + "type": "object", + "required": [ "id", "ids" ] + } + }, + "one_and_only_one_of_datum_or_datum_ensemble": { "allOf": [ { @@ -593,16 +639,24 @@ "area": { "type": "string" }, "bbox": { "$ref": "#/definitions/bbox" }, "remarks": { "type": "string" }, - "id": { "$ref": "#/definitions/id" } - } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ] }, { "type": "object", "properties": { "usages": { "$ref": "#/definitions/usages" }, "remarks": { "type": "string" }, - "id": { "$ref": "#/definitions/id" } - } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } + }, + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ] } ] }, @@ -619,9 +673,13 @@ ] }, "unit": { "$ref": "#/definitions/unit" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name", "value" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -638,7 +696,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "datum" ], "additionalProperties": false @@ -656,7 +714,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name" ], "additionalProperties": false @@ -668,9 +726,13 @@ "type": { "type": "string", "enum": ["PrimeMeridian"] }, "name": { "type": "string" }, "longitude": { "$ref": "#/definitions/value_and_unit" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false }, @@ -696,7 +758,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "base_crs", "conversion", "coordinate_system" ], "additionalProperties": false @@ -715,7 +777,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "datum" ], "additionalProperties": false @@ -734,7 +796,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "calendar" ], "additionalProperties": false @@ -760,7 +822,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name", "source_crs", "target_crs", "method", "parameters" ], "additionalProperties": false @@ -780,9 +842,13 @@ "TimeUnit", "ParametricUnit", "Unit"] }, "name": { "type": "string" }, "conversion_factor": { "type": "number" }, - "id": { "$ref": "#/definitions/id" } + "id": { "$ref": "#/definitions/id" }, + "ids": { "$ref": "#/definitions/ids" } }, "required" : [ "type", "name" ], + "allOf": [ + { "$ref": "#/definitions/id_ids_mutually_exclusive" } + ], "additionalProperties": false } ] @@ -836,7 +902,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name"], "description": "One and only one of datum and datum_ensemble must be provided", @@ -859,7 +925,7 @@ "bbox": {}, "usages": {}, "remarks": {}, - "id": {} + "id": {}, "ids": {} }, "required" : [ "name" ], "additionalProperties": false diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index cd54f4ea..9f4f6061 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -4389,6 +4389,7 @@ class JSONParser { static Length getLength(const json &j, const char *key); static Measure getMeasure(const json &j); + IdentifierNNPtr buildId(const json &j, bool removeInverseOf); ObjectDomainPtr buildObjectDomain(const json &j); PropertyMap buildProperties(const json &j, bool removeInverseOf = false); @@ -4659,6 +4660,34 @@ ObjectDomainPtr JSONParser::buildObjectDomain(const json &j) { // --------------------------------------------------------------------------- +IdentifierNNPtr JSONParser::buildId(const json &j, bool removeInverseOf) { + + PropertyMap propertiesId; + auto codeSpace(getString(j, "authority")); + if (removeInverseOf && starts_with(codeSpace, "INVERSE(") && + codeSpace.back() == ')') { + codeSpace = codeSpace.substr(strlen("INVERSE(")); + codeSpace.resize(codeSpace.size() - 1); + } + propertiesId.set(metadata::Identifier::CODESPACE_KEY, codeSpace); + propertiesId.set(metadata::Identifier::AUTHORITY_KEY, codeSpace); + if (!j.contains("code")) { + throw ParsingException("Missing \"code\" key"); + } + std::string code; + auto codeJ = j["code"]; + if (codeJ.is_string()) { + code = codeJ.get<std::string>(); + } else if (codeJ.is_number_integer()) { + code = internal::toString(codeJ.get<int>()); + } else { + throw ParsingException("Unexpected type for value of \"code\""); + } + return Identifier::create(code, propertiesId); +} + +// --------------------------------------------------------------------------- + PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf) { PropertyMap map; std::string name(getName(j)); @@ -4667,26 +4696,22 @@ PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf) { } map.set(IdentifiedObject::NAME_KEY, name); - if (j.contains("id")) { - auto id = getObject(j, "id"); - auto codeSpace(getString(id, "authority")); - if (removeInverseOf && starts_with(codeSpace, "INVERSE(") && - codeSpace.back() == ')') { - codeSpace = codeSpace.substr(strlen("INVERSE(")); - codeSpace.resize(codeSpace.size() - 1); - } - map.set(metadata::Identifier::CODESPACE_KEY, codeSpace); - if (!id.contains("code")) { - throw ParsingException("Missing \"code\" key"); - } - auto code = id["code"]; - if (code.is_string()) { - map.set(metadata::Identifier::CODE_KEY, code.get<std::string>()); - } else if (code.is_number_integer()) { - map.set(metadata::Identifier::CODE_KEY, code.get<int>()); - } else { - throw ParsingException("Unexpected type for value of \"code\""); + if (j.contains("ids")) { + auto idsJ = getArray(j, "ids"); + auto identifiers = ArrayOfBaseObject::create(); + for (const auto &idJ : idsJ) { + if (!idJ.is_object()) { + throw ParsingException( + "Unexpected type for value of \"ids\" child"); + } + identifiers->add(buildId(idJ, removeInverseOf)); } + map.set(IdentifiedObject::IDENTIFIERS_KEY, identifiers); + } else if (j.contains("id")) { + auto idJ = getObject(j, "id"); + auto identifiers = ArrayOfBaseObject::create(); + identifiers->add(buildId(idJ, removeInverseOf)); + map.set(IdentifiedObject::IDENTIFIERS_KEY, identifiers); } if (j.contains("remarks")) { diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 74ef82f3..e1d424e9 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -11323,3 +11323,28 @@ TEST(json_import, derived_temporal_crs) { ASSERT_TRUE(crs != nullptr); EXPECT_EQ(crs->exportToJSON((JSONFormatter::create().get())), json); } + +// --------------------------------------------------------------------------- + +TEST(json_import, multiple_ids) { + auto json = "{\n" + " \"type\": \"Ellipsoid\",\n" + " \"name\": \"WGS 84\",\n" + " \"semi_major_axis\": 6378137,\n" + " \"inverse_flattening\": 298.257223563,\n" + " \"ids\": [\n" + " {\n" + " \"authority\": \"EPSG\",\n" + " \"code\": 4326\n" + " },\n" + " {\n" + " \"authority\": \"FOO\",\n" + " \"code\": \"BAR\"\n" + " }\n" + " ]\n" + "}"; + auto obj = createFromUserInput(json, nullptr); + auto ellps = nn_dynamic_pointer_cast<Ellipsoid>(obj); + ASSERT_TRUE(ellps != nullptr); + EXPECT_EQ(ellps->exportToJSON((JSONFormatter::create().get())), json); +} |
