From b03ce6e607f0e789026914bfe839b66fbebf1ecd Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 2 Dec 2011 17:48:09 -0800 Subject: [PATCH] add support for arbitrary, custom parameters to be attached to the map during load and serialized when saved - refs #977 --- include/mapnik/map.hpp | 27 ++++++++++++++++-- src/load_map.cpp | 26 +++++++++++++++++ src/map.cpp | 28 ++++++++++++++++-- src/save_map.cpp | 20 +++++++++++++ tests/python_tests/extra_map_props.py | 41 +++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 tests/python_tests/extra_map_props.py diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 152ca0181..bbc5d9432 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -84,6 +84,7 @@ private: boost::optional > maximum_extent_; std::string base_path_; parameters extra_attr_; + parameters extra_params_; public: @@ -444,14 +445,34 @@ public: std::string get_metawriter_property(std::string name) const; /*! - * @brief Get extra properties that can be carried on the Map + * @brief Get extra valid attributes of the Map that are not true members */ parameters const& get_extra_attributes() const; /*! - * @brief Set extra properties that can be carried on the Map + * @brief Get non-const extra valid attributes of the Map that are not true members */ - void set_extra_attributes(parameters& params); + parameters& get_extra_attributes(); + + /*! + * @brief Set extra attributes of the Map + */ + void set_extra_attributes(parameters& attr); + + /*! + * @brief Get extra, arbitrary Parameters attached to the Map + */ + parameters const& get_extra_parameters() const; + + /*! + * @brief Get non-const extra, arbitrary Parameters attached to the Map + */ + parameters& get_extra_parameters(); + + /*! + * @brief Set extra, arbitary Parameters of the Map + */ + void set_extra_parameters(parameters& params); private: void fixAspectRatio(); diff --git a/src/load_map.cpp b/src/load_map.cpp index 623c9948d..c20125502 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -390,6 +390,32 @@ void map_parser::parse_map_include( Map & map, ptree const & include ) } datasource_templates_[name] = params; } + else if (v.first == "Parameters") + { + std::string name = get_attr(v.second, "name", std::string("Unnamed")); + parameters & params = map.get_extra_parameters(); + ptree::const_iterator paramIter = v.second.begin(); + ptree::const_iterator endParam = v.second.end(); + for (; paramIter != endParam; ++paramIter) + { + ptree const& param = paramIter->second; + + if (paramIter->first == "Parameter") + { + std::string name = get_attr(param, "name"); + std::string value = get_value( param, + "parameter"); + params[name] = value; + } + else if( paramIter->first != "" && + paramIter->first != "" ) + { + throw config_error(std::string("Unknown child node in ") + + "'Parameters'. Expected 'Parameter' but got '" + + paramIter->first + "'"); + } + } + } else if (v.first != "" && v.first != "") { diff --git a/src/map.cpp b/src/map.cpp index 2f6e7af43..ec974fb49 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -92,7 +92,8 @@ Map::Map(const Map& rhs) current_extent_(rhs.current_extent_), maximum_extent_(rhs.maximum_extent_), base_path_(rhs.base_path_), - extra_attr_(rhs.extra_attr_) {} + extra_attr_(rhs.extra_attr_), + extra_params_(rhs.extra_params_) {} Map& Map::operator=(const Map& rhs) { @@ -110,6 +111,7 @@ Map& Map::operator=(const Map& rhs) maximum_extent_=rhs.maximum_extent_; base_path_=rhs.base_path_; extra_attr_=rhs.extra_attr_; + extra_params_=rhs.extra_params_; return *this; } @@ -677,9 +679,29 @@ parameters const& Map::get_extra_attributes() const return extra_attr_; } -void Map::set_extra_attributes(parameters& params) +parameters& Map::get_extra_attributes() { - extra_attr_ = params; + return extra_attr_; +} + +void Map::set_extra_attributes(parameters& attr) +{ + extra_attr_ = attr; +} + +parameters const& Map::get_extra_parameters() const +{ + return extra_params_; +} + +parameters& Map::get_extra_parameters() +{ + return extra_params_; +} + +void Map::set_extra_parameters(parameters& params) +{ + extra_params_ = params; } } diff --git a/src/save_map.cpp b/src/save_map.cpp index 2a9e8368e..48d2f9099 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -761,6 +761,24 @@ void serialize_datasource( ptree & layer_node, datasource_ptr datasource) } } +void serialize_parameters( ptree & map_node, mapnik::parameters const& params) +{ + ptree & params_node = map_node.push_back( + ptree::value_type("Parameters", ptree()))->second; + + parameters::const_iterator it = params.begin(); + parameters::const_iterator end = params.end(); + for (; it != end; ++it) + { + boost::property_tree::ptree & param_node = params_node.push_back( + boost::property_tree::ptree::value_type("Parameter", + boost::property_tree::ptree()))->second; + param_node.put(".name", it->first ); + param_node.put_value( it->second ); + + } +} + void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defaults ) { ptree & layer_node = map_node.push_back( @@ -900,6 +918,8 @@ void serialize_map(ptree & pt, Map const & map, bool explicit_defaults) { set_attr( map_node, p_it->first, p_it->second ); } + + serialize_parameters( map_node, map.get_extra_parameters()); Map::const_style_iterator it = map.styles().begin(); Map::const_style_iterator end = map.styles().end(); diff --git a/tests/python_tests/extra_map_props.py b/tests/python_tests/extra_map_props.py new file mode 100644 index 000000000..7b41311b0 --- /dev/null +++ b/tests/python_tests/extra_map_props.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from nose.tools import * +from utilities import execution_path +from Queue import Queue +import threading + +import os, mapnik +import sqlite3 + +def setup(): + # All of the paths used are relative, if we run the tests + # from another directory we need to chdir() + os.chdir(execution_path('.')) + +def test_non_member_known_attributes(): + m = mapnik.Map(256,256) + mapnik.load_map(m,'../data/good_maps/extra_known_map_attributes.xml') + attr = m.extra_attributes + eq_(len(attr),2) + eq_(attr['font-directory'],'.') + eq_(attr['minimum-version'],'0.0.0') + +def test_arbitrary_parameters_attached_to_map(): + m = mapnik.Map(256,256) + mapnik.load_map(m,'../data/good_maps/extra_arbitary_map_parameters.xml') + attr = m.extra_attributes + eq_(len(attr),0) + + params = m.extra_parameters + eq_(len(params),3) + eq_(params['key'],'value2') + eq_(params['key3'],'value3') + eq_(params['unicode'],u'iván') + + +if __name__ == "__main__": + setup() + [eval(run)() for run in dir() if 'test_' in run] +