Skip to content

Commit

Permalink
Added JSON diffResult
Browse files Browse the repository at this point in the history
  • Loading branch information
mmd-osm committed May 30, 2024
1 parent 39a4eec commit 2d85c4e
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 54 deletions.
3 changes: 3 additions & 0 deletions include/cgimap/json_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class json_formatter : public output_formatter {
private:
std::unique_ptr<json_writer> writer;
bool is_in_elements_array{false};
bool is_in_diffresult_array{false};

void write_tags(const tags_t &tags);
void write_id(const element_info &elem);
Expand All @@ -38,6 +39,7 @@ class json_formatter : public output_formatter {
void end_document() override;
void write_bounds(const bbox &bounds) override;
void start_element_type(element_type type) override;
void start_diffresult() override;
void end_element_type(element_type type) override;
void start_action(action_type type) override;
void end_action(action_type type) override;
Expand All @@ -60,6 +62,7 @@ class json_formatter : public output_formatter {
const osm_nwr_signed_id_t old_id,
const osm_nwr_id_t new_id,
const osm_version_t new_version) override;

void write_diffresult_delete(const element_type elem,
const osm_nwr_signed_id_t old_id) override;

Expand Down
2 changes: 2 additions & 0 deletions include/cgimap/osm_diffresult_responder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class osm_diffresult_responder : public osm_responder {

~osm_diffresult_responder() override;

// lists the standard types that OSM format can respond in
std::vector<mime::type> types_available() const override;

void write(output_formatter& f,
const std::string &generator,
Expand Down
20 changes: 20 additions & 0 deletions include/cgimap/output_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ T element_type_name(element_type elt) noexcept {
return "";
}

template <typename T = const char*>
T action_type_name(action_type action) noexcept {

switch (action) {
case action_type::create:
return "create";
break;
case action_type::modify:
return "modify";
break;
case action_type::del:
return "delete";
break;
}
return "";
}

} // anonymous namespace

struct element_info {
Expand Down Expand Up @@ -214,6 +231,9 @@ struct output_formatter {
// end a type of element. this is called once for nodes, ways or relations
virtual void end_element_type(element_type type) = 0;

// marks the beginning of diffResult response processing
virtual void start_diffresult() = 0;

// TODO: document me.
virtual void start_action(action_type type) = 0;
virtual void end_action(action_type type) = 0;
Expand Down
1 change: 1 addition & 0 deletions include/cgimap/text_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class text_formatter : public output_formatter {
void write_bounds(const bbox &bounds) override;
void start_element_type(element_type type) override;
void end_element_type(element_type type) override;
void start_diffresult() override;
void start_action(action_type type) override;
void end_action(action_type type) override;
void error(const std::exception &e) override;
Expand Down
1 change: 1 addition & 0 deletions include/cgimap/xml_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class xml_formatter : public output_formatter {
void end_document() override;
void write_bounds(const bbox &bounds) override;
void start_element_type(element_type type) override;
void start_diffresult() override;
void end_element_type(element_type type) override;
void start_action(action_type type) override;
void end_action(action_type type) override;
Expand Down
3 changes: 2 additions & 1 deletion src/api06/changeset_upload_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ changeset_upload_responder::changeset_upload_responder(mime::type mt,

OSMChange_Handler handler(*node_updater, *way_updater, *relation_updater, changeset);

if (true) {
// TODO: check HTTP Accept header
if (mt != mime::type::application_json) {
OSMChangeXMLParser(handler).process_message(payload);
}
else {
Expand Down
39 changes: 21 additions & 18 deletions src/json_formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ void json_formatter::end_document() {

writer->end_array(); // end of elements array
is_in_elements_array = false;
is_in_diffresult_array = false;
writer->end_object();
}

Expand All @@ -69,11 +70,19 @@ void json_formatter::start_element_type(element_type type) {
is_in_elements_array = true;
}

void json_formatter::end_element_type(element_type type) {}
void json_formatter::start_diffresult() {
if (is_in_diffresult_array)
return;

void json_formatter::start_action(action_type type) {
writer->object_key("diffResult");
writer->start_array();
is_in_diffresult_array = true;
}

void json_formatter::end_element_type(element_type type) {}

void json_formatter::start_action(action_type type) {}

void json_formatter::end_action(action_type type) {
}

Expand Down Expand Up @@ -229,28 +238,22 @@ void json_formatter::write_diffresult_create_modify(const element_type elem,
const osm_version_t new_version)
{

// writer->start_object();
// writer->object_key("type");
// writer->entry_string(element_type_name(elem));
// writer->object_key("old_id");
// writer->entry_int(old_id);
// writer->object_key("new_id");
// writer->entry_int(new_id);
// writer->object_key("new_version");
// writer->entry_int(new_version);
// writer->end_object();
writer->start_object();
writer->property("type", element_type_name(elem));
writer->property("old_id", old_id);
writer->property("new_id", new_id);
writer->property("new_version", new_version);
writer->end_object();
}


void json_formatter::write_diffresult_delete(const element_type elem,
const osm_nwr_signed_id_t old_id)
{
// writer->start_object();
// writer->object_key("type");
// writer->entry_string(element_type_name(elem));
// writer->object_key("old_id");
// writer->entry_int(old_id);
// writer->end_object();
writer->start_object();
writer->property("type", element_type_name(elem));
writer->property("old_id", old_id);
writer->end_object();
}

void json_formatter::flush() { writer->flush(); }
Expand Down
10 changes: 9 additions & 1 deletion src/osm_diffresult_responder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,20 @@ namespace {

throw std::runtime_error("Unhandled object_type in as_elem_type.");
}

}

osm_diffresult_responder::osm_diffresult_responder(mime::type mt)
: osm_responder(mt) {}

osm_diffresult_responder::~osm_diffresult_responder() = default;

std::vector<mime::type> osm_diffresult_responder::types_available() const {
std::vector<mime::type> types;
types.push_back(mime::type::application_xml);
types.push_back(mime::type::application_json);
return types;
}

void osm_diffresult_responder::write(output_formatter& fmt,
const std::string &generator,
const std::chrono::system_clock::time_point &) {
Expand All @@ -48,6 +54,8 @@ void osm_diffresult_responder::write(output_formatter& fmt,
try {
fmt.start_document(generator, "diffResult");

fmt.start_diffresult();

// Iterate over all elements in the sequence defined in the osmChange
// message
for (const auto &item : m_diffresult) {
Expand Down
5 changes: 5 additions & 0 deletions src/osmchange_responder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ struct sorting_formatter : public output_formatter {
throw std::runtime_error("Unexpected call to end_action.");
}

void start_diffresult() override {
// this shouldn't be called here
throw std::runtime_error("Unexpected call to start_diffresult.");
}

void write(output_formatter &fmt) {
std::sort(m_elements.begin(), m_elements.end());
for (const auto &e : m_elements) {
Expand Down
4 changes: 4 additions & 0 deletions src/text_formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ void text_formatter::end_element_type(element_type) {
// nothing needed here
}

void text_formatter::start_diffresult() {
// nothing needed here
}

void text_formatter::start_action(action_type type) {
// nothing needed here
}
Expand Down
16 changes: 5 additions & 11 deletions src/xml_formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,12 @@ void xml_formatter::end_element_type(element_type) {
// ditto - nothing needed here for XML.
}

void xml_formatter::start_diffresult() {
// not needed in case of xml
}

void xml_formatter::start_action(action_type type) {
switch (type) {
case action_type::create:
writer->start("create");
break;
case action_type::modify:
writer->start("modify");
break;
case action_type::del:
writer->start("delete");
break;
}
writer->start(action_type_name(type));
}

void xml_formatter::end_action(action_type type) {
Expand Down
68 changes: 68 additions & 0 deletions test/test_apidb_backend_changeset_uploads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@
#include <iostream>
#include <optional>
#include <stdexcept>
#include <sstream>
#include <memory>
#include <thread>
#include <fmt/core.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <sys/time.h>

Expand All @@ -46,6 +51,9 @@ using Catch::Matchers::StartsWith;
using Catch::Matchers::EndsWith;
using Catch::Matchers::Equals;

namespace al = boost::algorithm;
namespace pt = boost::property_tree;

class global_settings_enable_upload_rate_limiter_test_class : public global_settings_default {

public:
Expand Down Expand Up @@ -2398,6 +2406,66 @@ TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_end_to_end", "[changeset
REQUIRE(req.response_status() == 200);
}

SECTION("JSON upload")
{
std::string payload = R"(
{
"version": "0.6",
"generator": "demo",
"osmChange": [
{
"type": "node",
"action": "create",
"id": -1,
"lat": 42,
"lon": 13,
"changeset": 1
},
{
"type": "node",
"action": "modify",
"id": -1,
"version": 1,
"lat": 42.7957187,
"lon": 13.5690032,
"changeset": 1,
"tags": {
"man_made": "mast",
"name": "Monte Piselli - San Giacomo"
}
}
]
}
)";

req.set_header("REQUEST_URI", "/api/0.6/changeset/1/upload.json");
req.set_payload(payload);

// execute the request
process_request(req, limiter, generator, route, *sel_factory, upd_factory.get());

CAPTURE(req.body().str());

REQUIRE(req.response_status() == 200);

SECTION("Validate diffResult in JSON format")
{
pt::ptree act_tree;
std::stringstream ss(req.body().str());
pt::read_json(ss, act_tree);

auto diffResult = act_tree.get_child("diffResult");
int version = 1;
for (auto & entry : diffResult) {
REQUIRE(entry.second.get<std::string>("type") == "node");
REQUIRE(entry.second.get<int64_t>("old_id") == -1);
REQUIRE(entry.second.get<int64_t>("new_id") > 0);
REQUIRE(entry.second.get<int64_t>("new_version") == version);
version++;
}
}
}

}

TEST_CASE_METHOD( DatabaseTestsFixture, "test_osmchange_rate_limiter", "[changeset][upload][db]" ) {
Expand Down
3 changes: 3 additions & 0 deletions test/test_formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ void test_formatter::start_document(
void test_formatter::end_document() {
}

void test_formatter::start_diffresult() {
}

void test_formatter::write_bounds(const bbox &bounds) {
}

Expand Down
1 change: 1 addition & 0 deletions test/test_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct test_formatter : public output_formatter {
mime::type mime_type() const override;
void start_document(const std::string &generator, const std::string &root_name) override;
void end_document() override;
void start_diffresult() override;
void write_bounds(const bbox &bounds) override;
void start_element_type(element_type type) override;
void end_element_type(element_type type) override;
Expand Down
Loading

0 comments on commit 2d85c4e

Please sign in to comment.