diff --git a/include/mapnik/feature_style_processor.hpp b/include/mapnik/feature_style_processor.hpp index 6fb1c1533..89caaec25 100644 --- a/include/mapnik/feature_style_processor.hpp +++ b/include/mapnik/feature_style_processor.hpp @@ -93,7 +93,7 @@ public: for (;metaItr!=metaItrEnd; ++metaItr) { - metaItr->second->start(); + metaItr->second->start(m_.metawriter_output_properties); } try diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index a19a6acf2..58052e5cc 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -420,7 +420,7 @@ public: /*! * @brief Get a metawriter property. */ - std::string get_metawriter_property(std::string name); /*TODO: const */ + std::string get_metawriter_property(std::string name) const; private: void fixAspectRatio(); diff --git a/include/mapnik/metawriter.hpp b/include/mapnik/metawriter.hpp index a61e0ad90..6dc2c18ee 100644 --- a/include/mapnik/metawriter.hpp +++ b/include/mapnik/metawriter.hpp @@ -40,6 +40,18 @@ namespace mapnik { +class metawriter_property_map +{ +public: + metawriter_property_map() {} + UnicodeString const& operator[](std::string const& key) const; + UnicodeString& operator[](std::string const& key) {return m_[key];} +private: + std::map m_; + UnicodeString not_found_; +}; + + /** All properties to be output by a metawriter. */ class metawriter_properties : public std::set { @@ -67,7 +79,7 @@ class metawriter proj_transform const& prj_trans, CoordTransform const &t, metawriter_properties const& properties = metawriter_properties())=0; - virtual void start() {}; + virtual void start(metawriter_property_map const& properties) {}; virtual void stop() {}; protected: metawriter_properties dflt_properties_; diff --git a/include/mapnik/metawriter_json.hpp b/include/mapnik/metawriter_json.hpp index a8cb87e16..5f250e3ee 100644 --- a/include/mapnik/metawriter_json.hpp +++ b/include/mapnik/metawriter_json.hpp @@ -26,28 +26,46 @@ // Mapnik #include +#include // STL -#include +#include namespace mapnik { -/** JSON writer. */ -class metawriter_json : public metawriter, private boost::noncopyable + + +/** Write JSON data to a stream object. */ +class metawriter_json_stream : public metawriter, private boost::noncopyable { - public: - metawriter_json(metawriter_properties dflt_properties, std::string fn); - metawriter_json(metawriter_properties dflt_properties, std::ostream); - ~metawriter_json(); - virtual void add_box(box2d box, Feature const &feature, - proj_transform const& prj_trans, - CoordTransform const& t, - metawriter_properties const& properties); - virtual void start(); - virtual void stop(); - private: - std::ostream *f; - std::string fn_; - int count; +public: + metawriter_json_stream(metawriter_properties dflt_properties); + virtual void add_box(box2d box, Feature const &feature, + proj_transform const& prj_trans, + CoordTransform const& t, + metawriter_properties const& properties); + + virtual void start(metawriter_property_map const& properties); + virtual void stop(); + void set_stream(std::ostream *f) { f_ = f; } + +private: + std::ostream *f_; + int count; +}; + +/** JSON writer. */ +class metawriter_json : public metawriter_json_stream +{ +public: + metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn); + ~metawriter_json(); + + virtual void start(metawriter_property_map const& properties); + virtual void stop(); + +private: + path_expression_ptr fn_; + std::fstream f_; }; }; diff --git a/src/load_map.cpp b/src/load_map.cpp index 94e0ecafc..349b54882 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -363,7 +363,7 @@ void map_parser::parse_metawriter(Map & map, ptree const & pt) if (type == "json") { string file = get_attr(pt, "file"); optional properties = get_opt_attr(pt, "default-output"); - writer = metawriter_ptr(new metawriter_json(properties, file)); + writer = metawriter_ptr(new metawriter_json(properties, parse_path(file))); } else { throw config_error(string("Unknown type '") + type + "'"); } diff --git a/src/map.cpp b/src/map.cpp index d86ccd9eb..87d734cb4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -614,7 +614,7 @@ void Map::set_metawriter_property(std::string name, std::string value) metawriter_output_properties[name] = UnicodeString::fromUTF8(value); } -std::string Map::get_metawriter_property(std::string name) +std::string Map::get_metawriter_property(std::string name) const { std::string result; to_utf8(metawriter_output_properties[name], result); diff --git a/src/metawriter.cpp b/src/metawriter.cpp index 562489886..40cf3aae3 100644 --- a/src/metawriter.cpp +++ b/src/metawriter.cpp @@ -32,48 +32,34 @@ // STL #include #include -#include namespace mapnik { -metawriter_json::metawriter_json(metawriter_properties dflt_properties, std::string fn) - : metawriter(dflt_properties), fn_(fn), count(0) +UnicodeString const& metawriter_property_map::operator[](std::string const& key) const { - + std::map::const_iterator it; + it = m_.find(key); + if (it != m_.end()) return not_found_; + return (*it).second; } -metawriter_json::~metawriter_json() +void metawriter_json_stream::start(metawriter_property_map const& properties) { - stop(); + assert(f_); + *f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n"; } -void metawriter_json::start() +void metawriter_json_stream::stop() { - if (!fn_.empty()) - { - if (f) - { - std::cerr << "ERROR: GeoJSON metawriter is already active!\n"; - return; - } - f = new std::fstream(fn_.c_str(), std::fstream::out | std::fstream::trunc); - if (f->fail()) perror((std::string("Failed to open file ") + fn_).c_str()); - } - assert(f); - *f << "{ \"type\": \"FeatureCollection\", \"features\": [\n"; -} - -void metawriter_json::stop() -{ - if (f) *f << " ] }\n"; - if (f && !fn_.empty()) - { - dynamic_cast(f)->close(); - f = 0; + if (f_) { + *f_ << " ] }\n"; } } -void metawriter_json::add_box(box2d box, Feature const &feature, +metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_properties) + : metawriter(dflt_properties), count(0) {} + +void metawriter_json_stream::add_box(box2d box, Feature const &feature, proj_transform const& prj_trans, CoordTransform const &t, const metawriter_properties& properties) { @@ -85,7 +71,7 @@ void metawriter_json::add_box(box2d box, Feature const &feature, if (props.empty()) { - std::cerr << "WARNING: No expression available for GeoJSON metawriter.\n"; + std::cerr << "WARNING: No properties available for GeoJSON metawriter.\n"; } /* Coordinate transform in renderer: @@ -112,8 +98,8 @@ void metawriter_json::add_box(box2d box, Feature const &feature, double maxx = box.maxx(); double maxy = box.maxy(); - if (count++) *f << ",\n"; - *f << std::fixed << std::setprecision(8) << "{ \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Polygon\",\n \"coordinates\": [ [ [" << + if (count++) *f_ << ",\n"; + *f_ << std::fixed << std::setprecision(8) << "{ \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Polygon\",\n \"coordinates\": [ [ [" << minx << ", " << miny << "], [" << maxx << ", " << miny << "], [" << maxx << ", " << maxy << "], [" << @@ -130,13 +116,46 @@ void metawriter_json::add_box(box2d box, Feature const &feature, //Property found text = boost::replace_all_copy(boost::replace_all_copy(itr->second.to_string(), "\\", "\\\\"), "\"", "\\\""); } - if (i++) *f << ","; - *f << "\n \"" << p << "\":\"" << text << "\""; + if (i++) *f_ << ","; + *f_ << "\n \"" << p << "\":\"" << text << "\""; } - *f << "\n} }"; + *f_ << "\n} }"; } + +/********************************************************************************************/ + +metawriter_json::metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn) + : metawriter_json_stream(dflt_properties), fn_(fn) {} + + +metawriter_json::~metawriter_json() +{ + stop(); +} + +void metawriter_json::start(metawriter_property_map const& properties) +{ + std::string filename = + path_processor::evaluate(*fn_, properties); +#ifdef MAPNIK_DEBUG + std::clog << "Metawriter JSON: filename=" << filename << "\n"; +#endif + f_.open(filename.c_str(), std::fstream::out | std::fstream::trunc); + if (f_.fail()) perror((std::string("Metawriter JSON: Failed to open file ") + filename).c_str()); + set_stream(&f_); + metawriter_json_stream::start(properties); +} + + +void metawriter_json::stop() +{ + metawriter_json_stream::stop(); + if (f_.is_open()) f_.close(); +} + + metawriter_properties::metawriter_properties(boost::optional str) { if (str) {