forked from osm2pgsql-dev/osm2pgsql
-
Notifications
You must be signed in to change notification settings - Fork 1
/
output.cpp
159 lines (122 loc) · 5.55 KB
/
output.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "output.hpp"
#include "output-pgsql.hpp"
#include "output-gazetteer.hpp"
#include "output-null.hpp"
#include "output-multi.hpp"
#include "taginfo_impl.hpp"
#include <string.h>
#include <stdexcept>
#include <boost/format.hpp>
#include <boost/functional/hash.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
namespace pt = boost::property_tree;
namespace {
template <typename T>
void override_if(T &t, const std::string &key, const pt::ptree &conf) {
boost::optional<T> opt = conf.get_optional<T>(key);
if (opt) {
t = *opt;
}
}
std::shared_ptr<output_t> parse_multi_single(const pt::ptree &conf,
const middle_query_t *mid,
const options_t &options) {
options_t new_opts = options;
std::string name = conf.get<std::string>("name");
std::string proc_type = conf.get<std::string>("type");
new_opts.tag_transform_script = conf.get_optional<std::string>("tagtransform");
new_opts.tag_transform_node_func = conf.get_optional<std::string>("tagtransform-node-function");
new_opts.tag_transform_way_func = conf.get_optional<std::string>("tagtransform-way-function");
new_opts.tag_transform_rel_func = conf.get_optional<std::string>("tagtransform-relation-function");
new_opts.tag_transform_rel_mem_func = conf.get_optional<std::string>("tagtransform-relation-member-function");
new_opts.tblsmain_index = conf.get_optional<std::string>("tablespace-index");
new_opts.tblsmain_data = conf.get_optional<std::string>("tablespace-data");
override_if<int>(new_opts.hstore_mode, "enable-hstore", conf);
override_if<bool>(new_opts.enable_hstore_index, "enable-hstore-index", conf);
override_if<bool>(new_opts.enable_multi, "enable-multi", conf);
override_if<bool>(new_opts.hstore_match_only, "hstore-match-only", conf);
hstores_t hstore_columns;
boost::optional<const pt::ptree &> hstores = conf.get_child_optional("hstores");
if (hstores) {
for (const pt::ptree::value_type &val: *hstores) {
hstore_columns.push_back(val.second.get_value<std::string>());
}
}
new_opts.hstore_columns = hstore_columns;
std::shared_ptr<geometry_processor> processor =
geometry_processor::create(proc_type, &new_opts);
// TODO: we're faking this up, but there has to be a better way?
OsmType osm_type = ((processor->interests() & geometry_processor::interest_node) > 0)
? OSMTYPE_NODE : OSMTYPE_WAY;
export_list columns;
const pt::ptree &tags = conf.get_child("tags");
for (const pt::ptree::value_type &val: tags) {
const pt::ptree &tag = val.second;
taginfo info;
info.name = tag.get<std::string>("name");
info.type = tag.get<std::string>("type");
std::string flags = tag.get_optional<std::string>("flags").get_value_or(std::string());
// TODO: we fake the line number here - any way to get the right one
// from the JSON parser?
info.flags = parse_tag_flags(flags.c_str(), -1);
// TODO: shouldn't need to specify a type here?
columns.add(osm_type, info);
}
return std::make_shared<output_multi_t>(name, processor, columns, mid, new_opts);
}
std::vector<std::shared_ptr<output_t> > parse_multi_config(const middle_query_t *mid, const options_t &options) {
std::vector<std::shared_ptr<output_t> > outputs;
if (!options.style.empty()) {
const std::string file_name(options.style);
try {
pt::ptree conf;
pt::read_json(file_name, conf);
for (const pt::ptree::value_type &val: conf) {
outputs.push_back(parse_multi_single(val.second, mid, options));
}
} catch (const std::exception &e) {
throw std::runtime_error((boost::format("Unable to parse multi config file `%1%': %2%")
% file_name % e.what()).str());
}
} else {
throw std::runtime_error("Style file is required for `multi' backend, but was not specified.");
}
return outputs;
}
} // anonymous namespace
std::vector<std::shared_ptr<output_t> > output_t::create_outputs(const middle_query_t *mid, const options_t &options) {
std::vector<std::shared_ptr<output_t> > outputs;
if (options.output_backend == "pgsql") {
outputs.push_back(std::make_shared<output_pgsql_t>(mid, options));
} else if (options.output_backend == "gazetteer") {
outputs.push_back(std::make_shared<output_gazetteer_t>(mid, options));
} else if (options.output_backend == "null") {
outputs.push_back(std::make_shared<output_null_t>(mid, options));
} else if (options.output_backend == "multi") {
outputs = parse_multi_config(mid, options);
} else {
throw std::runtime_error((boost::format("Output backend `%1%' not recognised. Should be one of [pgsql, gazetteer, null, multi].\n") % options.output_backend).str());
}
return outputs;
}
output_t::output_t(const middle_query_t *mid_, const options_t &options_): m_mid(mid_), m_options(options_) {
}
output_t::~output_t() {
}
size_t output_t::pending_count() const{
return 0;
}
const options_t *output_t::get_options()const {
return &m_options;
}
void output_t::merge_pending_relations(std::shared_ptr<output_t> other) {
}
void output_t::merge_expire_trees(std::shared_ptr<output_t> other) {
}
std::shared_ptr<id_tracker> output_t::get_pending_relations() {
return std::shared_ptr<id_tracker>();
}
std::shared_ptr<expire_tiles> output_t::get_expire_tree() {
return std::shared_ptr<expire_tiles>();
}