From 00e2cf8be1eaf2010a5dc26063a6b41b416f54b9 Mon Sep 17 00:00:00 2001 From: Vaclav Blazek Date: Thu, 11 Apr 2019 16:05:08 +0200 Subject: [PATCH] surface: introspection can reference local layer or remote layer --- externals/vts-libs | 2 +- mapproxy/src/mapproxy/CMakeLists.txt | 3 +- .../mapproxy/definition/geodatavectorbase.cpp | 10 +- mapproxy/src/mapproxy/definition/surface.cpp | 14 +- mapproxy/src/mapproxy/definition/surface.hpp | 14 +- .../definition/tms-raster-patchwork.cpp | 1 - .../mapproxy/definition/tms-raster-solid.cpp | 1 - .../generator/geodata-vector-tiled.cpp | 1 - .../mapproxy/generator/geodatavectorbase.cpp | 1 - mapproxy/src/mapproxy/generator/surface.cpp | 112 +++++++-------- mapproxy/src/mapproxy/resource.hpp | 3 + .../src/mapproxy/support/introspection.cpp | 108 +++++++++++++++ .../src/mapproxy/support/introspection.hpp | 120 +++++++++++++++++ .../src/mapproxy/support/serialization.cpp | 127 ++++++++++++------ .../src/mapproxy/support/serialization.hpp | 60 --------- 15 files changed, 392 insertions(+), 185 deletions(-) create mode 100644 mapproxy/src/mapproxy/support/introspection.cpp create mode 100644 mapproxy/src/mapproxy/support/introspection.hpp delete mode 100644 mapproxy/src/mapproxy/support/serialization.hpp diff --git a/externals/vts-libs b/externals/vts-libs index 79a9050..9df32f9 160000 --- a/externals/vts-libs +++ b/externals/vts-libs @@ -1 +1 @@ -Subproject commit 79a905002b24ed5e8ed55fe7d5f1c558f4cfb168 +Subproject commit 9df32f990fa18d49bbd503861c4ed9c08ba02345 diff --git a/mapproxy/src/mapproxy/CMakeLists.txt b/mapproxy/src/mapproxy/CMakeLists.txt index 68038f3..8a86bad 100644 --- a/mapproxy/src/mapproxy/CMakeLists.txt +++ b/mapproxy/src/mapproxy/CMakeLists.txt @@ -9,7 +9,8 @@ set(mapproxy-core_SOURCES support/coverage.hpp support/coverage.cpp support/tileindex.hpp support/tileindex.cpp support/fileclass.hpp support/fileclass.cpp - support/serialization.hpp support/serialization.cpp + support/introspection.hpp support/introspection.cpp + support/serialization.cpp support/aborter.hpp support/glob.hpp support/glob.cpp support/tilejson.hpp support/tilejson.cpp diff --git a/mapproxy/src/mapproxy/definition/geodatavectorbase.cpp b/mapproxy/src/mapproxy/definition/geodatavectorbase.cpp index 945f612..6fd74a6 100644 --- a/mapproxy/src/mapproxy/definition/geodatavectorbase.cpp +++ b/mapproxy/src/mapproxy/definition/geodatavectorbase.cpp @@ -34,7 +34,7 @@ #include "vts-libs/registry/py.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" +#include "../support/introspection.hpp" #include "geodata.hpp" #include "options.hpp" @@ -141,7 +141,7 @@ void parseDefinition(GeodataVectorBase &def const auto &jintrospection(value["introspection"]); def.introspection.surface - = introspectionIdFrom(jintrospection, "surface"); + = introspection::idFrom(jintrospection, "surface"); if (jintrospection.isMember("browserOptions")) { def.introspection.browserOptions @@ -220,8 +220,8 @@ void buildDefinition(Json::Value &value if (!def.introspection.empty()) { auto &jintrospection(value["introspection"] = Json::objectValue); - introspectionIdTo(jintrospection, "surface" - , def.introspection.surface); + introspection::idTo(jintrospection, "surface" + , def.introspection.surface); if (!def.introspection.browserOptions.empty()) { jintrospection["browserOptions"] @@ -331,7 +331,7 @@ void parseDefinition(GeodataVectorBase &def if (value.has_key("introspection")) { boost::python::dict pintrospection(value["introspection"]); def.introspection.surface - = introspectionIdFrom(pintrospection, "surface"); + = introspection::idFrom(pintrospection, "surface"); } } diff --git a/mapproxy/src/mapproxy/definition/surface.cpp b/mapproxy/src/mapproxy/definition/surface.cpp index 2990d4a..8d4879c 100644 --- a/mapproxy/src/mapproxy/definition/surface.cpp +++ b/mapproxy/src/mapproxy/definition/surface.cpp @@ -34,7 +34,6 @@ #include "vts-libs/registry/py.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" #include "surface.hpp" @@ -88,9 +87,9 @@ void Surface::parse(const Json::Value &value) const auto &jintrospection(value["introspection"]); introspection.tms - = introspectionListFrom(jintrospection, "tms"); + = introspection::layersFrom(jintrospection, "tms"); introspection.geodata - = introspectionListFrom(jintrospection, "geodata"); + = introspection::layersFrom(jintrospection, "geodata"); if (jintrospection.isMember("position")) { introspection.position @@ -122,8 +121,9 @@ void Surface::build(Json::Value &value) const if (!introspection.empty()) { auto &jintrospection(value["introspection"] = Json::objectValue); - introspectionListTo(jintrospection, "tms", introspection.tms) ; - introspectionListTo(jintrospection, "geodata", introspection.geodata); + introspection::layersTo(jintrospection, "tms", introspection.tms) ; + introspection::layersTo + (jintrospection, "geodata", introspection.geodata); if (introspection.position) { jintrospection["position"] = vr::asJson(*introspection.position); @@ -154,9 +154,9 @@ void Surface::parse(const boost::python::dict &value) if (value.has_key("introspection")) { boost::python::dict pintrospection(value["introspection"]); introspection.tms - = introspectionListFrom(pintrospection, "tms"); + = introspection::layersFrom(pintrospection, "tms"); introspection.geodata - = introspectionListFrom(pintrospection, "geodata"); + = introspection::layersFrom(pintrospection, "geodata"); if (pintrospection.has_key("position")) { introspection.position = boost::in_place(); diff --git a/mapproxy/src/mapproxy/definition/surface.hpp b/mapproxy/src/mapproxy/definition/surface.hpp index 7f9bddd..61dd6c3 100644 --- a/mapproxy/src/mapproxy/definition/surface.hpp +++ b/mapproxy/src/mapproxy/definition/surface.hpp @@ -37,6 +37,8 @@ #include "../heightfunction.hpp" +#include "../support/introspection.hpp" + // fwd namespace Json { class Value; } namespace boost { namespace python { class dict; } } @@ -48,8 +50,8 @@ namespace resource { class Surface : public DefinitionBase { public: struct Introspection { - Resource::Id::list tms; - Resource::Id::list geodata; + introspection::Layers tms; + introspection::Layers geodata; boost::optional position; boost::any browserOptions; @@ -66,6 +68,8 @@ class Surface : public DefinitionBase { void build(Json::Value &value) const; void parse(const boost::python::dict &value); + virtual boost::optional getGeoidGrid() const = 0; + static constexpr Resource::Generator::Type type = Resource::Generator::Type::surface; @@ -85,6 +89,9 @@ struct SurfaceSpheroid : public Surface { virtual void from_impl(const boost::any &value); virtual void to_impl(boost::any &value) const; virtual Changed changed_impl(const DefinitionBase &other) const; + virtual boost::optional getGeoidGrid() const { + return geoidGrid; + } }; struct SurfaceDem : public Surface { @@ -101,6 +108,9 @@ struct SurfaceDem : public Surface { virtual void from_impl(const boost::any &value); virtual void to_impl(boost::any &value) const; virtual Changed changed_impl(const DefinitionBase &other) const; + virtual boost::optional getGeoidGrid() const { + return dem.geoidGrid; + } }; } // namespace resource diff --git a/mapproxy/src/mapproxy/definition/tms-raster-patchwork.cpp b/mapproxy/src/mapproxy/definition/tms-raster-patchwork.cpp index 3e69541..71328ad 100644 --- a/mapproxy/src/mapproxy/definition/tms-raster-patchwork.cpp +++ b/mapproxy/src/mapproxy/definition/tms-raster-patchwork.cpp @@ -30,7 +30,6 @@ #include "jsoncpp/as.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" #include "tms.hpp" #include "factory.hpp" diff --git a/mapproxy/src/mapproxy/definition/tms-raster-solid.cpp b/mapproxy/src/mapproxy/definition/tms-raster-solid.cpp index 15fb5cb..5852564 100644 --- a/mapproxy/src/mapproxy/definition/tms-raster-solid.cpp +++ b/mapproxy/src/mapproxy/definition/tms-raster-solid.cpp @@ -30,7 +30,6 @@ #include "jsoncpp/as.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" #include "tms.hpp" #include "factory.hpp" diff --git a/mapproxy/src/mapproxy/generator/geodata-vector-tiled.cpp b/mapproxy/src/mapproxy/generator/geodata-vector-tiled.cpp index aa3aac4..4a849d9 100644 --- a/mapproxy/src/mapproxy/generator/geodata-vector-tiled.cpp +++ b/mapproxy/src/mapproxy/generator/geodata-vector-tiled.cpp @@ -39,7 +39,6 @@ #include "jsoncpp/as.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" #include "vts-libs/vts/opencv/navtile.hpp" diff --git a/mapproxy/src/mapproxy/generator/geodatavectorbase.cpp b/mapproxy/src/mapproxy/generator/geodatavectorbase.cpp index 2e1bc0f..7767c61 100644 --- a/mapproxy/src/mapproxy/generator/geodatavectorbase.cpp +++ b/mapproxy/src/mapproxy/generator/geodatavectorbase.cpp @@ -41,7 +41,6 @@ #include "vts-libs/storage/fstreams.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" #include "geodatavectorbase.hpp" #include "files.hpp" diff --git a/mapproxy/src/mapproxy/generator/surface.cpp b/mapproxy/src/mapproxy/generator/surface.cpp index e16c4c1..9c4ca52 100644 --- a/mapproxy/src/mapproxy/generator/surface.cpp +++ b/mapproxy/src/mapproxy/generator/surface.cpp @@ -63,12 +63,12 @@ #include "../support/srs.hpp" #include "../support/grid.hpp" #include "../support/python.hpp" -#include "../support/serialization.hpp" #include "../support/mmapped/qtree-rasterize.hpp" #include "../support/tilejson.hpp" #include "../support/cesiumconf.hpp" #include "../support/revision.hpp" #include "../support/tms.hpp" +#include "../support/introspection.hpp" #include "surface.hpp" @@ -503,54 +503,32 @@ SurfaceBase::extraProperties(const Definition &def) const { vts::ExtraTileSetProperties extra; - Resource::Id::list introspectionTmsList(def.introspection.tms); - if (introspectionTmsList.empty()) { - // defaults to patchwork - introspectionTmsList.emplace_back(referenceFrameId() - , systemGroup() - , "tms-raster-patchwork"); - } - - for (const auto &tms : introspectionTmsList) { + const auto &findResource([this](Resource::Generator::Type type + , const Resource::Id &id) + -> const Resource* + { if (auto other = otherGenerator - (Resource::Generator::Type::tms - , addReferenceFrame(tms, referenceFrameId()))) + (type, addReferenceFrame(id, referenceFrameId()))) { - // we have found tms resource, use it as a boundlayer - const auto otherId(tms.fullId()); - const auto &otherResource(other->resource()); - const auto resdiff(resolveRoot(resource(), otherResource)); - - const fs::path blPath - (prependRoot(fs::path(), otherResource, resdiff) - / "boundlayer.json"); + return &other->resource(); + } + return nullptr; + }); - extra.boundLayers.add(vr::BoundLayer(otherId, blPath.string())); + const auto &r(resource()); - extra.view.surfaces[id().fullId()] - .push_back(vr::View::BoundLayerParams(otherId)); - }; + if (def.introspection.tms.empty()) { + introspection::add + (extra, Resource::Generator::Type::tms, introspection::LocalLayer + ({}, systemGroup(), "tms-raster-patchwork") + , r, findResource); + } else { + introspection::add(extra, Resource::Generator::Type::tms + , def.introspection.tms, r, findResource); } - for (const auto &geodata : def.introspection.geodata) { - if (auto other = otherGenerator - (Resource::Generator::Type::geodata - , addReferenceFrame(geodata, referenceFrameId()))) - { - // we have found geodata resource, use it as a boundlayer - const auto otherId(geodata.fullId()); - const auto &otherResource(other->resource()); - const auto resdiff(resolveRoot(resource(), otherResource)); - - const fs::path flPath - (prependRoot(fs::path(), otherResource, resdiff) - / "freelayer.json"); - - extra.freeLayers.add(vr::FreeLayer(otherId, flPath.string())); - - extra.view.freeLayers[otherId]; - }; - } + introspection::add(extra, Resource::Generator::Type::geodata + , def.introspection.geodata, r, findResource); if (def.introspection.position) { extra.position = *def.introspection.position; @@ -559,7 +537,6 @@ SurfaceBase::extraProperties(const Definition &def) const // browser options (must be Json::Value!) extra.browserOptions = def.introspection.browserOptions; - return extra; } @@ -648,7 +625,7 @@ void SurfaceBase::generateTerrain(const vts::TileId &tmsTileId qmf::save(qmfMesh(lm.mesh, nodeInfo , (tms.physicalSrs ? *tms.physicalSrs : referenceFrame().model.physicalSrs) - , boost::none) + , definition_.getGeoidGrid()) , utility::Gzipper(os), fi.fileInfo.filename); auto sfi(fi.sinkFileInfo()); @@ -781,31 +758,36 @@ void SurfaceBase::layerJson(Sink &sink, const TerrainFileInfo &fi void SurfaceBase::cesiumConf(Sink &sink, const TerrainFileInfo &fi , const vre::Tms &tms) const { - const auto &def(definition_); - - const auto introId(def.introspection.tms.empty() - ? Resource::Id(referenceFrameId(), systemGroup() - , "tms-raster-patchwork") - : def.introspection.tms.front()); + const auto &findResource([this](Resource::Generator::Type type + , const Resource::Id &id) + -> const Resource* + { + if (auto other = otherGenerator + (type, addReferenceFrame(id, referenceFrameId()))) + { + return &other->resource(); + } + return nullptr; + }); CesiumConf conf; conf.tms = tms; - if (auto other = otherGenerator - (Resource::Generator::Type::tms - , addReferenceFrame(introId, referenceFrameId()))) + if (definition_.introspection.tms.empty()) { + if (const auto intro = introspection::remote + (Resource::Generator::Type::tms + , Resource::Id({}, systemGroup(), "tms-raster-patchwork") + , resource(), findResource)) + { + conf.boundLayer = intro->url; + } + } else if (const auto intro = introspection::remote + (Resource::Generator::Type::tms + , definition_.introspection.tms.front() + , resource(), findResource)) { - // we have found matching tms resource, use it as an imagery provider - const auto otherId(introId.fullId()); - const auto &otherResource(other->resource()); - const auto resdiff(resolveRoot(resource(), otherResource)); - - // boundlayer path - const fs::path blPath - (prependRoot(fs::path(), otherResource, resdiff) - / "boundlayer.json"); - conf.boundLayer = blPath.string(); - }; + conf.boundLayer = intro->url; + } const auto tb(terrainBounds(resource(), tms)); conf.defaultView = tb.bounds; diff --git a/mapproxy/src/mapproxy/resource.hpp b/mapproxy/src/mapproxy/resource.hpp index e9753cb..d478eba 100644 --- a/mapproxy/src/mapproxy/resource.hpp +++ b/mapproxy/src/mapproxy/resource.hpp @@ -163,6 +163,9 @@ struct Resource { typedef std::vector list; }; + typedef boost::optional OptId; + typedef std::vector OptIds; + struct Generator { enum class Type { tms, surface, geodata }; Type type; diff --git a/mapproxy/src/mapproxy/support/introspection.cpp b/mapproxy/src/mapproxy/support/introspection.cpp new file mode 100644 index 0000000..b9d99f8 --- /dev/null +++ b/mapproxy/src/mapproxy/support/introspection.cpp @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2017 Melown Technologies SE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dbglog/dbglog.hpp" + +#include "vts-libs/vts/tileset/properties.hpp" +#include "vts-libs/vts/urltemplate.hpp" + +#include "../error.hpp" +#include "introspection.hpp" + +namespace fs = boost::filesystem; +namespace vr = vtslibs::registry; + +namespace introspection { + +boost::optional +remote(Resource::Generator::Type type, const Layer &layer + , const Resource &resource, const FindResource &findResource) +{ + class Visitor + : public boost::static_visitor> + { + public: + Visitor(Resource::Generator::Type type, const Resource &resource + , const FindResource &findResource) + : type_(type), resource_(resource), findResource_(findResource) + {} + + boost::optional operator()(const LocalLayer &l) const { + const auto *other(findResource_(type_, l)); + if (!other) { return boost::none; } + + const auto otherId(other->id.fullId()); + const auto resdiff(resolveRoot(resource_, *other)); + + const fs::path path + (prependRoot(fs::path(), *other, resdiff) + / ((type_ == Resource::Generator::Type::geodata) + ? "freelayer.json" : "boundlayer.json")); + + return RemoteLayer(resource_.id.fullId(), path.string()); + } + + boost::optional operator()(RemoteLayer l) const { + // expand reference frame in URL + vts::UrlTemplate::Vars vars; + vars.rf = resource_.id.referenceFrame; + l.url = vts::UrlTemplate(l.url)(vars); + return l; + } + + private: + Resource::Generator::Type type_; + const Resource &resource_; + const FindResource &findResource_; + } visitor(type, resource, findResource); + + return boost::apply_visitor(visitor, layer); +} + +void add(vts::ExtraTileSetProperties &extra, Resource::Generator::Type type + , const Layer &layer, const Resource &resource + , const FindResource &findResource) +{ + if (const auto &r = remote(type, layer, resource, findResource)) { + switch (type) { + case Resource::Generator::Type::tms: { + vr::BoundLayer bl(r->id, r->url); + extra.boundLayers.add(bl); + extra.view.surfaces[resource.id.fullId()].emplace_back(bl.id); + } break; + + case Resource::Generator::Type::geodata: { + vr::FreeLayer fl(r->id, r->url); + extra.freeLayers.add(fl); + extra.view.freeLayers[fl.id]; + } break; + + default: break; // ignore + } + } +} + +} // namespace introspection diff --git a/mapproxy/src/mapproxy/support/introspection.hpp b/mapproxy/src/mapproxy/support/introspection.hpp new file mode 100644 index 0000000..bba2b00 --- /dev/null +++ b/mapproxy/src/mapproxy/support/introspection.hpp @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2017 Melown Technologies SE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef mapproxy_support_introspection_hpp_included_ +#define mapproxy_support_introspection_hpp_included_ + +#include +#include + +#include + +#include "../resource.hpp" + +// fwd +namespace Json { class Value; } +namespace boost { namespace python { class dict; } } +namespace vtslibs { namespace vts { struct ExtraTileSetProperties; } } + +namespace introspection { + +typedef Resource::Id LocalLayer; + +struct RemoteLayer { + std::string id; + std::string url; + + RemoteLayer(const std::string &id = std::string() + , const std::string &url = std::string()) + : id(id), url(url) {} + + bool operator<(const RemoteLayer &o) const; + bool operator==(const RemoteLayer &o) const; +}; + +typedef boost::variant Layer; +typedef std::vector Layers; + +typedef std::function FindResource; + +void add(vts::ExtraTileSetProperties &extra, Resource::Generator::Type type + , const Layer &layer, const Resource &resource + , const FindResource &findResource); + +void add(vts::ExtraTileSetProperties &extra, Resource::Generator::Type type + , const Layers &layers, const Resource &resource + , const FindResource &findResource); + +boost::optional +remote(Resource::Generator::Type type, const Layer &layer + , const Resource &resource, const FindResource &findResource); + +/** ------------------------------------------------------------------------ + * Parsing + */ +Layers layersFrom(const Json::Value &introspection, const std::string &key); + +void layersTo(Json::Value &introspection, const std::string &key + , const Layers &layers); + +Layers layersFrom(const boost::python::dict &introspection + , const std::string &key); + +Resource::OptId idFrom(const Json::Value &introspection + , const std::string &key); + +void idTo(Json::Value &introspection, const std::string &key + , const Resource::OptId &resource); + +Resource::OptId idFrom(const boost::python::dict &introspection + , const std::string &key); + +// inlines + +inline bool RemoteLayer::operator<(const RemoteLayer &o) const { + if (id < o.id) { return true; } + else if (o.id < id) { return false; } + + return url < o.url; +} + +inline bool RemoteLayer::operator==(const RemoteLayer &o) const { + return ((id == o.id) && (url == o.url)); +} + +inline void add(vts::ExtraTileSetProperties &extra + , Resource::Generator::Type type, const Layers &layers + , const Resource &resource, const FindResource &findResource) +{ + for (const auto &layer : layers) { + add(extra, type, layer, resource, findResource); + } +} + +} // namespace introspection + +#endif // mapproxy_support_serialization_hpp_included_ diff --git a/mapproxy/src/mapproxy/support/serialization.cpp b/mapproxy/src/mapproxy/support/serialization.cpp index cab638c..16ddbc8 100644 --- a/mapproxy/src/mapproxy/support/serialization.cpp +++ b/mapproxy/src/mapproxy/support/serialization.cpp @@ -24,75 +24,122 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "jsoncpp/as.hpp" + #include "python.hpp" -#include "serialization.hpp" +#include "introspection.hpp" + +namespace introspection { -Resource::Id::list introspectionListFrom(const Json::Value &introspection - , const std::string &key) +Layers layersFrom(const Json::Value &introspection, const std::string &key) { if (!introspection.isMember(key)) { return {}; } const auto &value(introspection[key]); - auto getRid([](const Json::Value &item) -> Resource::Id + + const auto &local([](const Json::Value &item) -> LocalLayer { - Resource::Id rid; - Json::get(rid.group, item, "group"); - Json::get(rid.id, item, "id"); - return rid; + LocalLayer l; + Json::get(l.group, item, "group"); + Json::get(l.id, item, "id"); + return l; + }); + + const auto &remote([](const Json::Value &item) -> RemoteLayer + { + RemoteLayer l; + Json::get(l.id, item, "id"); + Json::get(l.url, item, "url"); + return l; }); - Resource::Id::list out; + Layers out; + + const auto &add([&](const Json::Value &item) + { + if (item.isMember("url")) { + out.push_back(remote(item)); + } else { + out.push_back(local(item)); + } + }); if (value.isArray()) { for (const auto &item : value) { - out.push_back(getRid(item)); + add(item); } } else { - out.push_back(getRid(value)); + add(value); } return out; } -void introspectionListTo(Json::Value &introspection - , const std::string &key - , const Resource::Id::list &resources) +void layersTo(Json::Value &introspection, const std::string &key + , const Layers &layers) { - if (resources.empty()) { return; } + if (layers.empty()) { return; } - auto &list(introspection[key] = Json::arrayValue); - for (const auto &rid : resources) { - auto &item(list.append(Json::objectValue)); - item["group"] = rid.group; - item["id"] = rid.id; - } + struct Visitor : boost::static_visitor { + Json::Value &list; + Visitor(Json::Value &list) : list(list) {} + + void operator()(const LocalLayer &l) { + auto &item(list.append(Json::objectValue)); + item["group"] = l.group; + item["id"] = l.id; + } + + void operator()(const RemoteLayer &l) { + auto &item(list.append(Json::objectValue)); + item["id"] = l.id; + item["url"] = l.url; + } + } visitor(introspection[key] = Json::arrayValue); + + for (const auto &l : layers) { boost::apply_visitor(visitor, l); } } -Resource::Id::list -introspectionListFrom(const boost::python::dict &introspection - , const std::string &key) +Layers layersFrom(const boost::python::dict &introspection + , const std::string &key) { if (!introspection.has_key(key)) { return {}; } - auto getRid([](const boost::python::dict &item) -> Resource::Id + const auto &local([](const boost::python::dict &item) -> LocalLayer { - Resource::Id rid; - rid.group = py2utf8(item["group"]); - rid.id = py2utf8(item["id"]); - return rid; + LocalLayer l; + l.group = py2utf8(item["group"]); + l.id = py2utf8(item["id"]); + return l; }); - Resource::Id::list out; + const auto &remote([](const boost::python::dict &item) -> RemoteLayer + { + RemoteLayer l; + l.id = py2utf8(item["id"]); + l.url = py2utf8(item["url"]); + return l; + }); + + Layers out; + + const auto &add([&](const boost::python::dict &item) + { + if (item.has_key("url")) { + out.push_back(remote(item)); + } else { + out.push_back(local(item)); + } + }); // TODO: support list boost::python::dict value(introspection[key]); - out.push_back(getRid(value)); - + add(value); return out; } -boost::optional -introspectionIdFrom(const Json::Value &introspection, const std::string &key) +Resource::OptId idFrom(const Json::Value &introspection + , const std::string &key) { if (!introspection.isMember(key)) { return {}; } @@ -108,9 +155,8 @@ introspectionIdFrom(const Json::Value &introspection, const std::string &key) return getRid(value); } -void introspectionIdTo(Json::Value &introspection - , const std::string &key - , const boost::optional &resource) +void idTo(Json::Value &introspection, const std::string &key + , const Resource::OptId &resource) { if (!resource) { return; } @@ -119,9 +165,8 @@ void introspectionIdTo(Json::Value &introspection item["id"] = resource->id; } -boost::optional -introspectionIdFrom(const boost::python::dict &introspection - , const std::string &key) +Resource::OptId idFrom(const boost::python::dict &introspection + , const std::string &key) { if (!introspection.has_key(key)) { return {}; } @@ -136,3 +181,5 @@ introspectionIdFrom(const boost::python::dict &introspection boost::python::dict value(introspection[key]); return getRid(value); } + +} // namespace introspection diff --git a/mapproxy/src/mapproxy/support/serialization.hpp b/mapproxy/src/mapproxy/support/serialization.hpp deleted file mode 100644 index ecb8c37..0000000 --- a/mapproxy/src/mapproxy/support/serialization.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2017 Melown Technologies SE - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef mapproxy_support_serialization_hpp_included_ -#define mapproxy_support_serialization_hpp_included_ - -#include -#include - -#include "jsoncpp/json.hpp" -#include "jsoncpp/as.hpp" - -#include "../resource.hpp" - -Resource::Id::list introspectionListFrom(const Json::Value &introspection - , const std::string &key); - -void introspectionListTo(Json::Value &introspection - , const std::string &key - , const Resource::Id::list &resources); - -Resource::Id::list -introspectionListFrom(const boost::python::dict &introspection - , const std::string &key); - -boost::optional -introspectionIdFrom(const Json::Value &introspection, const std::string &key); - -void introspectionIdTo(Json::Value &introspection - , const std::string &key - , const boost::optional &resource); - -boost::optional -introspectionIdFrom(const boost::python::dict &introspection - , const std::string &key); - -#endif // mapproxy_support_serialization_hpp_included_