diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h index dd00eb96c778d15e96848810dddf8c0fe216d796..2ab904fa53e7c9f9374432b5ea7001102e0bdfec 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h @@ -145,8 +145,7 @@ IPAACA_HEADER_EXPORT class IUEventHandler {//{{{ IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef") = 0; -// LAST POSITION OPENED FIXME - IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, const rapidjson::Document&>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") = 0; + IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") = 0; IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") = 0; // IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") = 0; IPAACA_HEADER_EXPORT void _allocate_unique_name(const std::string& basename, const std::string& function); @@ -186,11 +185,11 @@ IPAACA_HEADER_EXPORT class IUEventHandler {//{{{ protected: // informing functions IPAACA_HEADER_EXPORT void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef"); - IPAACA_HEADER_EXPORT void _publish_iu_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); + IPAACA_HEADER_EXPORT void _publish_iu_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); IPAACA_HEADER_EXPORT void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, const rapidjson::Document&>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef"); IPAACA_HEADER_EXPORT void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name); - IPAACA_HEADER_EXPORT void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name); + //IPAACA_HEADER_EXPORT void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name); // remote access functions // _remote_update_links(IULinkUpdate) // _remote_update_payload(IUPayloadUpdate) @@ -247,10 +246,10 @@ IPAACA_HEADER_EXPORT class IUEventHandler {//{{{ { IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_commission() should never be invoked") } - IPAACA_HEADER_EXPORT inline void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") + /*IPAACA_HEADER_EXPORT inline void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") { IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_resendrequest() should never be invoked") - } + }*/ protected: IPAACA_HEADER_EXPORT InputBuffer(const BufferConfiguration& bufferconfiguration); IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::set<std::string>& category_interests); @@ -287,7 +286,7 @@ IPAACA_HEADER_EXPORT class IUEventHandler {//{{{ IPAACA_MEMBER_VAR_EXPORT revision_t revision; IPAACA_MEMBER_VAR_EXPORT std::string writer_name; IPAACA_MEMBER_VAR_EXPORT bool is_delta; - IPAACA_MEMBER_VAR_EXPORT std::map<std::string, const rapidjson::Document&> new_items; + IPAACA_MEMBER_VAR_EXPORT std::map<std::string, PayloadDocumentEntry::ptr> new_items; IPAACA_MEMBER_VAR_EXPORT std::vector<std::string> keys_to_remove; friend std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj); typedef boost::shared_ptr<IUPayloadUpdate> ptr; diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h index 034a9186f4cfb4a97d901ab3dfacfbf6a8225e62..856464a976cd3d546025796a83b4d3b0fb5be041 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h @@ -38,6 +38,8 @@ #error "Please do not include this file directly, use ipaaca.h instead" #endif +// LAST FIXME LAST +//typedef boost::shared_ptr<rapidjson::Document> JsonDocPtr; typedef uint32_t revision_t; @@ -200,7 +202,22 @@ IPAACA_HEADER_EXPORT class NotImplementedError: public Exception//{{{ _description = "NotImplementedError"; } };//}}} - +IPAACA_HEADER_EXPORT class PayloadAddressingError: public Exception//{{{ +{ + public: + IPAACA_HEADER_EXPORT inline ~PayloadAddressingError() throw() { } + IPAACA_HEADER_EXPORT inline PayloadAddressingError() { //boost::shared_ptr<IU> iu) { + _description = "PayloadAddressingError"; + } +};//}}} +IPAACA_HEADER_EXPORT class JsonParsingError: public Exception//{{{ +{ + public: + IPAACA_HEADER_EXPORT inline ~JsonParsingError() throw() { } + IPAACA_HEADER_EXPORT inline JsonParsingError() { //boost::shared_ptr<IU> iu) { + _description = "JsonParsingError"; + } +};//}}} /// Static library initialization IPAACA_HEADER_EXPORT class Initializer diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h index 8f0215297f807a519871f5888e842db70c96e064..5d648401fdd10b09e590dda2d46aac977b3825a8 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h @@ -41,6 +41,9 @@ /* * forward declarations */ +class PayloadDocumentEntry; +class PayloadDocumentStore; + class PayloadEntryProxy; class Payload; class IUInterface; diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h b/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h index ae2bdd0c2ffda36566fc79d6fc120552818d0e66..2bc528b1d5657c126b52d9386c2b696090e11e1b 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h @@ -41,6 +41,8 @@ #ifdef IPAACA_EXPOSE_FULL_RSB_API +IPAACA_HEADER_EXPORT inline std::string json_to_string(PayloadDocumentEntry::ptr entry); + IPAACA_HEADER_EXPORT class CallbackIUPayloadUpdate: public rsb::patterns::Server::Callback<IUPayloadUpdate, int> {//{{{ protected: IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer; diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h index 6656d18fc1fcc24f596a3f5f5a1ee3c2c3cb2210..75e22d7148592f52864e240c3e75c0e2b9d5f9ca 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h @@ -65,7 +65,7 @@ IPAACA_HEADER_EXPORT class IUInterface {//{{{ // Internal functions that perform the update logic, // e.g. sending a notification across the network IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) = 0; - IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_payload(bool is_delta, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) = 0; + IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) = 0; //void _set_buffer(boost::shared_ptr<Buffer> buffer); IPAACA_HEADER_EXPORT void _associate_with_buffer(Buffer* buffer); IPAACA_HEADER_EXPORT void _set_buffer(Buffer* buffer); @@ -96,7 +96,7 @@ IPAACA_HEADER_EXPORT class IUInterface {//{{{ // setters IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void commit() = 0; // functions to modify and update links: - IPAACA_HEADER_EXPORT void _publish_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); + //IPAACA_HEADER_EXPORT void _publish_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); IPAACA_HEADER_EXPORT void add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = ""); IPAACA_HEADER_EXPORT void remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = ""); @@ -134,7 +134,7 @@ IPAACA_HEADER_EXPORT class IU: public IUInterface {//{{{ protected: IPAACA_HEADER_EXPORT virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = ""); - IPAACA_HEADER_EXPORT virtual void _publish_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); + //IPAACA_HEADER_EXPORT virtual void _publish_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name); IPAACA_HEADER_EXPORT virtual void _modify_payload(bool is_delta, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = ""); protected: diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h index 3e9cebbcead7f4ce1d4331761a27154c97843d05..f41d4cf44814d7fed0749064a8f4f6e3fb690be9 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h @@ -38,6 +38,18 @@ #error "Please do not include this file directly, use ipaaca.h instead" #endif +IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{ +{ + public: + IPAACA_MEMBER_VAR_EXPORT ipaaca::Lock lock; + IPAACA_MEMBER_VAR_EXPORT rapidjson::Document document; + IPAACA_HEADER_EXPORT PayloadDocumentEntry(rapidjson::Document&& doc): document(std::move(doc)) {}; + IPAACA_HEADER_EXPORT PayloadDocumentEntry() {}; + IPAACA_HEADER_EXPORT std::string to_json_string_representation(); + static std::shared_ptr<PayloadDocumentEntry> from_json_string_representation(const std::string& input); + typedef std::shared_ptr<PayloadDocumentEntry> ptr; +}; +//}}} IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ { protected: @@ -45,8 +57,29 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ //IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node; IPAACA_MEMBER_VAR_EXPORT Payload* _payload; IPAACA_MEMBER_VAR_EXPORT std::string _key; + // + // new json stuff / hierarchical navigation + // + PayloadEntryProxy* parent; // parent (up to document root -> then null) + PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc + bool existant; // whether Value exist already (or blindly navigated) + bool addressed_as_array; // whether long or string navigation used + long addressed_index; + std::string addressed_key; + /// currently navigated value in json tree (or a new Null value) + rapidjson::Value& json_value; public: - IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key); + IPAACA_HEADER_EXPORT PayloadEntryProxy& operator[](long index); // array-style navigation + IPAACA_HEADER_EXPORT PayloadEntryProxy& operator[](const std::string& key); + protected: + IPAACA_HEADER_EXPORT void connect_to_existing_parents(); + protected: + IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(T t); //specializations below + public: + IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key, PayloadDocumentEntry::ptr entry); + IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key); + IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, long addressed_index); + // IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value); IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const char* value); IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(double value); @@ -63,6 +96,12 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ // getters IPAACA_HEADER_EXPORT template<typename T> T get(); // specializations below // setters + IPAACA_HEADER_EXPORT template<typename T> PayloadEntryProxy& set(T t); + /*{ + pack_into_json_value<T>(t); + connect_to_existing_parents(); + _payload->set(key, document_entry->document); + }*/ }; // Available interpretations of payload entries (or children thereof) below. // Usage of standard complex data structures (vector etc.) currently entails @@ -74,7 +113,14 @@ IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get(); IPAACA_HEADER_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get(); IPAACA_HEADER_EXPORT template<> std::list<std::string> PayloadEntryProxy::get(); IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get(); - +// value converters +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(long); +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(double); +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(bool); +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::string&); +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::vector<std::string>&); +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::list<std::string>&); +IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::map<std::string, std::string>&); //}}} /* @@ -116,6 +162,16 @@ IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryP //}}} */ +// shared_ptrs stored for shared read access, ref must be held +// even if the key for the entry is overwritten remotely +IPAACA_HEADER_EXPORT class PayloadDocumentStore//{{{ +: public std::map<std::string, PayloadDocumentEntry::ptr> +{ + public: + typedef std::shared_ptr<PayloadDocumentStore> ptr; +}; +//}}} + IPAACA_HEADER_EXPORT class Payload//{{{ { friend std::ostream& operator<<(std::ostream& os, const Payload& obj); @@ -130,28 +186,31 @@ IPAACA_HEADER_EXPORT class Payload//{{{ protected: IPAACA_MEMBER_VAR_EXPORT std::string _owner_name; //IPAACA_MEMBER_VAR_EXPORT rapidjson::Document _json_document; - IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rapidjson::Document> _json_store; + //IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rapidjson::Document> _json_store; + IPAACA_MEMBER_VAR_EXPORT PayloadDocumentStore _document_store; IPAACA_MEMBER_VAR_EXPORT boost::weak_ptr<IUInterface> _iu; protected: IPAACA_HEADER_EXPORT void initialize(boost::shared_ptr<IUInterface> iu); IPAACA_HEADER_EXPORT inline void _set_owner_name(const std::string& name) { _owner_name = name; } IPAACA_HEADER_EXPORT void _remotely_enforced_wipe(); IPAACA_HEADER_EXPORT void _remotely_enforced_delitem(const std::string& k); - IPAACA_HEADER_EXPORT void _remotely_enforced_setitem(const std::string& k, const rapidjson::Document& v); - IPAACA_HEADER_EXPORT void _internal_replace_all(const std::map<std::string, const rapidjson::Document&>& new_contents, const std::string& writer_name=""); - IPAACA_HEADER_EXPORT void _internal_merge(const std::map<std::string, const rapidjson::Document&>& contents_to_merge, const std::string& writer_name=""); - IPAACA_HEADER_EXPORT void _internal_set(const std::string& k, const rapidjson::Document& v, const std::string& writer_name=""); + IPAACA_HEADER_EXPORT void _remotely_enforced_setitem(const std::string& k, PayloadDocumentEntry::ptr entry); + IPAACA_HEADER_EXPORT void _internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name=""); + IPAACA_HEADER_EXPORT void _internal_merge(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::string& writer_name=""); + IPAACA_HEADER_EXPORT void _internal_set(const std::string& k, PayloadDocumentEntry::ptr v, const std::string& writer_name=""); IPAACA_HEADER_EXPORT void _internal_remove(const std::string& k, const std::string& writer_name=""); public: IPAACA_HEADER_EXPORT inline const std::string& owner_name() { return _owner_name; } // access IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const std::string& key); IPAACA_HEADER_EXPORT operator std::map<std::string, std::string>(); - IPAACA_HEADER_EXPORT inline void set(const std::map<std::string, const rapidjson::Document&>& all_elems) { _internal_replace_all(all_elems); } - IPAACA_HEADER_EXPORT inline void set(const std::string& k, const rapidjson::Document& v) { _internal_set(k, v); } - IPAACA_HEADER_EXPORT inline void merge(const std::map<std::string, const rapidjson::Document&>& elems_to_merge) { _internal_merge(elems_to_merge); } + IPAACA_HEADER_EXPORT inline void set(const std::string& k, PayloadDocumentEntry::ptr entry) { _internal_set(k, entry); } IPAACA_HEADER_EXPORT inline void remove(const std::string& k) { _internal_remove(k); } - IPAACA_HEADER_EXPORT std::string get(const std::string& k); + // FIXME: json: these two must support a bunch of standard types, not [only] json (users touch them) + // to be more precise: types of map<string, T> with T several interesting things (string, list<string>, etc.) + //IPAACA_HEADER_EXPORT inline void set(const std::map<std::string, const rapidjson::Document&>& all_elems) { _internal_replace_all(all_elems); } + //IPAACA_HEADER_EXPORT inline void merge(const std::map<std::string, const rapidjson::Document&>& elems_to_merge) { _internal_merge(elems_to_merge); } + IPAACA_HEADER_EXPORT PayloadEntryProxy get(const std::string& k); // json, changed str to proxy here, too typedef boost::shared_ptr<Payload> ptr; };//}}} diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca.h b/ipaacalib/cpp/include/ipaaca/ipaaca.h index 46629317f1f100cac2129cde75bc28c1dabb5f35..95cc0f0f8daeabed5f7f31146e23136ee1121f01 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca.h @@ -147,10 +147,13 @@ #include <boost/lexical_cast.hpp> #endif + #include <ipaaca/ipaaca.pb.h> #include <set> #include <list> +#include <algorithm> +#include <utility> namespace ipaaca { diff --git a/ipaacalib/cpp/src/ipaaca-buffers.cc b/ipaacalib/cpp/src/ipaaca-buffers.cc index 91a66e2a29fd4dec10e0f54f0e81038e2889e383..9d7208cfcf5d9765db5a27a79ade419037c05678 100644 --- a/ipaacalib/cpp/src/ipaaca-buffers.cc +++ b/ipaacalib/cpp/src/ipaaca-buffers.cc @@ -323,7 +323,8 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUResendRequest::call(const std::st //_buffer->call_iu_event_handlers(iu, true, IU_UPDATED, update->hidden_scope_name()); revision_t revision = iu->revision(); - iu->_publish_resend(iu, update->hidden_scope_name()); + _buffer->_publish_iu_resend(iu, update->hidden_scope_name()); + //iu->_publish_resend(iu, update->hidden_scope_name()); return boost::shared_ptr<int>(new int(revision)); } else { @@ -392,7 +393,7 @@ IPAACA_EXPORT void OutputBuffer::_send_iu_link_update(IUInterface* iu, bool is_d informer->publish(ldata); } -IPAACA_EXPORT void OutputBuffer::_send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, const rapidjson::Document&>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) +IPAACA_EXPORT void OutputBuffer::_send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) { IUPayloadUpdate* pup = new ipaaca::IUPayloadUpdate(); Informer<ipaaca::IUPayloadUpdate>::DataPtr pdata(pup); @@ -671,8 +672,7 @@ IPAACA_EXPORT ListenerPtr InputBuffer::_create_category_listener_if_needed(const return listener; } IPAACA_EXPORT void InputBuffer::_trigger_resend_request(EventPtr event) { - if (!triggerResend) - return; + if (!triggerResend) return; std::string type = event->getType(); std::string uid = ""; std::string writerName = ""; @@ -689,7 +689,7 @@ IPAACA_EXPORT void InputBuffer::_trigger_resend_request(EventPtr event) { uid = update->uid(); writerName = update->writer_name(); } else { - std::cout << "trigger ??? else" << std::endl; + std::cout << "_trigger_resend_request: unhandled event type " << type << std::endl; } if (!writerName.empty()) { @@ -702,7 +702,7 @@ IPAACA_EXPORT void InputBuffer::_trigger_resend_request(EventPtr event) { if (*result == 0) { throw IUResendRequestFailedError(); } else { - std::cout << "revision " << *result << std::endl; + //std::cout << "revision " << *result << std::endl; } } } diff --git a/ipaacalib/cpp/src/ipaaca-internal.cc b/ipaacalib/cpp/src/ipaaca-internal.cc index fe89565dca5c01526951463deccbfe5c1d38bb59..e8defae395a0f2e6e30de0762f8af41409782352 100644 --- a/ipaacalib/cpp/src/ipaaca-internal.cc +++ b/ipaacalib/cpp/src/ipaaca-internal.cc @@ -168,10 +168,10 @@ IPAACA_EXPORT std::string IUConverter::serialize(const AnnotatedData& data, std: } pbo->set_access_mode(a_m); pbo->set_read_only(obj->read_only()); - for (auto& kv: obj->_payload._store) { + for (auto& kv: obj->_payload._document_store) { protobuf::PayloadItem* item = pbo->add_payload(); item->set_key(kv.first); - item->set_value(kv.second); + item->set_value( kv.second.document.to_json_string_representation() ); item->set_type("json"); } for (LinkMap::const_iterator it=obj->_links._links.begin(); it!=obj->_links._links.end(); ++it) { @@ -216,10 +216,18 @@ IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSche obj->_committed = pbo->committed(); obj->_read_only = pbo->read_only(); obj->_access_mode = IU_ACCESS_PUSH; - // TODO JSONIZE for (int i=0; i<pbo->payload_size(); i++) { const protobuf::PayloadItem& it = pbo->payload(i); - obj->_payload._store[it.key()] = it.value(); + PayloadDocumentEntry::ptr entry; + if (it.type() == "json") { + // fully parse json text + entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) + } else { + // implying legacy "str" -> just copy value to raw string in document + entry = std::make_shared<PayloadDocumentEntry>(); + entry->document.SetString(it.value(), entry->document.GetAllocator()); + } + obj->_payload._document_store[it.key()] = entry; } for (int i=0; i<pbo->links_size(); i++) { const protobuf::LinkSet& pls = pbo->links(i); @@ -246,10 +254,18 @@ IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSche obj->_committed = pbo->committed(); obj->_read_only = pbo->read_only(); obj->_access_mode = IU_ACCESS_MESSAGE; - // TODO JSONIZE for (int i=0; i<pbo->payload_size(); i++) { const protobuf::PayloadItem& it = pbo->payload(i); - obj->_payload._store[it.key()] = it.value(); + PayloadDocumentEntry::ptr entry; + if (it.type() == "json") { + // fully parse json text + entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) + } else { + // implying legacy "str" -> just copy value to raw string in document + entry = std::make_shared<PayloadDocumentEntry>(); + entry->document.SetString(it.value(), entry->document.GetAllocator()); + } + obj->_payload._document_store[it.key()] = entry; } for (int i=0; i<pbo->links_size(); i++) { const protobuf::LinkSet& pls = pbo->links(i); @@ -304,12 +320,11 @@ IPAACA_EXPORT std::string MessageConverter::serialize(const AnnotatedData& data, } pbo->set_access_mode(a_m); pbo->set_read_only(obj->read_only()); - // TODO JSONIZE - for (std::map<std::string, std::string>::const_iterator it=obj->_payload._store.begin(); it!=obj->_payload._store.end(); ++it) { + for (auto& kv: obj->_payload._document_store) { protobuf::PayloadItem* item = pbo->add_payload(); - item->set_key(it->first); - item->set_value(it->second); - item->set_type("str"); // FIXME other types than str (later) + item->set_key(kv.first); + item->set_value( kv.second.document.to_json_string_representation() ); + item->set_type("json"); } for (LinkMap::const_iterator it=obj->_links._links.begin(); it!=obj->_links._links.end(); ++it) { protobuf::LinkSet* links = pbo->add_links(); @@ -350,10 +365,18 @@ IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wir obj->_committed = pbo->committed(); obj->_read_only = pbo->read_only(); obj->_access_mode = IU_ACCESS_PUSH; - // TODO JSONIZE for (int i=0; i<pbo->payload_size(); i++) { const protobuf::PayloadItem& it = pbo->payload(i); - obj->_payload._store[it.key()] = it.value(); + PayloadDocumentEntry::ptr entry; + if (it.type() == "json") { + // fully parse json text + entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) + } else { + // implying legacy "str" -> just copy value to raw string in document + entry = std::make_shared<PayloadDocumentEntry>(); + entry->document.SetString(it.value(), entry->document.GetAllocator()); + } + obj->_payload._document_store[it.key()] = entry; } for (int i=0; i<pbo->links_size(); i++) { const protobuf::LinkSet& pls = pbo->links(i); @@ -379,10 +402,18 @@ IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wir obj->_committed = pbo->committed(); obj->_read_only = pbo->read_only(); obj->_access_mode = IU_ACCESS_MESSAGE; - // TODO JSONIZE for (int i=0; i<pbo->payload_size(); i++) { const protobuf::PayloadItem& it = pbo->payload(i); - obj->_payload._store[it.key()] = it.value(); + PayloadDocumentEntry::ptr entry; + if (it.type() == "json") { + // fully parse json text + entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) + } else { + // implying legacy "str" -> just copy value to raw string in document + entry = std::make_shared<PayloadDocumentEntry>(); + entry->document.SetString(it.value(), entry->document.GetAllocator()); + } + obj->_payload._document_store[it.key()] = entry; } for (int i=0; i<pbo->links_size(); i++) { const protobuf::LinkSet& pls = pbo->links(i); @@ -419,16 +450,14 @@ IPAACA_EXPORT std::string IUPayloadUpdateConverter::serialize(const AnnotatedDat pbo->set_revision(obj->revision); pbo->set_writer_name(obj->writer_name); pbo->set_is_delta(obj->is_delta); - // TODO JSONIZE - for (std::map<std::string, std::string>::const_iterator it=obj->new_items.begin(); it!=obj->new_items.end(); ++it) { + for (auto& kv: obj->new_items) { protobuf::PayloadItem* item = pbo->add_new_items(); - item->set_key(it->first); - item->set_value(it->second); - item->set_type("str"); // FIXME other types than str (later) + item->set_key(kv.first); + item->set_value( kv.second.document.to_json_string_representation() ); + item->set_type("json"); } - // TODO JSONIZE - for (std::vector<std::string>::const_iterator it=obj->keys_to_remove.begin(); it!=obj->keys_to_remove.end(); ++it) { - pbo->add_keys_to_remove(*it); + for (auto& key: obj->keys_to_remove) { + pbo->add_keys_to_remove(key); } pbo->SerializeToString(&wire); return getWireSchema(); @@ -445,12 +474,19 @@ AnnotatedData IUPayloadUpdateConverter::deserialize(const std::string& wireSchem obj->revision = pbo->revision(); obj->writer_name = pbo->writer_name(); obj->is_delta = pbo->is_delta(); - // TODO JSONIZE for (int i=0; i<pbo->new_items_size(); i++) { const protobuf::PayloadItem& it = pbo->new_items(i); - obj->new_items[it.key()] = it.value(); + PayloadDocumentEntry::ptr entry; + if (it.type() == "json") { + // fully parse json text + entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) + } else { + // implying legacy "str" -> just copy value to raw string in document + entry = std::make_shared<PayloadDocumentEntry>(); + entry->document.SetString(it.value(), entry->document.GetAllocator()); + } + obj->new_items[it.key()] = entry; } - // TODO JSONIZE for (int i=0; i<pbo->keys_to_remove_size(); i++) { obj->keys_to_remove.push_back(pbo->keys_to_remove(i)); } diff --git a/ipaacalib/cpp/src/ipaaca-ius.cc b/ipaacalib/cpp/src/ipaaca-ius.cc index 39c9d5c7600f61fb0e3e2a154ea5a0edf80850ca..27a2f4c0ffee9cfa064ced1755cbf8f67d54bf6f 100644 --- a/ipaacalib/cpp/src/ipaaca-ius.cc +++ b/ipaacalib/cpp/src/ipaaca-ius.cc @@ -188,7 +188,8 @@ IPAACA_EXPORT void IU::_modify_links(bool is_delta, const LinkMap& new_links, co } -IPAACA_EXPORT void IU::_publish_resend(IU::ptr iu, const std::string& hidden_scope_name) +/* + * IPAACA_EXPORT void IU::_publish_resend(IU::ptr iu, const std::string& hidden_scope_name) { //_revision_lock.lock(); //if (_committed) { @@ -202,7 +203,7 @@ IPAACA_EXPORT void IU::_publish_resend(IU::ptr iu, const std::string& hidden_sco //} //_revision_lock.unlock(); } - +*/ diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc index 929e803a1ba94fcd397a83ecd2f1998b88f9ddb9..59089268f976ab26759851aae435ce8aff643eb9 100644 --- a/ipaacalib/cpp/src/ipaaca-json.cc +++ b/ipaacalib/cpp/src/ipaaca-json.cc @@ -39,23 +39,23 @@ using namespace std; int main(int, char*[]) { -#ifdef RAPIDJSON_HAS_CXX11_RVALUE_REFS - puts("OK - c++11 rvalue refs possible."); -#else - puts("WARNING - no c++11 rvalue refs!"); -#endif - - std::map<std::string, Document> documents; //////////////////////////////////////////////////////////////////////////// // 1. Parse a JSON text string to a document. const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4], \"dict\":{\"s\":\"stringvalue\", \"arr\":[6, 7, \"test\"]} } "; printf("Original JSON:\n %s\n", json); - Document _document; // Default template parameter uses UTF8 and MemoryPoolAllocator. - documents["document_test"] = std::move(_document); - Document& document = documents["document_test"]; + + ipaaca::PayloadDocumentStore ds; + ds["document_test"] = std::make_shared<ipaaca::PayloadDocumentEntry>(); + Document& document = ds["document_test"]->document; + + //std::map<std::string, Document> documents; + //Document _document; // Default template parameter uses UTF8 and MemoryPoolAllocator. + //documents["document_test"] = std::move(_document); + //Document& document = documents["document_test"]; + printf("Check whether document contains 'none' initially ..."); assert(document.IsNull()); // initial state of object -#if 0 +#if 1 // "normal" parsing, decode strings to new buffers. Can use other input stream via ParseStream(). if (document.Parse(json).HasParseError()) return 1; @@ -90,9 +90,15 @@ int main(int, char*[]) { puts("Putting new dict in array.\n"); Document::AllocatorType& allocator = document.GetAllocator(); Value dict; + Value insertstr; + insertstr.SetString("testvalue", allocator); dict.SetObject(); - dict.AddMember("testkey", "testvalue", allocator); + dict.AddMember("testkey", insertstr, allocator); arr.PushBack(dict, allocator); + + Value newint; + newint.SetInt(12345); + document["i"] = newint; puts("Done.\n"); // ->Assertion failed in []: // Value& nonexisting = document["dict"]["NONEXISTING"]; @@ -183,11 +189,16 @@ int main(int, char*[]) { assert(author.IsNull()); // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null. //////////////////////////////////////////////////////////////////////////// #endif - - // 4. Stringify JSON - printf("\nModified JSON with reformatting:\n"); - FileStream f(stdout); - PrettyWriter<FileStream> writer(f); - document.Accept(writer); // Accept() traverses the DOM and generates Handler events. + StringBuffer buffer; + Writer<StringBuffer> writer(buffer); + document.Accept(writer); + std::string docstring = buffer.GetString(); + std::cout << "FIRST DUMP: " << docstring << std::endl; + + //// 4. Stringify JSON + //printf("\nModified JSON with reformatting:\n"); + //FileStream f(stdout); + //PrettyWriter<FileStream> writer(f); + //document.Accept(writer); // Accept() traverses the DOM and generates Handler events. return 0; } diff --git a/ipaacalib/cpp/src/ipaaca-payload.cc b/ipaacalib/cpp/src/ipaaca-payload.cc index baba2cf9ab9da13feb7746bed77b16d6cbd1222a..00674e1fc2d7d72e8970bc747389f02f532d8c7b 100644 --- a/ipaacalib/cpp/src/ipaaca-payload.cc +++ b/ipaacalib/cpp/src/ipaaca-payload.cc @@ -44,7 +44,7 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{ { os << "{"; bool first = true; - for (std::map<std::string, std::string>::const_iterator it=obj._json_store.begin(); it!=obj._json_store.end(); ++it) { + for (std::map<std::string, std::string>::const_iterator it=obj._document_store.begin(); it!=obj._document_store.end(); ++it) { if (first) { first=false; } else { os << ", "; } os << "'" << it->first << "':'" << it->second << "'"; } @@ -53,12 +53,96 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{ } //}}} +// PayloadDocumentEntry//{{{ +IPAACA_HEADER_EXPORT inline std::string PayloadDocumentEntry::to_json_string_representation() +{ + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + document.Accept(writer); + return buffer.GetString(); +} +IPAACA_HEADER_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_string_representation(const std::string& json) +{ + PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>(); + if (entry->document.Parse(json).HasParseError()) { + throw JsonParsingError(); + } + return entry; +} +//}}} + // PayloadEntryProxy//{{{ -IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key) -: _payload(payload), _key(key) + // only if not top-level +IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents() +{ + rapidjson::Document::AllocatorType& allocator = document_entry->document.GetAllocator(); + PayloadEntryProxy* pep = this; + while (!(pep->existant) && pep->parent) { // only if not top-level + if (pep->addressed_as_array) { + Value& parent_value = pep->parent->json_value; + if (! parent_value.IsArray()) { + throw PayloadAddressingError(); + } else { + long idx = pep->addressed_index; + long s = parent_value.Size(); + if (idx<s) { + parent_value[idx] = json_value; + } else { + throw PayloadAddressingError(); + } + } + /*if (parent_value.IsNull()) { + wasnull = true; + parent_value.SetArray(); + } + if (wasnull || parent_value.IsArray()) { + long idx = pep->addressed_index; + long s = parent_value.Size(); + if (idx<s) { + // existing element modified + parent_value[idx] = json_value; + } else { + // implicitly initialize missing elements to null values + if (idx>s) { + long missing_elements = pep->addressed_index - p; + for (int i=0; i<missing_elements; ++i) { + parent_value.PushBack(, allocator) + } + } + } + if (s == + } else { + throw PayloadAddressingError(); + }*/ + } else { + // addressed as object (dict) + Value& parent_value = pep->parent->json_value; + if (! parent_value.IsObject()) { + throw PayloadAddressingError(); + } else { + parent_value.AddMember(pep->addressed_key, json_value, allocator); + } + } + // repeat for next parent in the tree + pep = pep->parent; + } +} + +IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key, PayloadDocumentEntry::ptr entry) +: _payload(payload), _key(key), parent(nullptr), document_entry(entry) { + PayloadEntryProxy* parent; // parent (up to document root -> then null) + PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc + bool existant; // whether Value exist already (or blindly navigated) + bool addressed_as_array; // whether long or string navigation used + long addressed_index; + std::string addressed_key; + /// currently navigated value in json tree (or a new Null value) + rapidjson::Value& json_value; + } + IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value) { //std::cout << "operator=(string)" << std::endl; @@ -169,12 +253,12 @@ IPAACA_EXPORT void Payload::initialize(boost::shared_ptr<IUInterface> iu) IPAACA_EXPORT PayloadEntryProxy Payload::operator[](const std::string& key) { //boost::shared_ptr<PayloadEntryProxy> p(new PayloadEntryProxy(this, key)); - return PayloadEntryProxy(this, key); + return PayloadEntryProxy(this, key, get(key)); } IPAACA_EXPORT Payload::operator std::map<std::string, std::string>() { std::map<std::string, std::string> result; - std::foreach(_json_store.begin(), _json_store.end(), [&result](auto pair) { + std::foreach(_document_store.begin(), _document_store.end(), [&result](auto pair) { result[pair.first] = pair.second.GetString(); }); return result; @@ -185,7 +269,7 @@ IPAACA_EXPORT void Payload::_internal_set(const std::string& k, const rapidjson: std::vector<std::string> _remove; _new[k]=v; _iu.lock()->_modify_payload(true, _new, _remove, writer_name ); - _json_store[k] = v; + _document_store[k] = v; } IPAACA_EXPORT void Payload::_internal_remove(const std::string& k, const std::string& writer_name) { std::map<std::string, const rapidjson::Document&> _new; @@ -204,26 +288,26 @@ IPAACA_EXPORT void Payload::_internal_merge(const std::map<std::string, const ra { std::vector<std::string> _remove; _iu.lock()->_modify_payload(true, contents_to_merge, _remove, writer_name ); - _json_store.insert(contents_to_merge.begin(), contents_to_merge.end()); + _document_store.insert(contents_to_merge.begin(), contents_to_merge.end()); //for (std::map<std::string, std::string>::iterator it = contents_to_merge.begin(); it!=contents_to_merge.end(); i++) { // _store[it->first] = it->second; //} } -IPAACA_EXPORT inline rapidjson::Document& Payload::get(const std::string& k) { - if (_json_store.count(k)>0) return _json_store[k]; - else return rapidjson::Document(); // if not found; contains 'null' value +IPAACA_EXPORT inline PayloadDocumentEntry::ptr Payload::get(const std::string& k) { + if (_document_store.count(k)>0) return _document_store[k]; + else return make_shared<PayloadDocumentEntry>(); // contains Document with 'null' value } IPAACA_EXPORT void Payload::_remotely_enforced_wipe() { - _json_store.clear(); + _document_store.clear(); } IPAACA_EXPORT void Payload::_remotely_enforced_delitem(const std::string& k) { - _json_store.erase(k); + _document_store.erase(k); } -IPAACA_EXPORT void Payload::_remotely_enforced_setitem(const std::string& k, const rapidjson::Document&) +IPAACA_EXPORT void Payload::_remotely_enforced_setitem(const std::string& k, rapidjson::Document&& received_json_doc) { - _json_store[k] = v; + _document_store[k] = make_shared<PayloadDocumentEntry>(std::move(received_json_doc)); } //}}}