Skip to content

Commit

Permalink
Merge pull request #439 from mmd-osm/patch/csjsonformat
Browse files Browse the repository at this point in the history
Rework changeset json output according to Rails implementation
  • Loading branch information
mmd-osm authored Aug 7, 2024
2 parents 1dcc832 + a81375e commit a2889bb
Show file tree
Hide file tree
Showing 19 changed files with 249 additions and 111 deletions.
4 changes: 2 additions & 2 deletions include/cgimap/api06/changeset_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
#define API06_CHANGESET_HANDLER_HPP

#include "cgimap/handler.hpp"
#include "cgimap/osm_current_responder.hpp"
#include "cgimap/osm_changeset_responder.hpp"
#include "cgimap/request.hpp"
#include <string>

namespace api06 {

class changeset_responder : public osm_current_responder {
class changeset_responder : public osm_changeset_responder {
public:
changeset_responder(mime::type, osm_changeset_id_t, bool, data_selection &);
};
Expand Down
9 changes: 6 additions & 3 deletions include/cgimap/json_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
class json_formatter : public output_formatter {
private:
std::unique_ptr<json_writer> writer;
bool is_in_elements_array{false};

void write_tags(const tags_t &tags);
void write_id(const element_info &elem);
Expand All @@ -37,8 +36,12 @@ class json_formatter : public output_formatter {
void start_document(const std::string &generator, const std::string &root_name) override;
void end_document() override;
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_element() override;
void end_element() override;
void start_changeset(bool) override;
void end_changeset(bool) override;

void start_action(action_type type) override;
void end_action(action_type type) override;
void error(const std::exception &e) override;
Expand Down
38 changes: 38 additions & 0 deletions include/cgimap/osm_changeset_responder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* SPDX-License-Identifier: GPL-2.0-only
*
* This file is part of openstreetmap-cgimap (https://github.com/zerebubuth/openstreetmap-cgimap/).
*
* Copyright (C) 2009-2023 by the CGImap developer community.
* For a full list of authors see the git log.
*/

#ifndef OSM_CHANGESET_RESPONDER_HPP
#define OSM_CHANGESET_RESPONDER_HPP

#include "cgimap/osm_responder.hpp"

#include <chrono>


class osm_changeset_responder : public osm_responder {
public:
// construct, passing the mime type down to the responder.
// multi_selection flag can be set if we plan to fetch and print multiple changesets
osm_changeset_responder(mime::type,
data_selection &s,
bool multi_selection);

// writes whatever is in the selection to the formatter
void write(output_formatter& f,
const std::string &generator,
const std::chrono::system_clock::time_point &now) override;

protected:
// current selection of elements to be written out
data_selection& sel;
// do we want to select and print multiple changesets?
bool multi_selection{false};
};

#endif /* OSM_CHANGESET_RESPONDER_HPP */
14 changes: 8 additions & 6 deletions include/cgimap/output_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,15 @@ struct output_formatter {
// to record the box used by a map call.
virtual void write_bounds(const bbox &bounds) = 0;

// start a type of element. this is called once for nodes, ways or
// relations. between the start and end called for a particular element
// type only write_* functions for that type will be called.
virtual void start_element_type(element_type type) = 0;
//
virtual void start_element() = 0;

//
virtual void end_element() = 0;

virtual void start_changeset(bool) = 0;

// end a type of element. this is called once for nodes, ways or relations
virtual void end_element_type(element_type type) = 0;
virtual void end_changeset(bool) = 0;

// TODO: document me.
virtual void start_action(action_type type) = 0;
Expand Down
8 changes: 6 additions & 2 deletions include/cgimap/text_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ class text_formatter : public output_formatter {
void start_document(const std::string &generator, const std::string &root_name) override;
void end_document() override;
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_element() override;
void end_element() override;
void start_changeset(bool) override;
void end_changeset(bool) override;

void start_action(action_type type) override;
void end_action(action_type type) override;
void error(const std::exception &e) override;
Expand Down
8 changes: 6 additions & 2 deletions include/cgimap/xml_formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ class xml_formatter : public output_formatter {
void start_document(const std::string &generator, const std::string &root_name) override;
void end_document() override;
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_element() override;
void end_element() override;
void start_changeset(bool) override;
void end_changeset(bool) 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 src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ target_sources(cgimap_core PRIVATE
oauth2.cpp
options.cpp
osm_responder.cpp
osm_changeset_responder.cpp
osm_current_responder.cpp
osm_diffresult_responder.cpp
osmchange_responder.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/api06/changeset_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ changeset_responder::changeset_responder(mime::type mt,
osm_changeset_id_t id,
bool include_discussion,
data_selection &w)
: osm_current_responder(mt, w) {
: osm_changeset_responder(mt, w, false) {

if (sel.select_changesets({id}) == 0) {
throw http::not_found(fmt::format("Changeset {:d} was not found.", id));
Expand Down
81 changes: 50 additions & 31 deletions src/json_formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,42 @@ void json_formatter::write_bounds(const bbox &bounds) {
writer->end_object();
}

void json_formatter::end_document() {
void json_formatter::start_element() {

writer->object_key("elements");
writer->start_array();
}

//
void json_formatter::end_element() {

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

void json_formatter::start_element_type(element_type type) {
void json_formatter::start_changeset(bool multi_selection) {

if (is_in_elements_array)
return;
if (multi_selection) {
writer->object_key("changesets");
writer->start_array();
}
else
{
writer->object_key("changeset");
}
}

writer->object_key("elements");
writer->start_array();
is_in_elements_array = true;
void json_formatter::end_changeset(bool multi_selection) {

if (multi_selection) {
writer->end_array();
}
}

void json_formatter::end_element_type(element_type type) {}

void json_formatter::end_document() {
writer->end_object();
}

void json_formatter::start_action(action_type type) {
}
Expand Down Expand Up @@ -170,59 +188,60 @@ void json_formatter::write_relation(const element_info &elem,
writer->end_object();
}

void json_formatter::write_changeset(const changeset_info &elem,
void json_formatter::write_changeset(const changeset_info &cs,
const tags_t &tags,
bool include_comments,
const comments_t &comments,
const std::chrono::system_clock::time_point &now) {

writer->start_object();
writer->property("type", "changeset");
writer->property("id", elem.id);
writer->property("created_at", elem.created_at);
writer->property("id", cs.id);
writer->property("created_at", cs.created_at);

const bool is_open = elem.is_open_at(now);
if (!is_open) {
writer->property("closed_at", elem.closed_at);
}
const bool is_open = cs.is_open_at(now);

writer->property("open", is_open);

if (elem.display_name && bool(elem.uid)) {
writer->property("user", *elem.display_name);
writer->property("uid", *elem.uid);
writer->property("comments_count", cs.comments_count);
writer->property("changes_count", cs.num_changes);

if (!is_open) {
writer->property("closed_at", cs.closed_at);
}

if (elem.bounding_box) {
writer->property("minlat", elem.bounding_box->minlat);
writer->property("minlon", elem.bounding_box->minlon);
writer->property("maxlat", elem.bounding_box->maxlat);
writer->property("maxlon", elem.bounding_box->maxlon);
if (cs.bounding_box) {
writer->property("min_lat", cs.bounding_box->minlat);
writer->property("min_lon", cs.bounding_box->minlon);
writer->property("max_lat", cs.bounding_box->maxlat);
writer->property("max_lon", cs.bounding_box->maxlon);
}

writer->property("comments_count", elem.comments_count);
writer->property("changes_count", elem.num_changes);
if (cs.display_name && bool(cs.uid)) {
writer->property("uid", *cs.uid);
writer->property("user", *cs.display_name);
}

write_tags(tags);

if (include_comments && !comments.empty()) {
writer->object_key("discussion");
writer->object_key("comments");
writer->start_array();
for (const auto & comment : comments) {
writer->start_object();
writer->property("id", comment.id);
writer->property("id", comment.id);
writer->property("visible", true);
writer->property("date", comment.created_at);
writer->property("uid", comment.author_id);
writer->property("uid", comment.author_id);
writer->property("user", comment.author_display_name);
writer->property("text", comment.body);
writer->end_object();
}
writer->end_array();
}

writer->end_object();
}


void json_formatter::write_diffresult_create_modify(const element_type elem,
const osm_nwr_signed_id_t old_id,
const osm_nwr_id_t new_id,
Expand Down
48 changes: 48 additions & 0 deletions src/osm_changeset_responder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* SPDX-License-Identifier: GPL-2.0-only
*
* This file is part of openstreetmap-cgimap (https://github.com/zerebubuth/openstreetmap-cgimap/).
*
* Copyright (C) 2009-2023 by the CGImap developer community.
* For a full list of authors see the git log.
*/

#include "cgimap/logger.hpp"
#include "cgimap/osm_changeset_responder.hpp"

#include <fmt/core.h>

#include <optional>

using std::list;

osm_changeset_responder::osm_changeset_responder(mime::type mt,
data_selection &s,
bool multi_selection)
: osm_responder(mt),
sel(s),
multi_selection(multi_selection){}


void osm_changeset_responder::write(output_formatter& fmt,
const std::string &generator,
const std::chrono::system_clock::time_point &now) {

try {
fmt.start_document(generator, "osm");

fmt.start_changeset(multi_selection);

// write changeset
sel.write_changesets(fmt, now);

fmt.end_changeset(multi_selection);

} catch (const std::exception &e) {
logger::message(fmt::format("Caught error in osm_changeset_responder: {}",
e.what()));
fmt.error(e);
}

fmt.end_document();
}
24 changes: 5 additions & 19 deletions src/osm_current_responder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,11 @@ void osm_current_responder::write(output_formatter& fmt,
fmt.write_bounds(*bounds);
}

// write all selected changesets
fmt.start_element_type(element_type::changeset);
sel.write_changesets(fmt, now);
fmt.end_element_type(element_type::changeset);

// write all selected nodes
fmt.start_element_type(element_type::node);
sel.write_nodes(fmt);
fmt.end_element_type(element_type::node);

// all selected ways
fmt.start_element_type(element_type::way);
sel.write_ways(fmt);
fmt.end_element_type(element_type::way);

// all selected relations
fmt.start_element_type(element_type::relation);
sel.write_relations(fmt);
fmt.end_element_type(element_type::relation);
fmt.start_element();
sel.write_nodes(fmt); // write all selected nodes
sel.write_ways(fmt); // all selected ways
sel.write_relations(fmt); // all selected relations
fmt.end_element();

} catch (const std::exception &e) {
logger::message(fmt::format("Caught error in osm_current_responder: {}",
Expand Down
16 changes: 12 additions & 4 deletions src/osmchange_responder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,20 @@ struct sorting_formatter : public output_formatter {
throw std::runtime_error("sorting_formatter::write_bounds unimplemented");
}

void start_element_type(element_type) override {
throw std::runtime_error("sorting_formatter::start_element_type unimplemented");
void start_element() {
throw std::runtime_error("sorting_formatter::start_element unimplemented");
}

void end_element_type(element_type) override {
throw std::runtime_error("sorting_formatter::end_element_type unimplemented");
void end_element() {
throw std::runtime_error("sorting_formatter::end_element unimplemented");
}

void start_changeset(bool) {
throw std::runtime_error("sorting_formatter::start_changeset unimplemented");
}

void end_changeset(bool) {
throw std::runtime_error("sorting_formatter::end_changeset unimplemented");
}

void write_node(
Expand Down
Loading

0 comments on commit a2889bb

Please sign in to comment.