From 31f60d9347047ea5bf42a95a0b6358ea882ffdca Mon Sep 17 00:00:00 2001
From: Ramin Yaghoubzadeh <ryaghoubzadeh@uni-bielefeld.de>
Date: Mon, 9 Feb 2015 12:49:11 +0100
Subject: [PATCH] further progress towards json port

---
 ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h |  13 +-
 .../cpp/include/ipaaca/ipaaca-definitions.h   |  19 ++-
 .../cpp/include/ipaaca/ipaaca-forwards.h      |   3 +
 .../cpp/include/ipaaca/ipaaca-internal.h      |   2 +
 ipaacalib/cpp/include/ipaaca/ipaaca-ius.h     |   6 +-
 ipaacalib/cpp/include/ipaaca/ipaaca-payload.h |  81 +++++++++++--
 ipaacalib/cpp/include/ipaaca/ipaaca.h         |   3 +
 ipaacalib/cpp/src/ipaaca-buffers.cc           |  12 +-
 ipaacalib/cpp/src/ipaaca-internal.cc          |  88 ++++++++++----
 ipaacalib/cpp/src/ipaaca-ius.cc               |   5 +-
 ipaacalib/cpp/src/ipaaca-json.cc              |  47 +++++---
 ipaacalib/cpp/src/ipaaca-payload.cc           | 112 +++++++++++++++---
 12 files changed, 303 insertions(+), 88 deletions(-)

diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h
index dd00eb9..2ab904f 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 034a918..856464a 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 8f02152..5d64840 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 ae2bdd0..2bc528b 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 6656d18..75e22d7 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 3e9cebb..f41d4cf 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 4662931..95cc0f0 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 91a66e2..9d7208c 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 fe89565..e8defae 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 39c9d5c..27a2f4c 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 929e803..5908926 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 baba2cf..00674e1 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));
 }
 
 //}}}
-- 
GitLab