diff --git a/.gitignore b/.gitignore
index 998b2b701fc21b88115143c8a36aca2f34ebd35d..e1a5fc4c1d536089f9d655ec80dadcbc218dcd56 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
 .DS_Store
 generatedsrc
 build
-docs
+docs/doxygen_generated
 lib
 test/lib
 report
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6359fd891778d27722ff758ccedbcccc9ea0f3c8
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,3 @@
+doxygen_generated
+.*.sw?
+
diff --git a/docs/ipaacaCpp.Doxyfile b/docs/ipaacaCpp.Doxyfile
new file mode 100644
index 0000000000000000000000000000000000000000..5d3a150a1c15d1962e4895bca852a8afe770173b
--- /dev/null
+++ b/docs/ipaacaCpp.Doxyfile
@@ -0,0 +1,2362 @@
+# Doxyfile 1.8.9.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "IPAACA-C++"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = "Revision 12 (Protocol 2.0)"
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "IPAACA - Incremental Processing Architecture for Artificial Conversational Agents (C++ version)"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doxygen_generated
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        = ../ipaacalib/cpp/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = YES  # user-set by ryaghoub from NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                   = ../ipaacalib/cpp/include ../ipaacalib/cpp/src  # user-set by ryaghoub from empty
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES  # user-set by ryaghoub from NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                = ../ipaacalib/cpp/include/rapidjson  # user-set by ryaghoub from empty
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = YES # user-set by ryaghoub from NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = YES  # user-set by ryaghoub from NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = YES  # user-set by ryaghoub from NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE        = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = YES    # user-set by ryaghoub from NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = YES    # user-set by ryaghoub from NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = ../ipaacalib/cpp/include   # user-set by ryaghoub from empty
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = IPAACA_EXPORT="" IPAACA_HEADER_EXPORT="" IPAACA_MEMBER_VAR_EXPORT="" _IPAACA_ABSTRACT_="" _IPAACA_OVERRIDE_="override"
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = YES  # user-set by ryaghoub from NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/docs/Photo 12.12.11 14 46 22.jpg b/docs/notes/Photo 12.12.11 14 46 22.jpg
similarity index 100%
rename from docs/Photo 12.12.11 14 46 22.jpg
rename to docs/notes/Photo 12.12.11 14 46 22.jpg
diff --git a/docs/Photo 14.11.11 14 14 03.jpg b/docs/notes/Photo 14.11.11 14 14 03.jpg
similarity index 100%
rename from docs/Photo 14.11.11 14 14 03.jpg
rename to docs/notes/Photo 14.11.11 14 14 03.jpg
diff --git a/docs/Photo 14.11.11 14 14 27.jpg b/docs/notes/Photo 14.11.11 14 14 27.jpg
similarity index 100%
rename from docs/Photo 14.11.11 14 14 27.jpg
rename to docs/notes/Photo 14.11.11 14 14 27.jpg
diff --git a/docs/Photo 18.11.11 13 29 58.jpg b/docs/notes/Photo 18.11.11 13 29 58.jpg
similarity index 100%
rename from docs/Photo 18.11.11 13 29 58.jpg
rename to docs/notes/Photo 18.11.11 13 29 58.jpg
diff --git a/docs/Photo 21.11.11 13 09 54.jpg b/docs/notes/Photo 21.11.11 13 09 54.jpg
similarity index 100%
rename from docs/Photo 21.11.11 13 09 54.jpg
rename to docs/notes/Photo 21.11.11 13 09 54.jpg
diff --git a/docs/Tafelbild-2011-07-25.JPG b/docs/notes/Tafelbild-2011-07-25.JPG
similarity index 100%
rename from docs/Tafelbild-2011-07-25.JPG
rename to docs/notes/Tafelbild-2011-07-25.JPG
diff --git a/docs/Tafelbild-2011-07-27-Ramin.jpeg b/docs/notes/Tafelbild-2011-07-27-Ramin.jpeg
similarity index 100%
rename from docs/Tafelbild-2011-07-27-Ramin.jpeg
rename to docs/notes/Tafelbild-2011-07-27-Ramin.jpeg
diff --git a/docs/Tafelbild-2011-07-27-Stefans-Impuls.jpeg b/docs/notes/Tafelbild-2011-07-27-Stefans-Impuls.jpeg
similarity index 100%
rename from docs/Tafelbild-2011-07-27-Stefans-Impuls.jpeg
rename to docs/notes/Tafelbild-2011-07-27-Stefans-Impuls.jpeg
diff --git a/docs/Tafelbild-2011-7-27-Hendrik.jpeg b/docs/notes/Tafelbild-2011-7-27-Hendrik.jpeg
similarity index 100%
rename from docs/Tafelbild-2011-7-27-Hendrik.jpeg
rename to docs/notes/Tafelbild-2011-7-27-Hendrik.jpeg
diff --git a/docs/Tech-ComponentNotify-1.pdf b/docs/notes/Tech-ComponentNotify-1.pdf
similarity index 100%
rename from docs/Tech-ComponentNotify-1.pdf
rename to docs/notes/Tech-ComponentNotify-1.pdf
diff --git a/docs/skizze-hendrik.pdf b/docs/notes/skizze-hendrik.pdf
similarity index 100%
rename from docs/skizze-hendrik.pdf
rename to docs/notes/skizze-hendrik.pdf
diff --git a/ipaacalib/cpp/CMakeLists.txt b/ipaacalib/cpp/CMakeLists.txt
index 037c76e684e20cbdc2b4f682aaf054f61a52dd11..688725b7a861ba801a9b2fd3b1f73c67f78b87cb 100644
--- a/ipaacalib/cpp/CMakeLists.txt
+++ b/ipaacalib/cpp/CMakeLists.txt
@@ -3,63 +3,127 @@ cmake_minimum_required (VERSION 2.6)
 # project name
 project (ipaaca_cpp)
 
+# use C++11 (starting with proto v2 / ipaaca-c++ release 12)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
 ## use the following line to enable console debug messages in ipaaca
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_DEBUG_MESSAGES")
 
 # expose the full RSB api in the headers (set only in ipaaca itself)
+#  !! NOTE: at the moment required in any ipaaca cpp project in Windows !!
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_EXPOSE_FULL_RSB_API")
 
 # find cmake modules locally too
-set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
-
-find_package(Boost COMPONENTS system filesystem thread regex REQUIRED)
-link_directories(${Boost_LIBRARY_DIRS})
-include_directories(${Boost_INCLUDE_DIRS})
-#set(BOOSTLIBS boost_regex-mt boost_date_time-mt boost_program_options-mt boost_thread-mt boost_filesystem-mt boost_signals-mt boost_system-mt)
-
-find_package(Protobuf REQUIRED)
-link_directories(${PROTOBUF_LIBRARY_DIRS})
-include_directories(${PROTOBUF_INCLUDE_DIRS})
+set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules )
+
+if(WIN32) # Check if we are on Windows
+	if(MSVC) # Check if we are using the Visual Studio compiler
+		#set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
+		#
+		#   Setup section for Windows build (using precompiled rsb + deps)
+		#
+		#   You need the rsx precompiled archive, even if you build rsb yourself,
+		#   for the dependencies. Make sure to grab the right version (bitness
+		#   and Visual Studio version). Tested with the rsx-0.10 branch.
+		#   Please unpack the rsx archive into the repo dir (where ipaaca also is).
+		#   Then set these environment variables before building rsb or ipaaca:
+		#
+		#   set BOOST_ROOT=%SOA_REPO_DIR%\rsx\boost
+		#   set PROTOBUF_ROOT=%SOA_REPO_DIR%\rsx\protobuf
+		#   set SPREAD_ROOT=%SOA_REPO_DIR%\rsx\spread
+		#
+		#
+		
+		#
+		#  If you want to compile rsb locally, check out the soa project 'rsb', build it
+		#  and use resolve.sh to pull its libraries into this project.
+		#  On the other hand, if you simply want to use the precompiled rsb from inside
+		#  "rsx" (it works but has no debug info), uncomment the following four lines.
+		#
+		include_directories( ${PROJECT_SOURCE_DIR}/../../../rsx/RSC-0.11.0-win32/include/rsc0.11 )
+		include_directories( ${PROJECT_SOURCE_DIR}/../../../rsx/RSB-0.11.2-win32/include/rsb0.11 )
+		link_directories( ${PROJECT_SOURCE_DIR}/../../../rsx/RSC-0.11.0-win32/lib )
+		link_directories( ${PROJECT_SOURCE_DIR}/../../../rsx/RSB-0.11.2-win32/lib )
+		
+		set(RSBLIBS rsc0.11 rsb0.11)
+		set(LIBS ${LIBS} rpcrt4)
+		
+		# Using custom Protobuf script (from rsc) because it honors PROTOBUF_ROOT
+		find_package(ProtocolBuffers REQUIRED)
+		link_directories(${PROTOBUF_LIBRARY_DIRS})
+		include_directories(${PROTOBUF_INCLUDE_DIRS})
+		
+		find_package(Boost COMPONENTS date_time program_options system filesystem thread signals regex REQUIRED)
+		link_directories(${Boost_LIBRARY_DIRS})
+		include_directories(${Boost_INCLUDE_DIRS})
+		
+		# Windows linkage hack: overriding the determined libs to remove boost_thread (causes multiple-definition issues)
+		set(CORRECT_BOOST_LIBS "")
+		foreach(BLIB ${Boost_LIBRARIES})
+			#message(STATUS "Boost lib: ${BLIB}")
+			string(REGEX MATCH "boost_thread[^/]+$" drop_item ${BLIB})
+			if(drop_item)
+				message(STATUS "(Windows hack:) Removing boost_thread library from the linkage list.")
+			else(drop_item)
+				list(APPEND CORRECT_BOOST_LIBS ${BLIB})
+			endif(drop_item)
+		endforeach(BLIB ${Boost_LIBRARIES})
+		set(Boost_LIBRARIES ${CORRECT_BOOST_LIBS})
+		
+	else()
+		message(SEND_ERROR "Unsupported compiler! Please build with MSVC (2010).")
+	endif()
+else()
+	#
+	#
+	# Setup section for Linux or OS X (using 'rsb' soa project)
+	#
+	#
+	find_package(Boost COMPONENTS system filesystem thread regex signals REQUIRED)
+	link_directories(${Boost_LIBRARY_DIRS})
+	include_directories(${Boost_INCLUDE_DIRS})
+	#set(BOOSTLIBS boost_regex-mt boost_date_time-mt boost_program_options-mt boost_thread-mt boost_filesystem-mt boost_signals-mt boost_system-mt)
+
+	find_package(ProtocolBuffers REQUIRED)
+	link_directories(${PROTOBUF_LIBRARY_DIRS})
+	include_directories(${PROTOBUF_INCLUDE_DIRS})
+
+	# change for each new rsb version
+	if (DEFINED APPLE)
+		set(RSBLIBS rsc0.11 rsb0.11)
+		#set(RSBLIBS rsc0.10 rsb.0.10)
+	else(DEFINED APPLE)
+		set(RSBLIBS ${PROJECT_SOURCE_DIR}/../../deps/lib/librsc0.11.so ${PROJECT_SOURCE_DIR}/../../deps/lib/librsb0.11.so )
+		set(LIBS ${LIBS} uuid)
+	endif(DEFINED APPLE)
+	# enhance the default search paths (headers, libs ...)
+	set(CMAKE_PREFIX_PATH ${PROJECT_SOURCE_DIR}:/opt/local:${CMAKE_PREFIX_PATH})
+	# MacPorts compatibility
+	if (DEFINED APPLE)
+		message(STATUS "Adding extra options for building on Mac OS X")
+		set(CXX_DEFINES "${CXX_DEFINES} -D__MACOSX__")
+		link_directories( /opt/local/lib )
+		include_directories( /opt/local/include )
+	endif(DEFINED APPLE)
+endif(WIN32)
 
-##set(PROTOLIBS protobuf)
-#set(RSBLIBS rsc rsbcore)
 
-# add for for each new rsb version
-include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsc0.9 )
-include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsb0.9 )
-# change for each new rsb version
-if (DEFINED APPLE)
-set(RSBLIBS rsc0.9 rsb.0.9)
-else(DEFINED APPLE)
-set(RSBLIBS ${PROJECT_SOURCE_DIR}/../../deps/lib/librsc0.9.so ${PROJECT_SOURCE_DIR}/../../deps/lib/librsb.so.0.9 )
-endif(DEFINED APPLE)
-
-#set(LIBS ${LIBS} ${BOOSTLIBS} ${PROTOLIBS} ${RSBLIBS})
-#set(LIBS ${LIBS} ${PROTOLIBS} ${RSBLIBS})
 set(LIBS ${LIBS} ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${RSBLIBS})
 
-if (NOT DEFINED APPLE)
-	set(LIBS ${LIBS} uuid)
-endif(NOT DEFINED APPLE)
-
-# enhance the default search paths (headers, libs ...)
-set(CMAKE_PREFIX_PATH ${PROJECT_SOURCE_DIR}:/opt/local:${CMAKE_PREFIX_PATH})
-
-## Ace2 uses deprecated style (non-template friend functions and non-const char*s)
-##  We just hide the warnings here
-#set(CXX_OLD_CODE_CONVENIENCE_FLAGS "-Wno-non-template-friend -Wno-write-strings")
+# Hide the rsb-induced boost-signals warning (FOR NOW)
+set(IPAACA_CXX_DEFINES "${IPAACA_CXX_DEFINES} -DBOOST_SIGNALS_NO_DEPRECATION_WARNING")
 
 # Compiler defines copied from the old build system
-set(CXX_DEFINES "-D_BSD_SOURCE -DUSE_AV -DMGC_USE_DOUBLE -DLEDA_PREFIX -D__NO_CAST_TO_LOCAL_TYPE__ -DDBGLVL=0")
-if (DEFINED APPLE)
-	message(STATUS "Adding extra options for building on Mac OS X")
-	set(CXX_DEFINES "${CXX_DEFINES} -D__MACOSX__")
-	link_directories( /opt/local/lib )
-	include_directories( /opt/local/include )
-endif(DEFINED APPLE)
+set(IPAACA_CXX_DEFINES "${IPAACA_CXX_DEFINES} -D_BSD_SOURCE -DUSE_AV -DMGC_USE_DOUBLE -DLEDA_PREFIX -D__NO_CAST_TO_LOCAL_TYPE__ -DDBGLVL=0")
 
 # Combine the extra compiler flags
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_OLD_CODE_CONVENIENCE_FLAGS} ${CXX_DEFINES}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_OLD_CODE_CONVENIENCE_FLAGS} ${IPAACA_CXX_DEFINES}")
+
+# add for for each new rsb version
+include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsc0.11 )
+include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsb0.11 )
+#include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsc0.10 )
+#include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsb0.10 )
 
 # add include dir for auto-generated headers placed in build/
 include_directories( ${PROJECT_SOURCE_DIR}/build )
@@ -74,17 +138,47 @@ link_directories( ${PROJECT_SOURCE_DIR}/../../deps/lib )
 # specify source files for ipaaca (auto-generated ones are in build/ )
 set (SOURCE
 	src/ipaaca.cc
+	src/ipaaca-buffers.cc
+	src/ipaaca-internal.cc
+	src/ipaaca-iuinterface.cc
+	src/ipaaca-ius.cc
+	src/ipaaca-links.cc
+	src/ipaaca-locking.cc
+	src/ipaaca-payload.cc
 	src/ipaaca-cmdline-parser.cc
 	src/ipaaca-string-utils.cc
 	src/util/notifier.cc
 	build/ipaaca/ipaaca.pb.cc
 	)
 
+set (JSON_TEST_SOURCE
+	src/ipaaca.cc
+	src/ipaaca-buffers.cc
+	src/ipaaca-fake.cc
+	src/ipaaca-internal.cc
+	src/ipaaca-iuinterface.cc
+	src/ipaaca-json.cc    # main
+	src/ipaaca-locking.cc
+	src/ipaaca-links.cc
+	src/ipaaca-payload.cc
+	src/ipaaca-cmdline-parser.cc
+	src/ipaaca-string-utils.cc
+	# more stuff going beyond the fake test case
+	src/ipaaca-ius.cc
+	build/ipaaca/ipaaca.pb.cc
+	)
+
+
+
+
 # compile all files to "ipaaca" shared library
 add_library(ipaaca SHARED ${SOURCE})
 # and link all the required external libs (found above using find_package etc.)
 target_link_libraries(ipaaca ${LIBS})
 
+add_executable (ipaaca-test-json ${JSON_TEST_SOURCE})
+target_link_libraries (ipaaca-test-json ${LIBS})
+
 set(DEFAULT_BIN_SUBDIR bin)
 set(DEFAULT_LIB_SUBDIR lib)
 set(DEFAULT_DATA_SUBDIR share/data)
@@ -98,12 +192,19 @@ install (
 	)
 install(
 	DIRECTORY include
-	DESTINATION /
+	DESTINATION .
 	FILES_MATCHING PATTERN "*.h" PATTERN "*.hh" PATTERN "*.hpp" PATTERN "*.inl"
 	)
 install(
 	FILES build/ipaaca/ipaaca.pb.h
-	DESTINATION /include/ipaaca/
+	DESTINATION include/ipaaca/
+	)
+
+install (
+	TARGETS ipaaca-test-json
+	RUNTIME DESTINATION bin
+	LIBRARY DESTINATION lib
+	ARCHIVE DESTINATION lib
 	)
 
 
diff --git a/ipaacalib/cpp/CMakeModules/FindProtocolBuffers.cmake b/ipaacalib/cpp/CMakeModules/FindProtocolBuffers.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..997c78f4cb6d2d32f4cb1055b359f1d1e4d4ac52
--- /dev/null
+++ b/ipaacalib/cpp/CMakeModules/FindProtocolBuffers.cmake
@@ -0,0 +1,484 @@
+# Locate and configure the Google Protocol Buffers library.
+# A modified version of the original macro from CMake 2.8.
+# Defines the following variables:
+#
+#   PROTOBUF_FOUND - Found the Google Protocol Buffers library
+#   PROTOBUF_INCLUDE_DIRS - Include directories for Google Protocol Buffers
+#   PROTOBUF_LIBRARIES - The protobuf library
+#
+# The following cache variables are also defined:
+#   PROTOBUF_LIBRARY - The protobuf library
+#   PROTOBUF_PROTOC_LIBRARY   - The protoc library
+#   PROTOBUF_INCLUDE_DIR - The include directory for protocol buffers
+#   PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler
+#
+# These variables are read for additional hints:
+#   PROTOBUF_ROOT - Root directory of the protobuf installation if not found
+#                   automatically
+#
+#  ====================================================================
+#  Example:
+#
+#   find_package(ProtocolBuffers REQUIRED)
+#   include_directories(${PROTOBUF_INCLUDE_DIRS})
+#
+#   include_directories(${CMAKE_CURRENT_BINARY_DIR})
+#   PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto)
+#   add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
+#   target_link_libraries(bar ${PROTOBUF_LIBRARY})
+#
+# NOTE: You may need to link against pthreads, depending
+# on the platform.
+#  ====================================================================
+#
+# PROTOBUF_GENERATE_CPP ([CPP srcs hdrs] [JAVA files] [PYTHON files] PROTOFILES files... [PROTOROOT root] [OUTPATH path] [EXPORT_MACRO macroName] [DEBUG])
+#   srcs = Variable to define with autogenerated
+#          source files
+#   hdrs = Variable to define with autogenerated
+#          header files
+#   PROTOROOT = Root under which the proto files are located. Paths starting
+#               from this root are used under OUTPATH as directory structure
+#               for the generated files. Defaults to CMAKE_CURRENT_SOURCE_DIR.
+#   OUTPATH = Path to store generated files under. Default is
+#             CMAKE_CURRENT_BINARY_DIR.
+#   EXPORT_MACRO = Tells protoc to generate DLL export definitions using the
+#                  specified macro name
+#   DEBUG = if set, debug messages will be generated
+#
+#  ====================================================================
+
+
+#=============================================================================
+# Copyright 2009 Kitware, Inc.
+# Copyright 2009 Philip Lowman <philip@yhbt.com>
+# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+INCLUDE(ParseArguments)
+
+FUNCTION(PROTOBUF_GENERATE)
+
+    # argument parsing
+    PARSE_ARGUMENTS(ARG "PROTOROOT;PROTOFILES;OUTPATH;INCLUDES;EXPORT_MACRO;CPP;JAVA;PYTHON;MATLAB" "DEBUG" ${ARGN})
+
+    IF(NOT ARG_PROTOFILES)
+        MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() called without any proto files")
+        RETURN()
+    ENDIF(NOT ARG_PROTOFILES)
+    LIST(LENGTH ARG_PROTOROOT PROTOROOT_LENGTH)
+    #IF(PROTOROOT_LENGTH GREATER 1)
+    #    MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() called with too many protoroots, only one is allowed")
+    #    RETURN()
+    #ENDIF()
+    LIST(LENGTH ARG_OUTPATH OUTPATH_LENGTH)
+    IF(OUTPATH_LENGTH GREATER 1)
+        MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() called with too many outpaths, only one is allowed")
+        RETURN()
+    ENDIF()
+    LIST(LENGTH ARG_EXPORT_MACRO EXPORT_MACRO_LENGTH)
+    IF(EXPORT_MACRO_LENGTH GREATER 1)
+        MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() called with too many export macro names, only one is allowed")
+        RETURN()
+    ENDIF()
+    
+    # decide whether to build CPP
+    LIST(LENGTH ARG_CPP CPP_LENGTH)
+    IF(CPP_LENGTH EQUAL 0)
+        SET(BUILD_CPP FALSE)
+    ELSE()
+        IF(NOT CPP_LENGTH EQUAL 2)
+            MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() CPP argument expects two parameters SRC_VAR and HDR_VAR")
+            RETURN()
+        ENDIF()
+        SET(BUILD_CPP TRUE)
+        LIST(GET ARG_CPP 0 RESULT_CPP_SRCS)
+        LIST(GET ARG_CPP 1 RESULT_CPP_HDRS)
+    ENDIF()
+    
+    # decide whether to build java
+    LIST(LENGTH ARG_JAVA JAVA_LENGTH)
+    IF(JAVA_LENGTH EQUAL 0)
+        SET(BUILD_JAVA FALSE)
+    ELSE()
+        IF(NOT JAVA_LENGTH EQUAL 1)
+            MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() JAVA argument expects one parameter JAVA_VAR")
+            RETURN()
+        ENDIF()
+        SET(BUILD_JAVA TRUE)
+        LIST(GET ARG_JAVA 0 RESULT_JAVA)
+    ENDIF()
+    
+    # decide whether to build PYTHON
+    LIST(LENGTH ARG_PYTHON PYTHON_LENGTH)
+    IF(PYTHON_LENGTH EQUAL 0)
+        SET(BUILD_PYTHON FALSE)
+    ELSE()
+        IF(NOT PYTHON_LENGTH EQUAL 1)
+            MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() PYTHON argument expects one parameter PYTHON_VAR")
+            RETURN()
+        ENDIF()
+        SET(BUILD_PYTHON TRUE)
+        LIST(GET ARG_PYTHON 0 RESULT_PYTHON)
+    ENDIF()
+    
+    # decide whether to build MATLAB
+    LIST(LENGTH ARG_MATLAB MATLAB_LENGTH)
+    IF(MATLAB_LENGTH EQUAL 0)
+        SET(BUILD_MATLAB FALSE)
+    ELSE()
+        IF(NOT MATLAB_LENGTH EQUAL 1)
+            MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE() MATLAB argument expects one parameter MATLAB_VAR")
+            RETURN()
+        ENDIF()
+        SET(BUILD_MATLAB TRUE)
+        LIST(GET ARG_MATLAB 0 RESULT_MATLAB)
+    ENDIF()
+    
+    # create proper export macro for CPP if desired
+    IF(EXPORT_MACRO_LENGTH EQUAL 1)
+        SET(ARG_EXPORT "dllexport_decl=${ARG_EXPORT_MACRO}:")
+        MESSAGE(STATUS "Enabling export macro ${ARG_EXPORT_MACRO} for CPP")
+    ENDIF()
+    
+    SET(OUTPATH ${CMAKE_CURRENT_BINARY_DIR})
+    IF(OUTPATH_LENGTH EQUAL 1)
+        SET(OUTPATH ${ARG_OUTPATH})
+    ENDIF()
+    SET(PROTOROOTS ${CMAKE_CURRENT_SOURCE_DIR})
+    IF(PROTOROOT_LENGTH GREATER 0)
+        SET(PROTOROOTS ${ARG_PROTOROOT})
+    ENDIF()
+    
+    SET(ARG_EXPORT "")
+    IF(EXPORT_MACRO_LENGTH EQUAL 1)
+        SET(ARG_EXPORT "dllexport_decl=${ARG_EXPORT_MACRO}:")
+    ENDIF()
+    
+    # build command line for additional includes paths
+    SET(INCLUDE_CMD_LINE)
+    FOREACH(P ${ARG_INCLUDES})
+        LIST(APPEND INCLUDE_CMD_LINE "--proto_path" ${P})
+    ENDFOREACH()
+    
+    IF(ARG_DEBUG)
+        MESSAGE("OUTPATH: ${OUTPATH}")
+        MESSAGE("PROTOROOTS: ${PROTOROOTS}")
+        MESSAGE("INCLUDE_CMD_LINE: ${INCLUDE_CMD_LINE}")
+    ENDIF()
+
+    SET(MATCHED_FILE_PATHS)
+    FOREACH(PROTOFILE ${ARG_PROTOFILES})
+    
+        FILE(TO_CMAKE_PATH ${PROTOFILE} PROTOFILE)
+    
+        # ensure that the file ends with .proto
+        STRING(REGEX MATCH "\\.proto$$" PROTOEND ${PROTOFILE})
+        IF(NOT PROTOEND)
+            MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' does not end with .proto")
+        ENDIF()
+    
+        GET_FILENAME_COMPONENT(PROTO_PATH ${PROTOFILE} PATH)
+        GET_FILENAME_COMPONENT(ABS_FILE ${PROTOFILE} ABSOLUTE)
+        GET_FILENAME_COMPONENT(FILE_WE ${PROTOFILE} NAME_WE)
+        
+        STRING(LENGTH ${ABS_FILE} ABS_FILE_LENGTH)
+        
+        IF(ARG_DEBUG)
+            MESSAGE("file ${PROTOFILE}:")
+            MESSAGE("  PATH=${PROTO_PATH}")
+            MESSAGE("  ABS_FILE=${ABS_FILE}")
+            MESSAGE("  FILE_WE=${FILE_WE}")
+            MESSAGE("  PROTOROOTS=${PROTOROOTS}")
+        ENDIF()
+        
+        # find out if the file is in one of the specified proto root
+        # we mimic the protoc logic here by taking the first matching proto_path
+        SET(MATCH_PATH)
+        FOREACH(ROOT ${PROTOROOTS})
+        
+            IF(ARG_DEBUG)
+                MESSAGE("  ROOT=${ROOT}")
+            ENDIF()
+        
+            FILE(RELATIVE_PATH REL_ABS ${ROOT} ${ABS_FILE})
+            STRING(LENGTH ${REL_ABS} REL_LENGTH)
+            
+            IF(ARG_DEBUG)
+                MESSAGE("    REL_ABS=${REL_ABS}")
+                MESSAGE("    REL_LENGTH=${REL_LENGTH}")
+            ENDIF()
+            
+            IF(${REL_LENGTH} GREATER 0 AND ${REL_LENGTH} LESS ${ABS_FILE_LENGTH})
+                # we did not need to go directories up, hence the path is shorter
+                # and this is a match... bad assumption but works
+                SET(MATCH_PATH ${REL_ABS})
+                SET(MATCH_ROOT ${ROOT})
+                IF(ARG_DEBUG)
+                    MESSAGE("  MATCH_ROOT=${MATCH_ROOT}")
+                ENDIF()
+                BREAK()
+            ENDIF()
+            
+        ENDFOREACH()
+        
+        IF(ARG_DEBUG)
+            MESSAGE("  MATCH_PATH=${MATCH_PATH}")
+        ENDIF()
+        
+        IF(NOT MATCH_PATH)
+            MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' is not in protoroots '${PROTOROOTS}'")
+        ENDIF()
+        LIST(APPEND MATCHED_FILE_PATHS ${ABS_FILE})
+        
+        # build the result file name
+        FILE(RELATIVE_PATH ROOT_CLEANED_FILE ${MATCH_ROOT} ${ABS_FILE})
+        IF(ARG_DEBUG)
+            MESSAGE("  ROOT_CLEANED_FILE=${ROOT_CLEANED_FILE}")
+        ENDIF()
+        STRING(REGEX REPLACE "\\.proto$$" "" EXT_CLEANED_FILE ${ROOT_CLEANED_FILE})
+        IF(ARG_DEBUG)
+            MESSAGE("  EXT_CLEANED_FILE=${EXT_CLEANED_FILE}")
+        ENDIF()
+        
+        SET(CPP_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.cc")
+        SET(HDR_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.h")
+        SET(PYTHON_FILE "${OUTPATH}/${EXT_CLEANED_FILE}_pb2.py")
+        
+        # determine the java file name
+        FILE(READ ${PROTOFILE} PROTO_CONTENT)
+        
+        # first the package
+        # TODO jwienke: ignore comments... see below TODO
+        SET(PACKAGE_REGEX "package[\t ]+([^;\n\r]+);")
+        STRING(REGEX MATCH ${PACKAGE_REGEX} PACKAGE_LINE ${PROTO_CONTENT})
+        IF(ARG_DEBUG)
+            MESSAGE("  PACKAGE_LINE=${PACKAGE_LINE}")
+        ENDIF()
+        SET(PACKAGE "")
+        IF(PACKAGE_LINE)
+            STRING(REGEX REPLACE ${PACKAGE_REGEX} "\\1" PACKAGE ${PACKAGE_LINE})
+        ENDIF()
+        STRING(REPLACE "." "/" JAVA_PACKAGE_PATH "${PACKAGE}")
+        IF(ARG_DEBUG)
+            MESSAGE("  PACKAGE=${PACKAGE}")
+            MESSAGE("  JAVA_PACKAGE_PATH=${JAVA_PACKAGE_PATH}")
+        ENDIF()
+        
+        # then the java class name
+        
+        # this is the default
+        # TODO jwienke: how to integrate that this line must not start with //?
+        #               cmake regex are strange, because ^ and $ match beginning
+        #               and end of file and not of each line
+        SET(JAVA_CLASS_REGEX "option[\t ]+java_outer_classname[\t ]+=[\t ]+\"([^\"]+)\"")
+        STRING(REGEX MATCH ${JAVA_CLASS_REGEX} JAVA_CLASS_LINE ${PROTO_CONTENT})
+        IF(ARG_DEBUG)
+            MESSAGE("  JAVA_CLASS_LINE=${JAVA_CLASS_LINE}")
+        ENDIF()
+        SET(JAVA_CLASS ${FILE_WE})
+        IF(JAVA_CLASS_LINE)
+            STRING(REGEX REPLACE ${JAVA_CLASS_REGEX} "\\1" JAVA_CLASS ${JAVA_CLASS_LINE})
+            # Now that we have the real java class name, this must be replaced
+            # in the original file name proposal. However, the subpath in the
+            # file system is also part of EXT_CLEANED_FILE. Hence, we need to
+            # do some replace logic again...
+        ENDIF()
+        IF(ARG_DEBUG)
+            MESSAGE("  JAVA_CLASS=${JAVA_CLASS}")
+        ENDIF()
+        
+        # finally deduce the real java name
+        SET(JAVA_FILE "${OUTPATH}/${JAVA_PACKAGE_PATH}/${JAVA_CLASS}.java")
+
+        IF(ARG_DEBUG)
+            MESSAGE("  CPP_FILE=${CPP_FILE}")
+            MESSAGE("  HDR_FILE=${HDR_FILE}")
+            MESSAGE("  JAVA_FILE=${JAVA_FILE}")
+            MESSAGE("  PYTHON_FILE=${PYTHON_FILE}")
+        ENDIF()
+        
+        # generate and use a list of protoroot arguments to pass to protoc
+        SET(ROOT_ARGS)
+        FOREACH(ROOT ${PROTOROOTS})
+            LIST(APPEND ROOT_ARGS "--proto_path" ${ROOT})
+        ENDFOREACH()
+        
+        IF(BUILD_CPP)
+            LIST(APPEND CPP_SRCS "${CPP_FILE}")
+            LIST(APPEND CPP_HDRS "${HDR_FILE}")
+    
+            ADD_CUSTOM_COMMAND(
+                OUTPUT "${CPP_FILE}"
+                       "${HDR_FILE}"
+                COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
+                COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+                ARGS "--cpp_out=${ARG_EXPORT}${OUTPATH}" ${ROOT_ARGS} ${INCLUDE_CMD_LINE} "${ABS_FILE}"
+                DEPENDS ${ABS_FILE}
+                COMMENT "Running C++ protocol buffer compiler on ${ABS_FILE} with root ${MATCH_ROOT}, generating: ${CPP_FILE}"
+                VERBATIM)
+        ENDIF()
+        
+        IF(BUILD_JAVA)
+            LIST(APPEND JAVA_FILES "${JAVA_FILE}")
+    
+            ADD_CUSTOM_COMMAND(
+                OUTPUT "${JAVA_FILE}"
+                COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
+                COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+                ARGS "--java_out=${OUTPATH}" ${ROOT_ARGS} ${INCLUDE_CMD_LINE} "${ABS_FILE}"
+                DEPENDS ${ABS_FILE}
+                COMMENT "Running Java protocol buffer compiler on ${ABS_FILE} with root ${MATCH_ROOT}, generating: ${JAVA_FILE}"
+                VERBATIM)
+        ENDIF()
+        
+        IF(BUILD_PYTHON)
+            LIST(APPEND PYTHON_FILES "${PYTHON_FILE}")
+    
+            ADD_CUSTOM_COMMAND(
+                OUTPUT "${PYTHON_FILE}"
+                COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
+                COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+                ARGS "--python_out=${OUTPATH}" ${ROOT_ARGS} ${INCLUDE_CMD_LINE} "${ABS_FILE}"
+                DEPENDS ${ABS_FILE}
+                COMMENT "Running Python protocol buffer compiler on ${ABS_FILE} with root ${MATCH_ROOT}, generating: ${PYTHON_FILE}"
+                VERBATIM)
+        ENDIF()
+            
+    ENDFOREACH()
+
+    IF(BUILD_CPP)
+        SET_SOURCE_FILES_PROPERTIES(${${CPP_SRCS}} ${${CPP_HDRS}} PROPERTIES GENERATED TRUE)
+        SET(${RESULT_CPP_SRCS} ${CPP_SRCS} PARENT_SCOPE)
+        SET(${RESULT_CPP_HDRS} ${CPP_HDRS} PARENT_SCOPE)
+    ENDIF()
+
+    IF(BUILD_JAVA)
+        SET_SOURCE_FILES_PROPERTIES(${${JAVA_FILES}} PROPERTIES GENERATED TRUE)
+        SET(${RESULT_JAVA} ${JAVA_FILES} PARENT_SCOPE)
+    ENDIF()
+
+    IF(BUILD_PYTHON)
+        SET_SOURCE_FILES_PROPERTIES(${${PYTHON_FILES}} PROPERTIES GENERATED TRUE)
+        SET(${RESULT_PYTHON} ${PYTHON_FILES} PARENT_SCOPE)
+    ENDIF()
+    
+    IF(BUILD_MATLAB)
+        ADD_CUSTOM_COMMAND(
+            OUTPUT ${OUTPATH}
+            COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
+            COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+            ARGS "--matlab_out=${OUTPATH}" ${ROOT_ARGS} ${INCLUDE_CMD_LINE} ${MATCHED_FILE_PATHS}
+            DEPENDS ${MATCHED_FILE_PATHS}
+            COMMENT "Running Matlab protocol buffer compiler to generate files in ${OUTPATH}"
+            VERBATIM)
+    ENDIF()
+
+    IF(BUILD_MATLAB)
+        SET(${RESULT_MATLAB} ${OUTPATH} PARENT_SCOPE)
+    ENDIF()
+    
+ENDFUNCTION()
+
+MACRO(PROTOBUF_GENERATE_CPP SRCS HDRS)
+    PROTOBUF_GENERATE(${ARGN} CPP ${SRCS} ${HDRS})
+ENDMACRO()
+
+FIND_PATH(PROTOBUF_INCLUDE_DIR NAMES google/protobuf/service.h
+          HINTS "${PROTOBUF_ROOT}/include"
+          DOC "The Google Protocol Buffers Headers")
+
+# Google's provided vcproj files generate libraries with a "lib"
+# prefix on Windows
+IF(WIN32)
+    SET(PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
+    SET(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
+ENDIF()
+
+FIND_LIBRARY(PROTOBUF_LIBRARY NAMES protobuf
+             HINTS "${PROTOBUF_ROOT}/bin"
+                   "${PROTOBUF_ROOT}/lib"
+             DOC "The Google Protocol Buffers Library"
+)
+FIND_LIBRARY(PROTOBUF_PROTOC_LIBRARY NAMES protoc
+             HINTS "${PROTOBUF_ROOT}/bin"
+                   "${PROTOBUF_ROOT}/lib"
+             DOC "The Google Protocol Buffers Compiler Library"
+)
+FIND_PROGRAM(PROTOBUF_PROTOC_EXECUTABLE NAMES protoc
+             HINTS "${PROTOBUF_ROOT}/bin"
+             DOC "The Google Protocol Buffers Compiler"
+)
+IF(PROTOBUF_PROTOC_EXECUTABLE AND NOT PROTOBUF_PROTOC_MATLAB)
+    # check whether this protoc version supports matlab
+    EXECUTE_PROCESS(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} "-h"
+                    ERROR_VARIABLE PROTOC_HELP_TEXT
+                    OUTPUT_QUIET)
+    STRING(REGEX MATCH "--matlab_out" PROTOC_MATLAB_OUT "${PROTOC_HELP_TEXT}")
+    IF(PROTOC_MATLAB_OUT)
+        SET(PROTOBUF_PROTOC_MATLAB TRUE CACHE BOOL "Whether protoc is able to generate matlab output.")
+        MESSAGE(STATUS "protoc supports matlab")
+    ELSE()
+        SET(PROTOBUF_PROTOC_MATLAB FALSE CACHE BOOL "Whether protoc is able to generate matlab output.")
+        MESSAGE(STATUS "protoc does not support matlab")
+    ENDIF()
+ENDIF()
+SET(PROTOBUF_PROTOC_VERSION "PROTOBUF_PROTOC_VERSION-NOTFOUND")
+IF(PROTOBUF_PROTOC_EXECUTABLE)
+    EXECUTE_PROCESS(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --version
+                    OUTPUT_VARIABLE PROTOBUF_PROTOC_VERSION_TEMP
+                    RESULT_VARIABLE PROTOBUF_PROTOC_VERSION_RESULT)
+    STRING(REGEX REPLACE ".*([0-9]\\.[0-9]\\.[0-9]).*" "\\1"
+           PROTOBUF_PROTOC_VERSION_TEMP "${PROTOBUF_PROTOC_VERSION_TEMP}")
+    IF(PROTOBUF_PROTOC_VERSION_TEMP)
+        SET(PROTOBUF_PROTOC_VERSION "${PROTOBUF_PROTOC_VERSION_TEMP}")
+    ENDIF()
+ENDIF()
+
+SET(KNOWN_VERSIONS 2.6.0 2.5.1 2.5.0 2.4.1 2.4.0 2.3.0)
+# if we know the compiler version, we should favor it
+IF(PROTOBUF_PROTOC_VERSION)
+    LIST(INSERT KNOWN_VERSIONS 0 ${PROTOBUF_PROTOC_VERSION})
+ENDIF()
+SET(JAVA_NAMES ${PROTOBUF_JAVA_NAME} protobuf.jar protobuf-java.jar)
+FOREACH(VERSION ${KNOWN_VERSIONS})
+    LIST(APPEND JAVA_NAMES "protobuf-java-${VERSION}.jar")
+ENDFOREACH()
+
+FIND_FILE(PROTOBUF_JAVA_LIBRARY
+          NAMES ${JAVA_NAMES}
+          HINTS ${PROTOBUF_JAVA_ROOT}
+                "${PROTOBUF_JAVA_ROOT}/share/java"
+                "/usr/share/java"
+                "/usr/share/java/protobuf-java"
+                "/usr/share/protobuf/lib"
+                "${CMAKE_INSTALL_PREFIX}/lib/java"
+                "${CMAKE_INSTALL_PREFIX}/share/java")
+
+MARK_AS_ADVANCED(PROTOBUF_INCLUDE_DIR
+                 PROTOBUF_LIBRARY
+                 PROTOBUF_PROTOC_LIBRARY
+                 PROTOBUF_PROTOC_EXECUTABLE
+                 PROTOBUF_JAVA_LIBRARY
+                 PROTOBUF_PROTOC_MATLAB)
+
+# Restore original find library prefixes
+IF(WIN32)
+    SET(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}")
+ENDIF()
+
+INCLUDE(FindPackageHandleStandardArgs) 
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)
+
+IF(PROTOBUF_FOUND)
+    SET(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
+    SET(PROTOBUF_LIBRARIES    ${PROTOBUF_LIBRARY})
+ENDIF()
diff --git a/ipaacalib/cpp/CMakeModules/ParseArguments.cmake b/ipaacalib/cpp/CMakeModules/ParseArguments.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..e13f671a73c1aa4d686e79cafa3762a9219eadbd
--- /dev/null
+++ b/ipaacalib/cpp/CMakeModules/ParseArguments.cmake
@@ -0,0 +1,52 @@
+# Parse arguments passed to a function into several lists separated by
+# upper-case identifiers and options that do not have an associated list e.g.:
+#
+# SET(arguments
+#   hello OPTION3 world
+#   LIST3 foo bar
+#   OPTION2
+#   LIST1 fuz baz
+#   )
+# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments})
+#
+# results in 7 distinct variables:
+#  * ARG_DEFAULT_ARGS: hello;world
+#  * ARG_LIST1: fuz;baz
+#  * ARG_LIST2:
+#  * ARG_LIST3: foo;bar
+#  * ARG_OPTION1: FALSE
+#  * ARG_OPTION2: TRUE
+#  * ARG_OPTION3: TRUE
+#
+# taken from http://www.cmake.org/Wiki/CMakeMacroParseArguments 
+
+MACRO(PARSE_ARGUMENTS prefix arg_names option_names)
+    SET(DEFAULT_ARGS)
+    FOREACH(arg_name ${arg_names})    
+        SET(${prefix}_${arg_name})
+    ENDFOREACH(arg_name)
+    FOREACH(option ${option_names})
+        SET(${prefix}_${option} FALSE)
+    ENDFOREACH(option)
+    
+    SET(current_arg_name DEFAULT_ARGS)
+    SET(current_arg_list)
+    FOREACH(arg ${ARGN})            
+        SET(larg_names ${arg_names})    
+        LIST(FIND larg_names "${arg}" is_arg_name)                   
+        IF (is_arg_name GREATER -1)
+            SET(${prefix}_${current_arg_name} ${current_arg_list})
+            SET(current_arg_name ${arg})
+            SET(current_arg_list)
+        ELSE (is_arg_name GREATER -1)
+            SET(loption_names ${option_names})    
+            LIST(FIND loption_names "${arg}" is_option)            
+            IF (is_option GREATER -1)
+                SET(${prefix}_${arg} TRUE)
+            ELSE (is_option GREATER -1)
+                SET(current_arg_list ${current_arg_list} ${arg})
+            ENDIF (is_option GREATER -1)
+        ENDIF (is_arg_name GREATER -1)
+    ENDFOREACH(arg)
+    SET(${prefix}_${current_arg_name} ${current_arg_list})
+ENDMACRO(PARSE_ARGUMENTS)
diff --git a/ipaacalib/cpp/build.xml b/ipaacalib/cpp/build.xml
index f205ed3674f49dd18e475bf98c64235bd6ff622a..c8f0ffb7a86f9826e94336379e30563c4c073684 100644
--- a/ipaacalib/cpp/build.xml
+++ b/ipaacalib/cpp/build.xml
@@ -18,5 +18,21 @@
       </exec>
    </target>
    <target name="-pre-compilation" depends="-proto-yes,-proto-no" />
+   <target name="-compilation" depends="-build-setup, -pre-compilation">
+      <!-- echo message="Using temporary RSBProtocol_DIR=${cmake.base.dir}/rsc_tmp/share/rsbprotocol0.10" / -->
+      <cmake srcdir="${cmake.base.dir}"
+         bindir="${build.dir}"
+         buildtype="Debug">
+         <generator name="Visual Studio 10" platform="windows" buildargs="ALL_BUILD.vcxproj">
+             <variable name="CMAKE_INSTALL_PREFIX" type="PATH" value="../${zip.tmp.dir}" />
+         </generator>
+         <generator name="Unix Makefiles">
+             <variable name="CMAKE_INSTALL_PREFIX" type="PATH" value="" />
+         </generator>
+         <variable name="SPREAD_ROOT" type="FILEPATH" value="${env.SPREAD_ROOT}" />
+         <variable name="PROTOBUF_ROOT" type="FILEPATH" value="${env.PROTOBUF_ROOT}" />
+      </cmake>
+   </target>
+
 </project>
 
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0a26c13e7e668977d5e86daea651a3ac5ec54ff
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h
@@ -0,0 +1,415 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#ifndef __ipaaca_buffers_h_INCLUDED__
+#define __ipaaca_buffers_h_INCLUDED__
+
+#ifndef __ipaaca_h_INCLUDED__
+#error "Please do not include this file directly, use ipaaca.h instead"
+#endif
+
+
+/// Store for local IUs (used in OutputBuffer)
+IPAACA_HEADER_EXPORT class IUStore: public std::map<std::string, boost::shared_ptr<IU> >
+{
+};
+/// Store for RemotePushIUs (used in InputBuffer)
+IPAACA_HEADER_EXPORT class RemotePushIUStore: public std::map<std::string, boost::shared_ptr<RemotePushIU> > // TODO genericize to all remote IU types
+{
+};
+
+typedef std::set<std::string> LinkSet;
+typedef std::map<std::string, LinkSet> LinkMap;
+
+/// Container for IU links that gracefully returns the empty set if required
+IPAACA_HEADER_EXPORT class SmartLinkMap {//{{{
+	friend std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj);
+	friend class IUInterface;
+	friend class IU;
+	friend class IUConverter;
+	friend class MessageConverter;
+	public:
+		IPAACA_HEADER_EXPORT const LinkSet& get_links(const std::string& key);
+		IPAACA_HEADER_EXPORT const LinkMap& get_all_links();
+
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT LinkMap _links;
+		/// The empty link set is returned if undefined links are read for an IU.
+		IPAACA_MEMBER_VAR_EXPORT static LinkSet empty_link_set;
+		IPAACA_HEADER_EXPORT void _add_and_remove_links(const LinkMap& add, const LinkMap& remove);
+		IPAACA_HEADER_EXPORT void _replace_links(const LinkMap& links);
+};//}}}
+
+/// The empty link set is returned if undefined links are read for an IU.
+IPAACA_MEMBER_VAR_EXPORT const LinkSet EMPTY_LINK_SET;
+
+/// Configuration object that can be passed to Buffer constructors.
+IPAACA_HEADER_EXPORT class BufferConfiguration//{{{
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::string _basename;
+		IPAACA_MEMBER_VAR_EXPORT std::vector<std::string> _category_interests;
+		IPAACA_MEMBER_VAR_EXPORT std::string _channel;
+	public:
+		IPAACA_HEADER_EXPORT inline BufferConfiguration(const std::string& basename): _basename(basename), _channel(__ipaaca_static_option_default_channel) { }
+		IPAACA_HEADER_EXPORT inline const std::string& get_basename() const { return _basename; }
+		IPAACA_HEADER_EXPORT inline const std::vector<std::string>& get_category_interests() const { return _category_interests; }
+		IPAACA_HEADER_EXPORT inline const std::string& get_channel() const { return _channel; }
+	public:
+		// setters, initialization helpers
+		IPAACA_HEADER_EXPORT inline BufferConfiguration& set_basename(const std::string& basename) { _basename = basename; return *this; }
+		IPAACA_HEADER_EXPORT inline BufferConfiguration& add_category_interest(const std::string& category) { _category_interests.push_back(category); return *this; }
+		IPAACA_HEADER_EXPORT inline BufferConfiguration& set_channel(const std::string& channel) { _channel = channel; return *this; }
+};//}}}
+
+/// Builder object for BufferConfiguration, not required for C++ [DEPRECATED]
+IPAACA_HEADER_EXPORT class BufferConfigurationBuilder: private BufferConfiguration//{{{
+{
+	public:
+		[[deprecated("Use setters in BufferConfiguration instead of the Builder")]]
+		IPAACA_HEADER_EXPORT inline BufferConfigurationBuilder(const std::string& basename): BufferConfiguration(basename) {}
+		IPAACA_HEADER_EXPORT inline void set_basename(const std::string& basename)
+		{
+			_basename = basename;
+		}
+		IPAACA_HEADER_EXPORT inline void add_category_interest(const std::string& category)
+		{
+			_category_interests.push_back(category);
+		}
+		IPAACA_HEADER_EXPORT inline void set_channel(const std::string& channel)
+		{
+			_channel = channel;
+		}
+
+		IPAACA_HEADER_EXPORT const BufferConfiguration& get_buffer_configuration() { return *this; }
+
+};//}}}
+
+/** \brief Type of user-space functions that can be registered on a Buffer to receive IU events.
+ *
+ * The signature of these functions is void(shared_ptr<IUInterface> iu, IUEventType evt_type, bool local), where:<br/>
+ *     iu can be used mostly like a locally-generated IU reference (e.g. iu->payload() ...)<br/>
+ *     evt_type is one of IU_ADDED, IU_UPDATED, IU_RETRACTED, IU_DELETED, IU_LINKSUPDATED, IU_COMMITTED, IU_MESSAGE<br/>
+ *     local indicates that a remote change to a local IU (in an OutputBuffer) was effected
+ *
+ *
+ */
+IPAACA_HEADER_EXPORT typedef boost::function<void (boost::shared_ptr<IUInterface>, IUEventType, bool)> IUEventHandlerFunction;
+
+/** \brief Internal handler type used in Buffer (wraps used-specified IUEventHandlerFunction)
+ */
+IPAACA_HEADER_EXPORT class IUEventHandler {//{{{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT IUEventHandlerFunction _function;
+		IPAACA_MEMBER_VAR_EXPORT IUEventType _event_mask;
+		IPAACA_MEMBER_VAR_EXPORT bool _for_all_categories;
+		IPAACA_MEMBER_VAR_EXPORT std::set<std::string> _categories;
+	protected:
+		IPAACA_HEADER_EXPORT inline bool _condition_met(IUEventType event_type, const std::string& category)
+		{
+			return ((_event_mask&event_type)!=0) && (_for_all_categories || (_categories.count(category)>0));
+		}
+	public:
+		IPAACA_HEADER_EXPORT IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category);
+		IPAACA_HEADER_EXPORT IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
+		//void call(Buffer* buffer, const std::string& uid, bool local, IUEventType event_type, const std::string& category);
+		IPAACA_HEADER_EXPORT void call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
+	typedef boost::shared_ptr<IUEventHandler> ptr;
+};//}}}
+
+/**
+ * \brief Buffer base class. Derived classes use its handler registration functionality.
+ *
+ * \b Note: This class is never instantiated directly (use OutputBuffer and InputBuffer, respectively).
+ */
+IPAACA_HEADER_EXPORT class Buffer { //: public boost::enable_shared_from_this<Buffer> {//{{{
+	friend class IU;
+	friend class RemotePushIU;
+	friend class CallbackIUPayloadUpdate;
+	friend class CallbackIULinkUpdate;
+	friend class CallbackIUCommission;
+	friend class CallbackIUResendRequest;
+	protected:
+		//Lock _handler_lock;
+		IPAACA_MEMBER_VAR_EXPORT std::string _uuid;
+		IPAACA_MEMBER_VAR_EXPORT std::string _basename;
+		IPAACA_MEMBER_VAR_EXPORT std::string _unique_name;
+		IPAACA_MEMBER_VAR_EXPORT std::string _id_prefix;
+		IPAACA_MEMBER_VAR_EXPORT std::string _channel;
+		IPAACA_MEMBER_VAR_EXPORT std::vector<IUEventHandler::ptr> _event_handlers;
+	protected:
+		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _publish_iu_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name) = 0;
+
+
+		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;
+		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);
+		IPAACA_HEADER_EXPORT inline Buffer(const std::string& basename, const std::string& function) {
+			_allocate_unique_name(basename, function);
+			_channel = __ipaaca_static_option_default_channel;
+		}
+		IPAACA_HEADER_EXPORT void call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
+	public:
+		IPAACA_HEADER_EXPORT virtual inline ~Buffer() { }
+		IPAACA_HEADER_EXPORT inline const std::string& unique_name() { return _unique_name; }
+		/// This version of register_handler takes a set of several category interests instead of just one.
+		IPAACA_HEADER_EXPORT void register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
+		/** \brief Register a user-specified handler for IU events. Unless specified, it triggers for all event types for all category interests of the buffer.
+		 *
+		 * \param function A function [object] that can be converted to #IUEventHandlerFunction (examples below)
+		 * \param event_mask Which event types to relay to the user (default: all)
+		 * \param category The category to filter for (default: do not filter)
+		 *
+		 * \b Examples:
+		 *
+		 * Adding a plain function as a handler:<br/>
+		 *     <pre>
+		 *     void global_iu_handler(IUInterface::ptr iu, IUEventType type, bool local) { do_something(); }
+		 *     ...
+		 *     int main() {
+		 *         OutputBuffer::ptr outbuf = OutputBuffer::create("mybufname");
+		 *         outbuf->register_handler(global_iu_handler);
+		 *         ...
+		 *     }
+		 *     </pre>
+		 *
+		 * Adding a class member as a handler (using boost::bind):<br/>
+		 *     <pre>
+		 *     class MyClass {
+		 *         protected:
+		 *             void my_internal_iu_handler(IUInterface::ptr iu, #IUEventType type, bool local) { do_something(); }
+		 *             InputBuffer::ptr inbuf;
+		 *         public:
+		 *             MyClass() {
+		 *                 inbuf = InputBuffer::create("bufname", "categoryInterest");
+		 *                 inbuf->register_handler(boost::bind(&MyClass::my_internal_iu_handler, this, _1, _2, _3));
+		 *             }
+		 *     };
+		 *     </pre>
+		 *
+		 * Adding a lambda function as a handler (C++11):<br/>
+		 *     <pre>
+		 *     inbuf->register_handler([](IUInterface::ptr iu, #IUEventType event_type, bool local) {
+		 *         do_something();
+		 *     });
+		 *     </pre>
+		 *
+		 */
+		IPAACA_HEADER_EXPORT void register_handler(IUEventHandlerFunction function, IUEventType event_mask = IU_ALL_EVENTS, const std::string& category="");
+		//_IPAACA_ABSTRACT_ virtual void add(boost::shared_ptr<IUInterface> iu) = 0;
+		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual boost::shared_ptr<IUInterface> get(const std::string& iu_uid) = 0;
+		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual std::set<boost::shared_ptr<IUInterface> > get_ius() = 0;
+
+		IPAACA_HEADER_EXPORT inline const std::string& channel() { return _channel; }
+};
+//}}}
+
+/**
+ * \brief A buffer to which own IUs can be added to publish them
+ *
+ * Use OutputBuffer::create() to obtain a smart pointer to a new output buffer.
+ * 
+ * Use OutputBuffer::add() to add (= publish) an IU.
+ *
+ * Use OutputBuffer::remove() to remove (= retract) an IU.
+ *
+ * Use Buffer::register_handler() to register a handler that will respond to remote changes to own published IUs.
+ */
+IPAACA_HEADER_EXPORT class OutputBuffer: public Buffer { //, public boost::enable_shared_from_this<OutputBuffer>  {//{{{
+	friend class IU;
+	friend class RemotePushIU;
+	friend class OutputBufferRsbAdaptor;
+	protected:
+	protected:
+		//OutputBufferRsbAdaptor _rsb;
+		IPAACA_MEMBER_VAR_EXPORT IUStore _iu_store;
+		IPAACA_MEMBER_VAR_EXPORT Lock _iu_id_counter_lock;
+#ifdef IPAACA_EXPOSE_FULL_RSB_API
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rsb::Informer<rsb::AnyType>::Ptr> _informer_store;
+		IPAACA_MEMBER_VAR_EXPORT rsb::patterns::ServerPtr _server;
+		IPAACA_HEADER_EXPORT rsb::Informer<rsb::AnyType>::Ptr _get_informer(const std::string& category);
+#endif
+	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_OVERRIDE_;
+		IPAACA_HEADER_EXPORT void _publish_iu_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name) _IPAACA_OVERRIDE_;
+
+		IPAACA_HEADER_EXPORT 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") _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name) _IPAACA_OVERRIDE_;
+		//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)
+		// _remote_commit(protobuf::IUCommission)
+		IPAACA_HEADER_EXPORT void _publish_iu(boost::shared_ptr<IU> iu);
+
+		IPAACA_HEADER_EXPORT void _retract_iu(boost::shared_ptr<IU> iu);
+	protected:
+		/// \b Note: constructor is protected. Use create()
+		IPAACA_HEADER_EXPORT OutputBuffer(const std::string& basename, const std::string& channel=""); // empty string auto-replaced with __ipaaca_static_option_default_channel
+		IPAACA_HEADER_EXPORT void _initialize_server();
+	public:
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<OutputBuffer> create(const std::string& basename);
+		IPAACA_HEADER_EXPORT ~OutputBuffer() {
+			IPAACA_IMPLEMENT_ME
+		}
+		IPAACA_HEADER_EXPORT void add(boost::shared_ptr<IU> iu);
+		IPAACA_HEADER_EXPORT boost::shared_ptr<IU> remove(const std::string& iu_uid);
+		IPAACA_HEADER_EXPORT boost::shared_ptr<IU> remove(boost::shared_ptr<IU> iu);
+		IPAACA_HEADER_EXPORT boost::shared_ptr<IUInterface> get(const std::string& iu_uid) _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT std::set<boost::shared_ptr<IUInterface> > get_ius() _IPAACA_OVERRIDE_;
+	typedef boost::shared_ptr<OutputBuffer> ptr;
+};
+//}}}
+
+/**
+ * \brief A buffer in which remote IUs (and changes to them) are received.
+ *
+ * Use InputBuffer::create() to obtain a smart pointer to a new input buffer.
+ *
+ * Set category interests (IU filter) via the different versions of create().
+ *
+ * Use Buffer::register_handler() to register a handler that will respond to relevant remote IUs.
+ */
+IPAACA_HEADER_EXPORT class InputBuffer: public Buffer { //, public boost::enable_shared_from_this<InputBuffer>  {//{{{
+	friend class IU;
+	friend class RemotePushIU;
+	friend class InputBufferRsbAdaptor;
+		//InputBufferRsbAdaptor _rsb;
+#ifdef IPAACA_EXPOSE_FULL_RSB_API
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rsb::ListenerPtr> _listener_store;
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rsb::patterns::RemoteServerPtr> _remote_server_store;
+		IPAACA_MEMBER_VAR_EXPORT RemotePushIUStore _iu_store;  // TODO genericize
+		IPAACA_HEADER_EXPORT rsb::patterns::RemoteServerPtr _get_remote_server(const std::string& unique_server_name);
+		IPAACA_HEADER_EXPORT rsb::ListenerPtr _create_category_listener_if_needed(const std::string& category);
+		IPAACA_HEADER_EXPORT void _handle_iu_events(rsb::EventPtr event);
+		IPAACA_HEADER_EXPORT void _trigger_resend_request(rsb::EventPtr event);
+#endif
+	protected:
+		IPAACA_HEADER_EXPORT inline 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_OVERRIDE_
+		{
+			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_link_update() should never be invoked")
+		}
+		IPAACA_HEADER_EXPORT inline void _publish_iu_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name) _IPAACA_OVERRIDE_
+		{
+			IPAACA_WARNING("(ERROR) InputBuffer::_publish_iu_resend() should never be invoked")
+		}
+		IPAACA_HEADER_EXPORT inline 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") _IPAACA_OVERRIDE_
+		{
+			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_payload_update() should never be invoked")
+		}
+		IPAACA_HEADER_EXPORT inline void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") _IPAACA_OVERRIDE_
+		{
+			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_WARNING("(ERROR) InputBuffer::_send_iu_resendrequest() should never be invoked")
+		}*/
+	protected:
+		/// \b Note: all constructors are protected. Use create()
+		IPAACA_HEADER_EXPORT InputBuffer(const BufferConfiguration& bufferconfiguration);
+		IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::set<std::string>& category_interests);
+		IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::vector<std::string>& category_interests);
+		IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::string& category_interest1);
+		IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2);
+		IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3);
+		IPAACA_HEADER_EXPORT InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4);
+
+		IPAACA_MEMBER_VAR_EXPORT bool triggerResend;
+
+	public:
+		/// Specify whether old but previously unseen IUs should be requested to be sent to the buffer over a hidden channel.
+		IPAACA_HEADER_EXPORT void set_resend(bool resendActive);
+		IPAACA_HEADER_EXPORT bool get_resend();
+		/// Create InputBuffer according to configuration in BufferConfiguration object
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const BufferConfiguration& bufferconfiguration);
+		/// Create InputBuffer from name and set of category interests
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::set<std::string>& category_interests);
+		/// Create InputBuffer from name and vector of category interests
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::vector<std::string>& category_interests);
+		// /// Create InputBuffer from name and initializer_list of category interests
+		// IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::initializer_list<std::string>& category_interests);
+		/// Convenience function: create InputBuffer from name and one category interest
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1);
+		/// Convenience function: create InputBuffer from name and two category interests [DEPRECATED]
+		[[deprecated("Use create(string, set<string>) instead")]]
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2);
+		/// Convenience function: create InputBuffer from name and three category interests [DEPRECATED]
+		[[deprecated("Use create(string, set<string>) instead")]]
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3);
+		/// Convenience function: create InputBuffer from name and four category interests [DEPRECATED]
+		[[deprecated("Use create(string, set<string>) instead")]]
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4);
+		IPAACA_HEADER_EXPORT ~InputBuffer() {
+			IPAACA_IMPLEMENT_ME
+		}
+		IPAACA_HEADER_EXPORT boost::shared_ptr<IUInterface> get(const std::string& iu_uid) _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT std::set<boost::shared_ptr<IUInterface> > get_ius() _IPAACA_OVERRIDE_;
+	typedef boost::shared_ptr<InputBuffer> ptr;
+};
+//}}}
+
+/// Internal, transport-independent, representation of payload updates
+IPAACA_HEADER_EXPORT class IUPayloadUpdate {//{{{
+	public:
+		IPAACA_MEMBER_VAR_EXPORT std::string uid;
+		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, PayloadDocumentEntry::ptr> new_items;
+		IPAACA_MEMBER_VAR_EXPORT std::vector<std::string> keys_to_remove;
+		IPAACA_MEMBER_VAR_EXPORT std::string payload_type; // to handle legacy mode
+	friend std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj);
+	typedef boost::shared_ptr<IUPayloadUpdate> ptr;
+};//}}}
+
+/// Internal, transport-independent, representation of link updates
+IPAACA_HEADER_EXPORT class IULinkUpdate {//{{{
+	public:
+		IPAACA_MEMBER_VAR_EXPORT std::string uid;
+		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, std::set<std::string> > new_links;
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::set<std::string> > links_to_remove;
+	friend std::ostream& operator<<(std::ostream& os, const IULinkUpdate& obj);
+	typedef boost::shared_ptr<IULinkUpdate> ptr;
+};//}}}
+
+
+#endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h
new file mode 100644
index 0000000000000000000000000000000000000000..42e4f1024d5e37feba5b932bd4695f80185fc99a
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h
@@ -0,0 +1,413 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-definitions.h
+ *
+ * \brief Header file for data and exception types and helper functions.
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_definitions_h_INCLUDED__
+#define __ipaaca_definitions_h_INCLUDED__
+
+#ifndef __ipaaca_h_INCLUDED__
+#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;
+
+/// Type of the IU event. Realized as an integer to enable bit masks for filters. One of: IU_ADDED, IU_COMMITTED, IU_DELETED, IU_RETRACTED, IU_UPDATED, IU_LINKSUPDATED, IU_MESSAGE
+typedef uint32_t IUEventType;
+#define IU_ADDED         1
+#define IU_COMMITTED     2
+#define IU_DELETED       4
+#define IU_RETRACTED     8
+#define IU_UPDATED      16
+#define IU_LINKSUPDATED 32
+#define IU_MESSAGE      64
+/// Bit mask for receiving all IU events  \see IUEventType
+#define IU_ALL_EVENTS  127
+
+/// Ipaaca (console) log levels
+#define IPAACA_LOG_LEVEL_NONE     0
+#define IPAACA_LOG_LEVEL_CRITICAL 1
+#define IPAACA_LOG_LEVEL_ERROR    2
+#define IPAACA_LOG_LEVEL_WARNING  3
+#define IPAACA_LOG_LEVEL_INFO     4
+#define IPAACA_LOG_LEVEL_DEBUG    5
+
+/// Convert an int event type to a human-readable string
+IPAACA_HEADER_EXPORT inline std::string iu_event_type_to_str(IUEventType type)
+{
+	switch(type) {
+		case IU_ADDED: return "ADDED";
+		case IU_COMMITTED: return "COMMITTED";
+		case IU_DELETED: return "DELETED";
+		case IU_RETRACTED: return "RETRACTED";
+		case IU_UPDATED: return "UPDATED";
+		case IU_LINKSUPDATED: return "LINKSUPDATED";
+		case IU_MESSAGE: return "MESSAGE";
+		default: return "(NOT A KNOWN SINGLE IU EVENT TYPE)";
+	}
+}
+
+/// IU access mode: PUSH means that updates are broadcast; REMOTE means that reads are RPC calls (currently NOT implemented); MESSAGE means a fire-and-forget message
+IPAACA_HEADER_EXPORT enum IUAccessMode {
+	IU_ACCESS_PUSH,
+	IU_ACCESS_REMOTE,
+	IU_ACCESS_MESSAGE
+};
+
+/// generate a UUID as an ASCII string
+IPAACA_HEADER_EXPORT std::string generate_uuid_string();
+
+/**
+ * Exception with string description
+ */
+IPAACA_HEADER_EXPORT class Exception: public std::exception//{{{
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::string _description;
+	public:
+		IPAACA_HEADER_EXPORT inline Exception(const std::string& description=""): _description(description) { }
+		IPAACA_HEADER_EXPORT inline ~Exception() throw() { }
+		IPAACA_HEADER_EXPORT const char* what() const throw() {
+			return _description.c_str();
+		}
+};//}}}
+IPAACA_HEADER_EXPORT class Abort: public std::exception//{{{
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::string _description;
+	public:
+		IPAACA_HEADER_EXPORT inline Abort(const std::string& description=""): _description(description) { }
+		IPAACA_HEADER_EXPORT inline ~Abort() throw() { }
+		IPAACA_HEADER_EXPORT const char* what() const throw() {
+			return _description.c_str();
+		}
+};//}}}
+
+/// IU was not found in a buffer
+IPAACA_HEADER_EXPORT class IUNotFoundError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUNotFoundError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUNotFoundError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUNotFoundError";
+		}
+};//}}}
+/// IU was already published
+IPAACA_HEADER_EXPORT class IUPublishedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUPublishedError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUPublishedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUPublishedError";
+		}
+};//}}}
+/// IU had already been committed to
+IPAACA_HEADER_EXPORT class IUCommittedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUCommittedError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUCommittedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUCommittedError";
+		}
+};//}}}
+/// Remote IU update failed because it had been modified in the mean time
+IPAACA_HEADER_EXPORT class IUUpdateFailedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUUpdateFailedError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUUpdateFailedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUUpdateFailedError";
+		}
+};//}}}
+/// Requested resend of old IU due to malformed channel specification
+IPAACA_HEADER_EXPORT class IUResendRequestFailedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUResendRequestFailedError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUResendRequestFailedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUResendRequestFailedError";
+		}
+};//}}}
+/// Write operation failed because IU had been set read-only
+IPAACA_HEADER_EXPORT class IUReadOnlyError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUReadOnlyError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUReadOnlyError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUReadOnlyError";
+		}
+};//}}}
+/// Buffer::add() failed because the IU had been previously placed in another buffer
+IPAACA_HEADER_EXPORT class IUAlreadyInABufferError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUAlreadyInABufferError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUAlreadyInABufferError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUAlreadyInABufferError";
+		}
+};//}}}
+/// A request was made that is only valid for an already published IU
+IPAACA_HEADER_EXPORT class IUUnpublishedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUUnpublishedError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUUnpublishedError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUUnpublishedError";
+		}
+};//}}}
+/// IU had already been allocated a UID
+IPAACA_HEADER_EXPORT class IUAlreadyHasAnUIDError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnUIDError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUAlreadyHasAnUIDError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUAlreadyHasAnUIDError";
+		}
+};//}}}
+/// IU had already been allocated an owner name
+IPAACA_HEADER_EXPORT class IUAlreadyHasAnOwnerNameError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnOwnerNameError() throw() { }
+		IPAACA_HEADER_EXPORT inline IUAlreadyHasAnOwnerNameError() { //boost::shared_ptr<IU> iu) {
+			_description = "IUAlreadyHasAnOwnerNameError";
+		}
+};//}}}
+/// UID generation failed (Windows only)
+IPAACA_HEADER_EXPORT class UUIDGenerationError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~UUIDGenerationError() throw() { }
+		IPAACA_HEADER_EXPORT inline UUIDGenerationError() { //boost::shared_ptr<IU> iu) {
+			_description = "UUIDGenerationError";
+		}
+};//}}}
+/// Not implemented (e.g. invalid request parameters via backend)
+IPAACA_HEADER_EXPORT class NotImplementedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~NotImplementedError() throw() { }
+		IPAACA_HEADER_EXPORT inline NotImplementedError() { //boost::shared_ptr<IU> iu) {
+			_description = "NotImplementedError";
+		}
+};//}}}
+/// PayloadEntryProxy requested type conversion failed (including lenient interpretation)
+IPAACA_HEADER_EXPORT class PayloadTypeConversionError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~PayloadTypeConversionError() throw() { }
+		IPAACA_HEADER_EXPORT inline PayloadTypeConversionError() { //boost::shared_ptr<IU> iu) {
+			_description = "PayloadTypeConversionError";
+		}
+};//}}}
+/// PayloadEntryProxy was addressed as list when not a list or as map when not a map
+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";
+		}
+};//}}}
+/// Malformed json was received for a Payload
+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";
+		}
+};//}}}
+/// PayloadEntryProxy invalidated (unused)
+IPAACA_HEADER_EXPORT class PayloadEntryProxyInvalidatedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~PayloadEntryProxyInvalidatedError() throw() { }
+		IPAACA_HEADER_EXPORT inline PayloadEntryProxyInvalidatedError() { //boost::shared_ptr<IU> iu) {
+			_description = "PayloadEntryProxyInvalidatedError";
+		}
+};//}}}
+/// Iterator over Payload entries was invalidated by an intermediate IU update operation
+IPAACA_HEADER_EXPORT class PayloadIteratorInvalidError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~PayloadIteratorInvalidError() throw() { }
+		IPAACA_HEADER_EXPORT inline PayloadIteratorInvalidError() { //boost::shared_ptr<IU> iu) {
+			_description = "PayloadIteratorInvalidError";
+		}
+};//}}}
+
+/** \brief Static library initialization for backend
+ *
+ * This static class (singleton) is called once (explicitly or on-demand).
+ * Unless called manually, it is initialized when ipaaca is first used
+ * (i.e. the first Buffer is created).
+ */
+IPAACA_HEADER_EXPORT class Initializer
+{
+	public:
+		/// Initialize the backend [DEPRECATED] (old name, use initialize_backend() instead)
+		[[deprecated("Use initialize_backend() instead")]]
+		IPAACA_HEADER_EXPORT static void initialize_ipaaca_rsb_if_needed();
+		/// Explicitly initialize the backend. No effect if already initialized. Automatically called during first Buffer construction.
+		IPAACA_HEADER_EXPORT static void initialize_backend();
+		IPAACA_HEADER_EXPORT static bool initialized();
+		IPAACA_HEADER_EXPORT static void dump_current_default_config();
+	protected:
+		IPAACA_HEADER_EXPORT static void auto_configure_rsb();
+		IPAACA_MEMBER_VAR_EXPORT static bool _initialized;
+};
+
+// in ipaaca-cmdline-parser.cc
+// additional misc classes ( Command line options )//{{{
+/** \brief Command line argument container for CommandLineParser
+ *
+ * Contains the results of argument parsing from CommandLineParser::parse()
+ *
+ * The parser is preconfigured to handle some standard options:
+ *
+ * Option                          | Function
+ * --------------------------------|------------------------------------------------------------------------------
+ * --help                          | Print list of available options
+ * --verbose                       | Set verbose flag
+ * --character-name <name>         | Set character name (legacy)
+ * --component-name <name>         | Set component name (legacy)
+ * --ipaaca-payload-type <type>    | Set default ipaaca payload type (default JSON, set STR for legacy protocol)
+ * --ipaaca-default-channel <name> | Set default channel name (default 'default')
+ * --ipaaca-enable-logging <level> | Set console log level, one of NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL
+ * --rsb-enable-logging <level>    | Set rsb (transport) log level
+ *
+ */
+IPAACA_HEADER_EXPORT class CommandLineOptions {
+	public:
+		IPAACA_HEADER_EXPORT inline CommandLineOptions()
+		//: _unconsumed_argc(0), _unconsumed_argv(nullptr)
+		{ }
+		IPAACA_HEADER_EXPORT inline ~CommandLineOptions() {
+			//if (_unconsumed_argv) delete[] _unconsumed_argv;
+		}
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> param_opts;
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> param_set;
+	public:
+		IPAACA_HEADER_EXPORT void set_option(const std::string& name, bool expect, const char* optarg);
+		/// Get the option argument or default value (if the option expected an argument)
+		IPAACA_HEADER_EXPORT std::string get_param(const std::string& o);
+		/// Check whether option has been set
+		IPAACA_HEADER_EXPORT bool is_set(const std::string& o);
+		IPAACA_HEADER_EXPORT void dump();
+	public:
+		//IPAACA_HEADER_EXPORT inline int unconsumed_argc() { return _unconsumed_argc; }
+		//IPAACA_HEADER_EXPORT inline char** unconsumed_argv() { return _unconsumed_argv; }
+	protected:
+		//IPAACA_MEMBER_VAR_EXPORT int _unconsumed_argc;
+		//IPAACA_MEMBER_VAR_EXPORT char** _unconsumed_argv;
+	public:
+	typedef boost::shared_ptr<CommandLineOptions> ptr;
+};
+
+/**
+ * \brief Command line parser for ipaaca programs.
+ *
+ * The parser is preconfigured to handle some standard options:
+ *
+ * Option                          | Function
+ * --------------------------------|------------------------------------------------------------------------------
+ * --help                          | Print list of available options
+ * --verbose                       | Set verbose flag
+ * --character-name <name>         | Set character name (legacy)
+ * --component-name <name>         | Set component name (legacy)
+ * --ipaaca-payload-type <type>    | Set default ipaaca payload type (default JSON, set STR for legacy protocol)
+ * --ipaaca-default-channel <name> | Set default channel name (default 'default')
+ * --ipaaca-enable-logging <level> | Set console log level, one of NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL
+ * --rsb-enable-logging <level>    | Set rsb (transport) log level
+ *
+ */
+class CommandLineParser {
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::map<char, std::string> longopt; // letter->name
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, char> shortopt; // letter->name
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> options; //  name / expect_param
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> defaults; // for opt params
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, int> set_flag; // for paramless opts
+	protected:
+		IPAACA_HEADER_EXPORT CommandLineParser();
+		IPAACA_MEMBER_VAR_EXPORT bool library_options_handled;
+		IPAACA_HEADER_EXPORT bool consume_library_option(const std::string& name, bool expect, const char* optarg);
+		IPAACA_HEADER_EXPORT void ensure_defaults_in( CommandLineOptions::ptr clo );
+	public:
+		IPAACA_HEADER_EXPORT inline ~CommandLineParser() { }
+		/// Create a new parser object reference.
+		IPAACA_HEADER_EXPORT static inline boost::shared_ptr<CommandLineParser> create() {
+			return boost::shared_ptr<CommandLineParser>(new CommandLineParser());
+		}
+		IPAACA_HEADER_EXPORT void initialize_parser_defaults();
+		IPAACA_HEADER_EXPORT void dump_options();
+		/** \brief Add a user-defined option
+		 *
+		 * \param optname      The long option name, e.g. verbose for --verbose
+		 * \param shortn       The short option (or \0 for none)
+		 * \param expect_param Whether an argument is expected for the option
+		 * \param defaultv     The default string value (unused if expect_param is false)
+		 */
+		IPAACA_HEADER_EXPORT void add_option(const std::string& optname, char shortn, bool expect_param, const std::string& defaultv);
+		/** \brief Parse argument list and return result.
+		 *
+		 * Parse argument list (e.g. from main()) with the parser, consuming the internal options.
+		 * The remaining options are packaged into a CommandLineOptions object.
+		 */
+		IPAACA_HEADER_EXPORT CommandLineOptions::ptr parse(int argc, char* const* argv);
+	typedef boost::shared_ptr<CommandLineParser> ptr;
+};
+//}}}
+// in ipaaca-string-utils.cc
+// additional misc functions ( String splitting / joining )//{{{
+IPAACA_HEADER_EXPORT std::string str_trim(const std::string &s);
+IPAACA_HEADER_EXPORT std::string str_join(const std::set<std::string>& set,const std::string& sep);
+IPAACA_HEADER_EXPORT std::string str_join(const std::vector<std::string>& vec,const std::string& sep);
+IPAACA_HEADER_EXPORT void str_split_wipe(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
+IPAACA_HEADER_EXPORT void str_split_append(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
+//}}}
+
+#endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d91d66fcb604b9bea353a8af46ba55b8eec49a3
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-forwards.h
+ *
+ * \brief Header file for forward definitions.
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_forwards_h_INCLUDED__
+#define __ipaaca_forwards_h_INCLUDED__
+
+#ifndef __ipaaca_h_INCLUDED__
+#error "Please do not include this file directly, use ipaaca.h instead"
+#endif
+
+/*
+ *  forward declarations
+ */
+class PayloadDocumentEntry;
+//class PayloadDocumentStore;
+
+class PayloadBatchUpdateLock;
+class PayloadEntryProxy;
+class Payload;
+class PayloadIterator;
+class IUInterface;
+class IU;
+class Message;
+class RemotePushIU;
+class IULinkUpdate;
+class IUPayloadUpdate;
+class IUStore;
+class FrozenIUStore;
+class Buffer;
+class InputBuffer;
+class OutputBuffer;
+
+class CallbackIUPayloadUpdate;
+class CallbackIULinkUpdate;
+class CallbackIUCommission;
+class CallbackIUResendRequest;
+class CallbackIURetraction;
+
+class IUConverter;
+class MessageConverter;
+class IUPayloadUpdateConverter;
+class IULinkUpdateConverter;
+class IntConverter;
+
+class BufferConfiguration;
+class BufferConfigurationBuilder;
+
+#endif
+
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h b/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5609fde3d2a301c1c76fe9fe1067e74d4f05c4a
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h
@@ -0,0 +1,136 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-internal.h
+ *
+ * \brief Header file for internal transport implementation (RSB).
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \b Note: This file is only included during compilation of ipaaca,
+ * for regular use, the full internal API is not exposed.
+ * Users generally need never touch the internal transport layer.
+ *
+ * The file provides callback glue from RSB, and wire converters
+ * for the respective ipaaca classes.
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_internal_h_INCLUDED__
+#define __ipaaca_internal_h_INCLUDED__
+
+#ifndef __ipaaca_h_INCLUDED__
+#error "Please do not include this file directly, use ipaaca.h instead"
+#endif
+
+
+#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;
+	public:
+		IPAACA_HEADER_EXPORT CallbackIUPayloadUpdate(Buffer* buffer);
+		IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update);
+};//}}}
+IPAACA_HEADER_EXPORT class CallbackIULinkUpdate: public rsb::patterns::Server::Callback<IULinkUpdate, int> {//{{{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
+	public:
+		IPAACA_HEADER_EXPORT CallbackIULinkUpdate(Buffer* buffer);
+	public:
+		IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IULinkUpdate> update);
+};//}}}
+IPAACA_HEADER_EXPORT class CallbackIUCommission: public rsb::patterns::Server::Callback<protobuf::IUCommission, int> {//{{{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
+	public:
+		IPAACA_HEADER_EXPORT CallbackIUCommission(Buffer* buffer);
+	public:
+		IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IUCommission> update);
+};//}}}
+IPAACA_HEADER_EXPORT class CallbackIUResendRequest: public rsb::patterns::Server::Callback<protobuf::IUResendRequest, int> {//{{{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
+	public:
+		IPAACA_HEADER_EXPORT CallbackIUResendRequest(Buffer* buffer);
+	public:
+		IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IUResendRequest> update);
+};//}}}
+IPAACA_HEADER_EXPORT class CallbackIURetraction: public rsb::patterns::Server::Callback<protobuf::IURetraction, int> {//{{{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
+	public:
+		IPAACA_HEADER_EXPORT CallbackIURetraction(Buffer* buffer);
+	public:
+		IPAACA_HEADER_EXPORT boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IURetraction> update);
+};//}}}
+
+IPAACA_HEADER_EXPORT class IUConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IPAACA_HEADER_EXPORT IUConverter();
+		IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+IPAACA_HEADER_EXPORT class MessageConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IPAACA_HEADER_EXPORT MessageConverter();
+		IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+IPAACA_HEADER_EXPORT class IUPayloadUpdateConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IPAACA_HEADER_EXPORT IUPayloadUpdateConverter();
+		IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+IPAACA_HEADER_EXPORT class IULinkUpdateConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IPAACA_HEADER_EXPORT IULinkUpdateConverter();
+		IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+IPAACA_HEADER_EXPORT class IntConverter: public rsb::converter::Converter<std::string> {//{{{
+	public:
+		IPAACA_HEADER_EXPORT IntConverter();
+		IPAACA_HEADER_EXPORT std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
+		IPAACA_HEADER_EXPORT rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
+};//}}}
+#endif
+
+#endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4fc8fc6044e9c1cd70ca39250f98695a9a1c986
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h
@@ -0,0 +1,322 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-ius.h
+ *
+ * \brief Header file for IU (incremental unit) classes.
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_ius_h_INCLUDED__
+#define __ipaaca_ius_h_INCLUDED__
+
+#ifndef __ipaaca_h_INCLUDED__
+#error "Please do not include this file directly, use ipaaca.h instead"
+#endif
+
+
+/** \brief Abstract base class for all IU-type classes
+ *
+ * In user programs, classes IU or Message should be instantiated.
+ *
+ * This abstract type is used in handler callback functions and
+ * contains most generic user-space functions.
+ *
+ */
+IPAACA_HEADER_EXPORT class IUInterface {//{{{
+	friend class IUConverter;
+	friend class MessageConverter;
+	friend std::ostream& operator<<(std::ostream& os, const IUInterface& obj);
+	protected:
+		IPAACA_HEADER_EXPORT IUInterface();
+	public:
+		IPAACA_HEADER_EXPORT inline virtual ~IUInterface() { }
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT std::string _uid;
+		IPAACA_MEMBER_VAR_EXPORT revision_t _revision;
+		IPAACA_MEMBER_VAR_EXPORT std::string _category;
+		IPAACA_MEMBER_VAR_EXPORT std::string _payload_type; // default is taken from __ipaaca_static_option_default_payload_type
+		IPAACA_MEMBER_VAR_EXPORT std::string _owner_name;
+		IPAACA_MEMBER_VAR_EXPORT bool _committed;
+		IPAACA_MEMBER_VAR_EXPORT bool _retracted;
+		IPAACA_MEMBER_VAR_EXPORT IUAccessMode _access_mode;
+		IPAACA_MEMBER_VAR_EXPORT bool _read_only;
+		//boost::shared_ptr<Buffer> _buffer;
+		IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
+		IPAACA_MEMBER_VAR_EXPORT SmartLinkMap _links;
+	protected:
+		friend class Payload;
+		// 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, 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);
+		IPAACA_HEADER_EXPORT void _set_uid(const std::string& uid);
+		IPAACA_HEADER_EXPORT void _set_owner_name(const std::string& owner_name);
+	protected:
+		// internal functions that do not emit update events
+		IPAACA_HEADER_EXPORT void _add_and_remove_links(const LinkMap& add, const LinkMap& remove) { _links._add_and_remove_links(add, remove); }
+		IPAACA_HEADER_EXPORT void _replace_links(const LinkMap& links) { _links._replace_links(links); }
+	public:
+		/// Return whether IU has already been published (is in a Buffer).
+		IPAACA_HEADER_EXPORT inline bool is_published() { return (_buffer != 0); }
+		/// Return auto-generated UID string (set during IU construction)
+		IPAACA_HEADER_EXPORT inline const std::string& uid() const { return _uid; }
+		/// Return current IU revision number (incremented for each update)
+		IPAACA_HEADER_EXPORT inline revision_t revision() const { return _revision; }
+		/// Return the IU category string (set during IU construction)
+		IPAACA_HEADER_EXPORT inline const std::string& category() const { return _category; }
+		/// Return the channel name the IU is resident on (set on publication)
+		IPAACA_HEADER_EXPORT const std::string& channel();
+		/// Return the payload type (default "JSON")
+		IPAACA_HEADER_EXPORT inline const std::string& payload_type() const { return _payload_type; }
+		/// Return the owner name (unique fully-qualified buffer name, set on publication)
+		IPAACA_HEADER_EXPORT inline const std::string& owner_name() const { return _owner_name; }
+		/// Return whether IU has been committed to (i.e. is complete, confirmed, and henceforth constant)
+		IPAACA_HEADER_EXPORT inline bool committed() const { return _committed; }
+		/// Return the access mode (not relevant for the time being)
+		IPAACA_HEADER_EXPORT inline IUAccessMode access_mode() const { return _access_mode; }
+		/// Return whether IU is read only (committed, a Message, or explicitly set read-only by owner)
+		IPAACA_HEADER_EXPORT inline bool read_only() const { return _read_only; }
+		//inline boost::shared_ptr<Buffer> buffer() { return _buffer; }
+		/// Return owning buffer [CAVEAT: do not rely on this function for future code]
+		IPAACA_HEADER_EXPORT inline Buffer* buffer() const { return _buffer; }
+		/// Return the link set for an arbitrary link type (e.g. "grounded_in"), or EMPTY_LINK_SET
+		IPAACA_HEADER_EXPORT inline const LinkSet& get_links(std::string type) { return _links.get_links(type); }
+		/// Return the map of all defined links
+		IPAACA_HEADER_EXPORT inline const LinkMap& get_all_links() { return _links.get_all_links(); }
+		// Payload
+		/// Return the Payload object of this IU, overridden in the derived classes
+		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual Payload& payload() = 0;
+		/// Const version of payload()
+		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual const Payload& const_payload() const = 0;
+		// setters
+		/// Commit to an IU (only possible for the IU owner)
+		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);
+
+		/// Add a set of new UIDs for a specific link type
+		IPAACA_HEADER_EXPORT void add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
+		/// Remove a set of UIDs from a link type
+		IPAACA_HEADER_EXPORT void remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
+		/// Bulk link modification function
+		IPAACA_HEADER_EXPORT void modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name = "");
+		/// Bulk link override function
+		IPAACA_HEADER_EXPORT void set_links(const LinkMap& links, const std::string& writer_name = "");
+		//    (with cpp specific convenience functions:)
+		/// Convenience function (C++): add a single UID string to an arbitrary link set
+		IPAACA_HEADER_EXPORT void add_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
+		/// Convenience function (C++): remove a single UID string from an arbitrary link set (if contained)
+		IPAACA_HEADER_EXPORT void remove_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
+	typedef boost::shared_ptr<IUInterface> ptr;
+};//}}}
+
+/** \brief Class of locally-owned IU objects.
+ *
+ * Use IU::create() (static) to create references to new IUs.
+ * Use IU::payload() to access the IUs payload object.
+ * Use OutputBuffer::add() to publish IUs.
+ *
+ * See IUInterface for a generic description of most user-space member functions.
+ */
+IPAACA_HEADER_EXPORT class IU: public IUInterface {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class CallbackIUPayloadUpdate;
+	friend class CallbackIULinkUpdate;
+	friend class CallbackIUCommission;
+	friend class CallbackIUResendRequest;
+	public:
+		IPAACA_MEMBER_VAR_EXPORT Payload _payload;
+	protected:
+	   IPAACA_MEMBER_VAR_EXPORT  Lock _revision_lock;
+	protected:
+		IPAACA_HEADER_EXPORT inline void _increase_revision_number() { _revision++; }
+		IPAACA_HEADER_EXPORT IU(const std::string& category, IUAccessMode access_mode=IU_ACCESS_PUSH, bool read_only=false, const std::string& payload_type="" ); // __ipaaca_static_option_default_payload_type
+	public:
+		IPAACA_HEADER_EXPORT inline ~IU() {
+			//IPAACA_IMPLEMENT_ME
+		}
+		[[deprecated("Please use the new argument order: category, payload_type, read_only")]]
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<IU> create(const std::string& category, IUAccessMode access_mode, bool read_only=false, const std::string& payload_type="" );
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<IU> create(const std::string& category, const std::string& payload_type="", bool read_only=false);
+		IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; }
+		IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; }
+		IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_;
+	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_OVERRIDE_;
+
+		//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, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT virtual void _internal_commit(const std::string& writer_name = "");
+	public:
+	typedef boost::shared_ptr<IU> ptr;
+};//}}}
+/** \brief Class of locally-owned message objects ('one-shot' IUs).
+ *
+ * This class works the same as IU, except that it sets the internal
+ * flags so that it is received as a message (ephemeral object) on
+ * the remote sides, instead of a persistent objects.
+ *
+ * Likewise, it is not actually stored by OutputBuffer::add(), but just broadcast.
+ * 
+ * See IUInterface for a generic description of most user-space member functions.
+ *
+ * \see IU, IUInterface
+ */
+IPAACA_HEADER_EXPORT class Message: public IU {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class CallbackIUPayloadUpdate;
+	friend class CallbackIULinkUpdate;
+	friend class CallbackIUCommission;
+	friend class CallbackIUResendRequest;
+	protected:
+		IPAACA_HEADER_EXPORT Message(const std::string& category, IUAccessMode access_mode=IU_ACCESS_MESSAGE, bool read_only=true, const std::string& payload_type="" );
+	public:
+		IPAACA_HEADER_EXPORT inline ~Message() {
+			//IPAACA_IMPLEMENT_ME
+		}
+		[[deprecated("Please use the new argument order: category, payload_type")]]
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<Message> create(const std::string& category, IUAccessMode access_mode, bool read_only=true, const std::string& payload_type="" );
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<Message> create(const std::string& category, const std::string& payload_type="");
+	protected:
+		IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT 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 = "") _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT void _internal_commit(const std::string& writer_name = "");
+	public:
+	typedef boost::shared_ptr<Message> ptr;
+};//}}}
+
+/// Copy of a remote IU, received in an InputBuffer. Setter functions call RPC over the backend (RSB). \b Note: Typically handled only as reference in a handler in user space.
+IPAACA_HEADER_EXPORT class RemotePushIU: public IUInterface {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class IUConverter;
+	friend class MessageConverter;
+	public:
+		IPAACA_MEMBER_VAR_EXPORT Payload _payload;
+	protected:
+		IPAACA_HEADER_EXPORT RemotePushIU();
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<RemotePushIU> create();
+	public:
+		IPAACA_HEADER_EXPORT inline ~RemotePushIU() {
+			//IPAACA_IMPLEMENT_ME
+		}
+		IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; }
+		IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; }
+		IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT 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 = "") _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT void _apply_update(IUPayloadUpdate::ptr update);
+		IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update);
+		IPAACA_HEADER_EXPORT void _apply_commission();
+		IPAACA_HEADER_EXPORT void _apply_retraction();
+	typedef boost::shared_ptr<RemotePushIU> ptr;
+};//}}}
+/// Copy of a remote Message, received in an InputBuffer. Setter functions all fail.\b Note: Typically handled only as reference in a handler in user space.
+IPAACA_HEADER_EXPORT class RemoteMessage: public IUInterface {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class IUConverter;
+	friend class MessageConverter;
+	public:
+		IPAACA_MEMBER_VAR_EXPORT Payload _payload;
+	protected:
+		IPAACA_HEADER_EXPORT RemoteMessage();
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<RemoteMessage> create();
+	public:
+		IPAACA_HEADER_EXPORT inline ~RemoteMessage() {
+			//IPAACA_IMPLEMENT_ME
+		}
+		IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; }
+		IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; }
+		IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT 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 = "") _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT void _apply_update(IUPayloadUpdate::ptr update);
+		IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update);
+		IPAACA_HEADER_EXPORT void _apply_commission();
+		IPAACA_HEADER_EXPORT void _apply_retraction();
+	typedef boost::shared_ptr<RemoteMessage> ptr;
+};//}}}
+
+/// Mock IU for testing purposes. [INTERNAL]
+IPAACA_HEADER_EXPORT class FakeIU: public IUInterface {//{{{
+	friend class Buffer;
+	friend class InputBuffer;
+	friend class OutputBuffer;
+	friend class IUConverter;
+	friend class MessageConverter;
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Payload _payload;
+		IPAACA_HEADER_EXPORT FakeIU();
+	public:
+		IPAACA_HEADER_EXPORT static boost::shared_ptr<FakeIU> create();
+		IPAACA_HEADER_EXPORT ~FakeIU();
+		IPAACA_HEADER_EXPORT Payload& payload() _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT const Payload& const_payload() const _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT void add_fake_payload_item(const std::string& key, PayloadDocumentEntry::ptr entry);
+	protected:
+		IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
+		IPAACA_HEADER_EXPORT 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 = "") _IPAACA_OVERRIDE_;
+	protected:
+		IPAACA_HEADER_EXPORT void _apply_update(IUPayloadUpdate::ptr update);
+		IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update);
+		IPAACA_HEADER_EXPORT void _apply_commission();
+		IPAACA_HEADER_EXPORT void _apply_retraction();
+	public:
+	typedef boost::shared_ptr<FakeIU> ptr;
+};//}}}
+
+#endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-json.h b/ipaacalib/cpp/include/ipaaca/ipaaca-json.h
new file mode 100644
index 0000000000000000000000000000000000000000..30cac6c0594617ea28efd941bee08840b07eac93
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-json.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-json.h
+ *
+ * \brief Header file for JSON tests. [superfluous]
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_json_H__
+#define __ipaaca_json_H__
+
+#include "rapidjson/document.h"
+#include "rapidjson/prettywriter.h"
+#include "rapidjson/filestream.h"
+#include <cstdio>
+
+// Notes:
+//  - From http://stackoverflow.com/questions/10426924/json-root-element
+//    Actually there are two different JSON specifications. RFC 4627 requires a JSON text to be
+//    an object or an array. ECMA-262, 5th edition, section 15.12 does not impose this restriction.
+
+
+
+#endif // __IPAACA_JSON_H__
+
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-locking.h b/ipaacalib/cpp/include/ipaaca/ipaaca-locking.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4519ed77176466eab03f7a03ebebcf4c573fbe0
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-locking.h
@@ -0,0 +1,156 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-locking.h
+ *
+ * \brief Header file for locking / mutexes.
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_locking_h_INCLUDED__
+#define __ipaaca_locking_h_INCLUDED__
+
+#ifndef __ipaaca_h_INCLUDED__
+#error "Please do not include this file directly, use ipaaca.h instead"
+#endif
+
+
+/// Reentrant lock/mutex class
+#ifdef WIN32
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/thread.hpp>
+IPAACA_HEADER_EXPORT class Lock
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT boost::recursive_mutex _mutex;
+	public:
+		IPAACA_HEADER_EXPORT inline Lock() {
+		}
+		IPAACA_HEADER_EXPORT inline ~Lock() {
+		}
+		IPAACA_HEADER_EXPORT inline void lock() {
+			_mutex.lock();
+			on_lock();
+		}
+		IPAACA_HEADER_EXPORT inline void unlock() {
+			on_unlock();
+			_mutex.unlock();
+		}
+		IPAACA_HEADER_EXPORT virtual inline void on_lock() {
+		}
+		IPAACA_HEADER_EXPORT virtual inline void on_unlock() {
+		}
+};
+#else
+#include <pthread.h>
+IPAACA_HEADER_EXPORT class Lock
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT pthread_mutexattr_t _attrs;
+		IPAACA_MEMBER_VAR_EXPORT pthread_mutex_t _mutex;
+	public:
+		IPAACA_HEADER_EXPORT inline Lock() {
+			pthread_mutexattr_init(&_attrs);
+			pthread_mutexattr_settype(&_attrs, PTHREAD_MUTEX_RECURSIVE);
+			pthread_mutex_init(&_mutex, &_attrs);
+		}
+		IPAACA_HEADER_EXPORT inline ~Lock() {
+			pthread_mutex_destroy(&_mutex);
+			pthread_mutexattr_destroy(&_attrs);
+		}
+		IPAACA_HEADER_EXPORT inline void lock() {
+			pthread_mutex_lock(&_mutex);
+			on_lock();
+		}
+		IPAACA_HEADER_EXPORT inline void unlock() {
+			on_unlock();
+			pthread_mutex_unlock(&_mutex);
+		}
+		IPAACA_HEADER_EXPORT virtual inline void on_lock() {
+		}
+		IPAACA_HEADER_EXPORT virtual inline void on_unlock() {
+		}
+};
+#endif
+
+/** \brief Stack-based lock holder.
+ *
+ * Stack-based lock holder. Create in a new stack frame
+ *  (i.e.  {}-block) and it will obtain the lock and
+ * auto-release in on exiting the stack frame.
+ */
+IPAACA_HEADER_EXPORT class Locker
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Lock* _lock;
+	private:
+		IPAACA_HEADER_EXPORT inline Locker(): _lock(NULL) { } // not available
+	public:
+		IPAACA_HEADER_EXPORT inline Locker(Lock& lock): _lock(&lock) {
+			_lock->lock();
+		}
+		IPAACA_HEADER_EXPORT inline ~Locker() {
+			_lock->unlock();
+		}
+};
+
+/** \brief Locker for existing pthread mutexes.
+ *
+ * Stack-based lock holder for existing pthread_mutex_t mutexes.
+ *
+ * \see Locker
+ */
+#ifndef WIN32
+IPAACA_HEADER_EXPORT class PthreadMutexLocker
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT pthread_mutex_t* _lock;
+	private:
+		IPAACA_HEADER_EXPORT inline PthreadMutexLocker(): _lock(NULL) { } // not available
+	public:
+		IPAACA_HEADER_EXPORT inline PthreadMutexLocker(pthread_mutex_t* lock): _lock(lock) {
+			if (!lock) throw Exception("PthreadMutexLocker got a NULL mutex!");
+			pthread_mutex_lock(_lock);
+		}
+		IPAACA_HEADER_EXPORT inline ~PthreadMutexLocker() {
+			pthread_mutex_unlock(_lock);
+		}
+};
+#endif
+
+#endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcf33e81d3d7ecebff94ff721e1e669b1ca0e17d
--- /dev/null
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
@@ -0,0 +1,621 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+/**
+ * \file   ipaaca-payload.h
+ *
+ * \brief Header file for IU payload functionality.
+ *
+ * Users should not include this file directly, but use ipaaca.h
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+#ifndef __ipaaca_payload_h_INCLUDED__
+#define __ipaaca_payload_h_INCLUDED__
+
+#include <typeinfo>
+
+#ifndef __ipaaca_h_INCLUDED__
+#error "Please do not include this file directly, use ipaaca.h instead"
+#endif
+
+// casting operators from Value&
+/// 'Smart' type conversions, allowing for some leeway type-wise (e.g. string "1.3" can be successfully cast to double or long). Used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT template<typename T> T json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<typename T> T json_value_cast(const rapidjson::Value* value) { if (!value) return T(); return json_value_cast<T>(*value); }
+IPAACA_HEADER_EXPORT template<> long json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> int json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> double json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> bool json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> std::string json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> std::vector<std::string> json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> std::list<std::string> json_value_cast(const rapidjson::Value&);
+IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> json_value_cast(const rapidjson::Value&);
+
+// helpers to set Value& from various standard types
+//IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, T t);
+/// Setter to store int into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, int);
+/// Setter to store int into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, long);
+/// Setter to store long into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, double);
+/// Setter to store double into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, bool);
+/// Setter to store bool into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::string&);
+/// Setter to store std::string into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const char*);
+// helpers to set Value& from several standard containers containing the above standard types
+/// Setter to store a vector of supported basic types into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::vector<T>& ts)
+{
+	valueobject.SetArray();
+	for (auto& val: ts) {
+		rapidjson::Value newv;
+		pack_into_json_value(newv, allocator, val);
+		valueobject.PushBack(newv, allocator);
+	}
+}
+/// Setter to store a list of supported basic types into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::list<T>& ts)
+{
+	valueobject.SetArray();
+	for (auto& val: ts) {
+		rapidjson::Value newv;
+		pack_into_json_value(newv, allocator, val);
+		valueobject.PushBack(newv, allocator);
+	}
+}
+/// Setter to store a map of string -> supported basic types into json value, used by PayloadEntryProxy.
+IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::map<std::string, T>& ts)
+{
+	valueobject.SetObject();
+	for (auto& val: ts) {
+		rapidjson::Value key;
+		key.SetString(val.first, allocator);
+		rapidjson::Value newv;
+		pack_into_json_value(newv, allocator, val.second);
+		valueobject.AddMember(key, newv, allocator);
+	}
+}
+/*IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::vector<std::string>&);
+IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::list<std::string>&);
+IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::map<std::string, std::string>&);
+*/
+
+// FIXME TODO locking / invalidating proxy on first write of a payload entry
+
+/// Single payload entry wrapping a rapidjson::Document with some conversion glue. Also handles copy-on-write Document cloning. <b>Internal type</b> - users generally do not see this.
+IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{
+{
+	friend std::ostream& operator<<(std::ostream& os, std::shared_ptr<PayloadDocumentEntry> entry);
+	public:
+		IPAACA_MEMBER_VAR_EXPORT ipaaca::Lock lock;
+		IPAACA_MEMBER_VAR_EXPORT bool modified;
+		//IPAACA_MEMBER_VAR_EXPORT std::string json_source;
+		IPAACA_MEMBER_VAR_EXPORT rapidjson::Document document;
+		IPAACA_HEADER_EXPORT inline PayloadDocumentEntry(): modified(false) { }
+		IPAACA_HEADER_EXPORT inline ~PayloadDocumentEntry() { }
+		//IPAACA_HEADER_EXPORT PayloadDocumentEntry(const std::string& source): modified(false), json_source(source), {};
+		IPAACA_HEADER_EXPORT std::string to_json_string_representation();
+		IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> from_json_string_representation(const std::string& input);
+		IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> from_unquoted_string_value(const std::string& input);
+		IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> create_null();
+		IPAACA_HEADER_EXPORT std::shared_ptr<PayloadDocumentEntry> clone();
+		IPAACA_HEADER_EXPORT rapidjson::Value& get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep);
+		//IPAACA_HEADER_EXPORT void update_json_source();
+	typedef std::shared_ptr<PayloadDocumentEntry> ptr;
+};
+//}}}
+
+typedef std::map<std::string, PayloadDocumentEntry::ptr> PayloadDocumentStore;
+
+
+#if 0
+/** \brief Lock to accumulate payload changes into one single update transaction
+ *
+ */
+IPAACA_HEADER_EXPORT class PayloadBatchUpdateLock: public ipaaca::Lock
+{
+	friend class Payload;
+	protected:
+		Payload* _payload;
+	public:
+		IPAACA_HEADER_EXPORT inline PayloadBatchUpdateLock(): Lock() { }
+		IPAACA_HEADER_EXPORT void on_lock() override;
+		IPAACA_HEADER_EXPORT void on_unlock() override;
+};
+#endif
+
+/** \brief Central class containing the user-set payload of any IUInterface class (IU, Message, RemotePushIU or RemoteMessage)
+ *
+ * Obtained by calling payload() on any IUInterface derived object. Created during IU creation.
+ */
+IPAACA_HEADER_EXPORT class Payload: public Lock //{{{
+{
+	friend std::ostream& operator<<(std::ostream& os, const Payload& obj);
+	friend class IUInterface;
+	friend class IU;
+	friend class Message;
+	friend class RemotePushIU;
+	friend class RemoteMessage;
+	friend class IUConverter;
+	friend class MessageConverter;
+	friend class CallbackIUPayloadUpdate;
+	friend class PayloadEntryProxy;
+	friend class PayloadIterator;
+	friend class FakeIU;
+	//friend class PayloadBatchUpdateLock;
+	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 PayloadDocumentStore _document_store;
+		IPAACA_MEMBER_VAR_EXPORT boost::weak_ptr<IUInterface> _iu;
+		//IPAACA_MEMBER_VAR_EXPORT PayloadBatchUpdateLock _batch_update_lock;
+		//
+		IPAACA_MEMBER_VAR_EXPORT Lock _payload_operation_mode_lock; //< enforcing atomicity wrt the bool flag below
+		//
+		IPAACA_MEMBER_VAR_EXPORT bool _update_on_every_change; //< true: batch update not active; false: collecting updates (payload locked)
+		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, PayloadDocumentEntry::ptr> _collected_modifications;
+		IPAACA_MEMBER_VAR_EXPORT std::vector<std::string> _collected_removals;
+		IPAACA_MEMBER_VAR_EXPORT std::string _batch_update_writer_name;
+	protected:
+		/// inherited from ipaaca::Lock, starting batch update collection mode
+		IPAACA_HEADER_EXPORT void on_lock() override;
+		/// inherited from ipaaca::Lock, finishing batch update collection mode
+		IPAACA_HEADER_EXPORT void on_unlock() override;
+	protected:
+		//IPAACA_HEADER_EXPORT ipaaca::Locker&& batch_update() { return std::move(ipaaca::Locker(*this); }
+		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, 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_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="");
+		IPAACA_HEADER_EXPORT void _internal_merge_and_remove(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="");
+	public:
+		IPAACA_HEADER_EXPORT inline Payload(): _batch_update_writer_name(""), _update_on_every_change(true) { }
+		IPAACA_HEADER_EXPORT inline const std::string& owner_name() { return _owner_name; }
+		// access
+		/// Obtain a payload item by name as a PayloadEntryProxy (returning null-type proxy if undefined)
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const std::string& key);
+		/// Legacy / convenience function: interpret the payload map as a map string->string (casting all entries to string)
+		IPAACA_HEADER_EXPORT operator std::map<std::string, std::string>();
+		/// remove a single payload entry
+		IPAACA_HEADER_EXPORT inline void remove(const std::string& k) { _internal_remove(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); }
+		// legacy / convenience setter
+		/// Legacy / convenience function: set the whole payload map from a map string->string (all JSON types are also set as string, no interpretation)
+		IPAACA_HEADER_EXPORT void set(const std::map<std::string, std::string>& all_elems);
+	protected:
+		/// set or overwrite a single payload entry with a PayloadDocumentEntry object (used by PayloadEntryProxy::operator=()).
+		IPAACA_HEADER_EXPORT inline void set(const std::string& k, PayloadDocumentEntry::ptr entry) { _internal_set(k, entry); }
+		IPAACA_HEADER_EXPORT PayloadDocumentEntry::ptr get_entry(const std::string& k); // json, changed str to proxy here, too
+	public:
+		[[deprecated("Use operator[] and operator std::string() instead")]]
+		/// Read a single entry as string [DEPRECATED] (use string conversion in PayloadEntryProxy instead)
+		IPAACA_HEADER_EXPORT std::string get(const std::string& k); // DEPRECATED
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT unsigned long internal_revision;
+		IPAACA_MEMBER_VAR_EXPORT inline void mark_revision_change() { internal_revision++; }
+		IPAACA_HEADER_EXPORT inline bool revision_changed(unsigned long reference_revision) { return internal_revision != reference_revision; }
+	public:
+		/// obtain a standard iterator marking the first entry in the payload
+		IPAACA_HEADER_EXPORT PayloadIterator begin();
+		/// obtain a standard iterator past the last entry in the payload
+		IPAACA_HEADER_EXPORT PayloadIterator end();
+	typedef boost::shared_ptr<Payload> ptr;
+};//}}}
+
+/** \brief Standard iterator for Payload (example below)
+ *
+ * \b Examples:
+ * <pre>
+ * // Print all key-value pairs from a payload (C++11)
+ * for (auto kv_pair: myiu->payload()) {
+ *     std::cout << kv_pair.first << " -> " << (std::string) kv_pair.second << std::endl;
+ * }
+ * </pre>
+ *
+ */
+IPAACA_HEADER_EXPORT class PayloadIterator//{{{
+{
+	friend class Payload;
+	friend std::ostream& operator<<(std::ostream& os, const PayloadIterator& iter);
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT Payload* _payload;
+		IPAACA_MEMBER_VAR_EXPORT unsigned long reference_payload_revision;
+		IPAACA_MEMBER_VAR_EXPORT PayloadDocumentStore::iterator raw_iterator;
+		//IPAACA_MEMBER_VAR_EXPORT bool is_end;
+	protected:
+		IPAACA_HEADER_EXPORT PayloadIterator(Payload* payload, PayloadDocumentStore::iterator&& pl_iter ); //, bool is_end);
+	public:
+		IPAACA_HEADER_EXPORT PayloadIterator(const PayloadIterator& iter);
+		IPAACA_HEADER_EXPORT PayloadIterator& operator++();
+		IPAACA_HEADER_EXPORT std::pair<std::string, PayloadEntryProxy> operator*();
+		IPAACA_HEADER_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > operator->();
+		IPAACA_HEADER_EXPORT bool operator==(const PayloadIterator& ref);
+		IPAACA_HEADER_EXPORT bool operator!=(const PayloadIterator& ref);
+		// constructor to create a new top-most parent proxy (from a payload key)
+};
+//}}}
+
+/// Iterator over a payload entry that is a json map-type object (returned type during dereferencing: pair<string, PayloadEntryProxy>)
+IPAACA_HEADER_EXPORT class PayloadEntryProxyMapIterator//{{{
+{
+	public:
+		typedef rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::MemberIterator RawIterator;
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+		IPAACA_MEMBER_VAR_EXPORT RawIterator raw_iterator;
+	public:
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator(PayloadEntryProxy* proxy, RawIterator&& raw_iter);
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator& operator++();
+		IPAACA_HEADER_EXPORT std::pair<std::string, PayloadEntryProxy> operator*();
+		IPAACA_HEADER_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > operator->();
+		IPAACA_HEADER_EXPORT bool operator==(const PayloadEntryProxyMapIterator& other_iter);
+		IPAACA_HEADER_EXPORT bool operator!=(const PayloadEntryProxyMapIterator& other_iter);
+};
+//}}}
+/// Iterator over a payload entry that is a json list-type object (returned type during dereferencing: PayloadEntryProxy)
+IPAACA_HEADER_EXPORT class PayloadEntryProxyListIterator//{{{
+{
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+		IPAACA_MEMBER_VAR_EXPORT size_t current_idx;
+		IPAACA_MEMBER_VAR_EXPORT size_t size;
+	public:
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator(PayloadEntryProxy* proxy, size_t idx, size_t size);
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator& operator++();
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator*();
+		IPAACA_HEADER_EXPORT std::shared_ptr<PayloadEntryProxy> operator->();
+		IPAACA_HEADER_EXPORT bool operator==(const PayloadEntryProxyListIterator& other_iter);
+		IPAACA_HEADER_EXPORT bool operator!=(const PayloadEntryProxyListIterator& other_iter);
+};
+//}}}
+/// Interpretation of a variant json value as a map-type object
+IPAACA_HEADER_EXPORT class PayloadEntryProxyMapDecorator//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline PayloadEntryProxyMapDecorator(PayloadEntryProxy* proxy_): proxy(proxy_) { }
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator begin();
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator end();
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+};
+//}}}
+/// Interpretation of a variant json value as a list-type object
+IPAACA_HEADER_EXPORT class PayloadEntryProxyListDecorator//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline PayloadEntryProxyListDecorator(PayloadEntryProxy* proxy_): proxy(proxy_) { }
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator begin();
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator end();
+	protected:
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
+};
+//}}}
+
+/** \brief Reference to an existent or nonexistent payload entry (or a value deeper in the json tree)
+ *
+ * This class is returned by IUInterface::operator[].
+ * The proxy handles automatic type conversions, requests remote changes of payloads, and enables navigation into and iteration over structured json objects.
+ *
+ * \b Examples (reading):
+ *
+ * <code>std::string received_name = iu->payload()["name"];</code>  // implicit conversion using operator string()
+ *
+ * <code>std::vector<double> vd = iu->payload()["double_list"];</code>  // some standard container types also supported
+ * 
+ * <code>auto p = iu->payload()["otherKey"];</code>  // auto type is PayloadEntryProxy (conversion is on-demand)
+ *
+ * <code>for (auto val: iu->payload()["my_list"].as_list()) { ... }</code>  // as_list is required to select list-type iteration (value type in iteration remains variant)
+ *
+ * <code>for (auto k_v_map: iu->payload()["my_map"].as_map()) { ... }</code>  // as_map is required to select map-type iteration (value type in iteration is a pair, second part remains variant)
+ *
+ * \b Examples (writing):
+ * 
+ * <code>iu->payload()["my_new_item"] = "new value";</code>  // most basic operation, set string value
+ *
+ * <code>iu->payload()["double_list"][0] = 100.0;</code>  // accessing and updating an item in a list
+ *
+ * <code>iu->payload()["name_list"] = std::list<std::string>{"Alpha", "Bravo", "Charlie"};</code>  // set from basic uniform containers
+ *
+ * <code>iu->payload()["name_list"].push_back("--- adding some numbers below ---");</code>  // append a supported value to an existing list
+ *
+ * <code>iu->payload()["name_list"].extend(iu->payload()["double_list"]);</code>  // extend list by items; \b Note: all setters also accept proxies as source values, creating copies of values
+ */
+IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
+{
+	friend class Payload;
+	friend class PayloadIterator;
+	friend class PayloadDocumentEntry;
+	friend class PayloadEntryProxyListDecorator;
+	friend class PayloadEntryProxyListIterator;
+	friend class PayloadEntryProxyMapDecorator;
+	friend class PayloadEntryProxyMapIterator;
+	friend std::ostream& operator<<(std::ostream& os, const PayloadEntryProxy& proxy);
+	public:
+		/// Select map-style iteration for this proxy (to select iterator content type). Will throw if not actually map-type. See example in the class description.
+		IPAACA_HEADER_EXPORT PayloadEntryProxyMapDecorator as_map();
+		/// Select list-style iteration for this proxy (to select iterator content type). Will throw if not actually list-type. See example in the class description.
+		IPAACA_HEADER_EXPORT PayloadEntryProxyListDecorator as_list();
+	protected:
+		//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node;
+		//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
+		//
+		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* parent; ///< Parent proxy (up to document root -> then null)
+		IPAACA_MEMBER_VAR_EXPORT PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc
+		IPAACA_MEMBER_VAR_EXPORT bool existent; ///< Whether Value exists already (or else 'blindly' navigated)
+		IPAACA_MEMBER_VAR_EXPORT bool addressed_as_array; ///< Whether long or string navigation was used
+		IPAACA_MEMBER_VAR_EXPORT long addressed_index; ///< Index that was used in list-style access
+		IPAACA_MEMBER_VAR_EXPORT std::string addressed_key; ///< Key that was used in map-style access
+		/// currently navigated value in json tree (or a new Null value)
+		IPAACA_MEMBER_VAR_EXPORT rapidjson::Value* json_value; ///< json value that corresponds to the current navigation (or nullptr)
+/*	protected:
+		IPAACA_HEADER_EXPORT void connect_to_existing_parents();
+*/
+	protected:
+		// constructor to create a new top-most parent proxy (from a payload key)
+		IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key);
+		// constructors for navigation through objects
+		IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key);
+		IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, size_t addressed_index);
+	public:
+		/// Return number of contained items (or 0 for non-container types)
+		IPAACA_HEADER_EXPORT size_t size();
+		/// Return whether value corresponds to json 'null'; also true if value is nonexistent so far (e.g. navigated to new map entry)
+		IPAACA_HEADER_EXPORT bool is_null();
+		/// Return whether value is of string type
+		IPAACA_HEADER_EXPORT bool is_string();
+		/// Return whether value is of a numerical type
+		IPAACA_HEADER_EXPORT bool is_number();
+		/// Return whether value is of list type
+		IPAACA_HEADER_EXPORT bool is_list();
+		/// Return whether value is of map type
+		IPAACA_HEADER_EXPORT bool is_map();
+	public:
+		/// Array-style navigation over json value
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](size_t index); // array-style navigation
+		/// Array-style navigation over json value (added to catch [0])
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](int index); // int is UNFORTUNATELY required to catch
+																	  // [0] (addressing using literal zero)
+																	  // because ambiguity with const char*
+																	  // arises if only [](size_t) is provided.
+																	  // size_t is obviously superior ...
+																	  // TODO: remove if better solution known
+		/// Dict-style navigation over json value
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const std::string& key); // dict-style navigation
+		/// Dict-style navigation over json value
+		IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const char* key);
+		//
+		/// Set or overwrite some portion of a payload from the point navigated to
+		IPAACA_HEADER_EXPORT template<typename T> PayloadEntryProxy& operator=(T t)
+		{
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& newval = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			pack_into_json_value(newval, new_entry->document.GetAllocator(), t);
+			//new_entry->update_json_source();
+			_payload->set(_key, new_entry);
+			return *this;
+		}
+		/// Value comparison with other proxy contents
+		IPAACA_HEADER_EXPORT inline bool operator==(const PayloadEntryProxy& otherproxy) { return (json_value && otherproxy.json_value && ((*json_value)==*(otherproxy.json_value))); }
+		/// Value comparison with other proxy contents
+		IPAACA_HEADER_EXPORT inline bool operator!=(const PayloadEntryProxy& otherproxy) { return !operator==(otherproxy); }
+		/// Value comparison with supported basic types
+		IPAACA_HEADER_EXPORT template<typename T> bool operator==(T othervalue)
+		{
+			if (!json_value) return false;
+			try {
+				return json_value_cast<T>(*json_value) == othervalue;
+			} catch(PayloadTypeConversionError& ex) {
+				// assume conversion error = type mismatch = unequal
+				return false;
+			}
+		}
+		/// Value comparison with supported basic types
+		IPAACA_HEADER_EXPORT template<typename T> bool operator!=(T othervalue) { return !operator==(othervalue); }
+		/// Value comparison with char* (required to be explicitly added)
+		IPAACA_HEADER_EXPORT inline bool operator==(const char* othervalue)
+		{
+			if (!json_value) return false;
+			return json_value_cast<std::string>(*json_value) == othervalue;
+		}
+		/// Value comparison with char* (required to be explicitly added)
+		IPAACA_HEADER_EXPORT inline bool operator!=(const char* othervalue) { return !operator==(othervalue); }
+		
+		/// Copy value from below other json node, preserving types
+		IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const PayloadEntryProxy& otherproxy);
+		
+		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value);
+		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const char* value);
+		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(double value);
+		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(bool value);
+		
+		/// Conversion to std::string (explicit or implicit)
+		IPAACA_HEADER_EXPORT operator std::string();
+		/// Conversion to long (explicit or implicit)
+		IPAACA_HEADER_EXPORT operator long();
+		/// Conversion to double (explicit or implicit)
+		IPAACA_HEADER_EXPORT operator double();
+		/// Conversion to bool (explicit or implicit)
+		IPAACA_HEADER_EXPORT operator bool();
+		/// Conversion to uniform std::vector of supported basic type
+		IPAACA_HEADER_EXPORT template<typename Inner> operator std::vector<Inner>() {
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			std::vector<Inner> result;
+			for (auto it = json_value->Begin(); it != json_value->End(); ++it) {
+				result.push_back( json_value_cast<Inner>(*it) );
+			}
+			return result;
+		}
+		/// Conversion to uniform std::list of supported basic type
+		IPAACA_HEADER_EXPORT template<typename Inner> operator std::list<Inner>() {
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			std::list<Inner> result;
+			for (auto it = json_value->Begin(); it != json_value->End(); ++it) {
+				result.push_back( json_value_cast<Inner>(*it) );
+			}
+			return result;
+		}
+		/// Conversion to uniform std::map of string -> supported basic type
+		IPAACA_HEADER_EXPORT template<typename Inner> operator std::map<std::string, Inner>() {
+			if ((!json_value) || (!json_value->IsObject())) throw PayloadAddressingError();
+			std::map<std::string, Inner> result;
+			for (auto it = json_value->MemberBegin(); it != json_value->MemberEnd(); ++it) {
+				result[std::string(it->name.GetString())] = json_value_cast<Inner>(it->value);
+			}
+			return result;
+		}
+		// FIXME why are these needed again?
+		/// [DECPRECATED] use normal type conversion syntax instead
+		[[deprecated("Use operator std::string() instead (i.e. explicit or implicit cast)")]]
+		IPAACA_HEADER_EXPORT std::string to_str();
+		//long to_int() { return operator long(); ;
+		/// [DECPRECATED] use normal type conversion syntax instead
+		[[deprecated("Use operator long() instead (i.e. explicit or implicit cast)")]]
+		IPAACA_HEADER_EXPORT long to_long();
+		/// [DECPRECATED] use normal type conversion syntax instead
+		[[deprecated("Use operator double() instead (i.e. explicit or implicit cast)")]]
+		IPAACA_HEADER_EXPORT double to_float();
+		/// [DECPRECATED] use normal type conversion syntax instead
+		[[deprecated("Use operator bool() instead (i.e. explicit or implicit cast)")]]
+		IPAACA_HEADER_EXPORT bool to_bool();
+		// getters  (not needed since conversions are enough?)
+		//IPAACA_HEADER_EXPORT template<typename T> T get() { return json_value_cast<T>(json_value); }
+		// 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);
+		}*/
+		/// Append a supported type to a list-type payload value
+		IPAACA_HEADER_EXPORT template<typename T> void push_back(T t)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			rapidjson::Value newval;
+			pack_into_json_value(newval, new_entry->document.GetAllocator(), t);
+			list.PushBack(newval, new_entry->document.GetAllocator());
+			_payload->set(_key, new_entry);
+		}
+		/// Append the value of another proxy (or a null value) to a list-type value
+		IPAACA_HEADER_EXPORT void push_back(const PayloadEntryProxy& otherproxy)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			rapidjson::Value newval;
+			auto valueptr = otherproxy.json_value;
+			if (valueptr) { // only set if value is valid, keep default null value otherwise
+				newval.CopyFrom(*valueptr, new_entry->document.GetAllocator());
+			}
+			list.PushBack(newval, new_entry->document.GetAllocator());
+			_payload->set(_key, new_entry);
+		}
+		/// Extend a list-type payload value with a vector containing items of a supported type
+		IPAACA_HEADER_EXPORT template<typename T> void extend(const std::vector<T>& ts)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			for (auto& t: ts) {
+				rapidjson::Value newval;
+				pack_into_json_value(newval, new_entry->document.GetAllocator(), t);
+				list.PushBack(newval, new_entry->document.GetAllocator());
+			}
+			_payload->set(_key, new_entry);
+		}
+		/// Extend a list-type payload value with a list containing items of a supported type
+		IPAACA_HEADER_EXPORT template<typename T> void extend(const std::list<T>& ts)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			for (auto& t: ts) {
+				rapidjson::Value newval;
+				pack_into_json_value(newval, new_entry->document.GetAllocator(), t);
+				list.PushBack(newval, new_entry->document.GetAllocator());
+			}
+			_payload->set(_key, new_entry);
+		}
+		/// Extend a list-type payload value with items (copies) from another list-type value
+		IPAACA_HEADER_EXPORT void extend(const PayloadEntryProxy& otherproxy)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			if ((!otherproxy.json_value) || (!(otherproxy.json_value->IsArray()))) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			for (size_t i=0; i<otherproxy.json_value->Size(); ++i) {
+				rapidjson::Value newval;
+				rapidjson::Value& value = (*(otherproxy.json_value))[i];
+				newval.CopyFrom(value, new_entry->document.GetAllocator());
+				list.PushBack(newval, new_entry->document.GetAllocator());
+			}
+			_payload->set(_key, new_entry);
+		}
+};
+// Available interpretations of payload entries (or children thereof) below.
+//  Usage of standard complex data structures (vector etc.) currently entails
+//  casting all entries to a uniform type (a-priori choice: std::string).
+/*
+IPAACA_HEADER_EXPORT template<> long PayloadEntryProxy::get();
+IPAACA_HEADER_EXPORT template<> double PayloadEntryProxy::get();
+IPAACA_HEADER_EXPORT template<> bool PayloadEntryProxy::get();
+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();
+*/
+
+//}}}
+
+#endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca.h b/ipaacalib/cpp/include/ipaaca/ipaaca.h
index 057ff191995fcbc14cd4033ba729be485ad828ba..04f62ee0d2b2c45b079747a732007be22451c30e 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca.h
@@ -1,10 +1,11 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".  
+ *   for Artificial Conversational Agents".
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -21,7 +22,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -30,27 +31,90 @@
  * Excellence Initiative.
  */
 
-#ifndef __IPAACA_H__
-#define __IPAACA_H__
+/**
+ * \file   ipaaca.h
+ *
+ * \brief Central header file for IPAACA-C++.
+ *
+ * This is the central header file for the C++ version of IPAACA. Users should <b>include this file only.</b>
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
+/**
+\mainpage Documentation for IPAACA-C++
+
+This is the automatically generated documentation for the C++ implementation of IPAACA.
+
+List of most relevant entry points:
+
+Buffers: InputBuffer, OutputBuffer
+
+IUs: IUInterface, IU, Message
+
+IU handling (user-set): #IUEventHandlerFunction
+
+IU payload contents: Payload, PayloadEntryProxy
+*/
+
+#ifndef __ipaaca_h_INCLUDED__
+#define __ipaaca_h_INCLUDED__
 
 /// ipaaca/IU/RSB protocol major version number
-#define IPAACA_PROTOCOL_VERSION_MAJOR         1
+#define IPAACA_PROTOCOL_VERSION_MAJOR         2
 /// ipaaca/IU/RSB protocol minor version number
 #define IPAACA_PROTOCOL_VERSION_MINOR         0
 
 /// running release number of ipaaca-c++
-#define IPAACA_CPP_RELEASE_NUMBER             1
+#define IPAACA_CPP_RELEASE_NUMBER             12
 /// date of last release number increment
-#define IPAACA_CPP_RELEASE_DATE     "2012-09-08"
+#define IPAACA_CPP_RELEASE_DATE     "2015-01-15"
+
+#ifndef __FUNCTION_NAME__
+	#ifdef WIN32   // Windows
+		#define __FUNCTION_NAME__   __FUNCTION__
+	#else          // POSIX
+		#define __FUNCTION_NAME__   __func__
+	#endif
+#endif
+
+#ifdef WIN32
+	#define IPAACA_SYSTEM_DEPENDENT_CLASS_NAME(c) "class "##c
+#else
+	#define IPAACA_SYSTEM_DEPENDENT_CLASS_NAME(c) c
+#endif
+
+#ifdef WIN32
+	#if defined(ipaaca_EXPORTS)
+		#define  IPAACA_EXPORT
+		#define  IPAACA_HEADER_EXPORT __declspec(dllexport)
+		#define  IPAACA_MEMBER_VAR_EXPORT
+	#else
+		#define  IPAACA_EXPORT
+		#define  IPAACA_HEADER_EXPORT __declspec(dllimport)
+		#define  IPAACA_MEMBER_VAR_EXPORT
+	#endif
+#else
+	#define IPAACA_EXPORT
+	#define IPAACA_HEADER_EXPORT
+	#define IPAACA_MEMBER_VAR_EXPORT
+#endif
 
 #ifdef IPAACA_DEBUG_MESSAGES
-#define IPAACA_INFO(i) std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- " << i << std::endl;
-#define IPAACA_WARNING(i) std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- WARNING: " << i << std::endl;
-#define IPAACA_IMPLEMENT_ME std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- IMPLEMENT ME" << std::endl;
-#define IPAACA_TODO(i) std::cout << __FILE__ << ":" << __LINE__ << ": " << __func__ << "() -- TODO: " << i << std::endl;
+#define IPAACA_DEBUG(i)     if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_DEBUG) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- Debug: " << i << std::endl; }
+#define IPAACA_INFO(i)      if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- Info: " << i << std::endl; }
+#define IPAACA_WARNING(i)   if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_WARNING) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- WARNING: " << i << std::endl; }
+#define IPAACA_ERROR(i)     if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_ERROR) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- ERROR: " << i << std::endl; }
+#define IPAACA_CRITICAL(i)  if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_CRITICAL) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- CRITICAL: " << i << std::endl; }
+#define IPAACA_IMPLEMENT_ME if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- IMPLEMENT_ME:" << std::endl; }
+#define IPAACA_TODO(i)      if (__ipaaca_static_option_log_level>=IPAACA_LOG_LEVEL_INFO) { std::cout << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION_NAME__ << "() -- TODO: " << i << std::endl; }
 #else
+#define IPAACA_DEBUG(i) ;
 #define IPAACA_INFO(i) ;
 #define IPAACA_WARNING(i) ;
+#define IPAACA_ERROR(i) ;
+#define IPAACA_CRITICAL(i) ;
 #define IPAACA_IMPLEMENT_ME ;
 #define IPAACA_TODO(i) ;
 #endif
@@ -60,16 +124,25 @@
 #include <rsb/Factory.h>
 #include <rsb/Handler.h>
 #include <rsb/Event.h>
+#include <rsb/ParticipantConfig.h>
 #include <rsb/converter/Repository.h>
 #include <rsb/converter/ProtocolBufferConverter.h>
 #include <rsb/converter/Converter.h>
 #include <rsb/rsbexports.h>
 #endif
 
+// new json-based payload API, used in several classes
+#define RAPIDJSON_HAS_STDSTRING 1
+#include "rapidjson/document.h"
+#include "rapidjson/prettywriter.h"
+#include "rapidjson/filestream.h"
+#include <cstdio>
 
 /// marking pure virtual functions for extra readability
 #define _IPAACA_ABSTRACT_
 
+#define _IPAACA_OVERRIDE_ override
+
 /// value to return when reading nonexistant payload keys
 #define IPAACA_PAYLOAD_DEFAULT_STRING_VALUE ""
 
@@ -81,7 +154,25 @@
 
 // for logger
 #include <iomanip>
+
+#ifdef WIN32
+// for Windows
+#include <time.h>
+#else
+// for Linux and OS X
 #include <sys/time.h>
+#endif
+
+#include <cstdlib>
+
+
+#ifdef WIN32
+#include <rpc.h>
+#else
+#include <uuid/uuid.h>
+#include <glob.h>
+#endif
+
 
 #ifndef Q_MOC_RUN
 #include <boost/bind.hpp>
@@ -92,812 +183,52 @@
 #include <boost/lexical_cast.hpp>
 #endif
 
-#include <ipaaca/ipaaca.pb.h>
 
-#include <pthread.h>
-#include <uuid/uuid.h>
+#include <ipaaca/ipaaca.pb.h>
 
 #include <set>
+#include <list>
+#include <algorithm>
+#include <utility>
+#include <initializer_list>
 
 namespace ipaaca {
 
-typedef uint32_t revision_t;
-
-/// Type of the IU event. Realized as an integer to enable bit masks for filters.
-typedef uint32_t IUEventType;
-#define IU_ADDED         1
-#define IU_COMMITTED     2
-#define IU_DELETED       4
-#define IU_RETRACTED     8
-#define IU_UPDATED      16
-#define IU_LINKSUPDATED 32
-#define IU_MESSAGE      64
-/// Bit mask for receiving all events
-#define IU_ALL_EVENTS  127
-
-/// Convert an int event type to a human-readable string
-inline std::string iu_event_type_to_str(IUEventType type)
-{
-	switch(type) {
-		case IU_ADDED: return "ADDED";
-		case IU_COMMITTED: return "COMMITTED";
-		case IU_DELETED: return "DELETED";
-		case IU_RETRACTED: return "RETRACTED";
-		case IU_UPDATED: return "UPDATED";
-		case IU_LINKSUPDATED: return "LINKSUPDATED";
-		case IU_MESSAGE: return "MESSAGE";
-		default: return "(NOT A KNOWN SINGLE IU EVENT TYPE)";
-	}
-}
-
-/// IU access mode: PUSH means that updates are broadcast; REMOTE means that reads are RPC calls; MESSAGE means a fire-and-forget message
-enum IUAccessMode {
-	IU_ACCESS_PUSH,
-	IU_ACCESS_REMOTE,
-	IU_ACCESS_MESSAGE
-};
-
-class PayloadEntryProxy;
-class Payload;
-class IUInterface;
-class IU;
-class Message;
-class RemotePushIU;
-class IULinkUpdate;
-class IUPayloadUpdate;
-class IUStore;
-class FrozenIUStore;
-class Buffer;
-class InputBuffer;
-class OutputBuffer;
-
-//class InputBufferRsbAdaptor;
-//class OutputBufferRsbAdaptor;
-
-class CallbackIUPayloadUpdate;
-class CallbackIULinkUpdate;
-class CallbackIUCommission;
-class CallbackIURetraction;
-
-class IUConverter;
-class MessageConverter;
-class IUPayloadUpdateConverter;
-class IULinkUpdateConverter;
-class IntConverter;
-
-/// generate a UUID as an ASCII string
-std::string generate_uuid_string();
-
-/// store for (local) IUs. TODO Stores need to be unified more
-class IUStore: public std::map<std::string, boost::shared_ptr<IU> >
-{
-};
-/// store for RemotePushIUs. TODO Stores need to be unified more
-class RemotePushIUStore: public std::map<std::string, boost::shared_ptr<RemotePushIU> > // TODO genericize to all remote IU types
-{
-};
-
-class Exception: public std::exception//{{{
-{
-	protected:
-		std::string _description;
-	public:
-		inline Exception(const std::string& description=""): _description(description) { }
-		inline ~Exception() throw() { }
-		const char* what() const throw() {
-			return _description.c_str();
-		}
-};//}}}
-class Abort: public std::exception//{{{
-{
-	protected:
-		std::string _description;
-	public:
-		inline Abort(const std::string& description=""): _description(description) { }
-		inline ~Abort() throw() { }
-		const char* what() const throw() {
-			return _description.c_str();
-		}
-};//}}}
-
-/// a reentrant lock/mutex
-class Lock
-{
-	protected:
-		pthread_mutexattr_t _attrs;
-		pthread_mutex_t _mutex;
-	public:
-		inline Lock() {
-			pthread_mutexattr_init(&_attrs);
-			pthread_mutexattr_settype(&_attrs, PTHREAD_MUTEX_RECURSIVE);
-			pthread_mutex_init(&_mutex, &_attrs);
-		}
-		inline ~Lock() {
-			pthread_mutex_destroy(&_mutex);
-			pthread_mutexattr_destroy(&_attrs);
-		}
-		inline void lock() {
-			pthread_mutex_lock(&_mutex);
-		}
-		inline void unlock() {
-			pthread_mutex_unlock(&_mutex);
-		}
-};
-
-/// Stack-based lock holder. Create in a new stack frame
-///  (i.e.  {}-block) and it will obtain the lock and
-///  auto-release in on exiting the stack frame.
-class Locker
-{
-	protected:
-		Lock* _lock;
-	private:
-		inline Locker(): _lock(NULL) { } // not available
-	public:
-		inline Locker(Lock& lock): _lock(&lock) {
-			//std::cout << "-- Locker: lock" << std::endl;
-			_lock->lock();
-		}
-		inline ~Locker() {
-			//std::cout << "-- Locker: unlock" << std::endl;
-			_lock->unlock();
-		}
-};
-class PthreadMutexLocker
-{
-	protected:
-		pthread_mutex_t* _lock;
-	private:
-		inline PthreadMutexLocker(): _lock(NULL) { } // not available
-	public:
-		inline PthreadMutexLocker(pthread_mutex_t* lock): _lock(lock) {
-			if (!lock) throw Exception("PthreadMutexLocker got a NULL mutex!");
-			pthread_mutex_lock(_lock);
-		}
-		inline ~PthreadMutexLocker() {
-			pthread_mutex_unlock(_lock);
-		}
-};
-
-typedef std::set<std::string> LinkSet;
-typedef std::map<std::string, LinkSet> LinkMap;
-class SmartLinkMap {
-	friend std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj);
-	friend class IUInterface;
-	friend class IU;
-	friend class IUConverter;
-	friend class MessageConverter;
-	public:
-		const LinkSet& get_links(const std::string& key);
-		const LinkMap& get_all_links();
-	
-	protected:
-		LinkMap _links;
-		static LinkSet empty_link_set;
-		void _add_and_remove_links(const LinkMap& add, const LinkMap& remove);
-		void _replace_links(const LinkMap& links);
-};
-
-const LinkSet EMPTY_LINK_SET;
-//const std::set<std::string> EMPTY_LINK_SET;
-
-//typedef boost::function<void (const std::string&, bool, IUEventType, const std::string&)> IUEventHandlerFunction;
-typedef boost::function<void (boost::shared_ptr<IUInterface>, IUEventType, bool)> IUEventHandlerFunction;
-
-class IUEventHandler {
-	protected:
-		IUEventHandlerFunction _function;
-		IUEventType _event_mask;
-		bool _for_all_categories;
-		std::set<std::string> _categories;
-	protected:
-		inline bool _condition_met(IUEventType event_type, const std::string& category)
-		{
-			return ((_event_mask&event_type)!=0) && (_for_all_categories || (_categories.count(category)>0));
-		}
-	public:
-		IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category);
-		IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
-		//void call(Buffer* buffer, const std::string& uid, bool local, IUEventType event_type, const std::string& category);
-		void call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
-	typedef boost::shared_ptr<IUEventHandler> ptr;
-};
-
-class Buffer { //: public boost::enable_shared_from_this<Buffer> {//{{{
-	friend class IU;
-	friend class RemotePushIU;
-	friend class CallbackIUPayloadUpdate;
-	friend class CallbackIULinkUpdate;
-	friend class CallbackIUCommission;
-	protected:
-		//Lock _handler_lock;
-		std::string _uuid;
-		std::string _basename;
-		std::string _unique_name;
-		std::string _id_prefix;
-		std::vector<IUEventHandler::ptr> _event_handlers;
-	protected:
-		_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;
-		_IPAACA_ABSTRACT_ virtual void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") = 0;
-		_IPAACA_ABSTRACT_ virtual void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") = 0;
-		void _allocate_unique_name(const std::string& basename, const std::string& function);
-		inline Buffer(const std::string& basename, const std::string& function) {
-			_allocate_unique_name(basename, function);
-		}
-		void call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
-	public:
-		virtual inline ~Buffer() { }
-		inline const std::string& unique_name() { return _unique_name; }
-		void register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
-		void register_handler(IUEventHandlerFunction function, IUEventType event_mask = IU_ALL_EVENTS, const std::string& category="");
-		//_IPAACA_ABSTRACT_ virtual void add(boost::shared_ptr<IUInterface> iu) = 0;
-		_IPAACA_ABSTRACT_ virtual boost::shared_ptr<IUInterface> get(const std::string& iu_uid) = 0;
-		_IPAACA_ABSTRACT_ virtual std::set<boost::shared_ptr<IUInterface> > get_ius() = 0;
-};
-//}}}
-
-class OutputBuffer: public Buffer { //, public boost::enable_shared_from_this<OutputBuffer>  {//{{{
-	friend class IU;
-	friend class RemotePushIU;
-	friend class OutputBufferRsbAdaptor;
-	protected:
-	protected:
-		//OutputBufferRsbAdaptor _rsb;
-		IUStore _iu_store;
-		Lock _iu_id_counter_lock;
-#ifdef IPAACA_EXPOSE_FULL_RSB_API
-	protected:
-		std::map<std::string, rsb::Informer<rsb::AnyType>::Ptr> _informer_store;
-		rsb::patterns::ServerPtr _server;
-		rsb::Informer<rsb::AnyType>::Ptr _get_informer(const std::string& category);
-#endif
-	protected:
-		// informing functions
-		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");
-		void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef");
-		void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name);
-		// remote access functions
-		// _remote_update_links(IULinkUpdate)
-		// _remote_update_payload(IUPayloadUpdate)
-		// _remote_commit(protobuf::IUCommission)
-		void _publish_iu(boost::shared_ptr<IU> iu);
-		void _retract_iu(boost::shared_ptr<IU> iu);
-	protected:
-		OutputBuffer(const std::string& basename);
-		void _initialize_server();
-	public:
-		static boost::shared_ptr<OutputBuffer> create(const std::string& basename);
-		~OutputBuffer() {
-			IPAACA_IMPLEMENT_ME
-		}
-		void add(boost::shared_ptr<IU> iu);
-		boost::shared_ptr<IU> remove(const std::string& iu_uid);
-		boost::shared_ptr<IU> remove(boost::shared_ptr<IU> iu);
-		boost::shared_ptr<IUInterface> get(const std::string& iu_uid);
-		std::set<boost::shared_ptr<IUInterface> > get_ius();
-	typedef boost::shared_ptr<OutputBuffer> ptr;
-};
-//}}}
-
-class InputBuffer: public Buffer { //, public boost::enable_shared_from_this<InputBuffer>  {//{{{
-	friend class IU;
-	friend class RemotePushIU;
-	friend class InputBufferRsbAdaptor;
-		//InputBufferRsbAdaptor _rsb;
-#ifdef IPAACA_EXPOSE_FULL_RSB_API
-	protected:
-		std::map<std::string, rsb::ListenerPtr> _listener_store;
-		std::map<std::string, rsb::patterns::RemoteServerPtr> _remote_server_store;
-		RemotePushIUStore _iu_store;  // TODO genericize
-		rsb::patterns::RemoteServerPtr _get_remote_server(const std::string& unique_server_name);
-		rsb::ListenerPtr _create_category_listener_if_needed(const std::string& category);
-		void _handle_iu_events(rsb::EventPtr event);
+#include <ipaaca/ipaaca-definitions.h>
+#include <ipaaca/ipaaca-forwards.h>
+
+#include <ipaaca/ipaaca-locking.h>
+
+// Global static library variables (run-time default configuration)
+// Actual initial values are set in ipaaca.cc
+
+/// Default payload type for new IUs (defaults to "JSON")
+IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_default_payload_type;
+/// Default channel for buffers (defaults to "default")
+IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_default_channel;
+/// Current console log level (defaults to warning), one of: IPAACA_LOG_LEVEL_CRITICAL, IPAACA_LOG_LEVEL_ERROR, IPAACA_LOG_LEVEL_WARNING, IPAACA_LOG_LEVEL_INFO, IPAACA_LOG_LEVEL_DEBUG, IPAACA_LOG_LEVEL_NONE
+IPAACA_MEMBER_VAR_EXPORT extern unsigned int __ipaaca_static_option_log_level;
+
+IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock();
+
+#ifdef WIN32
+#define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); std::time_t result = std::time(NULL); std::cout << "[LOG] " << std::asctime(std::localtime(&result)) << " : " << msg << std::endl; }
+#else
+// use normal gettimeofday() on POSIX
+#define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); timeval logging_tim; gettimeofday(&logging_tim, NULL); double logging_t1=logging_tim.tv_sec+(logging_tim.tv_usec/1000000.0); std::cout << "[LOG] " << std::setprecision(15) << logging_t1 << " : " << msg << std::endl; }
 #endif
-	protected:
-		inline 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_WARNING("(ERROR) InputBuffer::_send_iu_link_update() should never be invoked")
-		}
-		inline void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef")
-		{
-			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_payload_update() should never be invoked")
-		}
-		inline void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef")
-		{
-			IPAACA_WARNING("(ERROR) InputBuffer::_send_iu_commission() should never be invoked")
-		}
-	protected:
-		InputBuffer(const std::string& basename, const std::set<std::string>& category_interests);
-		InputBuffer(const std::string& basename, const std::vector<std::string>& category_interests);
-		InputBuffer(const std::string& basename, const std::string& category_interest1);
-		InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2);
-		InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3);
-		InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4);
-	public:
-		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::set<std::string>& category_interests);
-		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::vector<std::string>& category_interests);
-		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1);
-		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2);
-		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3);
-		static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4);
-		~InputBuffer() {
-			IPAACA_IMPLEMENT_ME
-		}
-		boost::shared_ptr<IUInterface> get(const std::string& iu_uid);
-		std::set<boost::shared_ptr<IUInterface> > get_ius();
-	typedef boost::shared_ptr<InputBuffer> ptr;
-};
-//}}}
-
-class IUPayloadUpdate {//{{{
-	public:
-		std::string uid;
-		revision_t revision;
-		std::string writer_name;
-		bool is_delta;
-		std::map<std::string, std::string> new_items;
-		std::vector<std::string> keys_to_remove;
-	friend std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj);
-	typedef boost::shared_ptr<IUPayloadUpdate> ptr;
-};//}}}
-
-class IULinkUpdate {//{{{
-	public:
-		std::string uid;
-		revision_t revision;
-		std::string writer_name;
-		bool is_delta;
-		std::map<std::string, std::set<std::string> > new_links;
-		std::map<std::string, std::set<std::string> > links_to_remove;
-	friend std::ostream& operator<<(std::ostream& os, const IULinkUpdate& obj);
-	typedef boost::shared_ptr<IULinkUpdate> ptr;
-};//}}}
-
-
-
-class Initializer
-{
-	public:
-		static void initialize_ipaaca_rsb_if_needed();
-		static void initialize_updated_default_config();
-		static bool initialized();
-	protected:
-		static bool _initialized;
-};
-
-class PayloadEntryProxy//{{{
-{
-	protected:
-		Payload* _payload;
-		std::string _key;
-	public:
-		PayloadEntryProxy(Payload* payload, const std::string& key);
-		PayloadEntryProxy& operator=(const std::string& value);
-		PayloadEntryProxy& operator=(const char* value);
-		PayloadEntryProxy& operator=(double value);
-		PayloadEntryProxy& operator=(bool value);
-		operator std::string();
-		operator long();
-		operator double();
-		operator bool();
-		inline std::string to_str() { return operator std::string(); }
-		//inline long to_int() { return operator long(); }
-		inline long to_long() { return operator long(); }
-		inline double to_float() { return operator double(); }
-		inline bool to_bool() { return operator bool(); }
-};//}}}
-
-class Payload//{{{
-{
-	friend std::ostream& operator<<(std::ostream& os, const Payload& obj);
-	friend class IUInterface;
-	friend class IU;
-	friend class Message;
-	friend class RemotePushIU;
-	friend class RemoteMessage;
-	friend class IUConverter;
-	friend class MessageConverter;
-	friend class CallbackIUPayloadUpdate;
-	protected:
-		std::string _owner_name;
-		std::map<std::string, std::string> _store;
-		boost::weak_ptr<IUInterface> _iu;
-	protected:
-		void initialize(boost::shared_ptr<IUInterface> iu);
-		inline void _set_owner_name(const std::string& name) { _owner_name = name; }
-		void _remotely_enforced_wipe();
-		void _remotely_enforced_delitem(const std::string& k);
-		void _remotely_enforced_setitem(const std::string& k, const std::string& v);
-		void _internal_replace_all(const std::map<std::string, std::string>& new_contents, const std::string& writer_name="");
-		void _internal_merge(const std::map<std::string, std::string>& contents_to_merge, const std::string& writer_name="");
-		void _internal_set(const std::string& k, const std::string& v, const std::string& writer_name="");
-		void _internal_remove(const std::string& k, const std::string& writer_name="");
-	public:
-		inline const std::string& owner_name() { return _owner_name; }
-		// access
-		PayloadEntryProxy operator[](const std::string& key);
-		operator std::map<std::string, std::string>();
-		inline void set(const std::map<std::string, std::string>& all_elems) { _internal_replace_all(all_elems); }
-		inline void set(const std::string& k, const std::string& v) { _internal_set(k, v); }
-		inline void merge(const std::map<std::string, std::string>& elems_to_merge) { _internal_merge(elems_to_merge); }
-		inline void remove(const std::string& k) { _internal_remove(k); }
-		std::string get(const std::string& k);
-	typedef boost::shared_ptr<Payload> ptr;
-};//}}}
-
-class IUInterface {//{{{
-	friend class IUConverter;
-	friend class MessageConverter;
-	friend std::ostream& operator<<(std::ostream& os, const IUInterface& obj);
-	protected:
-		IUInterface();
-	public:
-		inline virtual ~IUInterface() { }
-	protected:
-		std::string _uid;
-		revision_t _revision;
-		std::string _category;
-		std::string _payload_type; // default is "MAP"
-		std::string _owner_name;
-		bool _committed;
-		bool _retracted;
-		IUAccessMode _access_mode;
-		bool _read_only;
-		//boost::shared_ptr<Buffer> _buffer;
-		Buffer* _buffer;
-		SmartLinkMap _links;
-	protected:
-		friend class Payload;
-		// Internal functions that perform the update logic,
-		//  e.g. sending a notification across the network
-		_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_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;
-		//void _set_buffer(boost::shared_ptr<Buffer> buffer);
-		void _associate_with_buffer(Buffer* buffer);
-		void _set_buffer(Buffer* buffer);
-		void _set_uid(const std::string& uid);
-		void _set_owner_name(const std::string& owner_name);
-	protected:
-		// internal functions that do not emit update events
-		inline void _add_and_remove_links(const LinkMap& add, const LinkMap& remove) { _links._add_and_remove_links(add, remove); }
-		inline void _replace_links(const LinkMap& links) { _links._replace_links(links); }
-	public:
-		inline bool is_published() { return (_buffer != 0); }
-		inline const std::string& uid() const { return _uid; }
-		inline revision_t revision() const { return _revision; }
-		inline const std::string& category() const { return _category; }
-		inline const std::string& payload_type() const { return _payload_type; }
-		inline const std::string& owner_name() const { return _owner_name; }
-		inline bool committed() const { return _committed; }
-		inline IUAccessMode access_mode() const { return _access_mode; }
-		inline bool read_only() const { return _read_only; }
-		//inline boost::shared_ptr<Buffer> buffer() { return _buffer; }
-		inline Buffer* buffer() const { return _buffer; }
-		inline const LinkSet& get_links(std::string type) { return _links.get_links(type); }
-		inline const LinkMap& get_all_links() { return _links.get_all_links(); }
-		// Payload
-		_IPAACA_ABSTRACT_ virtual Payload& payload() = 0;
-		_IPAACA_ABSTRACT_ virtual const Payload& const_payload() const = 0;
-		// setters
-		_IPAACA_ABSTRACT_ virtual void commit() = 0;
-		// functions to modify and update links:
-		void add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
-		void remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name = "");
-		void modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name = "");
-		void set_links(const LinkMap& links, const std::string& writer_name = "");
-		//    (with cpp specific convenience functions:)
-		void add_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
-		void remove_link(const std::string& type, const std::string& target, const std::string& writer_name = "");
-	typedef boost::shared_ptr<IUInterface> ptr;
-};//}}}
-
-class IU: public IUInterface {//{{{
-	friend class Buffer;
-	friend class InputBuffer;
-	friend class OutputBuffer;
-	friend class CallbackIUPayloadUpdate;
-	friend class CallbackIULinkUpdate;
-	friend class CallbackIUCommission;
-	public:
-		Payload _payload;
-	protected:
-		Lock _revision_lock;
-	protected:
-		inline void _increase_revision_number() { _revision++; }
-		IU(const std::string& category, IUAccessMode access_mode=IU_ACCESS_PUSH, bool read_only=false, const std::string& payload_type="MAP" );
-	public:
-		inline ~IU() {
-			//IPAACA_IMPLEMENT_ME
-		}
-		static boost::shared_ptr<IU> create(const std::string& category, IUAccessMode access_mode=IU_ACCESS_PUSH, bool read_only=false, const std::string& payload_type="MAP" );
-		inline Payload& payload() { return _payload; }
-		inline const Payload& const_payload() const { return _payload; }
-		void commit();
-	protected:
-		virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "");
-		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:
-		virtual void _internal_commit(const std::string& writer_name = "");
-	public:
-	typedef boost::shared_ptr<IU> ptr;
-};//}}}
-class Message: public IU {//{{{
-	friend class Buffer;
-	friend class InputBuffer;
-	friend class OutputBuffer;
-	friend class CallbackIUPayloadUpdate;
-	friend class CallbackIULinkUpdate;
-	friend class CallbackIUCommission;
-	protected:
-		Message(const std::string& category, IUAccessMode access_mode=IU_ACCESS_MESSAGE, bool read_only=true, const std::string& payload_type="MAP" );
-	public:
-		inline ~Message() {
-			//IPAACA_IMPLEMENT_ME
-		}
-		static boost::shared_ptr<Message> create(const std::string& category, IUAccessMode access_mode=IU_ACCESS_MESSAGE, bool read_only=true, const std::string& payload_type="MAP" );
-	protected:
-		void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "");
-		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:
-		void _internal_commit(const std::string& writer_name = "");
-	public:
-	typedef boost::shared_ptr<Message> ptr;
-};//}}}
-
-class RemotePushIU: public IUInterface {//{{{
-	friend class Buffer;
-	friend class InputBuffer;
-	friend class OutputBuffer;
-	friend class IUConverter;
-	friend class MessageConverter;
-	public:
-		Payload _payload;
-	protected:
-		RemotePushIU();
-		static boost::shared_ptr<RemotePushIU> create();
-	public:
-		inline ~RemotePushIU() {
-			//IPAACA_IMPLEMENT_ME
-		}
-		inline Payload& payload() { return _payload; }
-		inline const Payload& const_payload() const { return _payload; }
-		void commit();
-	protected:
-		void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "");
-		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:
-		void _apply_update(IUPayloadUpdate::ptr update);
-		void _apply_link_update(IULinkUpdate::ptr update);
-		void _apply_commission();
-		void _apply_retraction();
-	typedef boost::shared_ptr<RemotePushIU> ptr;
-};//}}}
-class RemoteMessage: public IUInterface {//{{{
-	friend class Buffer;
-	friend class InputBuffer;
-	friend class OutputBuffer;
-	friend class IUConverter;
-	friend class MessageConverter;
-	public:
-		Payload _payload;
-	protected:
-		RemoteMessage();
-		static boost::shared_ptr<RemoteMessage> create();
-	public:
-		inline ~RemoteMessage() {
-			//IPAACA_IMPLEMENT_ME
-		}
-		inline Payload& payload() { return _payload; }
-		inline const Payload& const_payload() const { return _payload; }
-		void commit();
-	protected:
-		void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "");
-		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:
-		void _apply_update(IUPayloadUpdate::ptr update);
-		void _apply_link_update(IULinkUpdate::ptr update);
-		void _apply_commission();
-		void _apply_retraction();
-	typedef boost::shared_ptr<RemoteMessage> ptr;
-};//}}}
-
-class IUNotFoundError: public Exception//{{{
-{
-	public:
-		inline ~IUNotFoundError() throw() { }
-		inline IUNotFoundError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUNotFoundError";
-		}
-};//}}}
-class IUPublishedError: public Exception//{{{
-{
-	public:
-		inline ~IUPublishedError() throw() { }
-		inline IUPublishedError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUPublishedError";
-		}
-};//}}}
-class IUCommittedError: public Exception//{{{
-{
-	public:
-		inline ~IUCommittedError() throw() { }
-		inline IUCommittedError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUCommittedError";
-		}
-};//}}}
-class IUUpdateFailedError: public Exception//{{{
-{
-	public:
-		inline ~IUUpdateFailedError() throw() { }
-		inline IUUpdateFailedError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUUpdateFailedError";
-		}
-};//}}}
-class IUReadOnlyError: public Exception//{{{
-{
-	public:
-		inline ~IUReadOnlyError() throw() { }
-		inline IUReadOnlyError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUReadOnlyError";
-		}
-};//}}}
-class IUAlreadyInABufferError: public Exception//{{{
-{
-	public:
-		inline ~IUAlreadyInABufferError() throw() { }
-		inline IUAlreadyInABufferError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUAlreadyInABufferError";
-		}
-};//}}}
-class IUAlreadyHasAnUIDError: public Exception//{{{
-{
-	public:
-		inline ~IUAlreadyHasAnUIDError() throw() { }
-		inline IUAlreadyHasAnUIDError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUAlreadyHasAnUIDError";
-		}
-};//}}}
-class IUAlreadyHasAnOwnerNameError: public Exception//{{{
-{
-	public:
-		inline ~IUAlreadyHasAnOwnerNameError() throw() { }
-		inline IUAlreadyHasAnOwnerNameError() { //boost::shared_ptr<IU> iu) {
-			_description = "IUAlreadyHasAnOwnerNameError";
-		}
-};//}}}
-class NotImplementedError: public Exception//{{{
-{
-	public:
-		inline ~NotImplementedError() throw() { }
-		inline NotImplementedError() { //boost::shared_ptr<IU> iu) {
-			_description = "NotImplementedError";
-		}
-};//}}}
 
+#include <ipaaca/ipaaca-payload.h>
+#include <ipaaca/ipaaca-buffers.h>
+#include <ipaaca/ipaaca-ius.h>
+
+/// Full API (including RSB transport) is only exposed during
+///  ipaaca compilation, user programs should use abstract API.
 #ifdef IPAACA_EXPOSE_FULL_RSB_API
-class CallbackIUPayloadUpdate: public rsb::patterns::Server::Callback<IUPayloadUpdate, int> {//{{{
-	protected:
-		Buffer* _buffer;
-	public:
-		CallbackIUPayloadUpdate(Buffer* buffer);
-		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update);
-};//}}}
-class CallbackIULinkUpdate: public rsb::patterns::Server::Callback<IULinkUpdate, int> {//{{{
-	protected:
-		Buffer* _buffer;
-	public:
-		CallbackIULinkUpdate(Buffer* buffer);
-	public:
-		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<IULinkUpdate> update);
-};//}}}
-class CallbackIUCommission: public rsb::patterns::Server::Callback<protobuf::IUCommission, int> {//{{{
-	protected:
-		Buffer* _buffer;
-	public:
-		CallbackIUCommission(Buffer* buffer);
-	public:
-		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IUCommission> update);
-};//}}}
-class CallbackIURetraction: public rsb::patterns::Server::Callback<protobuf::IURetraction, int> {//{{{
-	protected:
-		Buffer* _buffer;
-	public:
-		CallbackIURetraction(Buffer* buffer);
-	public:
-		boost::shared_ptr<int> call(const std::string& methodName, boost::shared_ptr<protobuf::IURetraction> update);
-};//}}}
-
-class IUConverter: public rsb::converter::Converter<std::string> {//{{{
-	public:
-		IUConverter();
-		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
-		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
-};//}}}
-class MessageConverter: public rsb::converter::Converter<std::string> {//{{{
-	public:
-		MessageConverter();
-		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
-		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
-};//}}}
-class IUPayloadUpdateConverter: public rsb::converter::Converter<std::string> {//{{{
-	public:
-		IUPayloadUpdateConverter();
-		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
-		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
-};//}}}
-class IULinkUpdateConverter: public rsb::converter::Converter<std::string> {//{{{
-	public:
-		IULinkUpdateConverter();
-		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
-		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
-};//}}}
-class IntConverter: public rsb::converter::Converter<std::string> {//{{{
-	public:
-		IntConverter();
-		std::string serialize(const rsb::AnnotatedData& data, std::string& wire);
-		rsb::AnnotatedData deserialize(const std::string& wireSchema, const std::string& wire);
-};//}}}
+#include <ipaaca/ipaaca-internal.h>
 #endif
 
 
-// additional misc classes ( Command line options )//{{{
-class CommandLineOptions {
-	public:
-		inline CommandLineOptions() { }
-		std::map<std::string, std::string> param_opts;
-		std::map<std::string, bool> param_set;
-	public:
-		void set_option(const std::string& name, bool expect, const char* optarg);
-		std::string get_param(const std::string& o);
-		bool is_set(const std::string& o);
-		void dump();
-	typedef boost::shared_ptr<CommandLineOptions> ptr;
-};
-
-class CommandLineParser {
-	protected:
-		std::map<char, std::string> longopt; // letter->name
-		std::map<std::string, char> shortopt; // letter->name
-		std::map<std::string, bool> options; //  name / expect_param
-		std::map<std::string, std::string> defaults; // for opt params
-		std::map<std::string, int> set_flag; // for paramless opts
-	protected:
-		CommandLineParser();
-	public:
-		inline ~CommandLineParser() { }
-		static inline boost::shared_ptr<CommandLineParser> create() {
-			return boost::shared_ptr<CommandLineParser>(new CommandLineParser());
-		}
-		void initialize_parser_defaults();
-		void dump_options();
-		void add_option(const std::string& optname, char shortn, bool expect_param, const std::string& defaultv);
-		void ensure_defaults_in( CommandLineOptions::ptr clo );
-		CommandLineOptions::ptr parse(int argc, char* const* argv);
-	typedef boost::shared_ptr<CommandLineParser> ptr;
-};
-//}}}
-
-// additional misc functions ( String splitting / joining )//{{{
-std::string str_join(const std::set<std::string>& set,const std::string& sep);
-std::string str_join(const std::vector<std::string>& vec,const std::string& sep);
-void str_split_wipe(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
-void str_split_append(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
-//}}}
-
-// (snippets) //{{{
-/*
-class IUEventFunctionHandler: public rsb::EventFunctionHandler {
-	protected:
-		Buffer* _buffer;
-	public:
-		inline IUEventFunctionHandler(Buffer* buffer, const EventFunction& function, const std::string& method="")
-			: EventFunctionHandler(function, method), _buffer(buffer) { }
-};
-*/
-//}}}
-
-Lock& logger_lock();
-#define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); timeval logging_tim; gettimeofday(&logging_tim, NULL); double logging_t1=logging_tim.tv_sec+(logging_tim.tv_usec/1000000.0); std::cout << "[LOG] " << std::setprecision(15) << logging_t1 << " : " << msg << std::endl; }
 
 } // of namespace ipaaca
 
diff --git a/ipaacalib/cpp/include/ipaaca/util/notifier.h b/ipaacalib/cpp/include/ipaaca/util/notifier.h
index 1bd507523c42ce6ab43501b73b8fcfaa4bd7658d..c16a4dfc35be4729f4d447d405ac3ea658118be8 100644
--- a/ipaacalib/cpp/include/ipaaca/util/notifier.h
+++ b/ipaacalib/cpp/include/ipaaca/util/notifier.h
@@ -30,6 +30,17 @@
  * Excellence Initiative.
  */
 
+/**
+ * \file   util/notifier.h
+ *
+ * \brief Header file for component notification (i.e. module-level introspection).
+ *
+ * Include this file in addition to ipaaca.h to use the functionality.
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
 #ifndef __IPAACA_UTIL_NOTIFIER_H__
 #define __IPAACA_UTIL_NOTIFIER_H__
 
diff --git a/ipaacalib/cpp/include/rapidjson/LICENSE-rapidjson.txt b/ipaacalib/cpp/include/rapidjson/LICENSE-rapidjson.txt
new file mode 100644
index 0000000000000000000000000000000000000000..40832c806d1024e0d4486b8915f2e715f48d8788
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/LICENSE-rapidjson.txt
@@ -0,0 +1,24 @@
+Copyright (C) 2011 Milo Yip
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+-- 
+This software and license copied in January 2015 from
+https://github.com/miloyip/rapidjson/
diff --git a/ipaacalib/cpp/include/rapidjson/allocators.h b/ipaacalib/cpp/include/rapidjson/allocators.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0a26eea9f9a74db36c3d6d3eb2c2323d9e5cf1b
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/allocators.h
@@ -0,0 +1,245 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ALLOCATORS_H_
+#define RAPIDJSON_ALLOCATORS_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+    \brief Concept for allocating, resizing and freeing memory block.
+    
+    Note that Malloc() and Realloc() are non-static but Free() is static.
+    
+    So if an allocator need to support Free(), it needs to put its pointer in 
+    the header of memory block.
+
+\code
+concept Allocator {
+    static const bool kNeedFree;    //!< Whether this allocator needs to call Free().
+
+    // Allocate a memory block.
+    // \param size of the memory block in bytes.
+    // \returns pointer to the memory block.
+    void* Malloc(size_t size);
+
+    // Resize a memory block.
+    // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+    // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+    // \param newSize the new size in bytes.
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+    // Free a memory block.
+    // \param pointer to the memory block. Null pointer is permitted.
+    static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+    \note implements Allocator concept
+*/
+class CrtAllocator {
+public:
+    static const bool kNeedFree = true;
+    void* Malloc(size_t size) { return std::malloc(size); }
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
+    static void Free(void *ptr) { std::free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks. 
+
+    It does not free memory blocks. And Realloc() only allocate new memory.
+
+    The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+    User may also supply a buffer as the first chunk.
+
+    If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+    The user-buffer is not deallocated by this allocator.
+
+    \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+    \note implements Allocator concept
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+    static const bool kNeedFree = false;    //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+    //! Constructor with chunkSize.
+    /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+        \param baseAllocator The allocator for allocating memory chunks.
+    */
+    MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 
+        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+    {
+    }
+
+    //! Constructor with user-supplied buffer.
+    /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+        The user buffer will not be deallocated when this allocator is destructed.
+
+        \param buffer User supplied buffer.
+        \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+        \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+        \param baseAllocator The allocator for allocating memory chunks.
+    */
+    MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+        chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+    {
+        RAPIDJSON_ASSERT(buffer != 0);
+        RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+        chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
+        chunkHead_->capacity = size - sizeof(ChunkHeader);
+        chunkHead_->size = 0;
+        chunkHead_->next = 0;
+    }
+
+    //! Destructor.
+    /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+    */
+    ~MemoryPoolAllocator() {
+        Clear();
+        RAPIDJSON_DELETE(ownBaseAllocator_);
+    }
+
+    //! Deallocates all memory chunks, excluding the user-supplied buffer.
+    void Clear() {
+        while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
+            ChunkHeader* next = chunkHead_->next;
+            baseAllocator_->Free(chunkHead_);
+            chunkHead_ = next;
+        }
+    }
+
+    //! Computes the total capacity of allocated memory chunks.
+    /*! \return total capacity in bytes.
+    */
+    size_t Capacity() const {
+        size_t capacity = 0;
+        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+            capacity += c->capacity;
+        return capacity;
+    }
+
+    //! Computes the memory blocks allocated.
+    /*! \return total used bytes.
+    */
+    size_t Size() const {
+        size_t size = 0;
+        for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+            size += c->size;
+        return size;
+    }
+
+    //! Allocates a memory block. (concept Allocator)
+    void* Malloc(size_t size) {
+        size = RAPIDJSON_ALIGN(size);
+        if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+            AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+
+        void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
+        chunkHead_->size += size;
+        return buffer;
+    }
+
+    //! Resizes a memory block (concept Allocator)
+    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+        if (originalPtr == 0)
+            return Malloc(newSize);
+
+        // Do not shrink if new size is smaller than original
+        if (originalSize >= newSize)
+            return originalPtr;
+
+        // Simply expand it if it is the last allocation and there is sufficient space
+        if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
+            size_t increment = static_cast<size_t>(newSize - originalSize);
+            increment = RAPIDJSON_ALIGN(increment);
+            if (chunkHead_->size + increment <= chunkHead_->capacity) {
+                chunkHead_->size += increment;
+                return originalPtr;
+            }
+        }
+
+        // Realloc process: allocate and copy memory, do not free original buffer.
+        void* newBuffer = Malloc(newSize);
+        RAPIDJSON_ASSERT(newBuffer != 0);   // Do not handle out-of-memory explicitly.
+        return std::memcpy(newBuffer, originalPtr, originalSize);
+    }
+
+    //! Frees a memory block (concept Allocator)
+    static void Free(void *ptr) { (void)ptr; } // Do nothing
+
+private:
+    //! Copy constructor is not permitted.
+    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
+    //! Copy assignment operator is not permitted.
+    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
+
+    //! Creates a new chunk.
+    /*! \param capacity Capacity of the chunk in bytes.
+    */
+    void AddChunk(size_t capacity) {
+        if (!baseAllocator_)
+            ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
+        ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
+        chunk->capacity = capacity;
+        chunk->size = 0;
+        chunk->next = chunkHead_;
+        chunkHead_ =  chunk;
+    }
+
+    static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+    //! Chunk header for perpending to each chunk.
+    /*! Chunks are stored as a singly linked list.
+    */
+    struct ChunkHeader {
+        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).
+        size_t size;        //!< Current size of allocated memory in bytes.
+        ChunkHeader *next;  //!< Next chunk in the linked list.
+    };
+
+    ChunkHeader *chunkHead_;    //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+    size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated.
+    void *userBuffer_;          //!< User supplied buffer.
+    BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks.
+    BaseAllocator* ownBaseAllocator_;   //!< base allocator created by this object.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/ipaacalib/cpp/include/rapidjson/document.h b/ipaacalib/cpp/include/rapidjson/document.h
new file mode 100644
index 0000000000000000000000000000000000000000..7656f446d6accbc2516273c68b5ecafc45f722c3
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/document.h
@@ -0,0 +1,1932 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+/*! \file document.h */
+
+#include "reader.h"
+#include "internal/meta.h"
+#include "internal/strfunc.h"
+#include <new>      // placement new
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_HAS_STDSTRING
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
+#else
+#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
+#endif
+/*! \def RAPIDJSON_HAS_STDSTRING
+    \ingroup RAPIDJSON_CONFIG
+    \brief Enable RapidJSON support for \c std::string
+
+    By defining this preprocessor symbol to \c 1, several convenience functions for using
+    \ref rapidjson::GenericValue with \c std::string are enabled, especially
+    for construction and comparison.
+
+    \hideinitializer
+*/
+#include <string>
+#endif // RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include <iterator> // std::iterator, std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// Forward declaration.
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+//! Name-value pair in a JSON object value.
+/*!
+    This class was internal to GenericValue. It used to be a inner struct.
+    But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
+    https://code.google.com/p/rapidjson/issues/detail?id=64
+*/
+template <typename Encoding, typename Allocator> 
+struct GenericMember { 
+    GenericValue<Encoding, Allocator> name;     //!< name of member (must be a string)
+    GenericValue<Encoding, Allocator> value;    //!< value of member.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericMemberIterator
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+
+//! (Constant) member iterator for a JSON object value
+/*!
+    \tparam Const Is this a constant iterator?
+    \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
+    \tparam Allocator   Allocator type for allocating memory of object, array and string.
+
+    This class implements a Random Access Iterator for GenericMember elements
+    of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
+
+    \note This iterator implementation is mainly intended to avoid implicit
+        conversions from iterator values to \c NULL,
+        e.g. from GenericValue::FindMember.
+
+    \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
+        pointer-based implementation, if your platform doesn't provide
+        the C++ <iterator> header.
+
+    \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
+ */
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator
+    : public std::iterator<std::random_access_iterator_tag
+        , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
+
+    friend class GenericValue<Encoding,Allocator>;
+    template <bool, typename, typename> friend class GenericMemberIterator;
+
+    typedef GenericMember<Encoding,Allocator> PlainType;
+    typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+    typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
+
+public:
+    //! Iterator type itself
+    typedef GenericMemberIterator Iterator;
+    //! Constant iterator type
+    typedef GenericMemberIterator<true,Encoding,Allocator>  ConstIterator;
+    //! Non-constant iterator type
+    typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
+
+    //! Pointer to (const) GenericMember
+    typedef typename BaseType::pointer         Pointer;
+    //! Reference to (const) GenericMember
+    typedef typename BaseType::reference       Reference;
+    //! Signed integer type (e.g. \c ptrdiff_t)
+    typedef typename BaseType::difference_type DifferenceType;
+
+    //! Default constructor (singular value)
+    /*! Creates an iterator pointing to no element.
+        \note All operations, except for comparisons, are undefined on such values.
+     */
+    GenericMemberIterator() : ptr_() {}
+
+    //! Iterator conversions to more const
+    /*!
+        \param it (Non-const) iterator to copy from
+
+        Allows the creation of an iterator from another GenericMemberIterator
+        that is "less const".  Especially, creating a non-constant iterator
+        from a constant iterator are disabled:
+        \li const -> non-const (not ok)
+        \li const -> const (ok)
+        \li non-const -> const (ok)
+        \li non-const -> non-const (ok)
+
+        \note If the \c Const template parameter is already \c false, this
+            constructor effectively defines a regular copy-constructor.
+            Otherwise, the copy constructor is implicitly defined.
+    */
+    GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+
+    //! @name stepping
+    //@{
+    Iterator& operator++(){ ++ptr_; return *this; }
+    Iterator& operator--(){ --ptr_; return *this; }
+    Iterator  operator++(int){ Iterator old(*this); ++ptr_; return old; }
+    Iterator  operator--(int){ Iterator old(*this); --ptr_; return old; }
+    //@}
+
+    //! @name increment/decrement
+    //@{
+    Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
+    Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
+
+    Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
+    Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
+    //@}
+
+    //! @name relations
+    //@{
+    bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
+    bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
+    bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
+    bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
+    bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
+    bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
+    //@}
+
+    //! @name dereference
+    //@{
+    Reference operator*() const { return *ptr_; }
+    Pointer   operator->() const { return ptr_; }
+    Reference operator[](DifferenceType n) const { return ptr_[n]; }
+    //@}
+
+    //! Distance
+    DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
+
+private:
+    //! Internal constructor from plain pointer
+    explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
+
+    Pointer ptr_; //!< raw pointer
+};
+
+#else // RAPIDJSON_NOMEMBERITERATORCLASS
+
+// class-based member iterator implementation disabled, use plain pointers
+
+template <bool Const, typename Encoding, typename Allocator>
+struct GenericMemberIterator;
+
+//! non-const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<false,Encoding,Allocator> {
+    //! use plain pointer as iterator type
+    typedef GenericMember<Encoding,Allocator>* Iterator;
+};
+//! const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<true,Encoding,Allocator> {
+    //! use plain const pointer as iterator type
+    typedef const GenericMember<Encoding,Allocator>* Iterator;
+};
+
+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericStringRef
+
+//! Reference to a constant string (not taking a copy)
+/*!
+    \tparam CharType character type of the string
+
+    This helper class is used to automatically infer constant string
+    references for string literals, especially from \c const \b (!)
+    character arrays.
+
+    The main use is for creating JSON string values without copying the
+    source string via an \ref Allocator.  This requires that the referenced
+    string pointers have a sufficient lifetime, which exceeds the lifetime
+    of the associated GenericValue.
+
+    \b Example
+    \code
+    Value v("foo");   // ok, no need to copy & calculate length
+    const char foo[] = "foo";
+    v.SetString(foo); // ok
+
+    const char* bar = foo;
+    // Value x(bar); // not ok, can't rely on bar's lifetime
+    Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
+    Value y(StringRef(bar, 3));  // ok, explicitly pass length
+    \endcode
+
+    \see StringRef, GenericValue::SetString
+*/
+template<typename CharType>
+struct GenericStringRef {
+    typedef CharType Ch; //!< character type of the string
+
+    //! Create string reference from \c const character array
+    /*!
+        This constructor implicitly creates a constant string reference from
+        a \c const character array.  It has better performance than
+        \ref StringRef(const CharType*) by inferring the string \ref length
+        from the array length, and also supports strings containing null
+        characters.
+
+        \tparam N length of the string, automatically inferred
+
+        \param str Constant character array, lifetime assumed to be longer
+            than the use of the string in e.g. a GenericValue
+
+        \post \ref s == str
+
+        \note Constant complexity.
+        \note There is a hidden, private overload to disallow references to
+            non-const character arrays to be created via this constructor.
+            By this, e.g. function-scope arrays used to be filled via
+            \c snprintf are excluded from consideration.
+            In such cases, the referenced string should be \b copied to the
+            GenericValue instead.
+     */
+    template<SizeType N>
+    GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
+        : s(str), length(N-1) {}
+
+    //! Explicitly create string reference from \c const character pointer
+    /*!
+        This constructor can be used to \b explicitly  create a reference to
+        a constant string pointer.
+
+        \see StringRef(const CharType*)
+
+        \param str Constant character pointer, lifetime assumed to be longer
+            than the use of the string in e.g. a GenericValue
+
+        \post \ref s == str
+
+        \note There is a hidden, private overload to disallow references to
+            non-const character arrays to be created via this constructor.
+            By this, e.g. function-scope arrays used to be filled via
+            \c snprintf are excluded from consideration.
+            In such cases, the referenced string should be \b copied to the
+            GenericValue instead.
+     */
+    explicit GenericStringRef(const CharType* str)
+        : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
+
+    //! Create constant string reference from pointer and length
+    /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+        \param len length of the string, excluding the trailing NULL terminator
+
+        \post \ref s == str && \ref length == len
+        \note Constant complexity.
+     */
+    GenericStringRef(const CharType* str, SizeType len)
+        : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
+
+    //! implicit conversion to plain CharType pointer
+    operator const Ch *() const { return s; }
+
+    const Ch* const s; //!< plain CharType pointer
+    const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
+
+private:
+    //! Disallow copy-assignment
+    GenericStringRef operator=(const GenericStringRef&);
+    //! Disallow construction from non-const array
+    template<SizeType N>
+    GenericStringRef(CharType (&str)[N]) /* = delete */;
+};
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal".  This function
+    can be used to avoid copying a character string to be referenced as a
+    value in a JSON GenericValue object, if the string's lifetime is known
+    to be valid long enough.
+    \tparam CharType Character type of the string
+    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+    \return GenericStringRef string reference object
+    \relatesalso GenericStringRef
+
+    \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str) {
+    return GenericStringRef<CharType>(str, internal::StrLen(str));
+}
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal".  This function
+    can be used to avoid copying a character string to be referenced as a
+    value in a JSON GenericValue object, if the string's lifetime is known
+    to be valid long enough.
+
+    This version has better performance with supplied length, and also
+    supports string containing null characters.
+
+    \tparam CharType character type of the string
+    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+    \param length The length of source string.
+    \return GenericStringRef string reference object
+    \relatesalso GenericStringRef
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
+    return GenericStringRef<CharType>(str, SizeType(length));
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+//! Mark a string object as constant string
+/*! Mark a string object (e.g. \c std::string) as a "string literal".
+    This function can be used to avoid copying a string to be referenced as a
+    value in a JSON GenericValue object, if the string's lifetime is known
+    to be valid long enough.
+
+    \tparam CharType character type of the string
+    \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+    \return GenericStringRef string reference object
+    \relatesalso GenericStringRef
+    \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
+    return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue type traits
+namespace internal {
+
+template <typename T, typename Encoding = void, typename Allocator = void>
+struct IsGenericValueImpl : FalseType {};
+
+// select candidates according to nested encoding and allocator types
+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
+    : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
+
+// helper to match arbitrary GenericValue instantiations, including derived classes
+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+    A JSON value can be one of 7 types. This class is a variant type supporting
+    these types.
+
+    Use the Value if UTF8 and default allocator
+
+    \tparam Encoding    Encoding of the value. (Even non-string values need to have the same encoding in a document)
+    \tparam Allocator   Allocator type for allocating memory of object, array and string.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > 
+class GenericValue {
+public:
+    //! Name-value pair in an object.
+    typedef GenericMember<Encoding, Allocator> Member;
+    typedef Encoding EncodingType;                  //!< Encoding type from template parameter.
+    typedef Allocator AllocatorType;                //!< Allocator type from template parameter.
+    typedef typename Encoding::Ch Ch;               //!< Character type derived from Encoding.
+    typedef GenericStringRef<Ch> StringRefType;     //!< Reference to a constant string
+    typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator;  //!< Member iterator for iterating in object.
+    typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator;  //!< Constant member iterator for iterating in object.
+    typedef GenericValue* ValueIterator;            //!< Value iterator for iterating in array.
+    typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+
+    //!@name Constructors and destructor.
+    //@{
+
+    //! Default constructor creates a null value.
+    GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move constructor in C++11
+    GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
+        rhs.flags_ = kNullFlag; // give up contents
+    }
+#endif
+
+private:
+    //! Copy constructor is not permitted.
+    GenericValue(const GenericValue& rhs);
+
+public:
+
+    //! Constructor with JSON value type.
+    /*! This creates a Value of specified type with default content.
+        \param type Type of the value.
+        \note Default content for number is zero.
+    */
+    explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
+        static const unsigned defaultFlags[7] = {
+            kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
+            kNumberAnyFlag
+        };
+        RAPIDJSON_ASSERT(type <= kNumberType);
+        flags_ = defaultFlags[type];
+
+        // Use ShortString to store empty string.
+        if (type == kStringType)
+            data_.ss.SetLength(0);
+    }
+
+    //! Explicit copy constructor (with allocator)
+    /*! Creates a copy of a Value by using the given Allocator
+        \tparam SourceAllocator allocator of \c rhs
+        \param rhs Value to copy from (read-only)
+        \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
+        \see CopyFrom()
+    */
+    template< typename SourceAllocator >
+    GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+
+    //! Constructor for boolean value.
+    /*! \param b Boolean value
+        \note This constructor is limited to \em real boolean values and rejects
+            implicitly converted types like arbitrary pointers.  Use an explicit cast
+            to \c bool, if you want to construct a boolean JSON value in such cases.
+     */
+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
+    template <typename T>
+    explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
+#else
+    explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
+#endif
+        : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
+            // safe-guard against failing SFINAE
+            RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+    }
+
+    //! Constructor for int value.
+    explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
+        data_.n.i64 = i;
+        if (i >= 0)
+            flags_ |= kUintFlag | kUint64Flag;
+    }
+
+    //! Constructor for unsigned value.
+    explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
+        data_.n.u64 = u; 
+        if (!(u & 0x80000000))
+            flags_ |= kIntFlag | kInt64Flag;
+    }
+
+    //! Constructor for int64_t value.
+    explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
+        data_.n.i64 = i64;
+        if (i64 >= 0) {
+            flags_ |= kNumberUint64Flag;
+            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+                flags_ |= kUintFlag;
+            if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+                flags_ |= kIntFlag;
+        }
+        else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+            flags_ |= kIntFlag;
+    }
+
+    //! Constructor for uint64_t value.
+    explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
+        data_.n.u64 = u64;
+        if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+            flags_ |= kInt64Flag;
+        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+            flags_ |= kUintFlag;
+        if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+            flags_ |= kIntFlag;
+    }
+
+    //! Constructor for double value.
+    explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
+
+    //! Constructor for constant string (i.e. do not make a copy of string)
+    GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
+
+    //! Constructor for constant string (i.e. do not make a copy of string)
+    explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
+
+    //! Constructor for copy-string (i.e. do make a copy of string)
+    GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
+
+    //! Constructor for copy-string (i.e. do make a copy of string)
+    GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+    //! Constructor for copy-string from a string object (i.e. do make a copy of string)
+    /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+     */
+    GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+#endif
+
+    //! Destructor.
+    /*! Need to destruct elements of array, members of object, or copy-string.
+    */
+    ~GenericValue() {
+        if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+            switch(flags_) {
+            case kArrayFlag:
+                for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+                    v->~GenericValue();
+                Allocator::Free(data_.a.elements);
+                break;
+
+            case kObjectFlag:
+                for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+                    m->~Member();
+                Allocator::Free(data_.o.members);
+                break;
+
+            case kCopyStringFlag:
+                Allocator::Free(const_cast<Ch*>(data_.s.str));
+                break;
+
+            default:
+                break;  // Do nothing for other types.
+            }
+        }
+    }
+
+    //@}
+
+    //!@name Assignment operators
+    //@{
+
+    //! Assignment with move semantics.
+    /*! \param rhs Source of the assignment. It will become a null value after assignment.
+    */
+    GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+        RAPIDJSON_ASSERT(this != &rhs);
+        this->~GenericValue();
+        RawAssign(rhs);
+        return *this;
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move assignment in C++11
+    GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+        return *this = rhs.Move();
+    }
+#endif
+
+    //! Assignment of constant string reference (no copy)
+    /*! \param str Constant string reference to be assigned
+        \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
+        \see GenericStringRef, operator=(T)
+    */
+    GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
+        GenericValue s(str);
+        return *this = s;
+    }
+
+    //! Assignment with primitive types.
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+        \param value The value to be assigned.
+
+        \note The source type \c T explicitly disallows all pointer types,
+            especially (\c const) \ref Ch*.  This helps avoiding implicitly
+            referencing character strings with insufficient lifetime, use
+            \ref SetString(const Ch*, Allocator&) (for copying) or
+            \ref StringRef() (to explicitly mark the pointer as constant) instead.
+            All other pointer types would implicitly convert to \c bool,
+            use \ref SetBool() instead.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
+    operator=(T value) {
+        GenericValue v(value);
+        return *this = v;
+    }
+
+    //! Deep-copy assignment from Value
+    /*! Assigns a \b copy of the Value to the current Value object
+        \tparam SourceAllocator Allocator type of \c rhs
+        \param rhs Value to copy from (read-only)
+        \param allocator Allocator to use for copying
+     */
+    template <typename SourceAllocator>
+    GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
+        RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
+        this->~GenericValue();
+        new (this) GenericValue(rhs, allocator);
+        return *this;
+    }
+
+    //! Exchange the contents of this value with those of other.
+    /*!
+        \param other Another value.
+        \note Constant complexity.
+    */
+    GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
+        GenericValue temp;
+        temp.RawAssign(*this);
+        RawAssign(other);
+        other.RawAssign(temp);
+        return *this;
+    }
+
+    //! Prepare Value for move semantics
+    /*! \return *this */
+    GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
+    //@}
+
+    //!@name Equal-to and not-equal-to operators
+    //@{
+    //! Equal-to operator
+    /*!
+        \note If an object contains duplicated named member, comparing equality with any object is always \c false.
+        \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
+    */
+    template <typename SourceAllocator>
+    bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+        typedef GenericValue<Encoding, SourceAllocator> RhsType;
+        if (GetType() != rhs.GetType())
+            return false;
+
+        switch (GetType()) {
+        case kObjectType: // Warning: O(n^2) inner-loop
+            if (data_.o.size != rhs.data_.o.size)
+                return false;           
+            for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
+                typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
+                if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
+                    return false;
+            }
+            return true;
+            
+        case kArrayType:
+            if (data_.a.size != rhs.data_.a.size)
+                return false;
+            for (SizeType i = 0; i < data_.a.size; i++)
+                if ((*this)[i] != rhs[i])
+                    return false;
+            return true;
+
+        case kStringType:
+            return StringEqual(rhs);
+
+        case kNumberType:
+            if (IsDouble() || rhs.IsDouble())
+                return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
+            else
+                return data_.n.u64 == rhs.data_.n.u64;
+
+        default: // kTrueType, kFalseType, kNullType
+            return true;
+        }
+    }
+
+    //! Equal-to operator with const C-string pointer
+    bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
+
+#if RAPIDJSON_HAS_STDSTRING
+    //! Equal-to operator with string object
+    /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+     */
+    bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
+#endif
+
+    //! Equal-to operator with primitive types
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
+    */
+    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
+
+    //! Not-equal-to operator
+    /*! \return !(*this == rhs)
+     */
+    template <typename SourceAllocator>
+    bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
+
+    //! Not-equal-to operator with const C-string pointer
+    bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
+
+    //! Not-equal-to operator with arbitrary types
+    /*! \return !(*this == rhs)
+     */
+    template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
+
+    //! Equal-to operator with arbitrary types (symmetric version)
+    /*! \return (rhs == lhs)
+     */
+    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
+
+    //! Not-Equal-to operator with arbitrary types (symmetric version)
+    /*! \return !(rhs == lhs)
+     */
+    template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
+    //@}
+
+    //!@name Type
+    //@{
+
+    Type GetType()  const { return static_cast<Type>(flags_ & kTypeMask); }
+    bool IsNull()   const { return flags_ == kNullFlag; }
+    bool IsFalse()  const { return flags_ == kFalseFlag; }
+    bool IsTrue()   const { return flags_ == kTrueFlag; }
+    bool IsBool()   const { return (flags_ & kBoolFlag) != 0; }
+    bool IsObject() const { return flags_ == kObjectFlag; }
+    bool IsArray()  const { return flags_ == kArrayFlag; }
+    bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
+    bool IsInt()    const { return (flags_ & kIntFlag) != 0; }
+    bool IsUint()   const { return (flags_ & kUintFlag) != 0; }
+    bool IsInt64()  const { return (flags_ & kInt64Flag) != 0; }
+    bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
+    bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
+    bool IsString() const { return (flags_ & kStringFlag) != 0; }
+
+    //@}
+
+    //!@name Null
+    //@{
+
+    GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+    //@}
+
+    //!@name Bool
+    //@{
+
+    bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
+    //!< Set boolean value
+    /*! \post IsBool() == true */
+    GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+    //@}
+
+    //!@name Object
+    //@{
+
+    //! Set this value as an empty object.
+    /*! \post IsObject() == true */
+    GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+    //! Get the number of members in the object.
+    SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
+
+    //! Check whether the object is empty.
+    bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
+
+    //! Get a value from an object associated with the name.
+    /*! \pre IsObject() == true
+        \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
+        \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
+        Since 0.2, if the name is not correct, it will assert.
+        If user is unsure whether a member exists, user should use HasMember() first.
+        A better approach is to use FindMember().
+        \note Linear time complexity.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
+        GenericValue n(StringRef(name));
+        return (*this)[n];
+    }
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+    //! Get a value from an object associated with the name.
+    /*! \pre IsObject() == true
+        \tparam SourceAllocator Allocator of the \c name value
+
+        \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
+        And it can also handle strings with embedded null characters.
+
+        \note Linear time complexity.
+    */
+    template <typename SourceAllocator>
+    GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
+        MemberIterator member = FindMember(name);
+        if (member != MemberEnd())
+            return member->value;
+        else {
+            RAPIDJSON_ASSERT(false);    // see above note
+            static GenericValue NullValue;
+            return NullValue;
+        }
+    }
+    template <typename SourceAllocator>
+    const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+    //! Const member iterator
+    /*! \pre IsObject() == true */
+    ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
+    //! Const \em past-the-end member iterator
+    /*! \pre IsObject() == true */
+    ConstMemberIterator MemberEnd() const   { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
+    //! Member iterator
+    /*! \pre IsObject() == true */
+    MemberIterator MemberBegin()            { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
+    //! \em Past-the-end member iterator
+    /*! \pre IsObject() == true */
+    MemberIterator MemberEnd()              { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
+
+    //! Check whether a member exists in the object.
+    /*!
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Whether a member with that name exists.
+        \note It is better to use FindMember() directly if you need the obtain the value as well.
+        \note Linear time complexity.
+    */
+    bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
+
+    //! Check whether a member exists in the object with GenericValue name.
+    /*!
+        This version is faster because it does not need a StrLen(). It can also handle string with null character.
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Whether a member with that name exists.
+        \note It is better to use FindMember() directly if you need the obtain the value as well.
+        \note Linear time complexity.
+    */
+    template <typename SourceAllocator>
+    bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
+
+    //! Find member by name.
+    /*!
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Iterator to member, if it exists.
+            Otherwise returns \ref MemberEnd().
+
+        \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+            the requested member doesn't exist. For consistency with e.g.
+            \c std::map, this has been changed to MemberEnd() now.
+        \note Linear time complexity.
+    */
+    MemberIterator FindMember(const Ch* name) {
+        GenericValue n(StringRef(name));
+        return FindMember(n);
+    }
+
+    ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+    //! Find member by name.
+    /*!
+        This version is faster because it does not need a StrLen(). It can also handle string with null character.
+        \param name Member name to be searched.
+        \pre IsObject() == true
+        \return Iterator to member, if it exists.
+            Otherwise returns \ref MemberEnd().
+
+        \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+            the requested member doesn't exist. For consistency with e.g.
+            \c std::map, this has been changed to MemberEnd() now.
+        \note Linear time complexity.
+    */
+    template <typename SourceAllocator>
+    MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(name.IsString());
+        MemberIterator member = MemberBegin();
+        for ( ; member != MemberEnd(); ++member)
+            if (name.StringEqual(member->name))
+                break;
+        return member;
+    }
+    template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+    //! Add a member (name-value pair) to the object.
+    /*! \param name A string value as name of member.
+        \param value Value of any type.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \note The ownership of \c name and \c value will be transferred to this object on success.
+        \pre  IsObject() && name.IsString()
+        \post name.IsNull() && value.IsNull()
+        \note Amortized Constant time complexity.
+    */
+    GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(name.IsString());
+
+        Object& o = data_.o;
+        if (o.size >= o.capacity) {
+            if (o.capacity == 0) {
+                o.capacity = kDefaultObjectCapacity;
+                o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
+            }
+            else {
+                SizeType oldCapacity = o.capacity;
+                o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
+                o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
+            }
+        }
+        o.members[o.size].name.RawAssign(name);
+        o.members[o.size].value.RawAssign(value);
+        o.size++;
+        return *this;
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
+        return AddMember(name, value, allocator);
+    }
+    GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
+        return AddMember(name, value, allocator);
+    }
+    GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
+        return AddMember(name, value, allocator);
+    }
+    GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
+        GenericValue n(name);
+        return AddMember(n, value, allocator);
+    }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+
+    //! Add a member (name-value pair) to the object.
+    /*! \param name A constant string reference as name of member.
+        \param value Value of any type.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \note The ownership of \c value will be transferred to this object on success.
+        \pre  IsObject()
+        \post value.IsNull()
+        \note Amortized Constant time complexity.
+    */
+    GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
+        GenericValue n(name);
+        return AddMember(n, value, allocator);
+    }
+
+    //! Add a constant string value as member (name-value pair) to the object.
+    /*! \param name A constant string reference as name of member.
+        \param value constant string reference as value of member.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \pre  IsObject()
+        \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
+        \note Amortized Constant time complexity.
+    */
+    GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
+        GenericValue v(value);
+        return AddMember(name, v, allocator);
+    }
+
+    //! Add any primitive value as member (name-value pair) to the object.
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+        \param name A constant string reference as name of member.
+        \param value Value of primitive type \c T as value of member
+        \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \pre  IsObject()
+
+        \note The source type \c T explicitly disallows all pointer types,
+            especially (\c const) \ref Ch*.  This helps avoiding implicitly
+            referencing character strings with insufficient lifetime, use
+            \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+            AddMember(StringRefType, StringRefType, Allocator&).
+            All other pointer types would implicitly convert to \c bool,
+            use an explicit cast instead, if needed.
+        \note Amortized Constant time complexity.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+    AddMember(StringRefType name, T value, Allocator& allocator) {
+        GenericValue n(name);
+        GenericValue v(value);
+        return AddMember(n, v, allocator);
+    }
+
+    //! Remove all members in the object.
+    /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
+        \note Linear time complexity.
+    */
+    void RemoveAllMembers() {
+        RAPIDJSON_ASSERT(IsObject()); 
+        for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+            m->~Member();
+        data_.o.size = 0;
+    }
+
+    //! Remove a member in object by its name.
+    /*! \param name Name of member to be removed.
+        \return Whether the member existed.
+        \note This function may reorder the object members. Use \ref
+            EraseMember(ConstMemberIterator) if you need to preserve the
+            relative order of the remaining members.
+        \note Linear time complexity.
+    */
+    bool RemoveMember(const Ch* name) {
+        GenericValue n(StringRef(name));
+        return RemoveMember(n);
+    }
+
+    template <typename SourceAllocator>
+    bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
+        MemberIterator m = FindMember(name);
+        if (m != MemberEnd()) {
+            RemoveMember(m);
+            return true;
+        }
+        else
+            return false;
+    }
+
+    //! Remove a member in object by iterator.
+    /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
+        \return the new iterator after removal.
+        \note This function may reorder the object members. Use \ref
+            EraseMember(ConstMemberIterator) if you need to preserve the
+            relative order of the remaining members.
+        \note Constant time complexity.
+    */
+    MemberIterator RemoveMember(MemberIterator m) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(data_.o.size > 0);
+        RAPIDJSON_ASSERT(data_.o.members != 0);
+        RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
+
+        MemberIterator last(data_.o.members + (data_.o.size - 1));
+        if (data_.o.size > 1 && m != last) {
+            // Move the last one to this place
+            *m = *last;
+        }
+        else {
+            // Only one left, just destroy
+            m->~Member();
+        }
+        --data_.o.size;
+        return m;
+    }
+
+    //! Remove a member from an object by iterator.
+    /*! \param pos iterator to the member to remove
+        \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
+        \return Iterator following the removed element.
+            If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
+        \note This function preserves the relative order of the remaining object
+            members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
+        \note Linear time complexity.
+    */
+    MemberIterator EraseMember(ConstMemberIterator pos) {
+        return EraseMember(pos, pos +1);
+    }
+
+    //! Remove members in the range [first, last) from an object.
+    /*! \param first iterator to the first member to remove
+        \param last  iterator following the last member to remove
+        \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
+        \return Iterator following the last removed element.
+        \note This function preserves the relative order of the remaining object
+            members.
+        \note Linear time complexity.
+    */
+    MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
+        RAPIDJSON_ASSERT(IsObject());
+        RAPIDJSON_ASSERT(data_.o.size > 0);
+        RAPIDJSON_ASSERT(data_.o.members != 0);
+        RAPIDJSON_ASSERT(first >= MemberBegin());
+        RAPIDJSON_ASSERT(first <= last);
+        RAPIDJSON_ASSERT(last <= MemberEnd());
+
+        MemberIterator pos = MemberBegin() + (first - MemberBegin());
+        for (MemberIterator itr = pos; itr != last; ++itr)
+            itr->~Member();
+        std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
+        data_.o.size -= (last - first);
+        return pos;
+    }
+
+    //@}
+
+    //!@name Array
+    //@{
+
+    //! Set this value as an empty array.
+    /*! \post IsArray == true */
+    GenericValue& SetArray() {  this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+    //! Get the number of elements in array.
+    SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+    //! Get the capacity of array.
+    SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+    //! Check whether the array is empty.
+    bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+    //! Remove all elements in the array.
+    /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+        \note Linear time complexity.
+    */
+    void Clear() {
+        RAPIDJSON_ASSERT(IsArray()); 
+        for (SizeType i = 0; i < data_.a.size; ++i)
+            data_.a.elements[i].~GenericValue();
+        data_.a.size = 0;
+    }
+
+    //! Get an element from array by index.
+    /*! \pre IsArray() == true
+        \param index Zero-based index of element.
+        \see operator[](T*)
+    */
+    GenericValue& operator[](SizeType index) {
+        RAPIDJSON_ASSERT(IsArray());
+        RAPIDJSON_ASSERT(index < data_.a.size);
+        return data_.a.elements[index];
+    }
+    const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+    //! Element iterator
+    /*! \pre IsArray() == true */
+    ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
+    //! \em Past-the-end element iterator
+    /*! \pre IsArray() == true */
+    ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
+    //! Constant element iterator
+    /*! \pre IsArray() == true */
+    ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+    //! Constant \em past-the-end element iterator
+    /*! \pre IsArray() == true */
+    ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+    //! Request the array to have enough capacity to store elements.
+    /*! \param newCapacity  The capacity that the array at least need to have.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \note Linear time complexity.
+    */
+    GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+        RAPIDJSON_ASSERT(IsArray());
+        if (newCapacity > data_.a.capacity) {
+            data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
+            data_.a.capacity = newCapacity;
+        }
+        return *this;
+    }
+
+    //! Append a GenericValue at the end of the array.
+    /*! \param value        Value to be appended.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \pre IsArray() == true
+        \post value.IsNull() == true
+        \return The value itself for fluent API.
+        \note The ownership of \c value will be transferred to this array on success.
+        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+        \note Amortized constant time complexity.
+    */
+    GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+        RAPIDJSON_ASSERT(IsArray());
+        if (data_.a.size >= data_.a.capacity)
+            Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
+        data_.a.elements[data_.a.size++].RawAssign(value);
+        return *this;
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
+        return PushBack(value, allocator);
+    }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+    //! Append a constant string reference at the end of the array.
+    /*! \param value        Constant string reference to be appended.
+        \param allocator    Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
+        \pre IsArray() == true
+        \return The value itself for fluent API.
+        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+        \note Amortized constant time complexity.
+        \see GenericStringRef
+    */
+    GenericValue& PushBack(StringRefType value, Allocator& allocator) {
+        return (*this).template PushBack<StringRefType>(value, allocator);
+    }
+
+    //! Append a primitive value at the end of the array.
+    /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+        \param value Value of primitive type T to be appended.
+        \param allocator    Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+        \pre IsArray() == true
+        \return The value itself for fluent API.
+        \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+
+        \note The source type \c T explicitly disallows all pointer types,
+            especially (\c const) \ref Ch*.  This helps avoiding implicitly
+            referencing character strings with insufficient lifetime, use
+            \ref PushBack(GenericValue&, Allocator&) or \ref
+            PushBack(StringRefType, Allocator&).
+            All other pointer types would implicitly convert to \c bool,
+            use an explicit cast instead, if needed.
+        \note Amortized constant time complexity.
+    */
+    template <typename T>
+    RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+    PushBack(T value, Allocator& allocator) {
+        GenericValue v(value);
+        return PushBack(v, allocator);
+    }
+
+    //! Remove the last element in the array.
+    /*!
+        \note Constant time complexity.
+    */
+    GenericValue& PopBack() {
+        RAPIDJSON_ASSERT(IsArray());
+        RAPIDJSON_ASSERT(!Empty());
+        data_.a.elements[--data_.a.size].~GenericValue();
+        return *this;
+    }
+
+    //! Remove an element of array by iterator.
+    /*!
+        \param pos iterator to the element to remove
+        \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
+        \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
+        \note Linear time complexity.
+    */
+    ValueIterator Erase(ConstValueIterator pos) {
+        return Erase(pos, pos + 1);
+    }
+
+    //! Remove elements in the range [first, last) of the array.
+    /*!
+        \param first iterator to the first element to remove
+        \param last  iterator following the last element to remove
+        \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
+        \return Iterator following the last removed element.
+        \note Linear time complexity.
+    */
+    ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
+        RAPIDJSON_ASSERT(IsArray());
+        RAPIDJSON_ASSERT(data_.a.size > 0);
+        RAPIDJSON_ASSERT(data_.a.elements != 0);
+        RAPIDJSON_ASSERT(first >= Begin());
+        RAPIDJSON_ASSERT(first <= last);
+        RAPIDJSON_ASSERT(last <= End());
+        ValueIterator pos = Begin() + (first - Begin());
+        for (ValueIterator itr = pos; itr != last; ++itr)
+            itr->~GenericValue();       
+        std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
+        data_.a.size -= (last - first);
+        return pos;
+    }
+
+    //@}
+
+    //!@name Number
+    //@{
+
+    int GetInt() const          { RAPIDJSON_ASSERT(flags_ & kIntFlag);   return data_.n.i.i;   }
+    unsigned GetUint() const    { RAPIDJSON_ASSERT(flags_ & kUintFlag);  return data_.n.u.u;   }
+    int64_t GetInt64() const    { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
+    uint64_t GetUint64() const  { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
+
+    double GetDouble() const {
+        RAPIDJSON_ASSERT(IsNumber());
+        if ((flags_ & kDoubleFlag) != 0)                return data_.n.d;   // exact type, no conversion.
+        if ((flags_ & kIntFlag) != 0)                   return data_.n.i.i; // int -> double
+        if ((flags_ & kUintFlag) != 0)                  return data_.n.u.u; // unsigned -> double
+        if ((flags_ & kInt64Flag) != 0)                 return (double)data_.n.i64; // int64_t -> double (may lose precision)
+        RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0);  return (double)data_.n.u64; // uint64_t -> double (may lose precision)
+    }
+
+    GenericValue& SetInt(int i)             { this->~GenericValue(); new (this) GenericValue(i);    return *this; }
+    GenericValue& SetUint(unsigned u)       { this->~GenericValue(); new (this) GenericValue(u);    return *this; }
+    GenericValue& SetInt64(int64_t i64)     { this->~GenericValue(); new (this) GenericValue(i64);  return *this; }
+    GenericValue& SetUint64(uint64_t u64)   { this->~GenericValue(); new (this) GenericValue(u64);  return *this; }
+    GenericValue& SetDouble(double d)       { this->~GenericValue(); new (this) GenericValue(d);    return *this; }
+
+    //@}
+
+    //!@name String
+    //@{
+
+    const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
+
+    //! Get the length of string.
+    /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+    */
+    SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
+
+    //! Set this value as a string without copying source string.
+    /*! This version has better performance with supplied length, and also support string containing null character.
+        \param s source string pointer. 
+        \param length The length of source string, excluding the trailing null terminator.
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() == s && GetStringLength() == length
+        \see SetString(StringRefType)
+    */
+    GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
+
+    //! Set this value as a string without copying source string.
+    /*! \param s source string reference
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() == s && GetStringLength() == s.length
+    */
+    GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
+
+    //! Set this value as a string by copying from source string.
+    /*! This version has better performance with supplied length, and also support string containing null character.
+        \param s source string. 
+        \param length The length of source string, excluding the trailing null terminator.
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+    */
+    GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
+
+    //! Set this value as a string by copying from source string.
+    /*! \param s source string. 
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+    */
+    GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+    //! Set this value as a string by copying from source string.
+    /*! \param s source string.
+        \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+        \return The value itself for fluent API.
+        \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
+        \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+    */
+    GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
+#endif
+
+    //@}
+
+    //! Generate events of this value to a Handler.
+    /*! This function adopts the GoF visitor pattern.
+        Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+        It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+        \tparam Handler type of handler.
+        \param handler An object implementing concept Handler.
+    */
+    template <typename Handler>
+    bool Accept(Handler& handler) const {
+        switch(GetType()) {
+        case kNullType:     return handler.Null();
+        case kFalseType:    return handler.Bool(false);
+        case kTrueType:     return handler.Bool(true);
+
+        case kObjectType:
+            if (!handler.StartObject())
+                return false;
+            for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
+                RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
+                if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
+                    return false;
+                if (!m->value.Accept(handler))
+                    return false;
+            }
+            return handler.EndObject(data_.o.size);
+
+        case kArrayType:
+            if (!handler.StartArray())
+                return false;
+            for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+                if (!v->Accept(handler))
+                    return false;
+            return handler.EndArray(data_.a.size);
+    
+        case kStringType:
+            return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
+    
+        case kNumberType:
+            if (IsInt())            return handler.Int(data_.n.i.i);
+            else if (IsUint())      return handler.Uint(data_.n.u.u);
+            else if (IsInt64())     return handler.Int64(data_.n.i64);
+            else if (IsUint64())    return handler.Uint64(data_.n.u64);
+            else                    return handler.Double(data_.n.d);
+    
+        default:
+            RAPIDJSON_ASSERT(false);
+        }
+        return false;
+    }
+
+private:
+    template <typename, typename> friend class GenericValue;
+    template <typename, typename, typename> friend class GenericDocument;
+
+    enum {
+        kBoolFlag = 0x100,
+        kNumberFlag = 0x200,
+        kIntFlag = 0x400,
+        kUintFlag = 0x800,
+        kInt64Flag = 0x1000,
+        kUint64Flag = 0x2000,
+        kDoubleFlag = 0x4000,
+        kStringFlag = 0x100000,
+        kCopyFlag = 0x200000,
+        kInlineStrFlag = 0x400000,
+
+        // Initial flags of different types.
+        kNullFlag = kNullType,
+        kTrueFlag = kTrueType | kBoolFlag,
+        kFalseFlag = kFalseType | kBoolFlag,
+        kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+        kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+        kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+        kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+        kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+        kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
+        kConstStringFlag = kStringType | kStringFlag,
+        kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+        kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
+        kObjectFlag = kObjectType,
+        kArrayFlag = kArrayType,
+
+        kTypeMask = 0xFF    // bitwise-and with mask of 0xFF can be optimized by compiler
+    };
+
+    static const SizeType kDefaultArrayCapacity = 16;
+    static const SizeType kDefaultObjectCapacity = 16;
+
+    struct String {
+        const Ch* str;
+        SizeType length;
+        unsigned hashcode;  //!< reserved
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
+    // (excluding the terminating zero) and store a value to determine the length of the contained
+    // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
+    // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
+    // the string terminator as well. For getting the string length back from that value just use
+    // "MaxSize - str[LenPos]".
+    // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
+    // inline (for `UTF8`-encoded strings).
+    struct ShortString {
+        enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+        Ch str[MaxChars];
+
+        inline static bool Usable(SizeType len) { return            (MaxSize >= len); }
+        inline void     SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize -  len); }
+        inline SizeType GetLength() const       { return  (SizeType)(MaxSize -  str[LenPos]); }
+    };  // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    // By using proper binary layout, retrieval of different integer types do not need conversions.
+    union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+        struct I {
+            int i;
+            char padding[4];
+        }i;
+        struct U {
+            unsigned u;
+            char padding2[4];
+        }u;
+#else
+        struct I {
+            char padding[4];
+            int i;
+        }i;
+        struct U {
+            char padding2[4];
+            unsigned u;
+        }u;
+#endif
+        int64_t i64;
+        uint64_t u64;
+        double d;
+    };  // 8 bytes
+
+    struct Object {
+        Member* members;
+        SizeType size;
+        SizeType capacity;
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    struct Array {
+        GenericValue* elements;
+        SizeType size;
+        SizeType capacity;
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    union Data {
+        String s;
+        ShortString ss;
+        Number n;
+        Object o;
+        Array a;
+    };  // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+    // Initialize this value as array with initial data, without calling destructor.
+    void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
+        flags_ = kArrayFlag;
+        data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
+        std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
+        data_.a.size = data_.a.capacity = count;
+    }
+
+    //! Initialize this value as object with initial data, without calling destructor.
+    void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
+        flags_ = kObjectFlag;
+        data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
+        std::memcpy(data_.o.members, members, count * sizeof(Member));
+        data_.o.size = data_.o.capacity = count;
+    }
+
+    //! Initialize this value as constant string, without calling destructor.
+    void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
+        flags_ = kConstStringFlag;
+        data_.s.str = s;
+        data_.s.length = s.length;
+    }
+
+    //! Initialize this value as copy string with initial data, without calling destructor.
+    void SetStringRaw(StringRefType s, Allocator& allocator) {
+        Ch* str = NULL;
+        if(ShortString::Usable(s.length)) {
+            flags_ = kShortStringFlag;
+            data_.ss.SetLength(s.length);
+            str = data_.ss.str;
+        } else {
+            flags_ = kCopyStringFlag;
+            data_.s.length = s.length;
+            str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
+            data_.s.str = str;
+        }
+        std::memcpy(str, s, s.length * sizeof(Ch));
+        str[s.length] = '\0';
+    }
+
+    //! Assignment without calling destructor
+    void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+        data_ = rhs.data_;
+        flags_ = rhs.flags_;
+        rhs.flags_ = kNullFlag;
+    }
+
+    template <typename SourceAllocator>
+    bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+        RAPIDJSON_ASSERT(IsString());
+        RAPIDJSON_ASSERT(rhs.IsString());
+
+        const SizeType len1 = GetStringLength();
+        const SizeType len2 = rhs.GetStringLength();
+        if(len1 != len2) { return false; }
+
+        const Ch* const str1 = GetString();
+        const Ch* const str2 = rhs.GetString();
+        if(str1 == str2) { return true; } // fast path for constant string
+
+        return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
+    }
+
+    Data data_;
+    unsigned flags_;
+};
+
+//! GenericValue with UTF8 encoding
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument 
+
+//! A document for parsing JSON text as DOM.
+/*!
+    \note implements Handler concept
+    \tparam Encoding Encoding for both parsing and string storage.
+    \tparam Allocator Allocator for allocating memory for the DOM
+    \tparam StackAllocator Allocator for allocating memory for stack during parsing.
+    \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor.  To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+    typedef typename Encoding::Ch Ch;                       //!< Character type derived from Encoding.
+    typedef GenericValue<Encoding, Allocator> ValueType;    //!< Value type of the document.
+    typedef Allocator AllocatorType;                        //!< Allocator type from template parameter.
+
+    //! Constructor
+    /*! \param allocator        Optional allocator for allocating memory.
+        \param stackCapacity    Optional initial capacity of stack in bytes.
+        \param stackAllocator   Optional allocator for allocating memory for stack.
+    */
+    GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : 
+        allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+    {
+        if (!allocator_)
+            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move constructor in C++11
+    GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+        : ValueType(std::move(rhs)),
+          allocator_(rhs.allocator_),
+          ownAllocator_(rhs.ownAllocator_),
+          stack_(std::move(rhs.stack_)),
+          parseResult_(rhs.parseResult_)
+    {
+        rhs.allocator_ = 0;
+        rhs.ownAllocator_ = 0;
+        rhs.parseResult_ = ParseResult();
+    }
+#endif
+
+    ~GenericDocument() {
+        Destroy();
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    //! Move assignment in C++11
+    GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+    {
+        // The cast to ValueType is necessary here, because otherwise it would
+        // attempt to call GenericValue's templated assignment operator.
+        ValueType::operator=(std::forward<ValueType>(rhs));
+
+        // Calling the destructor here would prematurely call stack_'s destructor
+        Destroy();
+
+        allocator_ = rhs.allocator_;
+        ownAllocator_ = rhs.ownAllocator_;
+        stack_ = std::move(rhs.stack_);
+        parseResult_ = rhs.parseResult_;
+
+        rhs.allocator_ = 0;
+        rhs.ownAllocator_ = 0;
+        rhs.parseResult_ = ParseResult();
+
+        return *this;
+    }
+#endif
+
+    //!@name Parse from stream
+    //!@{
+
+    //! Parse JSON text from an input stream (with Encoding conversion)
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam SourceEncoding Encoding of input stream
+        \tparam InputStream Type of input stream, implementing Stream concept
+        \param is Input stream to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
+    GenericDocument& ParseStream(InputStream& is) {
+        ValueType::SetNull(); // Remove existing root if exist
+        GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
+        ClearStackOnExit scope(*this);
+        parseResult_ = reader.template Parse<parseFlags>(is, *this);
+        if (parseResult_) {
+            RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+            this->RawAssign(*stack_.template Pop<ValueType>(1));    // Add this-> to prevent issue 13.
+        }
+        return *this;
+    }
+
+    //! Parse JSON text from an input stream
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam InputStream Type of input stream, implementing Stream concept
+        \param is Input stream to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags, typename InputStream>
+    GenericDocument& ParseStream(InputStream& is) {
+        return ParseStream<parseFlags,Encoding,InputStream>(is);
+    }
+
+    //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
+    /*! \tparam InputStream Type of input stream, implementing Stream concept
+        \param is Input stream to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <typename InputStream>
+    GenericDocument& ParseStream(InputStream& is) {
+        return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
+    }
+    //!@}
+
+    //!@name Parse in-place from mutable string
+    //!@{
+
+    //! Parse JSON text from a mutable string (with Encoding conversion)
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam SourceEncoding Transcoding from input Encoding
+        \param str Mutable zero-terminated string to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags, typename SourceEncoding>
+    GenericDocument& ParseInsitu(Ch* str) {
+        GenericInsituStringStream<Encoding> s(str);
+        return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
+    }
+
+    //! Parse JSON text from a mutable string
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \param str Mutable zero-terminated string to be parsed.
+        \return The document itself for fluent API.
+    */
+    template <unsigned parseFlags>
+    GenericDocument& ParseInsitu(Ch* str) {
+        return ParseInsitu<parseFlags, Encoding>(str);
+    }
+
+    //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
+    /*! \param str Mutable zero-terminated string to be parsed.
+        \return The document itself for fluent API.
+    */
+    GenericDocument& ParseInsitu(Ch* str) {
+        return ParseInsitu<kParseDefaultFlags, Encoding>(str);
+    }
+    //!@}
+
+    //!@name Parse from read-only string
+    //!@{
+
+    //! Parse JSON text from a read-only string (with Encoding conversion)
+    /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+        \tparam SourceEncoding Transcoding from input Encoding
+        \param str Read-only zero-terminated string to be parsed.
+    */
+    template <unsigned parseFlags, typename SourceEncoding>
+    GenericDocument& Parse(const Ch* str) {
+        RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+        GenericStringStream<SourceEncoding> s(str);
+        return ParseStream<parseFlags, SourceEncoding>(s);
+    }
+
+    //! Parse JSON text from a read-only string
+    /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+        \param str Read-only zero-terminated string to be parsed.
+    */
+    template <unsigned parseFlags>
+    GenericDocument& Parse(const Ch* str) {
+        return Parse<parseFlags, Encoding>(str);
+    }
+
+    //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
+    /*! \param str Read-only zero-terminated string to be parsed.
+    */
+    GenericDocument& Parse(const Ch* str) {
+        return Parse<kParseDefaultFlags>(str);
+    }
+    //!@}
+
+    //!@name Handling parse errors
+    //!@{
+
+    //! Whether a parse error has occured in the last parsing.
+    bool HasParseError() const { return parseResult_.IsError(); }
+
+    //! Get the \ref ParseErrorCode of last parsing.
+    ParseErrorCode GetParseError() const { return parseResult_.Code(); }
+
+    //! Get the position of last parsing error in input, 0 otherwise.
+    size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+    //!@}
+
+    //! Get the allocator of this document.
+    Allocator& GetAllocator() { return *allocator_; }
+
+    //! Get the capacity of stack in bytes.
+    size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+    // clear stack on any exit from ParseStream, e.g. due to exception
+    struct ClearStackOnExit {
+        explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
+        ~ClearStackOnExit() { d_.ClearStack(); }
+    private:
+        ClearStackOnExit(const ClearStackOnExit&);
+        ClearStackOnExit& operator=(const ClearStackOnExit&);
+        GenericDocument& d_;
+    };
+
+    // callers of the following private Handler functions
+    template <typename,typename,typename> friend class GenericReader; // for parsing
+    template <typename, typename> friend class GenericValue; // for deep copying
+
+    // Implementation of Handler
+    bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
+    bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
+    bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+    bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
+
+    bool String(const Ch* str, SizeType length, bool copy) { 
+        if (copy) 
+            new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+        else
+            new (stack_.template Push<ValueType>()) ValueType(str, length);
+        return true;
+    }
+
+    bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
+    
+    bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
+
+    bool EndObject(SizeType memberCount) {
+        typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+        stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
+        return true;
+    }
+
+    bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
+    
+    bool EndArray(SizeType elementCount) {
+        ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+        stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+        return true;
+    }
+
+private:
+    //! Prohibit copying
+    GenericDocument(const GenericDocument&);
+    //! Prohibit assignment
+    GenericDocument& operator=(const GenericDocument&);
+
+    void ClearStack() {
+        if (Allocator::kNeedFree)
+            while (stack_.GetSize() > 0)    // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+                (stack_.template Pop<ValueType>(1))->~ValueType();
+        else
+            stack_.Clear();
+        stack_.ShrinkToFit();
+    }
+
+    void Destroy() {
+        RAPIDJSON_DELETE(ownAllocator_);
+    }
+
+    static const size_t kDefaultStackCapacity = 1024;
+    Allocator* allocator_;
+    Allocator* ownAllocator_;
+    internal::Stack<StackAllocator> stack_;
+    ParseResult parseResult_;
+};
+
+//! GenericDocument with UTF8 encoding
+typedef GenericDocument<UTF8<> > Document;
+
+// defined here due to the dependency on GenericDocument
+template <typename Encoding, typename Allocator>
+template <typename SourceAllocator>
+inline
+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
+{
+    switch (rhs.GetType()) {
+    case kObjectType:
+    case kArrayType: { // perform deep copy via SAX Handler
+            GenericDocument<Encoding,Allocator> d(&allocator);
+            rhs.Accept(d);
+            RawAssign(*d.stack_.template Pop<GenericValue>(1));
+        }
+        break;
+    case kStringType:
+        if (rhs.flags_ == kConstStringFlag) {
+            flags_ = rhs.flags_;
+            data_  = *reinterpret_cast<const Data*>(&rhs.data_);
+        } else {
+            SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+        }
+        break;
+    default: // kNumberType, kTrueType, kFalseType, kNullType
+        flags_ = rhs.flags_;
+        data_  = *reinterpret_cast<const Data*>(&rhs.data_);
+    }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(_MSC_VER) || defined(__GNUC__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_DOCUMENT_H_
diff --git a/ipaacalib/cpp/include/rapidjson/encodedstream.h b/ipaacalib/cpp/include/rapidjson/encodedstream.h
new file mode 100644
index 0000000000000000000000000000000000000000..c310d2e58bf8db37d58fdc1a3283c8e16cce6d3a
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/encodedstream.h
@@ -0,0 +1,290 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
+#define RAPIDJSON_ENCODEDSTREAM_H_
+
+#include "rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Input byte stream wrapper with a statically bound encoding.
+/*!
+    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+    \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
+*/
+template <typename Encoding, typename InputByteStream>
+class EncodedInputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+    typedef typename Encoding::Ch Ch;
+
+    EncodedInputStream(InputByteStream& is) : is_(is) { 
+        current_ = Encoding::TakeBOM(is_);
+    }
+
+    Ch Peek() const { return current_; }
+    Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
+    size_t Tell() const { return is_.Tell(); }
+
+    // Not implemented
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); } 
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    EncodedInputStream(const EncodedInputStream&);
+    EncodedInputStream& operator=(const EncodedInputStream&);
+
+    InputByteStream& is_;
+    Ch current_;
+};
+
+//! Output byte stream wrapper with statically bound encoding.
+/*!
+    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+    \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
+*/
+template <typename Encoding, typename OutputByteStream>
+class EncodedOutputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+    typedef typename Encoding::Ch Ch;
+
+    EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { 
+        if (putBOM)
+            Encoding::PutBOM(os_);
+    }
+
+    void Put(Ch c) { Encoding::Put(os_, c);  }
+    void Flush() { os_.Flush(); }
+
+    // Not implemented
+    Ch Peek() const { RAPIDJSON_ASSERT(false); }
+    Ch Take() { RAPIDJSON_ASSERT(false);  }
+    size_t Tell() const { RAPIDJSON_ASSERT(false);  return 0; }
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    EncodedOutputStream(const EncodedOutputStream&);
+    EncodedOutputStream& operator=(const EncodedOutputStream&);
+
+    OutputByteStream& os_;
+};
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+    \tparam CharType Type of character for reading.
+    \tparam InputByteStream type of input byte stream to be wrapped.
+*/
+template <typename CharType, typename InputByteStream>
+class AutoUTFInputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+    typedef CharType Ch;
+
+    //! Constructor.
+    /*!
+        \param is input stream to be wrapped.
+        \param type UTF encoding type if it is not detected from the stream.
+    */
+    AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
+        DetectType();
+        static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
+        takeFunc_ = f[type_];
+        current_ = takeFunc_(*is_);
+    }
+
+    UTFType GetType() const { return type_; }
+    bool HasBOM() const { return hasBOM_; }
+
+    Ch Peek() const { return current_; }
+    Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
+    size_t Tell() const { return is_->Tell(); }
+
+    // Not implemented
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); } 
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    AutoUTFInputStream(const AutoUTFInputStream&);
+    AutoUTFInputStream& operator=(const AutoUTFInputStream&);
+
+    // Detect encoding type with BOM or RFC 4627
+    void DetectType() {
+        // BOM (Byte Order Mark):
+        // 00 00 FE FF  UTF-32BE
+        // FF FE 00 00  UTF-32LE
+        // FE FF        UTF-16BE
+        // FF FE        UTF-16LE
+        // EF BB BF     UTF-8
+
+        const unsigned char* c = (const unsigned char *)is_->Peek4();
+        if (!c)
+            return;
+
+        unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+        hasBOM_ = false;
+        if (bom == 0xFFFE0000)                  { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+        else if (bom == 0x0000FEFF)             { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+        else if ((bom & 0xFFFF) == 0xFFFE)      { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take();                           }
+        else if ((bom & 0xFFFF) == 0xFEFF)      { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take();                           }
+        else if ((bom & 0xFFFFFF) == 0xBFBBEF)  { type_ = kUTF8;    hasBOM_ = true; is_->Take(); is_->Take(); is_->Take();              }
+
+        // RFC 4627: Section 3
+        // "Since the first two characters of a JSON text will always be ASCII
+        // characters [RFC0020], it is possible to determine whether an octet
+        // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
+        // at the pattern of nulls in the first four octets."
+        // 00 00 00 xx  UTF-32BE
+        // 00 xx 00 xx  UTF-16BE
+        // xx 00 00 00  UTF-32LE
+        // xx 00 xx 00  UTF-16LE
+        // xx xx xx xx  UTF-8
+
+        if (!hasBOM_) {
+            unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
+            switch (pattern) {
+            case 0x08: type_ = kUTF32BE; break;
+            case 0x0A: type_ = kUTF16BE; break;
+            case 0x01: type_ = kUTF32LE; break;
+            case 0x05: type_ = kUTF16LE; break;
+            case 0x0F: type_ = kUTF8;    break;
+            default: break; // Use type defined by user.
+            }
+        }
+
+        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+        switch (type_) {
+        case kUTF8:
+            // Do nothing
+            break;
+        case kUTF16LE:
+        case kUTF16BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+            break;
+        case kUTF32LE:
+        case kUTF32BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+            break;
+        default:
+            RAPIDJSON_ASSERT(false);    // Invalid type
+        }
+    }
+
+    typedef Ch (*TakeFunc)(InputByteStream& is);
+    InputByteStream* is_;
+    UTFType type_;
+    Ch current_;
+    TakeFunc takeFunc_;
+    bool hasBOM_;
+};
+
+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+    \tparam CharType Type of character for writing.
+    \tparam InputByteStream type of output byte stream to be wrapped.
+*/
+template <typename CharType, typename OutputByteStream>
+class AutoUTFOutputStream {
+    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+    typedef CharType Ch;
+
+    //! Constructor.
+    /*!
+        \param os output stream to be wrapped.
+        \param type UTF encoding type.
+        \param putBOM Whether to write BOM at the beginning of the stream.
+    */
+    AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
+        // RUntime check whether the size of character type is sufficient. It only perform checks with assertion.
+        switch (type_) {
+        case kUTF16LE:
+        case kUTF16BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+            break;
+        case kUTF32LE:
+        case kUTF32BE:
+            RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+            break;
+        case kUTF8:
+            // Do nothing
+            break;
+        default:
+            RAPIDJSON_ASSERT(false);    // Invalid UTFType
+        }
+
+        static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
+        putFunc_ = f[type_];
+
+        if (putBOM)
+            PutBOM();
+    }
+
+    UTFType GetType() const { return type_; }
+
+    void Put(Ch c) { putFunc_(*os_, c); }
+    void Flush() { os_->Flush(); } 
+
+    // Not implemented
+    Ch Peek() const { RAPIDJSON_ASSERT(false); }
+    Ch Take() { RAPIDJSON_ASSERT(false); }
+    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    AutoUTFOutputStream(const AutoUTFOutputStream&);
+    AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
+
+    void PutBOM() { 
+        typedef void (*PutBOMFunc)(OutputByteStream&);
+        static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
+        f[type_](*os_);
+    }
+
+    typedef void (*PutFunc)(OutputByteStream&, Ch);
+
+    OutputByteStream* os_;
+    UTFType type_;
+    PutFunc putFunc_;
+};
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ipaacalib/cpp/include/rapidjson/encodings.h b/ipaacalib/cpp/include/rapidjson/encodings.h
new file mode 100644
index 0000000000000000000000000000000000000000..6bc8aec5d5f1ca1a383d09c3c3ae7ee040427ef3
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/encodings.h
@@ -0,0 +1,630 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ENCODINGS_H_
+#define RAPIDJSON_ENCODINGS_H_
+
+#include "rapidjson.h"
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+    \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+    typename Ch;    //! Type of character. A "character" is actually a code unit in unicode's definition.
+
+    enum { supportUnicode = 1 }; // or 0 if not supporting unicode
+
+    //! \brief Encode a Unicode codepoint to an output stream.
+    //! \param os Output stream.
+    //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint);
+
+    //! \brief Decode a Unicode codepoint from an input stream.
+    //! \param is Input stream.
+    //! \param codepoint Output of the unicode codepoint.
+    //! \return true if a valid codepoint can be decoded from the stream.
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint);
+
+    //! \brief Validate one Unicode codepoint from an encoded stream.
+    //! \param is Input stream to obtain codepoint.
+    //! \param os Output for copying one codepoint.
+    //! \return true if it is valid.
+    //! \note This function just validating and copying the codepoint without actually decode it.
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os);
+
+    // The following functions are deal with byte streams.
+
+    //! Take a character from input byte stream, skip BOM if exist.
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is);
+
+    //! Take a character from input byte stream.
+    template <typename InputByteStream>
+    static Ch Take(InputByteStream& is);
+
+    //! Put BOM to output byte stream.
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os);
+
+    //! Put a character to output byte stream.
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, Ch c);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+    http://tools.ietf.org/html/rfc3629
+    \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
+    \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct UTF8 {
+    typedef CharType Ch;
+
+    enum { supportUnicode = 1 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        if (codepoint <= 0x7F) 
+            os.Put(static_cast<Ch>(codepoint & 0xFF));
+        else if (codepoint <= 0x7FF) {
+            os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+        }
+        else if (codepoint <= 0xFFFF) {
+            os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+        }
+        else {
+            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+            os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+        }
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+        Ch c = is.Take();
+        if (!(c & 0x80)) {
+            *codepoint = (unsigned char)c;
+            return true;
+        }
+
+        unsigned char type = GetRange((unsigned char)c);
+        *codepoint = (0xFF >> type) & (unsigned char)c;
+        bool result = true;
+        switch (type) {
+        case 2: TAIL(); return result;
+        case 3: TAIL(); TAIL(); return result;
+        case 4: COPY(); TRANS(0x50); TAIL(); return result;
+        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+        case 6: TAIL(); TAIL(); TAIL(); return result;
+        case 10: COPY(); TRANS(0x20); TAIL(); return result;
+        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+        default: return false;
+        }
+#undef COPY
+#undef TRANS
+#undef TAIL
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+#define COPY() os.Put(c = is.Take())
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+        Ch c;
+        COPY();
+        if (!(c & 0x80))
+            return true;
+
+        bool result = true;
+        switch (GetRange((unsigned char)c)) {
+        case 2: TAIL(); return result;
+        case 3: TAIL(); TAIL(); return result;
+        case 4: COPY(); TRANS(0x50); TAIL(); return result;
+        case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+        case 6: TAIL(); TAIL(); TAIL(); return result;
+        case 10: COPY(); TRANS(0x20); TAIL(); return result;
+        case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+        default: return false;
+        }
+#undef COPY
+#undef TRANS
+#undef TAIL
+    }
+
+    static unsigned char GetRange(unsigned char c) {
+        // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+        // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
+        static const unsigned char type[] = {
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+            0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+            8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+            10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+        };
+        return type[c];
+    }
+
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        Ch c = Take(is);
+        if ((unsigned char)c != 0xEFu) return c;
+        c = is.Take();
+        if ((unsigned char)c != 0xBBu) return c;
+        c = is.Take();
+        if ((unsigned char)c != 0xBFu) return c;
+        c = is.Take();
+        return c;
+    }
+
+    template <typename InputByteStream>
+    static Ch Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        return is.Take();
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, Ch c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(static_cast<typename OutputByteStream::Ch>(c));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+    http://tools.ietf.org/html/rfc2781
+    \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+    \note implements Encoding concept
+
+    \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+    For streaming, use UTF16LE and UTF16BE, which handle endianness.
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+    typedef CharType Ch;
+    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
+
+    enum { supportUnicode = 1 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+        if (codepoint <= 0xFFFF) {
+            RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair 
+            os.Put(static_cast<typename OutputStream::Ch>(codepoint));
+        }
+        else {
+            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+            unsigned v = codepoint - 0x10000;
+            os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+            os.Put((v & 0x3FF) | 0xDC00);
+        }
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+        Ch c = is.Take();
+        if (c < 0xD800 || c > 0xDFFF) {
+            *codepoint = c;
+            return true;
+        }
+        else if (c <= 0xDBFF) {
+            *codepoint = (c & 0x3FF) << 10;
+            c = is.Take();
+            *codepoint |= (c & 0x3FF);
+            *codepoint += 0x10000;
+            return c >= 0xDC00 && c <= 0xDFFF;
+        }
+        return false;
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+        Ch c;
+        os.Put(c = is.Take());
+        if (c < 0xD800 || c > 0xDFFF)
+            return true;
+        else if (c <= 0xDBFF) {
+            os.Put(c = is.Take());
+            return c >= 0xDC00 && c <= 0xDFFF;
+        }
+        return false;
+    }
+};
+
+//! UTF-16 little endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16LE : UTF16<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take();
+        c |= (unsigned char)is.Take() << 8;
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xFFu); os.Put(0xFEu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(c & 0xFFu);
+        os.Put((c >> 8) & 0xFFu);
+    }
+};
+
+//! UTF-16 big endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16BE : UTF16<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take() << 8;
+        c |= (unsigned char)is.Take();
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xFEu); os.Put(0xFFu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put((c >> 8) & 0xFFu);
+        os.Put(c & 0xFFu);
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding. 
+/*! http://en.wikipedia.org/wiki/UTF-32
+    \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+    \note implements Encoding concept
+
+    \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+    For streaming, use UTF32LE and UTF32BE, which handle endianness.
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+    typedef CharType Ch;
+    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
+
+    enum { supportUnicode = 1 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+        os.Put(codepoint);
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+        Ch c = is.Take();
+        *codepoint = c;
+        return c <= 0x10FFFF;
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+        Ch c;
+        os.Put(c = is.Take());
+        return c <= 0x10FFFF;
+    }
+};
+
+//! UTF-32 little endian enocoding.
+template<typename CharType = unsigned>
+struct UTF32LE : UTF32<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take();
+        c |= (unsigned char)is.Take() << 8;
+        c |= (unsigned char)is.Take() << 16;
+        c |= (unsigned char)is.Take() << 24;
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(c & 0xFFu);
+        os.Put((c >> 8) & 0xFFu);
+        os.Put((c >> 16) & 0xFFu);
+        os.Put((c >> 24) & 0xFFu);
+    }
+};
+
+//! UTF-32 big endian encoding.
+template<typename CharType = unsigned>
+struct UTF32BE : UTF32<CharType> {
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = Take(is);
+        return (unsigned)c == 0x0000FEFFu ? Take(is) : c; 
+    }
+
+    template <typename InputByteStream>
+    static CharType Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        CharType c = (unsigned char)is.Take() << 24;
+        c |= (unsigned char)is.Take() << 16;
+        c |= (unsigned char)is.Take() << 8;
+        c |= (unsigned char)is.Take();
+        return c;
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, CharType c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put((c >> 24) & 0xFFu);
+        os.Put((c >> 16) & 0xFFu);
+        os.Put((c >> 8) & 0xFFu);
+        os.Put(c & 0xFFu);
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ASCII
+
+//! ASCII encoding.
+/*! http://en.wikipedia.org/wiki/ASCII
+    \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
+    \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct ASCII {
+    typedef CharType Ch;
+
+    enum { supportUnicode = 0 };
+
+    template<typename OutputStream>
+    static void Encode(OutputStream& os, unsigned codepoint) {
+        RAPIDJSON_ASSERT(codepoint <= 0x7F);
+        os.Put(static_cast<Ch>(codepoint & 0xFF));
+    }
+
+    template <typename InputStream>
+    static bool Decode(InputStream& is, unsigned* codepoint) {
+        unsigned char c = static_cast<unsigned char>(is.Take());
+        *codepoint = c;
+        return c <= 0X7F;
+    }
+
+    template <typename InputStream, typename OutputStream>
+    static bool Validate(InputStream& is, OutputStream& os) {
+        unsigned char c = is.Take();
+        os.Put(c);
+        return c <= 0x7F;
+    }
+
+    template <typename InputByteStream>
+    static CharType TakeBOM(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        Ch c = Take(is);
+        return c;
+    }
+
+    template <typename InputByteStream>
+    static Ch Take(InputByteStream& is) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+        return is.Take();
+    }
+
+    template <typename OutputByteStream>
+    static void PutBOM(OutputByteStream& os) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        (void)os;
+    }
+
+    template <typename OutputByteStream>
+    static void Put(OutputByteStream& os, Ch c) {
+        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+        os.Put(static_cast<typename OutputByteStream::Ch>(c));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoUTF
+
+//! Runtime-specified UTF encoding type of a stream.
+enum UTFType {
+    kUTF8 = 0,      //!< UTF-8.
+    kUTF16LE = 1,   //!< UTF-16 little endian.
+    kUTF16BE = 2,   //!< UTF-16 big endian.
+    kUTF32LE = 3,   //!< UTF-32 little endian.
+    kUTF32BE = 4    //!< UTF-32 big endian.
+};
+
+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
+*/
+template<typename CharType>
+struct AutoUTF {
+    typedef CharType Ch;
+
+    enum { supportUnicode = 1 };
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+    template<typename OutputStream>
+    RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
+        typedef void (*EncodeFunc)(OutputStream&, unsigned);
+        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
+        (*f[os.GetType()])(os, codepoint);
+    }
+
+    template <typename InputStream>
+    RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+        typedef bool (*DecodeFunc)(InputStream&, unsigned*);
+        static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
+        return (*f[is.GetType()])(is, codepoint);
+    }
+
+    template <typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+        typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
+        static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
+        return (*f[is.GetType()])(is, os);
+    }
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Transcoder
+
+//! Encoding conversion.
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder {
+    //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+        unsigned codepoint;
+        if (!SourceEncoding::Decode(is, &codepoint))
+            return false;
+        TargetEncoding::Encode(os, codepoint);
+        return true;
+    }
+
+    //! Validate one Unicode codepoint from an encoded stream.
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+        return Transcode(is, os);   // Since source/target encoding is different, must transcode.
+    }
+};
+
+//! Specialization of Transcoder with same source and target encoding.
+template<typename Encoding>
+struct Transcoder<Encoding, Encoding> {
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+        os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class.
+        return true;
+    }
+    
+    template<typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+        return Encoding::Validate(is, os);  // source/target encoding are the same
+    }
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__GNUC__) || defined(_MSV_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/ipaacalib/cpp/include/rapidjson/error/en.h b/ipaacalib/cpp/include/rapidjson/error/en.h
new file mode 100644
index 0000000000000000000000000000000000000000..01711833e1ef1ebe1392a3a56392eeab44918e18
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/error/en.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ERROR_EN_H__
+#define RAPIDJSON_ERROR_EN_H__
+
+#include "error.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Maps error code of parsing into error message.
+/*!
+    \ingroup RAPIDJSON_ERRORS
+    \param parseErrorCode Error code obtained in parsing.
+    \return the error message.
+    \note User can make a copy of this function for localization.
+        Using switch-case is safer for future modification of error codes.
+*/
+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
+    switch (parseErrorCode) {
+        case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING("No error.");
+
+        case kParseErrorDocumentEmpty:                  return RAPIDJSON_ERROR_STRING("The document is empty.");
+        case kParseErrorDocumentRootNotSingular:        return RAPIDJSON_ERROR_STRING("The document root must not follow by other values.");
+    
+        case kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");
+    
+        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
+        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
+        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
+    
+        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
+
+        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
+        case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
+        case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
+        case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
+        case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
+
+        case kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
+        case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
+        case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
+
+        case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
+        case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
+
+        default:
+            return RAPIDJSON_ERROR_STRING("Unknown error.");
+    }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ERROR_EN_H__
diff --git a/ipaacalib/cpp/include/rapidjson/error/error.h b/ipaacalib/cpp/include/rapidjson/error/error.h
new file mode 100644
index 0000000000000000000000000000000000000000..161ef87878ef34a6613c76103e7a5ce44928d25a
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/error/error.h
@@ -0,0 +1,150 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ERROR_ERROR_H__
+#define RAPIDJSON_ERROR_ERROR_H__
+
+/*! \file error.h */
+
+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_CHARTYPE
+
+//! Character type of error messages.
+/*! \ingroup RAPIDJSON_ERRORS
+    The default character type is \c char.
+    On Windows, user can define this macro as \c TCHAR for supporting both
+    unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_CHARTYPE
+#define RAPIDJSON_ERROR_CHARTYPE char
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_STRING
+
+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
+/*! \ingroup RAPIDJSON_ERRORS
+    By default this conversion macro does nothing.
+    On Windows, user can define this macro as \c _T(x) for supporting both
+    unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_STRING
+#define RAPIDJSON_ERROR_STRING(x) x
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseErrorCode
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+    \see GenericReader::Parse, GenericReader::GetParseErrorCode
+*/
+enum ParseErrorCode {
+    kParseErrorNone = 0,                        //!< No error.
+
+    kParseErrorDocumentEmpty,                   //!< The document is empty.
+    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.
+
+    kParseErrorValueInvalid,                    //!< Invalid value.
+
+    kParseErrorObjectMissName,                  //!< Missing a name for object member.
+    kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member.
+    kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member.
+
+    kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element.
+
+    kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\u escape in string.
+    kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid.
+    kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string.
+    kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string.
+    kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string.
+
+    kParseErrorNumberTooBig,                    //!< Number too big to be stored in double.
+    kParseErrorNumberMissFraction,              //!< Miss fraction part in number.
+    kParseErrorNumberMissExponent,              //!< Miss exponent in number.
+
+    kParseErrorTermination,                     //!< Parsing was terminated.
+    kParseErrorUnspecificSyntaxError,           //!< Unspecific syntax error.
+};
+
+//! Result of parsing (wraps ParseErrorCode)
+/*!
+    \ingroup RAPIDJSON_ERRORS
+    \code
+        Document doc;
+        ParseResult ok = doc.Parse("[42]");
+        if (!ok) {
+            fprintf(stderr, "JSON parse error: %s (%u)",
+                    GetParseError_En(ok.Code()), ok.Offset());
+            exit(EXIT_FAILURE);
+        }
+    \endcode
+    \see GenericReader::Parse, GenericDocument::Parse
+*/
+struct ParseResult {
+
+    //! Default constructor, no error.
+    ParseResult() : code_(kParseErrorNone), offset_(0) {}
+    //! Constructor to set an error.
+    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
+
+    //! Get the error code.
+    ParseErrorCode Code() const { return code_; }
+    //! Get the error offset, if \ref IsError(), 0 otherwise.
+    size_t Offset() const { return offset_; }
+
+    //! Conversion to \c bool, returns \c true, iff !\ref IsError().
+    operator bool() const { return !IsError(); }
+    //! Whether the result is an error.
+    bool IsError() const { return code_ != kParseErrorNone; }
+
+    bool operator==(const ParseResult& that) const { return code_ == that.code_; }
+    bool operator==(ParseErrorCode code) const { return code_ == code; }
+    friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
+
+    //! Reset error code.
+    void Clear() { Set(kParseErrorNone); }
+    //! Update error code and offset.
+    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
+
+private:
+    ParseErrorCode code_;
+    size_t offset_;
+};
+
+//! Function pointer type of GetParseError().
+/*! \ingroup RAPIDJSON_ERRORS
+
+    This is the prototype for \c GetParseError_X(), where \c X is a locale.
+    User can dynamically change locale in runtime, e.g.:
+\code
+    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
+    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
+\endcode
+*/
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ERROR_ERROR_H__
diff --git a/ipaacalib/cpp/include/rapidjson/filereadstream.h b/ipaacalib/cpp/include/rapidjson/filereadstream.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ff4ab9c526ec24699a06bb013b1732f2d120f26
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/filereadstream.h
@@ -0,0 +1,94 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_FILEREADSTREAM_H_
+#define RAPIDJSON_FILEREADSTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! File byte stream for input using fread().
+/*!
+    \note implements Stream concept
+*/
+class FileReadStream {
+public:
+    typedef char Ch;    //!< Character type (byte).
+
+    //! Constructor.
+    /*!
+        \param fp File pointer opened for read.
+        \param buffer user-supplied buffer.
+        \param bufferSize size of buffer in bytes. Must >=4 bytes.
+    */
+    FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 
+        RAPIDJSON_ASSERT(fp_ != 0);
+        RAPIDJSON_ASSERT(bufferSize >= 4);
+        Read();
+    }
+
+    Ch Peek() const { return *current_; }
+    Ch Take() { Ch c = *current_; Read(); return c; }
+    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
+
+    // Not implemented
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); } 
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+    // For encoding detection only.
+    const Ch* Peek4() const {
+        return (current_ + 4 <= bufferLast_) ? current_ : 0;
+    }
+
+private:
+    void Read() {
+        if (current_ < bufferLast_)
+            ++current_;
+        else if (!eof_) {
+            count_ += readCount_;
+            readCount_ = fread(buffer_, 1, bufferSize_, fp_);
+            bufferLast_ = buffer_ + readCount_ - 1;
+            current_ = buffer_;
+
+            if (readCount_ < bufferSize_) {
+                buffer_[readCount_] = '\0';
+                ++bufferLast_;
+                eof_ = true;
+            }
+        }
+    }
+
+    std::FILE* fp_;
+    Ch *buffer_;
+    size_t bufferSize_;
+    Ch *bufferLast_;
+    Ch *current_;
+    size_t readCount_;
+    size_t count_;  //!< Number of characters read
+    bool eof_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ipaacalib/cpp/include/rapidjson/filestream.h b/ipaacalib/cpp/include/rapidjson/filestream.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2e7172299f8b9bbf3ea6aa9819a8e2c4d4914a4
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/filestream.h
@@ -0,0 +1,73 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_FILESTREAM_H_
+#define RAPIDJSON_FILESTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! (Deprecated) Wrapper of C file stream for input or output.
+/*!
+    This simple wrapper does not check the validity of the stream.
+    \note implements Stream concept
+    \note deprecated: This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead.
+*/
+class FileStream {
+public:
+    typedef char Ch;    //!< Character type. Only support char.
+
+    FileStream(std::FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); }
+    char Peek() const { return current_; }
+    char Take() { char c = current_; Read(); return c; }
+    size_t Tell() const { return count_; }
+    void Put(char c) { fputc(c, fp_); }
+    void Flush() { fflush(fp_); }
+
+    // Not implemented
+    char* PutBegin() { return 0; }
+    size_t PutEnd(char*) { return 0; }
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    FileStream(const FileStream&);
+    FileStream& operator=(const FileStream&);
+
+    void Read() {
+        RAPIDJSON_ASSERT(fp_ != 0);
+        int c = fgetc(fp_);
+        if (c != EOF) {
+            current_ = (char)c;
+            count_++;
+        }
+        else if (current_ != '\0')
+            current_ = '\0';
+    }
+
+    std::FILE* fp_;
+    char current_;
+    size_t count_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ipaacalib/cpp/include/rapidjson/filewritestream.h b/ipaacalib/cpp/include/rapidjson/filewritestream.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f4977d620e346489fa615efbf46d7492d5be0dc
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/filewritestream.h
@@ -0,0 +1,97 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
+#define RAPIDJSON_FILEWRITESTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of C file stream for input using fread().
+/*!
+    \note implements Stream concept
+*/
+class FileWriteStream {
+public:
+    typedef char Ch;    //!< Character type. Only support char.
+
+    FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 
+        RAPIDJSON_ASSERT(fp_ != 0);
+    }
+
+    void Put(char c) { 
+        if (current_ >= bufferEnd_)
+            Flush();
+
+        *current_++ = c;
+    }
+
+    void PutN(char c, size_t n) {
+        size_t avail = static_cast<size_t>(bufferEnd_ - current_);
+        while (n > avail) {
+            std::memset(current_, c, avail);
+            current_ += avail;
+            Flush();
+            n -= avail;
+            avail = static_cast<size_t>(bufferEnd_ - current_);
+        }
+
+        if (n > 0) {
+            std::memset(current_, c, n);
+            current_ += n;
+        }
+    }
+
+    void Flush() {
+        if (current_ != buffer_) {
+            fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
+            current_ = buffer_;
+        }
+    }
+
+    // Not implemented
+    char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+    char Take() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+    char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    FileWriteStream(const FileWriteStream&);
+    FileWriteStream& operator=(const FileWriteStream&);
+
+    std::FILE* fp_;
+    char *buffer_;
+    char *bufferEnd_;
+    char *current_;
+};
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(FileWriteStream& stream, char c, size_t n) {
+    stream.PutN(c, n);
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/biginteger.h b/ipaacalib/cpp/include/rapidjson/internal/biginteger.h
new file mode 100755
index 0000000000000000000000000000000000000000..72acfc385334cd637646ccda6ac9f1954b25622b
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/biginteger.h
@@ -0,0 +1,294 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_BIGINTEGER_H_
+#define RAPIDJSON_BIGINTEGER_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h> // for _umul128
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class BigInteger {
+public:
+    typedef uint64_t Type;
+
+    BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
+        std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+    }
+
+    explicit BigInteger(uint64_t u) : count_(1) {
+        digits_[0] = u;
+    }
+
+    BigInteger(const char* decimals, size_t length) : count_(1) {
+        RAPIDJSON_ASSERT(length > 0);
+        digits_[0] = 0;
+        size_t i = 0;
+        const size_t kMaxDigitPerIteration = 19;  // 2^64 = 18446744073709551616 > 10^19
+        while (length >= kMaxDigitPerIteration) {
+            AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
+            length -= kMaxDigitPerIteration;
+            i += kMaxDigitPerIteration;
+        }
+
+        if (length > 0)
+            AppendDecimal64(decimals + i, decimals + i + length);
+    }
+
+    BigInteger& operator=(uint64_t u) {
+        digits_[0] = u;            
+        count_ = 1;
+        return *this;
+    }
+
+    BigInteger& operator+=(uint64_t u) {
+        Type backup = digits_[0];
+        digits_[0] += u;
+        for (size_t i = 0; i < count_ - 1; i++) {
+            if (digits_[i] >= backup)
+                return *this; // no carry
+            backup = digits_[i + 1];
+            digits_[i + 1] += 1;
+        }
+
+        // Last carry
+        if (digits_[count_ - 1] < backup)
+            PushBack(1);
+
+        return *this;
+    }
+
+    BigInteger& operator*=(uint64_t u) {
+        if (u == 0) return *this = 0;
+        if (u == 1) return *this;
+        if (*this == 1) return *this = u;
+
+        uint64_t k = 0;
+        for (size_t i = 0; i < count_; i++) {
+            uint64_t hi;
+            digits_[i] = MulAdd64(digits_[i], u, k, &hi);
+            k = hi;
+        }
+        
+        if (k > 0)
+            PushBack(k);
+
+        return *this;
+    }
+
+    BigInteger& operator*=(uint32_t u) {
+        if (u == 0) return *this = 0;
+        if (u == 1) return *this;
+        if (*this == 1) return *this = u;
+
+        uint32_t k = 0;
+        for (size_t i = 0; i < count_; i++) {
+            const uint64_t c = digits_[i] >> 32;
+            const uint64_t d = digits_[i] & 0xFFFFFFFF;
+            const uint64_t uc = u * c;
+            const uint64_t ud = u * d;
+            const uint64_t p0 = ud + k;
+            const uint64_t p1 = uc + (p0 >> 32);
+            digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
+            k = p1 >> 32;
+        }
+        
+        if (k > 0)
+            PushBack(k);
+
+        return *this;
+    }
+
+    BigInteger& operator<<=(size_t shift) {
+        if (IsZero() || shift == 0) return *this;
+
+        size_t offset = shift / kTypeBit;
+        size_t interShift = shift % kTypeBit;
+        RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
+
+        if (interShift == 0) {
+            std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
+            count_ += offset;
+        }
+        else {
+            digits_[count_] = 0;
+            for (size_t i = count_; i > 0; i--)
+                digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
+            digits_[offset] = digits_[0] << interShift;
+            count_ += offset;
+            if (digits_[count_])
+                count_++;
+        }
+
+        std::memset(digits_, 0, offset * sizeof(Type));
+
+        return *this;
+    }
+
+    bool operator==(const BigInteger& rhs) const {
+        return count_ == rhs.count_ && memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
+    }
+
+    bool operator==(const Type rhs) const {
+        return count_ == 1 && digits_[0] == rhs;
+    }
+
+    BigInteger& MultiplyPow5(unsigned exp) {
+        static const uint32_t kPow5[12] = {
+            5,
+            5 * 5,
+            5 * 5 * 5,
+            5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+        };
+        if (exp == 0) return *this;
+        for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
+        for (; exp >= 13; exp -= 13) *this *= 1220703125u; // 5^13
+        if (exp > 0)                 *this *= kPow5[exp - 1];
+        return *this;
+    }
+
+    // Compute absolute difference of this and rhs.
+    // Return false if this < rhs
+    bool Difference(const BigInteger& rhs, BigInteger* out) const {
+        int cmp = Compare(rhs);
+        if (cmp == 0) {
+            *out = BigInteger(0);
+            return false;
+        }
+        const BigInteger *a, *b;  // Makes a > b
+        bool ret;
+        if (cmp < 0) { a = &rhs; b = this; ret = true; }
+        else         { a = this; b = &rhs; ret = false; }
+
+        Type borrow = 0;
+        for (size_t i = 0; i < a->count_; i++) {
+            Type d = a->digits_[i] - borrow;
+            if (i < b->count_)
+                d -= b->digits_[i];
+            borrow = (d > a->digits_[i]) ? 1 : 0;
+            out->digits_[i] = d;
+            if (d != 0)
+                out->count_ = i + 1;
+        }
+
+        return ret;
+    }
+
+    int Compare(const BigInteger& rhs) const {
+        if (count_ != rhs.count_)
+            return count_ < rhs.count_ ? -1 : 1;
+
+        for (size_t i = count_; i-- > 0;)
+            if (digits_[i] != rhs.digits_[i])
+                return digits_[i] < rhs.digits_[i] ? -1 : 1;
+
+        return 0;
+    }
+
+    size_t GetCount() const { return count_; }
+    Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
+    bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
+
+private:
+    void AppendDecimal64(const char* begin, const char* end) {
+        uint64_t u = ParseUint64(begin, end);
+        if (IsZero())
+            *this = u;
+        else {
+            unsigned exp = static_cast<unsigned>(end - begin);
+            (MultiplyPow5(exp) <<= exp) += u;   // *this = *this * 10^exp + u
+        }
+    }
+
+    void PushBack(Type digit) {
+        RAPIDJSON_ASSERT(count_ < kCapacity);
+        digits_[count_++] = digit;
+    }
+
+    static uint64_t ParseUint64(const char* begin, const char* end) {
+        uint64_t r = 0;
+        for (const char* p = begin; p != end; ++p) {
+            RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
+            r = r * 10 + (*p - '0');
+        }
+        return r;
+    }
+
+    // Assume a * b + k < 2^128
+    static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+        uint64_t low = _umul128(a, b, outHigh) + k;
+        if (low < k)
+            (*outHigh)++;
+        return low;
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+        unsigned __int128 p = static_cast<unsigned __int128>(a) * static_cast<unsigned __int128>(b);
+        p += k;
+        *outHigh = p >> 64;
+        return static_cast<uint64_t>(p);
+#else
+        const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
+        uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
+        x1 += (x0 >> 32); // can't give carry
+        x1 += x2;
+        if (x1 < x2)
+            x3 += (static_cast<uint64_t>(1) << 32);
+        uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
+        uint64_t hi = x3 + (x1 >> 32);
+
+        lo += k;
+        if (lo < k)
+            hi++;
+        *outHigh = hi;
+        return lo;
+#endif
+    }
+
+    static Type FullAdd(Type a, Type b, bool inCarry, bool* outCarry) {
+        Type c = a + b + (inCarry ? 1 : 0);
+        *outCarry = c < a;
+        return c;
+    }
+
+    static const size_t kBitCount = 3328;  // 64bit * 54 > 10^1000
+    static const size_t kCapacity = kBitCount / sizeof(Type);
+    static const size_t kTypeBit = sizeof(Type) * 8;
+
+    Type digits_[kCapacity];
+    size_t count_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_BIGINTEGER_H_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/diyfp.h b/ipaacalib/cpp/include/rapidjson/internal/diyfp.h
new file mode 100644
index 0000000000000000000000000000000000000000..174b9facfb0fd0218479e594a288b8e28943724a
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/diyfp.h
@@ -0,0 +1,268 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DIYFP_H_
+#define RAPIDJSON_DIYFP_H_
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#if defined(_M_AMD64)
+#pragma intrinsic(_BitScanReverse64)
+#endif
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+struct DiyFp {
+    DiyFp() {}
+
+    DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
+
+    explicit DiyFp(double d) {
+        union {
+            double d;
+            uint64_t u64;
+        } u = { d };
+
+        int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
+        uint64_t significand = (u.u64 & kDpSignificandMask);
+        if (biased_e != 0) {
+            f = significand + kDpHiddenBit;
+            e = biased_e - kDpExponentBias;
+        } 
+        else {
+            f = significand;
+            e = kDpMinExponent + 1;
+        }
+    }
+
+    DiyFp operator-(const DiyFp& rhs) const {
+        return DiyFp(f - rhs.f, e);
+    }
+
+    DiyFp operator*(const DiyFp& rhs) const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+        uint64_t h;
+        uint64_t l = _umul128(f, rhs.f, &h);
+        if (l & (uint64_t(1) << 63)) // rounding
+            h++;
+        return DiyFp(h, e + rhs.e + 64);
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+        unsigned __int128 p = static_cast<unsigned __int128>(f) * static_cast<unsigned __int128>(rhs.f);
+        uint64_t h = p >> 64;
+        uint64_t l = static_cast<uint64_t>(p);
+        if (l & (uint64_t(1) << 63)) // rounding
+            h++;
+        return DiyFp(h, e + rhs.e + 64);
+#else
+        const uint64_t M32 = 0xFFFFFFFF;
+        const uint64_t a = f >> 32;
+        const uint64_t b = f & M32;
+        const uint64_t c = rhs.f >> 32;
+        const uint64_t d = rhs.f & M32;
+        const uint64_t ac = a * c;
+        const uint64_t bc = b * c;
+        const uint64_t ad = a * d;
+        const uint64_t bd = b * d;
+        uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
+        tmp += 1U << 31;  /// mult_round
+        return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
+#endif
+    }
+
+    DiyFp Normalize() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+        unsigned long index;
+        _BitScanReverse64(&index, f);
+        return DiyFp(f << (63 - index), e - (63 - index));
+#elif defined(__GNUC__) && __GNUC__ >= 4
+        int s = __builtin_clzll(f);
+        return DiyFp(f << s, e - s);
+#else
+        DiyFp res = *this;
+        while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
+            res.f <<= 1;
+            res.e--;
+        }
+        return res;
+#endif
+    }
+
+    DiyFp NormalizeBoundary() const {
+        DiyFp res = *this;
+        while (!(res.f & (kDpHiddenBit << 1))) {
+            res.f <<= 1;
+            res.e--;
+        }
+        res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+        res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+        return res;
+    }
+
+    void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+        DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+        DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+        mi.f <<= mi.e - pl.e;
+        mi.e = pl.e;
+        *plus = pl;
+        *minus = mi;
+    }
+
+    double ToDouble() const {
+        union {
+            double d;
+            uint64_t u64;
+        }u;
+        uint64_t significand = f;
+        int exponent = e;
+        while (significand > kDpHiddenBit + kDpSignificandMask) {
+            significand >>= 1;
+            exponent++;
+        }
+        while (exponent > kDpDenormalExponent && (significand & kDpHiddenBit) == 0) {
+            significand <<= 1;
+            exponent--;
+        }
+        if (exponent >= kDpMaxExponent) {
+            u.u64 = kDpExponentMask;    // Infinity
+            return u.d;
+        }
+        else if (exponent < kDpDenormalExponent)
+            return 0.0;
+        const uint64_t be = (exponent == kDpDenormalExponent && (significand & kDpHiddenBit) == 0) ? 0 : 
+            static_cast<uint64_t>(exponent + kDpExponentBias);
+        u.u64 = (significand & kDpSignificandMask) | (be << kDpSignificandSize);
+        return u.d;
+    }
+
+    static const int kDiySignificandSize = 64;
+    static const int kDpSignificandSize = 52;
+    static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
+    static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
+    static const int kDpMinExponent = -kDpExponentBias;
+    static const int kDpDenormalExponent = -kDpExponentBias + 1;
+    static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+    static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+    static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+    uint64_t f;
+    int e;
+};
+
+inline DiyFp GetCachedPowerByIndex(size_t index) {
+    // 10^-348, 10^-340, ..., 10^340
+    static const uint64_t kCachedPowers_F[] = {
+        RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
+        RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
+        RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
+        RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
+        RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
+        RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
+        RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
+        RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
+        RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
+        RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
+        RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
+        RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
+        RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
+        RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
+        RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
+        RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
+        RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
+        RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
+        RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
+        RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
+        RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
+        RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
+        RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
+        RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
+        RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
+        RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
+        RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
+        RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
+        RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
+        RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
+        RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
+        RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
+        RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
+        RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
+        RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
+        RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
+        RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
+        RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
+        RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
+        RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
+        RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
+        RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
+        RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
+        RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
+    };
+    static const int16_t kCachedPowers_E[] = {
+        -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,
+        -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,
+        -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,
+        -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183,
+        -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83,
+        109,   136,   162,   189,   216,   242,   269,   295,   322,   348,
+        375,   402,   428,   455,   481,   508,   534,   561,   588,   614,
+        641,   667,   694,   720,   747,   774,   800,   827,   853,   880,
+        907,   933,   960,   986,  1013,  1039,  1066
+    };
+    return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
+}
+    
+inline DiyFp GetCachedPower(int e, int* K) {
+
+    //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+    double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive
+    int k = static_cast<int>(dk);
+    if (k != dk)
+        k++;
+
+    unsigned index = static_cast<unsigned>((k >> 3) + 1);
+    *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table
+
+    return GetCachedPowerByIndex(index);
+}
+
+inline DiyFp GetCachedPower10(int exp, int *outExp) {
+     unsigned index = (exp + 348) / 8;
+     *outExp = -348 + index * 8;
+     return GetCachedPowerByIndex(index);
+ }
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DIYFP_H_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/dtoa.h b/ipaacalib/cpp/include/rapidjson/internal/dtoa.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0fa2b89085c0de916c27515c96bb2d380595581
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/dtoa.h
@@ -0,0 +1,225 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DTOA_
+#define RAPIDJSON_DTOA_
+
+#include "itoa.h" // GetDigitsLut()
+#include "diyfp.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+    while (rest < wp_w && delta - rest >= ten_kappa &&
+           (rest + ten_kappa < wp_w ||  /// closer
+            wp_w - rest > rest + ten_kappa - wp_w)) {
+        buffer[len - 1]--;
+        rest += ten_kappa;
+    }
+}
+
+inline unsigned CountDecimalDigit32(uint32_t n) {
+    // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+    if (n < 10) return 1;
+    if (n < 100) return 2;
+    if (n < 1000) return 3;
+    if (n < 10000) return 4;
+    if (n < 100000) return 5;
+    if (n < 1000000) return 6;
+    if (n < 10000000) return 7;
+    if (n < 100000000) return 8;
+    if (n < 1000000000) return 9;
+    return 10;
+}
+
+inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+    static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+    const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+    const DiyFp wp_w = Mp - W;
+    uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+    uint64_t p2 = Mp.f & (one.f - 1);
+    int kappa = CountDecimalDigit32(p1);
+    *len = 0;
+
+    while (kappa > 0) {
+        uint32_t d;
+        switch (kappa) {
+            case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
+            case  9: d = p1 /  100000000; p1 %=  100000000; break;
+            case  8: d = p1 /   10000000; p1 %=   10000000; break;
+            case  7: d = p1 /    1000000; p1 %=    1000000; break;
+            case  6: d = p1 /     100000; p1 %=     100000; break;
+            case  5: d = p1 /      10000; p1 %=      10000; break;
+            case  4: d = p1 /       1000; p1 %=       1000; break;
+            case  3: d = p1 /        100; p1 %=        100; break;
+            case  2: d = p1 /         10; p1 %=         10; break;
+            case  1: d = p1;              p1 =           0; break;
+            default: 
+#if defined(_MSC_VER)
+                __assume(0);
+#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+                __builtin_unreachable();
+#else
+                d = 0;
+#endif
+        }
+        if (d || *len)
+            buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
+        kappa--;
+        uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+        if (tmp <= delta) {
+            *K += kappa;
+            GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+            return;
+        }
+    }
+
+    // kappa = 0
+    for (;;) {
+        p2 *= 10;
+        delta *= 10;
+        char d = static_cast<char>(p2 >> -one.e);
+        if (d || *len)
+            buffer[(*len)++] = static_cast<char>('0' + d);
+        p2 &= one.f - 1;
+        kappa--;
+        if (p2 < delta) {
+            *K += kappa;
+            GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
+            return;
+        }
+    }
+}
+
+inline void Grisu2(double value, char* buffer, int* length, int* K) {
+    const DiyFp v(value);
+    DiyFp w_m, w_p;
+    v.NormalizedBoundaries(&w_m, &w_p);
+
+    const DiyFp c_mk = GetCachedPower(w_p.e, K);
+    const DiyFp W = v.Normalize() * c_mk;
+    DiyFp Wp = w_p * c_mk;
+    DiyFp Wm = w_m * c_mk;
+    Wm.f++;
+    Wp.f--;
+    DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+
+inline char* WriteExponent(int K, char* buffer) {
+    if (K < 0) {
+        *buffer++ = '-';
+        K = -K;
+    }
+
+    if (K >= 100) {
+        *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
+        K %= 100;
+        const char* d = GetDigitsLut() + K * 2;
+        *buffer++ = d[0];
+        *buffer++ = d[1];
+    }
+    else if (K >= 10) {
+        const char* d = GetDigitsLut() + K * 2;
+        *buffer++ = d[0];
+        *buffer++ = d[1];
+    }
+    else
+        *buffer++ = static_cast<char>('0' + static_cast<char>(K));
+
+    return buffer;
+}
+
+inline char* Prettify(char* buffer, int length, int k) {
+    const int kk = length + k;  // 10^(kk-1) <= v < 10^kk
+
+    if (length <= kk && kk <= 21) {
+        // 1234e7 -> 12340000000
+        for (int i = length; i < kk; i++)
+            buffer[i] = '0';
+        buffer[kk] = '.';
+        buffer[kk + 1] = '0';
+        return &buffer[kk + 2];
+    }
+    else if (0 < kk && kk <= 21) {
+        // 1234e-2 -> 12.34
+        std::memmove(&buffer[kk + 1], &buffer[kk], length - kk);
+        buffer[kk] = '.';
+        return &buffer[length + 1];
+    }
+    else if (-6 < kk && kk <= 0) {
+        // 1234e-6 -> 0.001234
+        const int offset = 2 - kk;
+        std::memmove(&buffer[offset], &buffer[0], length);
+        buffer[0] = '0';
+        buffer[1] = '.';
+        for (int i = 2; i < offset; i++)
+            buffer[i] = '0';
+        return &buffer[length + offset];
+    }
+    else if (length == 1) {
+        // 1e30
+        buffer[1] = 'e';
+        return WriteExponent(kk - 1, &buffer[2]);
+    }
+    else {
+        // 1234e30 -> 1.234e33
+        std::memmove(&buffer[2], &buffer[1], length - 1);
+        buffer[1] = '.';
+        buffer[length + 1] = 'e';
+        return WriteExponent(kk - 1, &buffer[0 + length + 2]);
+    }
+}
+
+inline char* dtoa(double value, char* buffer) {
+    if (value == 0) {
+        buffer[0] = '0';
+        buffer[1] = '.';
+        buffer[2] = '0';
+        return &buffer[3];
+    }
+    else {
+        if (value < 0) {
+            *buffer++ = '-';
+            value = -value;
+        }
+        int length, K;
+        Grisu2(value, buffer, &length, &K);
+        return Prettify(buffer, length, K);
+    }
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DTOA_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/ieee754.h b/ipaacalib/cpp/include/rapidjson/internal/ieee754.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab65cc9a8207e68fadfc203c7528aa273955d291
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/ieee754.h
@@ -0,0 +1,90 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_IEEE754_
+#define RAPIDJSON_IEEE754_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class Double {
+public:
+    Double() {}
+    Double(double d) : d(d) {}
+    Double(uint64_t u) : u(u) {}
+
+    double Value() const { return d; }
+    uint64_t Uint64Value() const { return u; }
+
+    double NextPositiveDouble() const {
+        RAPIDJSON_ASSERT(!Sign());
+        return Double(u + 1).Value();
+    }
+
+    double PreviousPositiveDouble() const {
+        RAPIDJSON_ASSERT(!Sign());
+        if (d == 0.0)
+            return 0.0;
+        else
+            return Double(u - 1).Value();
+    }
+
+    bool Sign() const { return (u & kSignMask) != 0; }
+    uint64_t Significand() const { return u & kSignificandMask; }
+    int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
+
+    bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; }
+    bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; }
+    bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; }
+
+    uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
+    int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
+    uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; }
+
+    static unsigned EffectiveSignificandSize(int order) {
+        if (order >= -1021)
+            return 53;
+        else if (order <= -1074)
+            return 0;
+        else
+            return order + 1074;
+    }
+
+private:
+    static const int kSignificandSize = 52;
+    static const int kExponentBias = 0x3FF;
+    static const int kDenormalExponent = 1 - kExponentBias;
+    static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
+    static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+    static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+    static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+    union {
+        double d;
+        uint64_t u;
+    };
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_IEEE754_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/itoa.h b/ipaacalib/cpp/include/rapidjson/internal/itoa.h
new file mode 100644
index 0000000000000000000000000000000000000000..3684f07363f6ec4632291f59f1ebfea750bfaae5
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/itoa.h
@@ -0,0 +1,306 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_ITOA_
+#define RAPIDJSON_ITOA_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline const char* GetDigitsLut() {
+    static const char cDigitsLut[200] = {
+        '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+        '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+        '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+        '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+        '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+        '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+        '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+        '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+        '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+        '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+    };
+    return cDigitsLut;
+}
+
+inline char* u32toa(uint32_t value, char* buffer) {
+    const char* cDigitsLut = GetDigitsLut();
+
+    if (value < 10000) {
+        const uint32_t d1 = (value / 100) << 1;
+        const uint32_t d2 = (value % 100) << 1;
+        
+        if (value >= 1000)
+            *buffer++ = cDigitsLut[d1];
+        if (value >= 100)
+            *buffer++ = cDigitsLut[d1 + 1];
+        if (value >= 10)
+            *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+    }
+    else if (value < 100000000) {
+        // value = bbbbcccc
+        const uint32_t b = value / 10000;
+        const uint32_t c = value % 10000;
+        
+        const uint32_t d1 = (b / 100) << 1;
+        const uint32_t d2 = (b % 100) << 1;
+        
+        const uint32_t d3 = (c / 100) << 1;
+        const uint32_t d4 = (c % 100) << 1;
+        
+        if (value >= 10000000)
+            *buffer++ = cDigitsLut[d1];
+        if (value >= 1000000)
+            *buffer++ = cDigitsLut[d1 + 1];
+        if (value >= 100000)
+            *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+        
+        *buffer++ = cDigitsLut[d3];
+        *buffer++ = cDigitsLut[d3 + 1];
+        *buffer++ = cDigitsLut[d4];
+        *buffer++ = cDigitsLut[d4 + 1];
+    }
+    else {
+        // value = aabbbbcccc in decimal
+        
+        const uint32_t a = value / 100000000; // 1 to 42
+        value %= 100000000;
+        
+        if (a >= 10) {
+            const unsigned i = a << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+        }
+        else
+            *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+
+        const uint32_t b = value / 10000; // 0 to 9999
+        const uint32_t c = value % 10000; // 0 to 9999
+        
+        const uint32_t d1 = (b / 100) << 1;
+        const uint32_t d2 = (b % 100) << 1;
+        
+        const uint32_t d3 = (c / 100) << 1;
+        const uint32_t d4 = (c % 100) << 1;
+        
+        *buffer++ = cDigitsLut[d1];
+        *buffer++ = cDigitsLut[d1 + 1];
+        *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+        *buffer++ = cDigitsLut[d3];
+        *buffer++ = cDigitsLut[d3 + 1];
+        *buffer++ = cDigitsLut[d4];
+        *buffer++ = cDigitsLut[d4 + 1];
+    }
+    return buffer;
+}
+
+inline char* i32toa(int32_t value, char* buffer) {
+    if (value < 0) {
+        *buffer++ = '-';
+        value = -value;
+    }
+
+    return u32toa(static_cast<uint32_t>(value), buffer);
+}
+
+inline char* u64toa(uint64_t value, char* buffer) {
+    const char* cDigitsLut = GetDigitsLut();
+    const uint64_t  kTen8 = 100000000;
+    const uint64_t  kTen9 = kTen8 * 10;
+    const uint64_t kTen10 = kTen8 * 100;
+    const uint64_t kTen11 = kTen8 * 1000;
+    const uint64_t kTen12 = kTen8 * 10000;
+    const uint64_t kTen13 = kTen8 * 100000;
+    const uint64_t kTen14 = kTen8 * 1000000;
+    const uint64_t kTen15 = kTen8 * 10000000;
+    const uint64_t kTen16 = kTen8 * kTen8;
+    
+    if (value < kTen8) {
+        uint32_t v = static_cast<uint32_t>(value);
+        if (v < 10000) {
+            const uint32_t d1 = (v / 100) << 1;
+            const uint32_t d2 = (v % 100) << 1;
+            
+            if (v >= 1000)
+                *buffer++ = cDigitsLut[d1];
+            if (v >= 100)
+                *buffer++ = cDigitsLut[d1 + 1];
+            if (v >= 10)
+                *buffer++ = cDigitsLut[d2];
+            *buffer++ = cDigitsLut[d2 + 1];
+        }
+        else {
+            // value = bbbbcccc
+            const uint32_t b = v / 10000;
+            const uint32_t c = v % 10000;
+            
+            const uint32_t d1 = (b / 100) << 1;
+            const uint32_t d2 = (b % 100) << 1;
+            
+            const uint32_t d3 = (c / 100) << 1;
+            const uint32_t d4 = (c % 100) << 1;
+            
+            if (value >= 10000000)
+                *buffer++ = cDigitsLut[d1];
+            if (value >= 1000000)
+                *buffer++ = cDigitsLut[d1 + 1];
+            if (value >= 100000)
+                *buffer++ = cDigitsLut[d2];
+            *buffer++ = cDigitsLut[d2 + 1];
+            
+            *buffer++ = cDigitsLut[d3];
+            *buffer++ = cDigitsLut[d3 + 1];
+            *buffer++ = cDigitsLut[d4];
+            *buffer++ = cDigitsLut[d4 + 1];
+        }
+    }
+    else if (value < kTen16) {
+        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+        
+        const uint32_t b0 = v0 / 10000;
+        const uint32_t c0 = v0 % 10000;
+        
+        const uint32_t d1 = (b0 / 100) << 1;
+        const uint32_t d2 = (b0 % 100) << 1;
+        
+        const uint32_t d3 = (c0 / 100) << 1;
+        const uint32_t d4 = (c0 % 100) << 1;
+
+        const uint32_t b1 = v1 / 10000;
+        const uint32_t c1 = v1 % 10000;
+        
+        const uint32_t d5 = (b1 / 100) << 1;
+        const uint32_t d6 = (b1 % 100) << 1;
+        
+        const uint32_t d7 = (c1 / 100) << 1;
+        const uint32_t d8 = (c1 % 100) << 1;
+
+        if (value >= kTen15)
+            *buffer++ = cDigitsLut[d1];
+        if (value >= kTen14)
+            *buffer++ = cDigitsLut[d1 + 1];
+        if (value >= kTen13)
+            *buffer++ = cDigitsLut[d2];
+        if (value >= kTen12)
+            *buffer++ = cDigitsLut[d2 + 1];
+        if (value >= kTen11)
+            *buffer++ = cDigitsLut[d3];
+        if (value >= kTen10)
+            *buffer++ = cDigitsLut[d3 + 1];
+        if (value >= kTen9)
+            *buffer++ = cDigitsLut[d4];
+        if (value >= kTen8)
+            *buffer++ = cDigitsLut[d4 + 1];
+        
+        *buffer++ = cDigitsLut[d5];
+        *buffer++ = cDigitsLut[d5 + 1];
+        *buffer++ = cDigitsLut[d6];
+        *buffer++ = cDigitsLut[d6 + 1];
+        *buffer++ = cDigitsLut[d7];
+        *buffer++ = cDigitsLut[d7 + 1];
+        *buffer++ = cDigitsLut[d8];
+        *buffer++ = cDigitsLut[d8 + 1];
+    }
+    else {
+        const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
+        value %= kTen16;
+        
+        if (a < 10)
+            *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+        else if (a < 100) {
+            const uint32_t i = a << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+        }
+        else if (a < 1000) {
+            *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
+            
+            const uint32_t i = (a % 100) << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+        }
+        else {
+            const uint32_t i = (a / 100) << 1;
+            const uint32_t j = (a % 100) << 1;
+            *buffer++ = cDigitsLut[i];
+            *buffer++ = cDigitsLut[i + 1];
+            *buffer++ = cDigitsLut[j];
+            *buffer++ = cDigitsLut[j + 1];
+        }
+        
+        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+        
+        const uint32_t b0 = v0 / 10000;
+        const uint32_t c0 = v0 % 10000;
+        
+        const uint32_t d1 = (b0 / 100) << 1;
+        const uint32_t d2 = (b0 % 100) << 1;
+        
+        const uint32_t d3 = (c0 / 100) << 1;
+        const uint32_t d4 = (c0 % 100) << 1;
+        
+        const uint32_t b1 = v1 / 10000;
+        const uint32_t c1 = v1 % 10000;
+        
+        const uint32_t d5 = (b1 / 100) << 1;
+        const uint32_t d6 = (b1 % 100) << 1;
+        
+        const uint32_t d7 = (c1 / 100) << 1;
+        const uint32_t d8 = (c1 % 100) << 1;
+        
+        *buffer++ = cDigitsLut[d1];
+        *buffer++ = cDigitsLut[d1 + 1];
+        *buffer++ = cDigitsLut[d2];
+        *buffer++ = cDigitsLut[d2 + 1];
+        *buffer++ = cDigitsLut[d3];
+        *buffer++ = cDigitsLut[d3 + 1];
+        *buffer++ = cDigitsLut[d4];
+        *buffer++ = cDigitsLut[d4 + 1];
+        *buffer++ = cDigitsLut[d5];
+        *buffer++ = cDigitsLut[d5 + 1];
+        *buffer++ = cDigitsLut[d6];
+        *buffer++ = cDigitsLut[d6 + 1];
+        *buffer++ = cDigitsLut[d7];
+        *buffer++ = cDigitsLut[d7 + 1];
+        *buffer++ = cDigitsLut[d8];
+        *buffer++ = cDigitsLut[d8 + 1];
+    }
+    
+    return buffer;
+}
+
+inline char* i64toa(int64_t value, char* buffer) {
+    if (value < 0) {
+        *buffer++ = '-';
+        value = -value;
+    }
+
+    return u64toa(static_cast<uint64_t>(value), buffer);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ITOA_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/meta.h b/ipaacalib/cpp/include/rapidjson/internal/meta.h
new file mode 100644
index 0000000000000000000000000000000000000000..226465a219f026eb97332f047047c853982e009f
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/meta.h
@@ -0,0 +1,189 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_INTERNAL_META_H_
+#define RAPIDJSON_INTERNAL_META_H_
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#error <rapidjson.h> not yet included. Do not include this file directly.
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+#if defined(_MSC_VER)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(6334)
+#endif
+
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+#include <type_traits>
+#endif
+
+//@cond RAPIDJSON_INTERNAL
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
+template <typename T> struct Void { typedef void Type; };
+
+///////////////////////////////////////////////////////////////////////////////
+// BoolType, TrueType, FalseType
+//
+template <bool Cond> struct BoolType {
+    static const bool Value = Cond;
+    typedef BoolType Type;
+};
+typedef BoolType<true> TrueType;
+typedef BoolType<false> FalseType;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
+//
+
+template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
+template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
+template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
+template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
+
+template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
+template <> struct AndExprCond<true, true> : TrueType {};
+template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
+template <> struct OrExprCond<false, false> : FalseType {};
+
+template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
+template <typename C> struct NotExpr  : SelectIf<C,FalseType,TrueType>::Type {};
+template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
+template <typename C1, typename C2> struct OrExpr  : OrExprCond<C1::Value, C2::Value>::Type {};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AddConst, MaybeAddConst, RemoveConst
+template <typename T> struct AddConst { typedef const T Type; };
+template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
+template <typename T> struct RemoveConst { typedef T Type; };
+template <typename T> struct RemoveConst<const T> { typedef T Type; };
+
+
+///////////////////////////////////////////////////////////////////////////////
+// IsSame, IsConst, IsMoreConst, IsPointer
+//
+template <typename T, typename U> struct IsSame : FalseType {};
+template <typename T> struct IsSame<T, T> : TrueType {};
+
+template <typename T> struct IsConst : FalseType {};
+template <typename T> struct IsConst<const T> : TrueType {};
+
+template <typename CT, typename T>
+struct IsMoreConst
+    : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
+              BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
+
+template <typename T> struct IsPointer : FalseType {};
+template <typename T> struct IsPointer<T*> : TrueType {};
+
+///////////////////////////////////////////////////////////////////////////////
+// IsBaseOf
+//
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+template <typename B, typename D> struct IsBaseOf
+    : BoolType< ::std::is_base_of<B,D>::value> {};
+
+#else // simplified version adopted from Boost
+
+template<typename B, typename D> struct IsBaseOfImpl {
+    RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
+    RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
+
+    typedef char (&Yes)[1];
+    typedef char (&No) [2];
+
+    template <typename T>
+    static Yes Check(const D*, T);
+    static No  Check(const B*, int);
+
+    struct Host {
+        operator const B*() const;
+        operator const D*();
+    };
+
+    enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
+};
+
+template <typename B, typename D> struct IsBaseOf
+    : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
+
+#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+
+//////////////////////////////////////////////////////////////////////////
+// EnableIf / DisableIf
+//
+template <bool Condition, typename T = void> struct EnableIfCond  { typedef T Type; };
+template <typename T> struct EnableIfCond<false, T> { /* empty */ };
+
+template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
+template <typename T> struct DisableIfCond<true, T> { /* empty */ };
+
+template <typename Condition, typename T = void>
+struct EnableIf : EnableIfCond<Condition::Value, T> {};
+
+template <typename Condition, typename T = void>
+struct DisableIf : DisableIfCond<Condition::Value, T> {};
+
+// SFINAE helpers
+struct SfinaeTag {};
+template <typename T> struct RemoveSfinaeTag;
+template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
+
+#define RAPIDJSON_REMOVEFPTR_(type) \
+    typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
+        < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
+
+#define RAPIDJSON_ENABLEIF(cond) \
+    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_DISABLEIF(cond) \
+    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
+    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond), \
+         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
+    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+        <RAPIDJSON_REMOVEFPTR_(cond), \
+         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+//@endcond
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_META_H_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/pow10.h b/ipaacalib/cpp/include/rapidjson/internal/pow10.h
new file mode 100644
index 0000000000000000000000000000000000000000..0252edfe582da7756f5708fbe42f0ff81e9cff33
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/pow10.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+    \param n non-negative exponent. Must <= 308.
+    \return 10.0^n
+*/
+inline double Pow10(int n) {
+    static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
+        1e+0,  
+        1e+1,  1e+2,  1e+3,  1e+4,  1e+5,  1e+6,  1e+7,  1e+8,  1e+9,  1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 
+        1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+        1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+        1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+        1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+        1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+        1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+        1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+        1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+        1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+        1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+        1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+        1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+        1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+        1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
+        1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
+    };
+    RAPIDJSON_ASSERT(n >= 0 && n <= 308);
+    return e[n];
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POW10_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/stack.h b/ipaacalib/cpp/include/rapidjson/internal/stack.h
new file mode 100644
index 0000000000000000000000000000000000000000..93c5f45a5a4b9f9a2967105c61ba7a7c207f7259
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/stack.h
@@ -0,0 +1,183 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+    // Optimization note: Do not allocate memory for stack_ in constructor.
+    // Do it lazily when first Push() -> Expand() -> Resize().
+    Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
+        RAPIDJSON_ASSERT(stackCapacity > 0);
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    Stack(Stack&& rhs)
+        : allocator_(rhs.allocator_),
+          ownAllocator_(rhs.ownAllocator_),
+          stack_(rhs.stack_),
+          stackTop_(rhs.stackTop_),
+          stackEnd_(rhs.stackEnd_),
+          initialCapacity_(rhs.initialCapacity_)
+    {
+        rhs.allocator_ = 0;
+        rhs.ownAllocator_ = 0;
+        rhs.stack_ = 0;
+        rhs.stackTop_ = 0;
+        rhs.stackEnd_ = 0;
+        rhs.initialCapacity_ = 0;
+    }
+#endif
+
+    ~Stack() {
+        Destroy();
+    }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    Stack& operator=(Stack&& rhs) {
+        if (&rhs != this)
+        {
+            Destroy();
+
+            allocator_ = rhs.allocator_;
+            ownAllocator_ = rhs.ownAllocator_;
+            stack_ = rhs.stack_;
+            stackTop_ = rhs.stackTop_;
+            stackEnd_ = rhs.stackEnd_;
+            initialCapacity_ = rhs.initialCapacity_;
+
+            rhs.allocator_ = 0;
+            rhs.ownAllocator_ = 0;
+            rhs.stack_ = 0;
+            rhs.stackTop_ = 0;
+            rhs.stackEnd_ = 0;
+            rhs.initialCapacity_ = 0;
+        }
+        return *this;
+    }
+#endif
+
+    void Clear() { stackTop_ = stack_; }
+
+    void ShrinkToFit() { 
+        if (Empty()) {
+            // If the stack is empty, completely deallocate the memory.
+            Allocator::Free(stack_);
+            stack_ = 0;
+            stackTop_ = 0;
+            stackEnd_ = 0;
+        }
+        else
+            Resize(GetSize());
+    }
+
+    // Optimization note: try to minimize the size of this function for force inline.
+    // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
+    template<typename T>
+    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+         // Expand the stack if needed
+        if (stackTop_ + sizeof(T) * count >= stackEnd_)
+            Expand<T>(count);
+
+        T* ret = reinterpret_cast<T*>(stackTop_);
+        stackTop_ += sizeof(T) * count;
+        return ret;
+    }
+
+    template<typename T>
+    T* Pop(size_t count) {
+        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+        stackTop_ -= count * sizeof(T);
+        return reinterpret_cast<T*>(stackTop_);
+    }
+
+    template<typename T>
+    T* Top() { 
+        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+    }
+
+    template<typename T>
+    T* Bottom() { return (T*)stack_; }
+
+    Allocator& GetAllocator() { return *allocator_; }
+    bool Empty() const { return stackTop_ == stack_; }
+    size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
+    size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
+
+private:
+    template<typename T>
+    void Expand(size_t count) {
+        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
+        size_t newCapacity;
+        if (stack_ == 0) {
+            if (!allocator_)
+                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+            newCapacity = initialCapacity_;
+        } else {
+            newCapacity = GetCapacity();
+            newCapacity += (newCapacity + 1) / 2;
+        }
+        size_t newSize = GetSize() + sizeof(T) * count;
+        if (newCapacity < newSize)
+            newCapacity = newSize;
+
+        Resize(newCapacity);
+    }
+
+    void Resize(size_t newCapacity) {
+        const size_t size = GetSize();  // Backup the current size
+        stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
+        stackTop_ = stack_ + size;
+        stackEnd_ = stack_ + newCapacity;
+    }
+
+    void Destroy() {
+        Allocator::Free(stack_);
+        RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
+    }
+
+    // Prohibit copy constructor & assignment operator.
+    Stack(const Stack&);
+    Stack& operator=(const Stack&);
+
+    Allocator* allocator_;
+    Allocator* ownAllocator_;
+    char *stack_;
+    char *stackTop_;
+    char *stackEnd_;
+    size_t initialCapacity_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STACK_H_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/strfunc.h b/ipaacalib/cpp/include/rapidjson/internal/strfunc.h
new file mode 100644
index 0000000000000000000000000000000000000000..c271dac4505c9a466cd3a86e3f106e17bc2510cc
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/strfunc.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+    \param s Null-terminated input string.
+    \return Number of characters in the string. 
+    \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+    const Ch* p = s;
+    while (*p) ++p;
+    return SizeType(p - s);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
diff --git a/ipaacalib/cpp/include/rapidjson/internal/strtod.h b/ipaacalib/cpp/include/rapidjson/internal/strtod.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fc6050eeb4470a596f74e9ae4bf21351749f86c
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/internal/strtod.h
@@ -0,0 +1,285 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_STRTOD_
+#define RAPIDJSON_STRTOD_
+
+#include "../rapidjson.h"
+#include "ieee754.h"
+#include "biginteger.h"
+#include "diyfp.h"
+#include "pow10.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline double FastPath(double significand, int exp) {
+    if (exp < -308)
+        return 0.0;
+    else if (exp >= 0)
+        return significand * internal::Pow10(exp);
+    else
+        return significand / internal::Pow10(-exp);
+}
+
+inline double StrtodNormalPrecision(double d, int p) {
+    if (p < -308) {
+        // Prevent expSum < -308, making Pow10(p) = 0
+        d = FastPath(d, -308);
+        d = FastPath(d, p + 308);
+    }
+    else
+        d = FastPath(d, p);
+    return d;
+}
+
+template <typename T>
+inline T Min3(T a, T b, T c) {
+    T m = a;
+    if (m > b) m = b;
+    if (m > c) m = c;
+    return m;
+}
+
+inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adjustToNegative) {
+    const Double db(b);
+    const uint64_t bInt = db.IntegerSignificand();
+    const int bExp = db.IntegerExponent();
+    const int hExp = bExp - 1;
+
+    int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
+
+    // Adjust for decimal exponent
+    if (dExp >= 0) {
+        dS_Exp2 += dExp;
+        dS_Exp5 += dExp;
+    }
+    else {
+        bS_Exp2 -= dExp;
+        bS_Exp5 -= dExp;
+        hS_Exp2 -= dExp;
+        hS_Exp5 -= dExp;
+    }
+
+    // Adjust for binary exponent
+    if (bExp >= 0)
+        bS_Exp2 += bExp;
+    else {
+        dS_Exp2 -= bExp;
+        hS_Exp2 -= bExp;
+    }
+
+    // Adjust for half ulp exponent
+    if (hExp >= 0)
+        hS_Exp2 += hExp;
+    else {
+        dS_Exp2 -= hExp;
+        bS_Exp2 -= hExp;
+    }
+
+    // Remove common power of two factor from all three scaled values
+    int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
+    dS_Exp2 -= common_Exp2;
+    bS_Exp2 -= common_Exp2;
+    hS_Exp2 -= common_Exp2;
+
+    BigInteger dS = d;
+    dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2;
+
+    BigInteger bS(bInt);
+    bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2;
+
+    BigInteger hS(1);
+    hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2;
+
+    BigInteger delta(0);
+    *adjustToNegative = dS.Difference(bS, &delta);
+
+    int cmp = delta.Compare(hS);
+    // If delta is within 1/2 ULP, check for special case when significand is power of two.
+    // In this case, need to compare with 1/2h in the lower bound.
+    if (cmp < 0 && *adjustToNegative && // within and dS < bS
+        db.IsNormal() && (bInt & (bInt - 1)) == 0 && // Power of 2
+        db.Uint64Value() != RAPIDJSON_UINT64_C2(0x00100000, 0x00000000)) // minimum normal number must not do this
+    {
+        delta <<= 1;
+        return delta.Compare(hS);
+    }
+    return cmp;
+}
+
+inline bool StrtodFast(double d, int p, double* result) {
+    // Use fast path for string-to-double conversion if possible
+    // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
+    if (p > 22  && p < 22 + 16) {
+        // Fast Path Cases In Disguise
+        d *= internal::Pow10(p - 22);
+        p = 22;
+    }
+
+    if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
+        *result = FastPath(d, p);
+        return true;
+    }
+    else
+        return false;
+}
+
+// Compute an approximation and see if it is within 1/2 ULP
+inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
+    uint64_t significand = 0;
+    size_t i = 0;   // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999    
+    for (; i < length; i++) {
+        if (significand  >  RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
+            (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
+            break;
+        significand = significand * 10 + (decimals[i] - '0');
+    }
+    
+    if (i < length && decimals[i] >= '5') // Rounding
+        significand++;
+
+    size_t remaining = length - i;
+    const unsigned kUlpShift = 3;
+    const unsigned kUlp = 1 << kUlpShift;
+    int error = (remaining == 0) ? 0 : kUlp / 2;
+
+    DiyFp v(significand, 0);
+    v = v.Normalize();
+    error <<= -v.e;
+
+    const int dExp = (int)decimalPosition - (int)i + exp;
+
+    int actualExp;
+    DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
+    if (actualExp != dExp) {
+        static const DiyFp kPow10[] = {
+            DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60),  // 10^1
+            DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57),  // 10^2
+            DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54),  // 10^3
+            DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50),  // 10^4
+            DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47),  // 10^5
+            DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44),  // 10^6
+            DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40)   // 10^7
+        };
+        int adjustment = dExp - actualExp - 1;
+        RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
+        v = v * kPow10[adjustment];
+        if (length + adjustment > 19) // has more digits than decimal digits in 64-bit
+            error += kUlp / 2;
+    }
+
+    v = v * cachedPower;
+
+    error += kUlp + (error == 0 ? 0 : 1);
+
+    const int oldExp = v.e;
+    v = v.Normalize();
+    error <<= oldExp - v.e;
+
+    const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
+    unsigned precisionSize = 64 - effectiveSignificandSize;
+    if (precisionSize + kUlpShift >= 64) {
+        unsigned scaleExp = (precisionSize + kUlpShift) - 63;
+        v.f >>= scaleExp;
+        v.e += scaleExp; 
+        error = (error >> scaleExp) + 1 + kUlp;
+        precisionSize -= scaleExp;
+    }
+
+    DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
+    const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
+    const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
+    if (precisionBits >= halfWay + error)
+        rounded.f++;
+
+    *result = rounded.ToDouble();
+
+    return halfWay - error >= precisionBits || precisionBits >= halfWay + error;
+}
+
+inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+    const BigInteger dInt(decimals, length);
+    const int dExp = (int)decimalPosition - (int)length + exp;
+    Double a(approx);
+    for (int i = 0; i < 10; i++) {
+        bool adjustToNegative;
+        int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative);
+        if (cmp < 0)
+            return a.Value();  // within half ULP
+        else if (cmp == 0) {
+            // Round towards even
+            if (a.Significand() & 1)
+                return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
+            else
+                return a.Value();
+        }
+        else // adjustment
+            a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble();
+    }
+
+    // This should not happen, but in case there is really a bug, break the infinite-loop
+    return a.Value();
+}
+
+inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+    RAPIDJSON_ASSERT(d >= 0.0);
+    RAPIDJSON_ASSERT(length >= 1);
+
+    double result;
+    if (StrtodFast(d, p, &result))
+        return result;
+
+    // Trim leading zeros
+    while (*decimals == '0' && length > 1) {
+        length--;
+        decimals++;
+        decimalPosition--;
+    }
+
+    // Trim trailing zeros
+    while (decimals[length - 1] == '0' && length > 1) {
+        length--;
+        decimalPosition--;
+        exp++;
+    }
+
+    // Trim right-most digits
+    const int kMaxDecimalDigit = 780;
+    if ((int)length > kMaxDecimalDigit) {
+        exp += (int(length) - kMaxDecimalDigit);
+        length = kMaxDecimalDigit;
+    }
+
+    // If too small, underflow to zero
+    if (int(length) + exp < -324)
+        return 0.0;
+
+    if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
+        return result;
+
+    // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
+    return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRTOD_
diff --git a/ipaacalib/cpp/include/rapidjson/memorybuffer.h b/ipaacalib/cpp/include/rapidjson/memorybuffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..95c68a38710e4d3ab6a3ed24b15d94dc787e1ea6
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/memorybuffer.h
@@ -0,0 +1,76 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_MEMORYBUFFER_H_
+#define RAPIDJSON_MEMORYBUFFER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output byte stream.
+/*!
+    This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
+
+    It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
+
+    Differences between MemoryBuffer and StringBuffer:
+    1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 
+    2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
+
+    \tparam Allocator type for allocating memory buffer.
+    \note implements Stream concept
+*/
+template <typename Allocator = CrtAllocator>
+struct GenericMemoryBuffer {
+    typedef char Ch; // byte
+
+    GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+    void Flush() {}
+
+    void Clear() { stack_.Clear(); }
+    void ShrinkToFit() { stack_.ShrinkToFit(); }
+    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+    const Ch* GetBuffer() const {
+        return stack_.template Bottom<Ch>();
+    }
+
+    size_t GetSize() const { return stack_.GetSize(); }
+
+    static const size_t kDefaultCapacity = 256;
+    mutable internal::Stack<Allocator> stack_;
+};
+
+typedef GenericMemoryBuffer<> MemoryBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
+    std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/ipaacalib/cpp/include/rapidjson/memorystream.h b/ipaacalib/cpp/include/rapidjson/memorystream.h
new file mode 100644
index 0000000000000000000000000000000000000000..f994a12fc47f544c3205507c257d6f047b195549
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/memorystream.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_MEMORYSTREAM_H_
+#define RAPIDJSON_MEMORYSTREAM_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory input byte stream.
+/*!
+    This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
+
+    It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
+
+    Differences between MemoryStream and StringStream:
+    1. StringStream has encoding but MemoryStream is a byte stream.
+    2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
+    3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
+    \note implements Stream concept
+*/
+struct MemoryStream {
+    typedef char Ch; // byte
+
+    MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
+
+    Ch Peek() const { return (src_ == end_) ? '\0' : *src_; }
+    Ch Take() { return (src_ == end_) ? '\0' : *src_++; }
+    size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
+
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+    // For encoding detection only.
+    const Ch* Peek4() const {
+        return Tell() + 4 <= size_ ? src_ : 0;
+    }
+
+    const Ch* src_;     //!< Current read position.
+    const Ch* begin_;   //!< Original head of the string.
+    const Ch* end_;     //!< End of stream.
+    size_t size_;       //!< Size of the stream.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/ipaacalib/cpp/include/rapidjson/msinttypes/inttypes.h b/ipaacalib/cpp/include/rapidjson/msinttypes/inttypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..af713c9adf54e060e77efe1df234dac350ddf4c0
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/msinttypes/inttypes.h
@@ -0,0 +1,312 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2013 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. Neither the name of the product nor the names of its contributors may
+//      be used to endorse or promote products derived from this software
+//      without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// miloyip: VC supports inttypes.h since VC2013
+#if _MSC_VER >= 1800
+#include <inttypes.h>
+#else
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#endif // _MSC_VER >= 1800
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/ipaacalib/cpp/include/rapidjson/msinttypes/stdint.h b/ipaacalib/cpp/include/rapidjson/msinttypes/stdint.h
new file mode 100644
index 0000000000000000000000000000000000000000..bbad95af1599feb099cf6a8a8def5c16f79c35b1
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/msinttypes/stdint.h
@@ -0,0 +1,296 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2013 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. Neither the name of the product nor the names of its contributors may
+//      be used to endorse or promote products derived from this software
+//      without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
+#if _MSC_VER >= 1600 // [
+#include <stdint.h>
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+#undef INT8_C
+#undef INT16_C
+#undef INT32_C
+#undef INT64_C
+#undef UINT8_C
+#undef UINT16_C
+#undef UINT32_C
+#undef UINT64_C
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C //   [
+#  define INTMAX_C   INT64_C
+#endif // INTMAX_C    ]
+#ifndef UINTMAX_C //  [
+#  define UINTMAX_C  UINT64_C
+#endif // UINTMAX_C   ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#else // ] _MSC_VER >= 1700 [
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C //   [
+#  define INTMAX_C   INT64_C
+#endif // INTMAX_C    ]
+#ifndef UINTMAX_C //  [
+#  define UINTMAX_C  UINT64_C
+#endif // UINTMAX_C   ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_VER >= 1600 ]
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/ipaacalib/cpp/include/rapidjson/prettywriter.h b/ipaacalib/cpp/include/rapidjson/prettywriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca62bb7f693b349a796d228065a3cfdf29207b41
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/prettywriter.h
@@ -0,0 +1,205 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Writer with indentation and spacing.
+/*!
+    \tparam OutputStream Type of ouptut os.
+    \tparam SourceEncoding Encoding of source string.
+    \tparam TargetEncoding Encoding of output stream.
+    \tparam StackAllocator Type of allocator for allocating memory of stack.
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
+public:
+    typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+    typedef typename Base::Ch Ch;
+
+    //! Constructor
+    /*! \param os Output stream.
+        \param allocator User supplied allocator. If it is null, it will create a private one.
+        \param levelDepth Initial capacity of stack.
+    */
+    PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
+        Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+    //! Set custom indentation.
+    /*! \param indentChar       Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
+        \param indentCharCount  Number of indent characters for each indentation level.
+        \note The default indentation is 4 spaces.
+    */
+    PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+        RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+        indentChar_ = indentChar;
+        indentCharCount_ = indentCharCount;
+        return *this;
+    }
+
+    /*! @name Implementation of Handler
+        \see Handler
+    */
+    //@{
+
+    bool Null()                 { PrettyPrefix(kNullType);   return Base::WriteNull(); }
+    bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
+    bool Int(int i)             { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
+    bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
+    bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
+    bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::WriteUint64(u64);  }
+    bool Double(double d)       { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
+
+    bool String(const Ch* str, SizeType length, bool copy = false) {
+        (void)copy;
+        PrettyPrefix(kStringType);
+        return Base::WriteString(str, length);
+    }
+
+    bool StartObject() {
+        PrettyPrefix(kObjectType);
+        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+        return Base::WriteStartObject();
+    }
+
+    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+	
+    bool EndObject(SizeType memberCount = 0) {
+        (void)memberCount;
+        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+        RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
+        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+        if (!empty) {
+            Base::os_->Put('\n');
+            WriteIndent();
+        }
+        if (!Base::WriteEndObject())
+            return false;
+        if (Base::level_stack_.Empty()) // end of json text
+            Base::os_->Flush();
+        return true;
+    }
+
+    bool StartArray() {
+        PrettyPrefix(kArrayType);
+        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+        return Base::WriteStartArray();
+    }
+
+    bool EndArray(SizeType memberCount = 0) {
+        (void)memberCount;
+        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+        RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
+        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+        if (!empty) {
+            Base::os_->Put('\n');
+            WriteIndent();
+        }
+        if (!Base::WriteEndArray())
+            return false;
+        if (Base::level_stack_.Empty()) // end of json text
+            Base::os_->Flush();
+        return true;
+    }
+
+    //@}
+
+    /*! @name Convenience extensions */
+    //@{
+
+    //! Simpler but slower overload.
+    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+    //@}
+protected:
+    void PrettyPrefix(Type type) {
+        (void)type;
+        if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+            typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+            if (level->inArray) {
+                if (level->valueCount > 0) {
+                    Base::os_->Put(','); // add comma if it is not the first element in array
+                    Base::os_->Put('\n');
+                }
+                else
+                    Base::os_->Put('\n');
+                WriteIndent();
+            }
+            else {  // in object
+                if (level->valueCount > 0) {
+                    if (level->valueCount % 2 == 0) {
+                        Base::os_->Put(',');
+                        Base::os_->Put('\n');
+                    }
+                    else {
+                        Base::os_->Put(':');
+                        Base::os_->Put(' ');
+                    }
+                }
+                else
+                    Base::os_->Put('\n');
+
+                if (level->valueCount % 2 == 0)
+                    WriteIndent();
+            }
+            if (!level->inArray && level->valueCount % 2 == 0)
+                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
+            level->valueCount++;
+        }
+        else {
+            RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root.
+            Base::hasRoot_ = true;
+        }
+    }
+
+    void WriteIndent()  {
+        size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
+        PutN(*Base::os_, indentChar_, count);
+    }
+
+    Ch indentChar_;
+    unsigned indentCharCount_;
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    PrettyWriter(const PrettyWriter&);
+    PrettyWriter& operator=(const PrettyWriter&);
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/ipaacalib/cpp/include/rapidjson/rapidjson.h b/ipaacalib/cpp/include/rapidjson/rapidjson.h
new file mode 100644
index 0000000000000000000000000000000000000000..b13e0b0adc8f8039a151f59f3d602b3e1047c9cb
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/rapidjson.h
@@ -0,0 +1,628 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
+// Version 0.1
+
+/*!\file rapidjson.h
+    \brief common definitions and configuration
+
+    \see RAPIDJSON_CONFIG
+ */
+
+/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
+    \brief Configuration macros for library features
+
+    Some RapidJSON features are configurable to adapt the library to a wide
+    variety of platforms, environments and usage scenarios.  Most of the
+    features can be configured in terms of overriden or predefined
+    preprocessor macros at compile-time.
+
+    Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
+
+    \note These macros should be given on the compiler command-line
+          (where applicable)  to avoid inconsistent values when compiling
+          different translation units of a single application.
+ */
+
+#include <cstdlib>  // malloc(), realloc(), free(), size_t
+#include <cstring>  // memset(), memcpy(), memmove(), memcmp()
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NAMESPACE_(BEGIN|END)
+/*! \def RAPIDJSON_NAMESPACE
+    \ingroup RAPIDJSON_CONFIG
+    \brief   provide custom rapidjson namespace
+
+    In order to avoid symbol clashes and/or "One Definition Rule" errors
+    between multiple inclusions of (different versions of) RapidJSON in
+    a single binary, users can customize the name of the main RapidJSON
+    namespace.
+
+    In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
+    to a custom name (e.g. \c MyRapidJSON) is sufficient.  If multiple
+    levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
+    RAPIDJSON_NAMESPACE_END need to be defined as well:
+
+    \code
+    // in some .cpp file
+    #define RAPIDJSON_NAMESPACE my::rapidjson
+    #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
+    #define RAPIDJSON_NAMESPACE_END   } }
+    #include "rapidjson/..."
+    \endcode
+
+    \see rapidjson
+ */
+/*! \def RAPIDJSON_NAMESPACE_BEGIN
+    \ingroup RAPIDJSON_CONFIG
+    \brief   provide custom rapidjson namespace (opening expression)
+    \see RAPIDJSON_NAMESPACE
+*/
+/*! \def RAPIDJSON_NAMESPACE_END
+    \ingroup RAPIDJSON_CONFIG
+    \brief   provide custom rapidjson namespace (closing expression)
+    \see RAPIDJSON_NAMESPACE
+*/
+#ifndef RAPIDJSON_NAMESPACE
+#define RAPIDJSON_NAMESPACE rapidjson
+#endif
+#ifndef RAPIDJSON_NAMESPACE_BEGIN
+#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
+#endif
+#ifndef RAPIDJSON_NAMESPACE_END
+#define RAPIDJSON_NAMESPACE_END }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_INT64DEFINE
+
+/*! \def RAPIDJSON_NO_INT64DEFINE
+    \ingroup RAPIDJSON_CONFIG
+    \brief Use external 64-bit integer types.
+
+    RapidJSON requires the 64-bit integer types \c int64_t and  \c uint64_t types
+    to be available at global scope.
+
+    If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
+    prevent RapidJSON from defining its own types.
+*/
+#ifndef RAPIDJSON_NO_INT64DEFINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#ifdef _MSC_VER
+#include "msinttypes/stdint.h"
+#include "msinttypes/inttypes.h"
+#else
+// Other compilers should have this.
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+//!@endcond
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_INT64DEFINE
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_FORCEINLINE
+
+#ifndef RAPIDJSON_FORCEINLINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#ifdef _MSC_VER
+#define RAPIDJSON_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
+#else
+#define RAPIDJSON_FORCEINLINE
+#endif
+//!@endcond
+#endif // RAPIDJSON_FORCEINLINE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN  0   //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN     1   //!< Big endian machine
+
+//! Endianness of the machine.
+/*!
+    \def RAPIDJSON_ENDIAN
+    \ingroup RAPIDJSON_CONFIG
+
+    GCC 4.6 provided macro for detecting endianness of the target machine. But other
+    compilers may not have this. User can define RAPIDJSON_ENDIAN to either
+    \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
+
+    Default detection implemented with reference to
+    \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
+    \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
+*/
+#ifndef RAPIDJSON_ENDIAN
+// Detect with GCC 4.6's macro
+#  ifdef __BYTE_ORDER__
+#    if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#    elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#    else
+#      error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+#    endif // __BYTE_ORDER__
+// Detect with GLIBC's endian.h
+#  elif defined(__GLIBC__)
+#    include <endian.h>
+#    if (__BYTE_ORDER == __LITTLE_ENDIAN)
+#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#    elif (__BYTE_ORDER == __BIG_ENDIAN)
+#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#    else
+#      error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+#   endif // __GLIBC__
+// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
+#  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#  elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+// Detect with architecture macros
+#  elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#  elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
+#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#  elif defined(RAPIDJSON_DOXYGEN_RUNNING)
+#    define RAPIDJSON_ENDIAN
+#  else
+#    error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.   
+#  endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_64BIT
+
+//! Whether using 64-bit architecture
+#ifndef RAPIDJSON_64BIT
+#if defined(__LP64__) || defined(_WIN64)
+#define RAPIDJSON_64BIT 1
+#else
+#define RAPIDJSON_64BIT 0
+#endif
+#endif // RAPIDJSON_64BIT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ALIGN
+
+//! Data alignment of the machine.
+/*! \ingroup RAPIDJSON_CONFIG
+    \param x pointer to align
+
+    Some machines require strict data alignment. Currently the default uses 4 bytes
+    alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.,
+*/
+#ifndef RAPIDJSON_ALIGN
+#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_UINT64_C2
+
+//! Construct a 64-bit literal by a pair of 32-bit integer.
+/*!
+    64-bit literal with or without ULL suffix is prone to compiler warnings.
+    UINT64_C() is C macro which cause compilation problems.
+    Use this macro to define 64-bit constants by a pair of 32-bit integer.
+*/
+#ifndef RAPIDJSON_UINT64_C2
+#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+/*! \def RAPIDJSON_SIMD
+    \ingroup RAPIDJSON_CONFIG
+    \brief Enable SSE2/SSE4.2 optimization.
+
+    RapidJSON supports optimized implementations for some parsing operations
+    based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
+    processors.
+
+    To enable these optimizations, two different symbols can be defined;
+    \code
+    // Enable SSE2 optimization.
+    #define RAPIDJSON_SSE2
+
+    // Enable SSE4.2 optimization.
+    #define RAPIDJSON_SSE42
+    \endcode
+
+    \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+
+    If any of these symbols is defined, RapidJSON defines the macro
+    \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
+*/
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
+    || defined(RAPIDJSON_DOXYGEN_RUNNING)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
+/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
+    \ingroup RAPIDJSON_CONFIG
+    \brief User-provided \c SizeType definition.
+
+    In order to avoid using 32-bit size types for indexing strings and arrays,
+    define this preprocessor symbol and provide the type rapidjson::SizeType
+    before including RapidJSON:
+    \code
+    #define RAPIDJSON_NO_SIZETYPEDEFINE
+    namespace rapidjson { typedef ::std::size_t SizeType; }
+    #include "rapidjson/..."
+    \endcode
+
+    \see rapidjson::SizeType
+*/
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_SIZETYPEDEFINE
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+//! Size type (for string lengths, array sizes, etc.)
+/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
+    instead of using \c size_t. Users may override the SizeType by defining
+    \ref RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+RAPIDJSON_NAMESPACE_END
+#endif
+
+// always import std::size_t to rapidjson namespace
+RAPIDJSON_NAMESPACE_BEGIN
+using std::size_t;
+RAPIDJSON_NAMESPACE_END
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! \ingroup RAPIDJSON_CONFIG
+    By default, rapidjson uses C \c assert() for internal assertions.
+    User can override it by defining RAPIDJSON_ASSERT(x) macro.
+
+    \note Parsing errors are handled and can be customized by the
+          \ref RAPIDJSON_ERRORS APIs.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_STATIC_ASSERT
+
+// Adopt from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+RAPIDJSON_NAMESPACE_BEGIN
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+template<int x> struct StaticAssertTest {};
+RAPIDJSON_NAMESPACE_END
+
+#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
+#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
+#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
+
+#if defined(__GNUC__)
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+#else
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE 
+#endif
+//!@endcond
+
+/*! \def RAPIDJSON_STATIC_ASSERT
+    \brief (Internal) macro to check for conditions at compile-time
+    \param x compile-time condition
+    \hideinitializer
+ */
+#define RAPIDJSON_STATIC_ASSERT(x) \
+    typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
+      sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
+    RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {  
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+// adopted from Boost
+#define RAPIDJSON_VERSION_CODE(x,y,z) \
+  (((x)*100000) + ((y)*100) + (z))
+
+// token stringification
+#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
+#define RAPIDJSON_DO_STRINGIFY(x) #x
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
+
+#if defined(__GNUC__)
+#define RAPIDJSON_GNUC \
+    RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
+
+#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
+#define RAPIDJSON_DIAG_OFF(x) \
+    RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
+
+// push/pop support in Clang and GCC>=4.6
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)
+#else // GCC >= 4.2, < 4.6
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+#endif
+
+#elif defined(_MSC_VER)
+
+// pragma (MSVC specific)
+#define RAPIDJSON_PRAGMA(x) __pragma(x)
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
+
+#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)
+
+#else
+
+#define RAPIDJSON_DIAG_OFF(x) /* ignored */
+#define RAPIDJSON_DIAG_PUSH   /* ignored */
+#define RAPIDJSON_DIAG_POP    /* ignored */
+
+#endif // RAPIDJSON_DIAG_*
+
+///////////////////////////////////////////////////////////////////////////////
+// C++11 features
+
+#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+      (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
+//    (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#else
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
+#endif
+#endif
+#if RAPIDJSON_HAS_CXX11_NOEXCEPT
+#define RAPIDJSON_NOEXCEPT noexcept
+#else
+#define RAPIDJSON_NOEXCEPT /* noexcept */
+#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
+
+// no automatic detection, yet
+#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
+#endif
+
+//!@endcond
+
+///////////////////////////////////////////////////////////////////////////////
+// new/delete
+
+#ifndef RAPIDJSON_NEW
+///! customization point for global \c new
+#define RAPIDJSON_NEW(x) new x
+#endif
+#ifndef RAPIDJSON_DELETE
+///! customization point for global \c delete
+#define RAPIDJSON_DELETE(x) delete x
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocators and Encodings
+
+#include "allocators.h"
+#include "encodings.h"
+
+/*! \namespace rapidjson
+    \brief main RapidJSON namespace
+    \see RAPIDJSON_NAMESPACE
+*/
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+//  Stream
+
+/*! \class rapidjson::Stream
+    \brief Concept for reading and writing characters.
+
+    For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
+
+    For write-only stream, only need to implement Put() and Flush().
+
+\code
+concept Stream {
+    typename Ch;    //!< Character type of the stream.
+
+    //! Read the current character from stream without moving the read cursor.
+    Ch Peek() const;
+
+    //! Read the current character from stream and moving the read cursor to next character.
+    Ch Take();
+
+    //! Get the current read cursor.
+    //! \return Number of characters read from start.
+    size_t Tell();
+
+    //! Begin writing operation at the current read pointer.
+    //! \return The begin writer pointer.
+    Ch* PutBegin();
+
+    //! Write a character.
+    void Put(Ch c);
+
+    //! Flush the buffer.
+    void Flush();
+
+    //! End the writing operation.
+    //! \param begin The begin write pointer returned by PutBegin().
+    //! \return Number of characters written.
+    size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Provides additional information for stream.
+/*!
+    By using traits pattern, this type provides a default configuration for stream.
+    For custom stream, this type can be specialized for other configuration.
+    See TEST(Reader, CustomStringStream) in readertest.cpp for example.
+*/
+template<typename Stream>
+struct StreamTraits {
+    //! Whether to make local copy of stream for optimization during parsing.
+    /*!
+        By default, for safety, streams do not use local copy optimization.
+        Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
+    */
+    enum { copyOptimization = 0 };
+};
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+    for (size_t i = 0; i < n; i++)
+        stream.Put(c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericStringStream {
+    typedef typename Encoding::Ch Ch;
+
+    GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+    Ch Peek() const { return *src_; }
+    Ch Take() { return *src_++; }
+    size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+
+    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); }
+    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+    const Ch* src_;     //!< Current read position.
+    const Ch* head_;    //!< Original head of the string.
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericStringStream<Encoding> > {
+    enum { copyOptimization = 1 };
+};
+
+//! String stream with UTF8 encoding.
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+    \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+    typedef typename Encoding::Ch Ch;
+
+    GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+    // Read
+    Ch Peek() { return *src_; }
+    Ch Take() { return *src_++; }
+    size_t Tell() { return static_cast<size_t>(src_ - head_); }
+
+    // Write
+    void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
+
+    Ch* PutBegin() { return dst_ = src_; }
+    size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
+    void Flush() {}
+
+    Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
+    void Pop(size_t count) { dst_ -= count; }
+
+    Ch* src_;
+    Ch* dst_;
+    Ch* head_;
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericInsituStringStream<Encoding> > {
+    enum { copyOptimization = 1 };
+};
+
+//! Insitu string stream with UTF8 encoding.
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+//! Type of JSON value
+enum Type {
+    kNullType = 0,      //!< null
+    kFalseType = 1,     //!< false
+    kTrueType = 2,      //!< true
+    kObjectType = 3,    //!< object
+    kArrayType = 4,     //!< array 
+    kStringType = 5,    //!< string
+    kNumberType = 6     //!< number
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/ipaacalib/cpp/include/rapidjson/reader.h b/ipaacalib/cpp/include/rapidjson/reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..f0aa318cb61fcfa288ddc8e4e4b9add7ace901bc
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/reader.h
@@ -0,0 +1,1444 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+/*! \file reader.h */
+
+#include "rapidjson.h"
+#include "encodings.h"
+#include "internal/meta.h"
+#include "internal/stack.h"
+#include "internal/strtod.h"
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127)  // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4702)  // unreachable code
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define RAPIDJSON_NOTHING /* deliberately empty */
+#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
+    RAPIDJSON_MULTILINEMACRO_BEGIN \
+    if (HasParseError()) { return value; } \
+    RAPIDJSON_MULTILINEMACRO_END
+#endif
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
+    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
+//!@endcond
+
+/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
+    \ingroup RAPIDJSON_ERRORS
+    \brief Macro to indicate a parse error.
+    \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+    \param offset  position of the error in JSON input (\c size_t)
+
+    This macros can be used as a customization point for the internal
+    error handling mechanism of RapidJSON.
+
+    A common usage model is to throw an exception instead of requiring the
+    caller to explicitly check the \ref rapidjson::GenericReader::Parse's
+    return value:
+
+    \code
+    #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
+       throw ParseException(parseErrorCode, #parseErrorCode, offset)
+
+    #include <stdexcept>               // std::runtime_error
+    #include "rapidjson/error/error.h" // rapidjson::ParseResult
+
+    struct ParseException : std::runtime_error, rapidjson::ParseResult {
+      ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
+        : std::runtime_error(msg), ParseResult(code, offset) {}
+    };
+
+    #include "rapidjson/reader.h"
+    \endcode
+
+    \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
+ */
+#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
+#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
+    RAPIDJSON_MULTILINEMACRO_BEGIN \
+    RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
+    SetParseError(parseErrorCode, offset); \
+    RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+/*! \def RAPIDJSON_PARSE_ERROR
+    \ingroup RAPIDJSON_ERRORS
+    \brief (Internal) macro to indicate and handle a parse error.
+    \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+    \param offset  position of the error in JSON input (\c size_t)
+
+    Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
+
+    \see RAPIDJSON_PARSE_ERROR_NORETURN
+    \hideinitializer
+ */
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
+    RAPIDJSON_MULTILINEMACRO_BEGIN \
+    RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
+    RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
+    RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+#include "error/error.h" // ParseErrorCode, ParseResult
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS 
+    \ingroup RAPIDJSON_CONFIG
+    \brief User-defined kParseDefaultFlags definition.
+
+    User can define this as any \c ParseFlag combinations.
+*/
+#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
+#endif
+
+//! Combination of parseFlags
+/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
+ */
+enum ParseFlag {
+    kParseNoFlags = 0,              //!< No flags are set.
+    kParseInsituFlag = 1,           //!< In-situ(destructive) parsing.
+    kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
+    kParseIterativeFlag = 4,        //!< Iterative(constant complexity in terms of function call stack size) parsing.
+    kParseStopWhenDoneFlag = 8,     //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
+    kParseFullPrecisionFlag = 16,   //!< Parse number in full precision (but slower).
+    kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS  //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+    \brief Concept for receiving events from GenericReader upon parsing.
+    The functions return true if no error occurs. If they return false, 
+    the event publisher should terminate the process.
+\code
+concept Handler {
+    typename Ch;
+
+    bool Null();
+    bool Bool(bool b);
+    bool Int(int i);
+    bool Uint(unsigned i);
+    bool Int64(int64_t i);
+    bool Uint64(uint64_t i);
+    bool Double(double d);
+    bool String(const Ch* str, SizeType length, bool copy);
+    bool StartObject();
+    bool Key(const Ch* str, SizeType length, bool copy);
+    bool EndObject(SizeType memberCount);
+    bool StartArray();
+    bool EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+    \note implements Handler concept
+*/
+template<typename Encoding = UTF8<>, typename Derived = void>
+struct BaseReaderHandler {
+    typedef typename Encoding::Ch Ch;
+
+    typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
+
+    bool Default() { return true; }
+    bool Null() { return static_cast<Override&>(*this).Default(); }
+    bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
+    bool Int(int) { return static_cast<Override&>(*this).Default(); }
+    bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
+    bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
+    bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
+    bool Double(double) { return static_cast<Override&>(*this).Default(); }
+    bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
+    bool StartObject() { return static_cast<Override&>(*this).Default(); }
+    bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+    bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
+    bool StartArray() { return static_cast<Override&>(*this).Default(); }
+    bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamLocalCopy
+
+namespace internal {
+
+template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
+class StreamLocalCopy;
+
+//! Do copy optimization.
+template<typename Stream>
+class StreamLocalCopy<Stream, 1> {
+public:
+    StreamLocalCopy(Stream& original) : s(original), original_(original) {}
+    ~StreamLocalCopy() { original_ = s; }
+
+    Stream s;
+
+private:
+    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+
+    Stream& original_;
+};
+
+//! Keep reference.
+template<typename Stream>
+class StreamLocalCopy<Stream, 0> {
+public:
+    StreamLocalCopy(Stream& original) : s(original) {}
+
+    Stream& s;
+
+private:
+    StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param is A input stream for skipping white spaces.
+    \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename InputStream>
+void SkipWhitespace(InputStream& is) {
+    internal::StreamLocalCopy<InputStream> copy(is);
+    InputStream& s(copy.s);
+
+    while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
+        s.Take();
+}
+
+#ifdef RAPIDJSON_SSE42
+//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+	// Fast return for single non-whitespace
+	if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+		++p;
+	else
+		return p;
+
+	// 16-byte align to the next boundary
+	const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+	while (p != nextAligned)
+		if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+			++p;
+		else
+			return p;
+
+    // The rest of string using SIMD
+	static const char whitespace[16] = " \n\r\t";
+	const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
+
+    for (;; p += 16) {
+        const __m128i s = _mm_load_si128((const __m128i *)p);
+        const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+        if (r != 0) {   // some of characters is non-whitespace
+#ifdef _MSC_VER         // Find the index of first non-whitespace
+            unsigned long offset;
+            _BitScanForward(&offset, r);
+            return p + offset;
+#else
+            return p + __builtin_ffs(r) - 1;
+#endif
+        }
+    }
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+	// Fast return for single non-whitespace
+	if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+		++p;
+	else
+		return p;
+
+    // 16-byte align to the next boundary
+	const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+	while (p != nextAligned)
+		if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+			++p;
+		else
+			return p;
+
+    // The rest of string
+	static const char whitespaces[4][17] = {
+		"                ",
+		"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
+		"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
+		"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
+
+		const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
+		const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
+		const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
+		const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
+
+    for (;; p += 16) {
+        const __m128i s = _mm_load_si128((const __m128i *)p);
+        __m128i x = _mm_cmpeq_epi8(s, w0);
+        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+        x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+        unsigned short r = (unsigned short)~_mm_movemask_epi8(x);
+        if (r != 0) {   // some of characters may be non-whitespace
+#ifdef _MSC_VER         // Find the index of first non-whitespace
+            unsigned long offset;
+            _BitScanForward(&offset, r);
+            return p + offset;
+#else
+            return p + __builtin_ffs(r) - 1;
+#endif
+        }
+    }
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& is) { 
+    is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& is) {
+    is.src_ = SkipWhitespace_SIMD(is.src_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an 
+    object implementing Handler concept.
+
+    It needs to allocate a stack for storing a single decoded string during 
+    non-destructive parsing.
+
+    For in-situ parsing, the decoded string is directly written to the source 
+    text string, no temporary buffer is required.
+
+    A GenericReader object can be reused for parsing multiple JSON text.
+    
+    \tparam SourceEncoding Encoding of the input stream.
+    \tparam TargetEncoding Encoding of the parse output.
+    \tparam StackAllocator Allocator type for stack.
+*/
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
+class GenericReader {
+public:
+    typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
+
+    //! Constructor.
+    /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+        \param stackCapacity stack capacity in bytes for storing a single decoded string.  (Only use for non-destructive parsing)
+    */
+    GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
+
+    //! Parse JSON text.
+    /*! \tparam parseFlags Combination of \ref ParseFlag.
+        \tparam InputStream Type of input stream, implementing Stream concept.
+        \tparam Handler Type of handler, implementing Handler concept.
+        \param is Input stream to be parsed.
+        \param handler The handler to receive events.
+        \return Whether the parsing is successful.
+    */
+    template <unsigned parseFlags, typename InputStream, typename Handler>
+    ParseResult Parse(InputStream& is, Handler& handler) {
+        if (parseFlags & kParseIterativeFlag)
+            return IterativeParse<parseFlags>(is, handler);
+
+        parseResult_.Clear();
+
+        ClearStackOnExit scope(*this);
+
+        SkipWhitespace(is);
+
+        if (is.Peek() == '\0') {
+            RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+        }
+        else {
+            ParseValue<parseFlags>(is, handler);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+            if (!(parseFlags & kParseStopWhenDoneFlag)) {
+                SkipWhitespace(is);
+
+                if (is.Peek() != '\0') {
+                    RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
+                    RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+                }
+            }
+        }
+
+        return parseResult_;
+    }
+
+    //! Parse JSON text (with \ref kParseDefaultFlags)
+    /*! \tparam InputStream Type of input stream, implementing Stream concept
+        \tparam Handler Type of handler, implementing Handler concept.
+        \param is Input stream to be parsed.
+        \param handler The handler to receive events.
+        \return Whether the parsing is successful.
+    */
+    template <typename InputStream, typename Handler>
+    ParseResult Parse(InputStream& is, Handler& handler) {
+        return Parse<kParseDefaultFlags>(is, handler);
+    }
+
+    //! Whether a parse error has occured in the last parsing.
+    bool HasParseError() const { return parseResult_.IsError(); }
+    
+    //! Get the \ref ParseErrorCode of last parsing.
+    ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
+
+    //! Get the position of last parsing error in input, 0 otherwise.
+    size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+protected:
+    void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    GenericReader(const GenericReader&);
+    GenericReader& operator=(const GenericReader&);
+
+    void ClearStack() { stack_.Clear(); }
+
+    // clear stack on any exit from ParseStream, e.g. due to exception
+    struct ClearStackOnExit {
+        explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
+        ~ClearStackOnExit() { r_.ClearStack(); }
+    private:
+        GenericReader& r_;
+        ClearStackOnExit(const ClearStackOnExit&);
+        ClearStackOnExit& operator=(const ClearStackOnExit&);
+    };
+
+    // Parse object: { string : value, ... }
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseObject(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == '{');
+        is.Take();  // Skip '{'
+        
+        if (!handler.StartObject())
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+        SkipWhitespace(is);
+
+        if (is.Peek() == '}') {
+            is.Take();
+            if (!handler.EndObject(0))  // empty object
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+            return;
+        }
+
+        for (SizeType memberCount = 0;;) {
+            if (is.Peek() != '"')
+                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+
+            ParseString<parseFlags>(is, handler, true);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+            SkipWhitespace(is);
+
+            if (is.Take() != ':')
+                RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+
+            SkipWhitespace(is);
+
+            ParseValue<parseFlags>(is, handler);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+            SkipWhitespace(is);
+
+            ++memberCount;
+
+            switch (is.Take()) {
+                case ',': SkipWhitespace(is); break;
+                case '}': 
+                    if (!handler.EndObject(memberCount))
+                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+                    return;
+                default:  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+            }
+        }
+    }
+
+    // Parse array: [ value, ... ]
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseArray(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == '[');
+        is.Take();  // Skip '['
+        
+        if (!handler.StartArray())
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        
+        SkipWhitespace(is);
+
+        if (is.Peek() == ']') {
+            is.Take();
+            if (!handler.EndArray(0)) // empty array
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+            return;
+        }
+
+        for (SizeType elementCount = 0;;) {
+            ParseValue<parseFlags>(is, handler);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+            ++elementCount;
+            SkipWhitespace(is);
+
+            switch (is.Take()) {
+                case ',': SkipWhitespace(is); break;
+                case ']': 
+                    if (!handler.EndArray(elementCount))
+                        RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+                    return;
+                default:  RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+            }
+        }
+    }
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseNull(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == 'n');
+        is.Take();
+
+        if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
+            if (!handler.Null())
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+    }
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseTrue(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == 't');
+        is.Take();
+
+        if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
+            if (!handler.Bool(true))
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+    }
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseFalse(InputStream& is, Handler& handler) {
+        RAPIDJSON_ASSERT(is.Peek() == 'f');
+        is.Take();
+
+        if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
+            if (!handler.Bool(false))
+                RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+    }
+
+    // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+    template<typename InputStream>
+    unsigned ParseHex4(InputStream& is) {
+        unsigned codepoint = 0;
+        for (int i = 0; i < 4; i++) {
+            Ch c = is.Take();
+            codepoint <<= 4;
+            codepoint += static_cast<unsigned>(c);
+            if (c >= '0' && c <= '9')
+                codepoint -= '0';
+            else if (c >= 'A' && c <= 'F')
+                codepoint -= 'A' - 10;
+            else if (c >= 'a' && c <= 'f')
+                codepoint -= 'a' - 10;
+            else {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1);
+                RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
+            }
+        }
+        return codepoint;
+    }
+
+    template <typename CharType>
+    class StackStream {
+    public:
+        typedef CharType Ch;
+
+        StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
+        RAPIDJSON_FORCEINLINE void Put(Ch c) {
+            *stack_.template Push<Ch>() = c;
+            ++length_;
+        }
+        size_t Length() const { return length_; }
+        Ch* Pop() {
+            return stack_.template Pop<Ch>(length_);
+        }
+
+    private:
+        StackStream(const StackStream&);
+        StackStream& operator=(const StackStream&);
+
+        internal::Stack<StackAllocator>& stack_;
+        SizeType length_;
+    };
+
+    // Parse string and generate String event. Different code paths for kParseInsituFlag.
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
+        internal::StreamLocalCopy<InputStream> copy(is);
+        InputStream& s(copy.s);
+
+        bool success = false;
+        if (parseFlags & kParseInsituFlag) {
+            typename InputStream::Ch *head = s.PutBegin();
+            ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+            size_t length = s.PutEnd(head) - 1;
+            RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+            const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head;
+            success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
+        }
+        else {
+            StackStream<typename TargetEncoding::Ch> stackStream(stack_);
+            ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
+            RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+            SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
+            const typename TargetEncoding::Ch* const str = stackStream.Pop();
+            success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
+        }
+        if (!success)
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+    }
+
+    // Parse string to an output is
+    // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
+    template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
+    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+        static const char escape[256] = {
+            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', 
+            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, 
+            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, 
+            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+        };
+#undef Z16
+//!@endcond
+
+        RAPIDJSON_ASSERT(is.Peek() == '\"');
+        is.Take();  // Skip '\"'
+
+        for (;;) {
+            Ch c = is.Peek();
+            if (c == '\\') {    // Escape
+                is.Take();
+                Ch e = is.Take();
+                if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
+                    os.Put(escape[(unsigned char)e]);
+                }
+                else if (e == 'u') {    // Unicode
+                    unsigned codepoint = ParseHex4(is);
+                    if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
+                        // Handle UTF-16 surrogate pair
+                        if (is.Take() != '\\' || is.Take() != 'u')
+                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+                        unsigned codepoint2 = ParseHex4(is);
+                        if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
+                            RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+                        codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+                    }
+                    TEncoding::Encode(os, codepoint);
+                }
+                else
+                    RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+            }
+            else if (c == '"') {    // Closing double quote
+                is.Take();
+                os.Put('\0');   // null-terminate the string
+                return;
+            }
+            else if (c == '\0')
+                RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
+            else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+                RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+            else {
+                if (parseFlags & kParseValidateEncodingFlag ? 
+                    !Transcoder<SEncoding, TEncoding>::Validate(is, os) : 
+                    !Transcoder<SEncoding, TEncoding>::Transcode(is, os))
+                    RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
+            }
+        }
+    }
+
+    template<typename InputStream, bool backup>
+    class NumberStream {};
+
+    template<typename InputStream>
+    class NumberStream<InputStream, false> {
+    public:
+        NumberStream(GenericReader& reader, InputStream& is) : is(is) { (void)reader;  }
+        ~NumberStream() {}
+
+        RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
+        RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
+        RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
+        size_t Tell() { return is.Tell(); }
+        size_t Length() { return 0; }
+        const char* Pop() { return 0; }
+
+    protected:
+        NumberStream& operator=(const NumberStream&);
+
+        InputStream& is;
+    };
+
+    template<typename InputStream>
+    class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
+        typedef NumberStream<InputStream, false> Base;
+    public:
+        NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
+        ~NumberStream() {}
+
+        RAPIDJSON_FORCEINLINE Ch TakePush() {
+            stackStream.Put((char)Base::is.Peek());
+            return Base::is.Take();
+        }
+
+        size_t Length() { return stackStream.Length(); }
+
+        const char* Pop() {
+            stackStream.Put('\0');
+            return stackStream.Pop();
+        }
+
+    private:
+        StackStream<char> stackStream;
+    };
+
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseNumber(InputStream& is, Handler& handler) {
+        internal::StreamLocalCopy<InputStream> copy(is);
+        NumberStream<InputStream, (parseFlags & kParseFullPrecisionFlag) != 0> s(*this, copy.s);
+
+        // Parse minus
+        bool minus = false;
+        if (s.Peek() == '-') {
+            minus = true;
+            s.Take();
+        }
+
+        // Parse int: zero / ( digit1-9 *DIGIT )
+        unsigned i = 0;
+        uint64_t i64 = 0;
+        bool use64bit = false;
+        int significandDigit = 0;
+        if (s.Peek() == '0') {
+            i = 0;
+            s.TakePush();
+        }
+        else if (s.Peek() >= '1' && s.Peek() <= '9') {
+            i = static_cast<unsigned>(s.TakePush() - '0');
+
+            if (minus)
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    if (i >= 214748364) { // 2^31 = 2147483648
+                        if (i != 214748364 || s.Peek() > '8') {
+                            i64 = i;
+                            use64bit = true;
+                            break;
+                        }
+                    }
+                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+            else
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    if (i >= 429496729) { // 2^32 - 1 = 4294967295
+                        if (i != 429496729 || s.Peek() > '5') {
+                            i64 = i;
+                            use64bit = true;
+                            break;
+                        }
+                    }
+                    i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+        }
+        else
+            RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+
+        // Parse 64bit int
+        bool useDouble = false;
+        double d = 0.0;
+        if (use64bit) {
+            if (minus) 
+                while (s.Peek() >= '0' && s.Peek() <= '9') {                    
+                     if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
+                        if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
+                            d = i64;
+                            useDouble = true;
+                            break;
+                        }
+                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+            else
+                while (s.Peek() >= '0' && s.Peek() <= '9') {                    
+                    if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
+                        if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
+                            d = i64;
+                            useDouble = true;
+                            break;
+                        }
+                    i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                    significandDigit++;
+                }
+        }
+
+        // Force double for big integer
+        if (useDouble) {
+            while (s.Peek() >= '0' && s.Peek() <= '9') {
+                if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
+                    RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+                d = d * 10 + (s.TakePush() - '0');
+            }
+        }
+
+        // Parse frac = decimal-point 1*DIGIT
+        int expFrac = 0;
+        size_t decimalPosition;
+        if (s.Peek() == '.') {
+            s.Take();
+            decimalPosition = s.Length();
+
+            if (!(s.Peek() >= '0' && s.Peek() <= '9'))
+                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
+
+            if (!useDouble) {
+#if RAPIDJSON_64BIT
+                // Use i64 to store significand in 64-bit architecture
+                if (!use64bit)
+                    i64 = i;
+        
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
+                        break;
+                    else {
+                        i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+                        --expFrac;
+                        if (i64 != 0)
+                            significandDigit++;
+                    }
+                }
+
+                d = (double)i64;
+#else
+                // Use double to store significand in 32-bit architecture
+                d = use64bit ? (double)i64 : (double)i;
+#endif
+                useDouble = true;
+            }
+
+            while (s.Peek() >= '0' && s.Peek() <= '9') {
+                if (significandDigit < 17) {
+                    d = d * 10.0 + (s.TakePush() - '0');
+                    --expFrac;
+                    if (d != 0.0)
+                        significandDigit++;
+                }
+                else
+                    s.TakePush();
+            }
+        }
+        else
+            decimalPosition = s.Length(); // decimal position at the end of integer.
+
+        // Parse exp = e [ minus / plus ] 1*DIGIT
+        int exp = 0;
+        if (s.Peek() == 'e' || s.Peek() == 'E') {
+            if (!useDouble) {
+                d = use64bit ? i64 : i;
+                useDouble = true;
+            }
+            s.Take();
+
+            bool expMinus = false;
+            if (s.Peek() == '+')
+                s.Take();
+            else if (s.Peek() == '-') {
+                s.Take();
+                expMinus = true;
+            }
+
+            if (s.Peek() >= '0' && s.Peek() <= '9') {
+                exp = s.Take() - '0';
+                while (s.Peek() >= '0' && s.Peek() <= '9') {
+                    exp = exp * 10 + (s.Take() - '0');
+                    if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
+                        RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+                }
+            }
+            else
+                RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
+
+            if (expMinus)
+                exp = -exp;
+        }
+
+        // Finish parsing, call event according to the type of number.
+        bool cont = true;
+        size_t length = s.Length();
+        const char* decimal = s.Pop();  // Pop stack no matter if it will be used or not.
+
+        if (useDouble) {
+            int p = exp + expFrac;
+            if (parseFlags & kParseFullPrecisionFlag)
+                d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
+            else
+                d = internal::StrtodNormalPrecision(d, p);
+
+            cont = handler.Double(minus ? -d : d);
+        }
+        else {
+            if (use64bit) {
+                if (minus)
+                    cont = handler.Int64(-(int64_t)i64);
+                else
+                    cont = handler.Uint64(i64);
+            }
+            else {
+                if (minus)
+                    cont = handler.Int(-(int)i);
+                else
+                    cont = handler.Uint(i);
+            }
+        }
+        if (!cont)
+            RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+    }
+
+    // Parse any JSON value
+    template<unsigned parseFlags, typename InputStream, typename Handler>
+    void ParseValue(InputStream& is, Handler& handler) {
+        switch (is.Peek()) {
+            case 'n': ParseNull  <parseFlags>(is, handler); break;
+            case 't': ParseTrue  <parseFlags>(is, handler); break;
+            case 'f': ParseFalse <parseFlags>(is, handler); break;
+            case '"': ParseString<parseFlags>(is, handler); break;
+            case '{': ParseObject<parseFlags>(is, handler); break;
+            case '[': ParseArray <parseFlags>(is, handler); break;
+            default : ParseNumber<parseFlags>(is, handler);
+        }
+    }
+
+    // Iterative Parsing
+
+    // States
+    enum IterativeParsingState {
+        IterativeParsingStartState = 0,
+        IterativeParsingFinishState,
+        IterativeParsingErrorState,
+
+        // Object states
+        IterativeParsingObjectInitialState,
+        IterativeParsingMemberKeyState,
+        IterativeParsingKeyValueDelimiterState,
+        IterativeParsingMemberValueState,
+        IterativeParsingMemberDelimiterState,
+        IterativeParsingObjectFinishState,
+
+        // Array states
+        IterativeParsingArrayInitialState,
+        IterativeParsingElementState,
+        IterativeParsingElementDelimiterState,
+        IterativeParsingArrayFinishState,
+
+        // Single value state
+        IterativeParsingValueState,
+
+        cIterativeParsingStateCount
+    };
+
+    // Tokens
+    enum Token {
+        LeftBracketToken = 0,
+        RightBracketToken,
+
+        LeftCurlyBracketToken,
+        RightCurlyBracketToken,
+
+        CommaToken,
+        ColonToken,
+
+        StringToken,
+        FalseToken,
+        TrueToken,
+        NullToken,
+        NumberToken,
+
+        kTokenCount
+    };
+
+    RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define N NumberToken
+#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
+        // Maps from ASCII to Token
+        static const unsigned char tokenMap[256] = {
+            N16, // 00~0F
+            N16, // 10~1F
+            N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
+            N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
+            N16, // 40~4F
+            N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
+            N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
+            N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
+            N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
+        };
+#undef N
+#undef N16
+//!@endcond
+        
+        if (sizeof(Ch) == 1 || unsigned(c) < 256)
+            return (Token)tokenMap[(unsigned char)c];
+        else
+            return NumberToken;
+    }
+
+    RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
+        // current state x one lookahead token -> new state
+        static const char G[cIterativeParsingStateCount][kTokenCount] = {
+            // Start
+            {
+                IterativeParsingArrayInitialState,  // Left bracket
+                IterativeParsingErrorState,         // Right bracket
+                IterativeParsingObjectInitialState, // Left curly bracket
+                IterativeParsingErrorState,         // Right curly bracket
+                IterativeParsingErrorState,         // Comma
+                IterativeParsingErrorState,         // Colon
+                IterativeParsingValueState,         // String
+                IterativeParsingValueState,         // False
+                IterativeParsingValueState,         // True
+                IterativeParsingValueState,         // Null
+                IterativeParsingValueState          // Number
+            },
+            // Finish(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // Error(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // ObjectInitial
+            {
+                IterativeParsingErrorState,         // Left bracket
+                IterativeParsingErrorState,         // Right bracket
+                IterativeParsingErrorState,         // Left curly bracket
+                IterativeParsingObjectFinishState,  // Right curly bracket
+                IterativeParsingErrorState,         // Comma
+                IterativeParsingErrorState,         // Colon
+                IterativeParsingMemberKeyState,     // String
+                IterativeParsingErrorState,         // False
+                IterativeParsingErrorState,         // True
+                IterativeParsingErrorState,         // Null
+                IterativeParsingErrorState          // Number
+            },
+            // MemberKey
+            {
+                IterativeParsingErrorState,             // Left bracket
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingErrorState,             // Left curly bracket
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingKeyValueDelimiterState, // Colon
+                IterativeParsingErrorState,             // String
+                IterativeParsingErrorState,             // False
+                IterativeParsingErrorState,             // True
+                IterativeParsingErrorState,             // Null
+                IterativeParsingErrorState              // Number
+            },
+            // KeyValueDelimiter
+            {
+                IterativeParsingArrayInitialState,      // Left bracket(push MemberValue state)
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingObjectInitialState,     // Left curly bracket(push MemberValue state)
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingMemberValueState,       // String
+                IterativeParsingMemberValueState,       // False
+                IterativeParsingMemberValueState,       // True
+                IterativeParsingMemberValueState,       // Null
+                IterativeParsingMemberValueState        // Number
+            },
+            // MemberValue
+            {
+                IterativeParsingErrorState,             // Left bracket
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingErrorState,             // Left curly bracket
+                IterativeParsingObjectFinishState,      // Right curly bracket
+                IterativeParsingMemberDelimiterState,   // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingErrorState,             // String
+                IterativeParsingErrorState,             // False
+                IterativeParsingErrorState,             // True
+                IterativeParsingErrorState,             // Null
+                IterativeParsingErrorState              // Number
+            },
+            // MemberDelimiter
+            {
+                IterativeParsingErrorState,         // Left bracket
+                IterativeParsingErrorState,         // Right bracket
+                IterativeParsingErrorState,         // Left curly bracket
+                IterativeParsingErrorState,         // Right curly bracket
+                IterativeParsingErrorState,         // Comma
+                IterativeParsingErrorState,         // Colon
+                IterativeParsingMemberKeyState,     // String
+                IterativeParsingErrorState,         // False
+                IterativeParsingErrorState,         // True
+                IterativeParsingErrorState,         // Null
+                IterativeParsingErrorState          // Number
+            },
+            // ObjectFinish(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // ArrayInitial
+            {
+                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
+                IterativeParsingArrayFinishState,       // Right bracket
+                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingElementState,           // String
+                IterativeParsingElementState,           // False
+                IterativeParsingElementState,           // True
+                IterativeParsingElementState,           // Null
+                IterativeParsingElementState            // Number
+            },
+            // Element
+            {
+                IterativeParsingErrorState,             // Left bracket
+                IterativeParsingArrayFinishState,       // Right bracket
+                IterativeParsingErrorState,             // Left curly bracket
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingElementDelimiterState,  // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingErrorState,             // String
+                IterativeParsingErrorState,             // False
+                IterativeParsingErrorState,             // True
+                IterativeParsingErrorState,             // Null
+                IterativeParsingErrorState              // Number
+            },
+            // ElementDelimiter
+            {
+                IterativeParsingArrayInitialState,      // Left bracket(push Element state)
+                IterativeParsingErrorState,             // Right bracket
+                IterativeParsingObjectInitialState,     // Left curly bracket(push Element state)
+                IterativeParsingErrorState,             // Right curly bracket
+                IterativeParsingErrorState,             // Comma
+                IterativeParsingErrorState,             // Colon
+                IterativeParsingElementState,           // String
+                IterativeParsingElementState,           // False
+                IterativeParsingElementState,           // True
+                IterativeParsingElementState,           // Null
+                IterativeParsingElementState            // Number
+            },
+            // ArrayFinish(sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            },
+            // Single Value (sink state)
+            {
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+                IterativeParsingErrorState
+            }
+        }; // End of G
+
+        return (IterativeParsingState)G[state][token];
+    }
+
+    // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
+    // May return a new state on state pop.
+    template <unsigned parseFlags, typename InputStream, typename Handler>
+    RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
+        switch (dst) {
+        case IterativeParsingStartState:
+            RAPIDJSON_ASSERT(false);
+            return IterativeParsingErrorState;
+
+        case IterativeParsingFinishState:
+            return dst;
+
+        case IterativeParsingErrorState:
+            return dst;
+
+        case IterativeParsingObjectInitialState:
+        case IterativeParsingArrayInitialState:
+        {
+            // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
+            // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
+            IterativeParsingState n = src;
+            if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
+                n = IterativeParsingElementState;
+            else if (src == IterativeParsingKeyValueDelimiterState)
+                n = IterativeParsingMemberValueState;
+            // Push current state.
+            *stack_.template Push<SizeType>(1) = n;
+            // Initialize and push the member/element count.
+            *stack_.template Push<SizeType>(1) = 0;
+            // Call handler
+            bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
+            // On handler short circuits the parsing.
+            if (!hr) {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+                return IterativeParsingErrorState;
+            }
+            else {
+                is.Take();
+                return dst;
+            }
+        }
+
+        case IterativeParsingMemberKeyState:
+            ParseString<parseFlags>(is, handler, true);
+            if (HasParseError())
+                return IterativeParsingErrorState;
+            else
+                return dst;
+
+        case IterativeParsingKeyValueDelimiterState:
+            if (token == ColonToken) {
+                is.Take();
+                return dst;
+            }
+            else
+                return IterativeParsingErrorState;
+
+        case IterativeParsingMemberValueState:
+            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+            ParseValue<parseFlags>(is, handler);
+            if (HasParseError()) {
+                return IterativeParsingErrorState;
+            }
+            return dst;
+
+        case IterativeParsingElementState:
+            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+            ParseValue<parseFlags>(is, handler);
+            if (HasParseError()) {
+                return IterativeParsingErrorState;
+            }
+            return dst;
+
+        case IterativeParsingMemberDelimiterState:
+        case IterativeParsingElementDelimiterState:
+            is.Take();
+            // Update member/element count.
+            *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
+            return dst;
+
+        case IterativeParsingObjectFinishState:
+        {
+            // Get member count.
+            SizeType c = *stack_.template Pop<SizeType>(1);
+            // If the object is not empty, count the last member.
+            if (src == IterativeParsingMemberValueState)
+                ++c;
+            // Restore the state.
+            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+            // Transit to Finish state if this is the topmost scope.
+            if (n == IterativeParsingStartState)
+                n = IterativeParsingFinishState;
+            // Call handler
+            bool hr = handler.EndObject(c);
+            // On handler short circuits the parsing.
+            if (!hr) {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+                return IterativeParsingErrorState;
+            }
+            else {
+                is.Take();
+                return n;
+            }
+        }
+
+        case IterativeParsingArrayFinishState:
+        {
+            // Get element count.
+            SizeType c = *stack_.template Pop<SizeType>(1);
+            // If the array is not empty, count the last element.
+            if (src == IterativeParsingElementState)
+                ++c;
+            // Restore the state.
+            IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+            // Transit to Finish state if this is the topmost scope.
+            if (n == IterativeParsingStartState)
+                n = IterativeParsingFinishState;
+            // Call handler
+            bool hr = handler.EndArray(c);
+            // On handler short circuits the parsing.
+            if (!hr) {
+                RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+                return IterativeParsingErrorState;
+            }
+            else {
+                is.Take();
+                return n;
+            }
+        }
+
+        case IterativeParsingValueState:
+            // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+            ParseValue<parseFlags>(is, handler);
+            if (HasParseError()) {
+                return IterativeParsingErrorState;
+            }
+            return IterativeParsingFinishState;
+
+        default:
+            RAPIDJSON_ASSERT(false);
+            return IterativeParsingErrorState;
+        }
+    }
+
+    template <typename InputStream>
+    void HandleError(IterativeParsingState src, InputStream& is) {
+        if (HasParseError()) {
+            // Error flag has been set.
+            return;
+        }
+        
+        switch (src) {
+        case IterativeParsingStartState:            RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
+        case IterativeParsingFinishState:           RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
+        case IterativeParsingObjectInitialState:
+        case IterativeParsingMemberDelimiterState:  RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+        case IterativeParsingMemberKeyState:        RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+        case IterativeParsingMemberValueState:      RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+        case IterativeParsingElementState:          RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+        default:                                    RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+        }       
+    }
+
+    template <unsigned parseFlags, typename InputStream, typename Handler>
+    ParseResult IterativeParse(InputStream& is, Handler& handler) {
+        parseResult_.Clear();
+        ClearStackOnExit scope(*this);
+        IterativeParsingState state = IterativeParsingStartState;
+
+        SkipWhitespace(is);
+        while (is.Peek() != '\0') {
+            Token t = Tokenize(is.Peek());
+            IterativeParsingState n = Predict(state, t);
+            IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
+
+            if (d == IterativeParsingErrorState) {
+                HandleError(state, is);
+                break;
+            }
+
+            state = d;
+
+            // Do not further consume streams if a root JSON has been parsed.
+            if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
+                break;
+
+            SkipWhitespace(is);
+        }
+
+        // Handle the end of file.
+        if (state != IterativeParsingFinishState)
+            HandleError(state, is);
+
+        return parseResult_;
+    }
+
+    static const size_t kDefaultStackCapacity = 256;    //!< Default stack capacity in bytes for storing a single decoded string.
+    internal::Stack<StackAllocator> stack_;  //!< A stack for storing decoded string temporarily during non-destructive parsing.
+    ParseResult parseResult_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<>, UTF8<> > Reader;
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_READER_H_
diff --git a/ipaacalib/cpp/include/rapidjson/stringbuffer.h b/ipaacalib/cpp/include/rapidjson/stringbuffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..db00af3efcf0cf9a92cfe36edf6bd6425421b9c5
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/stringbuffer.h
@@ -0,0 +1,99 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "rapidjson.h"
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output stream.
+/*!
+    \tparam Encoding Encoding of the stream.
+    \tparam Allocator type for allocating memory buffer.
+    \note implements Stream concept
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericStringBuffer {
+public:
+    typedef typename Encoding::Ch Ch;
+
+    GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+    GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
+    GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
+        if (&rhs != this)
+            stack_ = std::move(rhs.stack_);
+        return *this;
+    }
+#endif
+
+    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+    void Flush() {}
+
+    void Clear() { stack_.Clear(); }
+    void ShrinkToFit() {
+        // Push and pop a null terminator. This is safe.
+        *stack_.template Push<Ch>() = '\0';
+        stack_.ShrinkToFit();
+        stack_.template Pop<Ch>(1);
+    }
+    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+    const Ch* GetString() const {
+        // Push and pop a null terminator. This is safe.
+        *stack_.template Push<Ch>() = '\0';
+        stack_.template Pop<Ch>(1);
+
+        return stack_.template Bottom<Ch>();
+    }
+
+    size_t GetSize() const { return stack_.GetSize(); }
+
+    static const size_t kDefaultCapacity = 256;
+    mutable internal::Stack<Allocator> stack_;
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    GenericStringBuffer(const GenericStringBuffer&);
+    GenericStringBuffer& operator=(const GenericStringBuffer&);
+};
+
+//! String buffer with UTF8 encoding
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+    std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
diff --git a/ipaacalib/cpp/include/rapidjson/writer.h b/ipaacalib/cpp/include/rapidjson/writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..02d66803d4daeeed7488818ed7b4f50381cf3f98
--- /dev/null
+++ b/ipaacalib/cpp/include/rapidjson/writer.h
@@ -0,0 +1,391 @@
+// Copyright (C) 2011 Milo Yip
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include "internal/dtoa.h"
+#include "internal/itoa.h"
+#include "stringbuffer.h"
+#include <new>      // placement new
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+    It generates JSON text by events to an output os.
+
+    User may programmatically calls the functions of a writer to generate JSON text.
+
+    On the other side, a writer can also be passed to objects that generates events, 
+
+    for example Reader::Parse() and Document::Accept().
+
+    \tparam OutputStream Type of output stream.
+    \tparam SourceEncoding Encoding of source string.
+    \tparam TargetEncoding Encoding of output stream.
+    \tparam StackAllocator Type of allocator for allocating memory of stack.
+    \note implements Handler concept
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class Writer {
+public:
+    typedef typename SourceEncoding::Ch Ch;
+
+    //! Constructor
+    /*! \param os Output stream.
+        \param stackAllocator User supplied allocator. If it is null, it will create a private one.
+        \param levelDepth Initial capacity of stack.
+    */
+    explicit
+    Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 
+        os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+    explicit
+    Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+        os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+    //! Reset the writer with a new stream.
+    /*!
+        This function reset the writer with a new stream and default settings,
+        in order to make a Writer object reusable for output multiple JSONs.
+
+        \param os New output stream.
+        \code
+        Writer<OutputStream> writer(os1);
+        writer.StartObject();
+        // ...
+        writer.EndObject();
+
+        writer.Reset(os2);
+        writer.StartObject();
+        // ...
+        writer.EndObject();
+        \endcode
+    */
+    void Reset(OutputStream& os) {
+        os_ = &os;
+        hasRoot_ = false;
+        level_stack_.Clear();
+    }
+
+    //! Checks whether the output is a complete JSON.
+    /*!
+        A complete JSON has a complete root object or array.
+    */
+    bool IsComplete() const {
+        return hasRoot_ && level_stack_.Empty();
+    }
+
+    /*!@name Implementation of Handler
+        \see Handler
+    */
+    //@{
+
+    bool Null()                 { Prefix(kNullType);   return WriteNull(); }
+    bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
+    bool Int(int i)             { Prefix(kNumberType); return WriteInt(i); }
+    bool Uint(unsigned u)       { Prefix(kNumberType); return WriteUint(u); }
+    bool Int64(int64_t i64)     { Prefix(kNumberType); return WriteInt64(i64); }
+    bool Uint64(uint64_t u64)   { Prefix(kNumberType); return WriteUint64(u64); }
+
+    //! Writes the given \c double value to the stream
+    /*!
+        \param d The value to be written.
+        \return Whether it is succeed.
+    */
+    bool Double(double d)       { Prefix(kNumberType); return WriteDouble(d); }
+
+    bool String(const Ch* str, SizeType length, bool copy = false) {
+        (void)copy;
+        Prefix(kStringType);
+        return WriteString(str, length);
+    }
+
+    bool StartObject() {
+        Prefix(kObjectType);
+        new (level_stack_.template Push<Level>()) Level(false);
+        return WriteStartObject();
+    }
+
+    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+	
+    bool EndObject(SizeType memberCount = 0) {
+        (void)memberCount;
+        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+        RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+        level_stack_.template Pop<Level>(1);
+        bool ret = WriteEndObject();
+        if (level_stack_.Empty())   // end of json text
+            os_->Flush();
+        return ret;
+    }
+
+    bool StartArray() {
+        Prefix(kArrayType);
+        new (level_stack_.template Push<Level>()) Level(true);
+        return WriteStartArray();
+    }
+
+    bool EndArray(SizeType elementCount = 0) {
+        (void)elementCount;
+        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+        RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+        level_stack_.template Pop<Level>(1);
+        bool ret = WriteEndArray();
+        if (level_stack_.Empty())   // end of json text
+            os_->Flush();
+        return ret;
+    }
+    //@}
+
+    /*! @name Convenience extensions */
+    //@{
+
+    //! Simpler but slower overload.
+    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+    //@}
+
+protected:
+    //! Information for each nested level
+    struct Level {
+        Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
+        size_t valueCount;  //!< number of values in this level
+        bool inArray;       //!< true if in array, otherwise in object
+    };
+
+    static const size_t kDefaultLevelDepth = 32;
+
+    bool WriteNull()  {
+        os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
+    }
+
+    bool WriteBool(bool b)  {
+        if (b) {
+            os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
+        }
+        else {
+            os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
+        }
+        return true;
+    }
+
+    bool WriteInt(int i) {
+        char buffer[11];
+        const char* end = internal::i32toa(i, buffer);
+        for (const char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteUint(unsigned u) {
+        char buffer[10];
+        const char* end = internal::u32toa(u, buffer);
+        for (const char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteInt64(int64_t i64) {
+        char buffer[21];
+        const char* end = internal::i64toa(i64, buffer);
+        for (const char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteUint64(uint64_t u64) {
+        char buffer[20];
+        char* end = internal::u64toa(u64, buffer);
+        for (char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteDouble(double d) {
+        char buffer[25];
+        char* end = internal::dtoa(d, buffer);
+        for (char* p = buffer; p != end; ++p)
+            os_->Put(*p);
+        return true;
+    }
+
+    bool WriteString(const Ch* str, SizeType length)  {
+        static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+        static const char escape[256] = {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+            //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+              0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
+            Z16, Z16,                                                                       // 30~4F
+              0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
+            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
+#undef Z16
+        };
+
+        os_->Put('\"');
+        GenericStringStream<SourceEncoding> is(str);
+        while (is.Tell() < length) {
+            const Ch c = is.Peek();
+            if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
+                // Unicode escaping
+                unsigned codepoint;
+                if (!SourceEncoding::Decode(is, &codepoint))
+                    return false;
+                os_->Put('\\');
+                os_->Put('u');
+                if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
+                    os_->Put(hexDigits[(codepoint >> 12) & 15]);
+                    os_->Put(hexDigits[(codepoint >>  8) & 15]);
+                    os_->Put(hexDigits[(codepoint >>  4) & 15]);
+                    os_->Put(hexDigits[(codepoint      ) & 15]);
+                }
+                else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF)    {
+                    // Surrogate pair
+                    unsigned s = codepoint - 0x010000;
+                    unsigned lead = (s >> 10) + 0xD800;
+                    unsigned trail = (s & 0x3FF) + 0xDC00;
+                    os_->Put(hexDigits[(lead >> 12) & 15]);
+                    os_->Put(hexDigits[(lead >>  8) & 15]);
+                    os_->Put(hexDigits[(lead >>  4) & 15]);
+                    os_->Put(hexDigits[(lead      ) & 15]);
+                    os_->Put('\\');
+                    os_->Put('u');
+                    os_->Put(hexDigits[(trail >> 12) & 15]);
+                    os_->Put(hexDigits[(trail >>  8) & 15]);
+                    os_->Put(hexDigits[(trail >>  4) & 15]);
+                    os_->Put(hexDigits[(trail      ) & 15]);                    
+                }
+                else
+                    return false;   // invalid code point
+            }
+            else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c])  {
+                is.Take();
+                os_->Put('\\');
+                os_->Put(escape[(unsigned char)c]);
+                if (escape[(unsigned char)c] == 'u') {
+                    os_->Put('0');
+                    os_->Put('0');
+                    os_->Put(hexDigits[(unsigned char)c >> 4]);
+                    os_->Put(hexDigits[(unsigned char)c & 0xF]);
+                }
+            }
+            else
+                Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_);
+        }
+        os_->Put('\"');
+        return true;
+    }
+
+    bool WriteStartObject() { os_->Put('{'); return true; }
+    bool WriteEndObject()   { os_->Put('}'); return true; }
+    bool WriteStartArray()  { os_->Put('['); return true; }
+    bool WriteEndArray()    { os_->Put(']'); return true; }
+
+    void Prefix(Type type) {
+        (void)type;
+        if (level_stack_.GetSize() != 0) { // this value is not at root
+            Level* level = level_stack_.template Top<Level>();
+            if (level->valueCount > 0) {
+                if (level->inArray) 
+                    os_->Put(','); // add comma if it is not the first element in array
+                else  // in object
+                    os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
+            }
+            if (!level->inArray && level->valueCount % 2 == 0)
+                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
+            level->valueCount++;
+        }
+        else {
+            RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.
+            hasRoot_ = true;
+        }
+    }
+
+    OutputStream* os_;
+    internal::Stack<StackAllocator> level_stack_;
+    bool hasRoot_;
+
+private:
+    // Prohibit copy constructor & assignment operator.
+    Writer(const Writer&);
+    Writer& operator=(const Writer&);
+};
+
+// Full specialization for StringStream to prevent memory copying
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt(int i) {
+    char *buffer = os_->Push(11);
+    const char* end = internal::i32toa(i, buffer);
+    os_->Pop(11 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
+    char *buffer = os_->Push(10);
+    const char* end = internal::u32toa(u, buffer);
+    os_->Pop(10 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
+    char *buffer = os_->Push(21);
+    const char* end = internal::i64toa(i64, buffer);
+    os_->Pop(21 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
+    char *buffer = os_->Push(20);
+    const char* end = internal::u64toa(u, buffer);
+    os_->Pop(20 - (end - buffer));
+    return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteDouble(double d) {
+    char *buffer = os_->Push(25);
+    char* end = internal::dtoa(d, buffer);
+    os_->Pop(25 - (end - buffer));
+    return true;
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/ipaacalib/cpp/src/.gitignore b/ipaacalib/cpp/src/.gitignore
index 05c3e637fa52c0fb86ceb4bcc7022728da9210b5..d275adff65a1e1fbf3b51632769bc1073f82d614 100644
--- a/ipaacalib/cpp/src/.gitignore
+++ b/ipaacalib/cpp/src/.gitignore
@@ -1,3 +1,5 @@
 ipaaca.pb.cc
 ipaaca.pb.h
+*.sw?
+*~
 
diff --git a/ipaacalib/cpp/src/Makefile b/ipaacalib/cpp/src/Makefile
deleted file mode 100644
index 45ba15946eff401b5ad8cbfae12a09f78153baa0..0000000000000000000000000000000000000000
--- a/ipaacalib/cpp/src/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-ifeq ($(WBS_ARCH),mac)
-	LIB_SUFFIX=.dylib
-else
-	LIB_SUFFIX=.so
-endif
-
-CONFIG = -DIPAACA_DEBUG_MESSAGES
-IPAACASOURCES = ipaaca.cc ipaaca.pb.cc
-SOURCES = ${IPAACASOURCES} ipaaca-test-main.cc
-TEXTSOURCES = ${IPAACASOURCES} textsender.cc
-CCFLAGS=-I. -I/usr/local/include -I/opt/local/include ${CONFIG}
-LIBFLAGS=-fPIC -shared
-BOOSTLIBS = -L/opt/local/lib -lboost_regex-mt -lboost_date_time-mt -lboost_program_options-mt -lboost_thread-mt -lboost_filesystem-mt -lboost_signals-mt -lboost_system-mt
-PROTOLIBS = -L/opt/local/lib -lprotobuf
-LIBS = ${BOOSTLIBS} ${PROTOLIBS} -L/usr/local/lib -lrsc -lrsbcore
-
-COMPILER = gfilt
-
-all: lib
-	
-
-lib:
-	${COMPILER} ${CCFLAGS} ${IPAACASOURCES} ${LIBS} ${LIBFLAGS} -o libipaaca${LIB_SUFFIX}
-
-receiver:
-	${COMPILER} ${CCFLAGS} -DMAKE_RECEIVER -o ipaaca-receiver ${SOURCES} ${LIBS}
-
-sender:
-	${COMPILER} ${CCFLAGS} -DMAKE_SENDER -o ipaaca-sender ${SOURCES} ${LIBS}
-
-main:
-	${COMPILER} ${CCFLAGS} -o ipaaca-main ${SOURCES} ${LIBS}
-
-protoc:
-	protoc --proto_path=../../proto ../../proto/ipaaca.proto --cpp_out=.
-
-clean:
-	rm -f libipaaca${LIB_SUFFIX} ipaaca-main ipaaca-sender ipaaca-receiver ipaaca.pb.h ipaaca.pb.cc
-
-
diff --git a/ipaacalib/cpp/src/ipaaca-buffers.cc b/ipaacalib/cpp/src/ipaaca-buffers.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8c99b7d3b2a6db1c952694645bf61e0de70a4ca0
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-buffers.cc
@@ -0,0 +1,757 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+#define VERBOSE_HANDLERS 0  // remove later
+
+namespace ipaaca {
+
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj)//{{{
+{
+	os << "PayloadUpdate(uid=" << obj.uid << ", revision=" << obj.revision;
+	os << ", writer_name=" << obj.writer_name << ", is_delta=" << (obj.is_delta?"True":"False");
+	os << ", new_items = {";
+	bool first = true;
+	for (auto& newit: obj.new_items) {
+		if (first) { first=false; } else { os << ", "; }
+		//os << "'" << it->first << "':'" << it->second << "'";
+		os << "'" << newit.first << "': " << newit.second;
+	}
+	os << "}, keys_to_remove = [";
+	first = true;
+	for (std::vector<std::string>::const_iterator it=obj.keys_to_remove.begin(); it!=obj.keys_to_remove.end(); ++it) {
+		if (first) { first=false; } else { os << ", "; }
+		os << "'" << *it << "'";
+	}
+	os << "])";
+	return os;
+}
+//}}}
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IULinkUpdate& obj)//{{{
+{
+	os << "LinkUpdate(uid=" << obj.uid << ", revision=" << obj.revision;
+	os << ", writer_name=" << obj.writer_name << ", is_delta=" << (obj.is_delta?"True":"False");
+	os << ", new_links = {";
+	bool first = true;
+	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj.new_links.begin(); it!=obj.new_links.end(); ++it) {
+		if (first) { first=false; } else { os << ", "; }
+		os << "'" << it->first << "': [";
+		bool ffirst = true;
+		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			if (ffirst) { ffirst=false; } else { os << ", "; }
+			os << "'" << *it2 << "'";
+		}
+		os << "]";
+	}
+	os << "}, links_to_remove = {";
+	first = true;
+	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj.links_to_remove.begin(); it!=obj.links_to_remove.end(); ++it) {
+		if (first) { first=false; } else { os << ", "; }
+		os << "'" << it->first << "': [";
+		bool ffirst = true;
+		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			if (ffirst) { ffirst=false; } else { os << ", "; }
+			os << "'" << *it2 << "'";
+		}
+		os << "]";
+	}
+	os << "})";
+	return os;
+}
+//}}}
+
+// IUEventHandler//{{{
+IPAACA_EXPORT IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category)
+: _function(function), _event_mask(event_mask), _for_all_categories(false)
+{
+	if (category=="") {
+		_for_all_categories = true;
+	} else {
+		_categories.insert(category);
+	}
+}
+IPAACA_EXPORT IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories)
+: _function(function), _event_mask(event_mask), _for_all_categories(false)
+{
+	if (categories.size()==0) {
+		_for_all_categories = true;
+	} else {
+		_categories = categories;
+	}
+}
+IPAACA_EXPORT void IUEventHandler::call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category)
+{
+	if (_condition_met(event_type, category)) {
+		//IUInterface::ptr iu = buffer->get(uid);
+		//if (iu) {
+#if VERBOSE_HANDLERS == 1
+			std::cout << "[" << pthread_self() << " handler ENTER]" << std::endl;
+#endif
+			_function(iu, event_type, local);
+#if VERBOSE_HANDLERS == 1
+			std::cout << "[" << pthread_self() << " handler EXIT]" << std::endl;
+#endif
+		//}
+	}
+}
+//}}}
+
+// Buffer//{{{
+IPAACA_EXPORT void Buffer::_allocate_unique_name(const std::string& basename, const std::string& function) {
+	std::string uuid = ipaaca::generate_uuid_string();
+	_basename = basename;
+	_uuid = uuid.substr(0,8);
+	_unique_name = "/ipaaca/component/" + _basename + "ID" + _uuid + "/" + function;
+}
+IPAACA_EXPORT void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories)
+{
+	std::cout << "register_handler " << function << " " << event_mask << " " << categories << std::endl;
+	IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, categories));
+	_event_handlers.push_back(handler);
+}
+IPAACA_EXPORT void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category)
+{
+	std::cout << "register_handler " << function << " " << event_mask << " " << category << std::endl;
+	IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, category));
+	_event_handlers.push_back(handler);
+}
+IPAACA_EXPORT void Buffer::call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category)
+{
+	//IPAACA_INFO("handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid())
+	//std::cout << "handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid() << std::endl;
+	for (std::vector<IUEventHandler::ptr>::iterator it = _event_handlers.begin(); it != _event_handlers.end(); ++it) {
+		(*it)->call(this, iu, local, event_type, category);
+	}
+}
+//}}}
+
+// Callbacks for OutputBuffer//{{{
+IPAACA_EXPORT CallbackIUPayloadUpdate::CallbackIUPayloadUpdate(Buffer* buffer): _buffer(buffer) { }
+IPAACA_EXPORT CallbackIULinkUpdate::CallbackIULinkUpdate(Buffer* buffer): _buffer(buffer) { }
+IPAACA_EXPORT CallbackIUCommission::CallbackIUCommission(Buffer* buffer): _buffer(buffer) { }
+// dlw
+IPAACA_EXPORT CallbackIUResendRequest::CallbackIUResendRequest(Buffer* buffer): _buffer(buffer) { }
+
+IPAACA_EXPORT boost::shared_ptr<int> CallbackIUPayloadUpdate::call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update)
+{
+	IPAACA_INFO("")
+	//std::cout << "-- Received a modify_payload with " << update->new_items.size() << " keys to merge." << std::endl;
+	IUInterface::ptr iui = _buffer->get(update->uid);
+	if (! iui) {
+		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid)
+		return boost::shared_ptr<int>(new int(0));
+	}
+	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
+	iu->_revision_lock.lock();
+	if ((update->revision != 0) && (update->revision != iu->_revision)) {
+		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid)
+		IPAACA_INFO(" Referred-to revision was " << update->revision << " while local one is " << iu->_revision)
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	}
+	if (update->is_delta) {
+		// FIXME FIXME this is an unsolved problem atm: deletes in a delta update are
+		// sent individually. We should have something like _internal_merge_and_remove
+		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
+			iu->payload()._internal_remove(*it, update->writer_name); //_buffer->unique_name());
+		}
+		// but it is solved for pure merges:
+		iu->payload()._internal_merge(update->new_items, update->writer_name);
+	} else {
+		iu->payload()._internal_replace_all(update->new_items, update->writer_name); //_buffer->unique_name());
+	}
+	//std::cout << "-- Calling update handler due to remote write." << std::endl;
+	_buffer->call_iu_event_handlers(iu, true, IU_UPDATED, iu->category());
+	revision_t revision = iu->revision();
+	iu->_revision_lock.unlock();
+	return boost::shared_ptr<int>(new int(revision));
+}
+
+IPAACA_EXPORT boost::shared_ptr<int> CallbackIULinkUpdate::call(const std::string& methodName, boost::shared_ptr<IULinkUpdate> update)
+{
+	IUInterface::ptr iui = _buffer->get(update->uid);
+	if (! iui) {
+		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid)
+		return boost::shared_ptr<int>(new int(0));
+	}
+	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
+	iu->_revision_lock.lock();
+	if ((update->revision != 0) && (update->revision != iu->_revision)) {
+		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid)
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	}
+	if (update->is_delta) {
+		iu->modify_links(update->new_links, update->links_to_remove, update->writer_name);
+	} else {
+		iu->set_links(update->new_links, update->writer_name);
+	}
+	_buffer->call_iu_event_handlers(iu, true, IU_LINKSUPDATED, iu->category());
+	revision_t revision = iu->revision();
+	iu->_revision_lock.unlock();
+	return boost::shared_ptr<int>(new int(revision));
+}
+IPAACA_EXPORT boost::shared_ptr<int> CallbackIUCommission::call(const std::string& methodName, boost::shared_ptr<protobuf::IUCommission> update)
+{
+	IUInterface::ptr iui = _buffer->get(update->uid());
+	if (! iui) {
+		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid())
+		return boost::shared_ptr<int>(new int(0));
+	}
+	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
+	iu->_revision_lock.lock();
+	if ((update->revision() != 0) && (update->revision() != iu->_revision)) {
+		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid())
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	}
+	if (iu->committed()) {
+		return boost::shared_ptr<int>(new int(0));
+	} else {
+	}
+	iu->_internal_commit(update->writer_name());
+	_buffer->call_iu_event_handlers(iu, true, IU_LINKSUPDATED, iu->category());
+	revision_t revision = iu->revision();
+	iu->_revision_lock.unlock();
+	return boost::shared_ptr<int>(new int(revision));
+}
+/** dlw */
+IPAACA_EXPORT boost::shared_ptr<int> CallbackIUResendRequest::call(const std::string& methodName, boost::shared_ptr<protobuf::IUResendRequest> update)
+{
+	IUInterface::ptr iui = _buffer->get(update->uid());
+	if (! iui) {
+		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid())
+		return boost::shared_ptr<int>(new int(0));
+	}
+	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
+	if ((update->has_hidden_scope_name() == true)&&(update->hidden_scope_name().compare("") != 0)){
+		//_buffer->call_iu_event_handlers(iu, true, IU_UPDATED, update->hidden_scope_name());
+		revision_t revision = iu->revision();
+
+		_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 {
+		revision_t revision = 0;
+		return boost::shared_ptr<int>(new int(revision));
+	}
+}
+//}}}
+
+// OutputBuffer//{{{
+
+IPAACA_EXPORT OutputBuffer::OutputBuffer(const std::string& basename, const std::string& channel)
+:Buffer(basename, "OB")
+{
+	//IPAACA_INFO("Entering ...")
+	_id_prefix = _basename + "-" + _uuid + "-IU-";
+	_channel = (channel=="") ? __ipaaca_static_option_default_channel: channel;
+	_initialize_server();
+	//IPAACA_INFO("... exiting.")
+}
+IPAACA_EXPORT void OutputBuffer::_initialize_server()
+{
+	//IPAACA_INFO("Entering ...")
+	_server = getFactory().createLocalServer( Scope( _unique_name ) );
+	//_server = getFactory().createServer( Scope( _unique_name ) );
+	//IPAACA_INFO("Registering methods")
+	_server->registerMethod("updatePayload", Server::CallbackPtr(new CallbackIUPayloadUpdate(this)));
+	_server->registerMethod("updateLinks", Server::CallbackPtr(new CallbackIULinkUpdate(this)));
+	_server->registerMethod("commit", Server::CallbackPtr(new CallbackIUCommission(this)));
+	// dlw
+	_server->registerMethod("resendRequest", Server::CallbackPtr(new CallbackIUResendRequest(this)));
+
+	//IPAACA_INFO("... exiting.")
+}
+IPAACA_EXPORT OutputBuffer::ptr OutputBuffer::create(const std::string& basename)
+{
+	Initializer::initialize_backend();
+	return OutputBuffer::ptr(new OutputBuffer(basename));
+}
+IPAACA_EXPORT IUInterface::ptr OutputBuffer::get(const std::string& iu_uid)
+{
+	IUStore::iterator it = _iu_store.find(iu_uid);
+	if (it==_iu_store.end()) return IUInterface::ptr();
+	return it->second;
+}
+IPAACA_EXPORT std::set<IUInterface::ptr> OutputBuffer::get_ius()
+{
+	std::set<IUInterface::ptr> set;
+	for (IUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) set.insert(it->second);
+	return set;
+}
+
+IPAACA_EXPORT void OutputBuffer::_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)
+{
+	IULinkUpdate* lup = new ipaaca::IULinkUpdate();
+	Informer<ipaaca::IULinkUpdate>::DataPtr ldata(lup);
+	lup->uid = iu->uid();
+	lup->is_delta = is_delta;
+	lup->revision = revision;
+	lup->is_delta = true;
+	lup->new_links = new_links;
+	if (is_delta) lup->links_to_remove = links_to_remove;
+	if (writer_name=="") lup->writer_name = _unique_name;
+	else lup->writer_name = writer_name;
+	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
+	informer->publish(ldata);
+}
+
+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);
+	pup->payload_type = iu->payload_type();
+	pup->uid = iu->uid();
+	pup->is_delta = is_delta;
+	pup->revision = revision;
+	pup->new_items = new_items;
+	if (is_delta) pup->keys_to_remove = keys_to_remove;
+	if (writer_name=="") pup->writer_name = _unique_name;
+	else pup->writer_name = writer_name;
+	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
+	informer->publish(pdata);
+}
+
+IPAACA_EXPORT void OutputBuffer::_send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name)
+{
+	Informer<protobuf::IUCommission>::DataPtr data(new protobuf::IUCommission());
+	data->set_uid(iu->uid());
+	data->set_revision(revision);
+	if (writer_name=="") data->set_writer_name(_unique_name);
+	else data->set_writer_name(writer_name);
+
+	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
+	informer->publish(data);
+}
+
+
+
+
+
+
+IPAACA_EXPORT void OutputBuffer::add(IU::ptr iu)
+{
+	if (_iu_store.count(iu->uid()) > 0) {
+		throw IUPublishedError();
+	}
+	if (iu->is_published()) {
+		throw IUPublishedError();
+	}
+	if (iu->access_mode() != IU_ACCESS_MESSAGE) {
+		// (for Message-type IUs: do not actually store them)
+		_iu_store[iu->uid()] = iu;
+	}
+	iu->_associate_with_buffer(this); //shared_from_this());
+	_publish_iu(iu);
+}
+
+IPAACA_EXPORT void OutputBuffer::_publish_iu(IU::ptr iu)
+{
+	Informer<AnyType>::Ptr informer = _get_informer(iu->_category);
+	Informer<ipaaca::IU>::DataPtr iu_data(iu);
+	informer->publish(iu_data);
+}
+
+IPAACA_EXPORT void OutputBuffer::_publish_iu_resend(IU::ptr iu, const std::string& hidden_scope_name)
+{
+	Informer<AnyType>::Ptr informer = _get_informer(hidden_scope_name);
+	Informer<ipaaca::IU>::DataPtr iu_data(iu);
+	informer->publish(iu_data);
+}
+
+
+
+
+IPAACA_EXPORT Informer<AnyType>::Ptr OutputBuffer::_get_informer(const std::string& category)
+{
+	if (_informer_store.count(category) > 0) {
+		return _informer_store[category];
+	} else {
+		//IPAACA_INFO("Making new informer for category " << category)
+		std::string scope_string = "/ipaaca/channel/" + _channel + "/category/" + category;
+		IPAACA_INFO("Adding informer on " << scope_string)
+
+		Informer<AnyType>::Ptr informer = getFactory().createInformer<AnyType> ( Scope(scope_string));
+		_informer_store[category] = informer;
+		return informer;
+	}
+}
+IPAACA_EXPORT boost::shared_ptr<IU> OutputBuffer::remove(const std::string& iu_uid)
+{
+	IUStore::iterator it = _iu_store.find(iu_uid);
+	if (it == _iu_store.end()) {
+		IPAACA_WARNING("Removal of IU " << iu_uid << " requested, but not present in our OutputBuffer")
+		//throw IUNotFoundError();
+	}
+	IU::ptr iu = it->second;
+	_retract_iu(iu);
+	_iu_store.erase(iu_uid);
+	return iu;
+}
+IPAACA_EXPORT boost::shared_ptr<IU> OutputBuffer::remove(IU::ptr iu)
+{
+	return remove(iu->uid()); // to make sure it is in the store
+}
+
+IPAACA_EXPORT void OutputBuffer::_retract_iu(IU::ptr iu)
+{
+	Informer<protobuf::IURetraction>::DataPtr data(new protobuf::IURetraction());
+	data->set_uid(iu->uid());
+	data->set_revision(iu->revision());
+	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
+	informer->publish(data);
+}
+
+
+//}}}
+
+// InputBuffer//{{{
+IPAACA_EXPORT InputBuffer::InputBuffer(const BufferConfiguration& bufferconfiguration)
+:Buffer(bufferconfiguration.get_basename(), "IB")
+{
+	_channel = bufferconfiguration.get_channel();
+
+	for (std::vector<std::string>::const_iterator it=bufferconfiguration.get_category_interests().begin(); it!=bufferconfiguration.get_category_interests().end(); ++it) {
+		_create_category_listener_if_needed(*it);
+	}
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::set<std::string>& category_interests)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	for (std::set<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
+		_create_category_listener_if_needed(*it);
+	}
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::vector<std::string>& category_interests)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	for (std::vector<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
+		_create_category_listener_if_needed(*it);
+	}
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+/*IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::initializer_list<std::string>& category_interests)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	for (std::initializer_list<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
+		_create_category_listener_if_needed(*it);
+	}
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}*/
+IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	_create_category_listener_if_needed(category_interest1);
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	_create_category_listener_if_needed(category_interest1);
+	_create_category_listener_if_needed(category_interest2);
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	_create_category_listener_if_needed(category_interest1);
+	_create_category_listener_if_needed(category_interest2);
+	_create_category_listener_if_needed(category_interest3);
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4)
+:Buffer(basename, "IB")
+{
+	_channel = __ipaaca_static_option_default_channel;
+
+	_create_category_listener_if_needed(category_interest1);
+	_create_category_listener_if_needed(category_interest2);
+	_create_category_listener_if_needed(category_interest3);
+	_create_category_listener_if_needed(category_interest4);
+	_create_category_listener_if_needed(_uuid);
+	triggerResend = false;
+}
+
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const BufferConfiguration& bufferconfiguration)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(bufferconfiguration));
+}
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::set<std::string>& category_interests)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(basename, category_interests));
+}
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::vector<std::string>& category_interests)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(basename, category_interests));
+}
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(basename, category_interest1));
+}
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2));
+}
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3));
+}
+IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4)
+{
+	Initializer::initialize_backend();
+	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3, category_interest4));
+}
+
+
+IPAACA_EXPORT void InputBuffer::set_resend(bool resendActive)
+{
+	triggerResend = resendActive;
+}
+
+IPAACA_EXPORT bool InputBuffer::get_resend()
+{
+	return triggerResend;
+}
+
+
+IPAACA_EXPORT IUInterface::ptr InputBuffer::get(const std::string& iu_uid)
+{
+	RemotePushIUStore::iterator it = _iu_store.find(iu_uid); // TODO genericize
+	if (it==_iu_store.end()) return IUInterface::ptr();
+	return it->second;
+}
+IPAACA_EXPORT std::set<IUInterface::ptr> InputBuffer::get_ius()
+{
+	std::set<IUInterface::ptr> set;
+	for (RemotePushIUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) set.insert(it->second); // TODO genericize
+	return set;
+}
+
+
+IPAACA_EXPORT RemoteServerPtr InputBuffer::_get_remote_server(const std::string& unique_server_name)
+{
+	std::map<std::string, RemoteServerPtr>::iterator it = _remote_server_store.find(unique_server_name);
+	if (it!=_remote_server_store.end()) return it->second;
+	RemoteServerPtr remote_server = getFactory().createRemoteServer(Scope(unique_server_name));
+	_remote_server_store[unique_server_name] = remote_server;
+	return remote_server;
+}
+
+IPAACA_EXPORT ListenerPtr InputBuffer::_create_category_listener_if_needed(const std::string& category)
+{
+	std::map<std::string, ListenerPtr>::iterator it = _listener_store.find(category);
+	if (it!=_listener_store.end()) {
+		return it->second;
+	}
+	//IPAACA_INFO("Creating a new listener for category " << category)
+	std::string scope_string = "/ipaaca/channel/" + _channel + "/category/" + category;
+
+	ListenerPtr listener = getFactory().createListener( Scope(scope_string) );
+	IPAACA_INFO("Adding listener on " << scope_string)
+	HandlerPtr event_handler = HandlerPtr(
+			new EventFunctionHandler(
+				boost::bind(&InputBuffer::_handle_iu_events, this, _1)
+			)
+		);
+	listener->addHandler(event_handler);
+	_listener_store[category] = listener;
+	return listener;
+}
+IPAACA_EXPORT void InputBuffer::_trigger_resend_request(EventPtr event) {
+	if (!triggerResend) return;
+	std::string type = event->getType();
+	std::string uid = "";
+	std::string writerName = "";
+	if (type == "ipaaca::IUPayloadUpdate") {
+		boost::shared_ptr<IUPayloadUpdate> update = boost::static_pointer_cast<IUPayloadUpdate>(event->getData());
+		uid = update->uid;
+		writerName = update->writer_name;
+	} else if (type == "ipaaca::IULinkUpdate") {
+		boost::shared_ptr<IULinkUpdate> update = boost::static_pointer_cast<IULinkUpdate>(event->getData());
+		uid = update->uid;
+		writerName = update->writer_name;
+	} else if (type == "ipaaca::protobuf::IUCommission") {
+		boost::shared_ptr<protobuf::IUCommission> update = boost::static_pointer_cast<protobuf::IUCommission>(event->getData());
+		uid = update->uid();
+		writerName = update->writer_name();
+	} else {
+		std::cout << "_trigger_resend_request: unhandled event type " << type << std::endl;
+	}
+
+	if (!writerName.empty()) {
+		RemoteServerPtr server = _get_remote_server(writerName);
+		if (!uid.empty()) {
+			boost::shared_ptr<protobuf::IUResendRequest> update = boost::shared_ptr<protobuf::IUResendRequest>(new protobuf::IUResendRequest());
+			update->set_uid(uid);
+			update->set_hidden_scope_name(_uuid);
+			boost::shared_ptr<int> result = server->call<int>("resendRequest", update, IPAACA_REMOTE_SERVER_TIMEOUT);
+			if (*result == 0) {
+				throw IUResendRequestFailedError();
+			} else {
+				//std::cout << "revision " << *result << std::endl;
+			}
+		}
+	}
+}
+IPAACA_EXPORT void InputBuffer::_handle_iu_events(EventPtr event)
+{
+	std::string type = event->getType();
+	if (type == "ipaaca::RemotePushIU") {
+		boost::shared_ptr<RemotePushIU> iu = boost::static_pointer_cast<RemotePushIU>(event->getData());
+		if (_iu_store.count(iu->category()) > 0) {
+			// already got the IU... ignore
+		} else {
+			_iu_store[iu->uid()] = iu;
+			iu->_set_buffer(this);
+			call_iu_event_handlers(iu, false, IU_ADDED, iu->category() );
+		}
+		//IPAACA_INFO( "New RemotePushIU state: " << (*iu) )
+	} else if (type == "ipaaca::RemoteMessage") {
+		boost::shared_ptr<RemoteMessage> iu = boost::static_pointer_cast<RemoteMessage>(event->getData());
+		//_iu_store[iu->uid()] = iu;
+		//iu->_set_buffer(this);
+		//std::cout << "REFCNT after cast, before calling handlers: " << iu.use_count() << std::endl;
+		call_iu_event_handlers(iu, false, IU_MESSAGE, iu->category() );
+		//_iu_store.erase(iu->uid());
+	} else {
+		RemotePushIUStore::iterator it;
+		if (type == "ipaaca::IUPayloadUpdate") {
+			boost::shared_ptr<IUPayloadUpdate> update = boost::static_pointer_cast<IUPayloadUpdate>(event->getData());
+			//IPAACA_INFO("** writer name: " << update->writer_name)
+			std::cout << "writer name " << update->writer_name << std::endl;
+			if (update->writer_name == _unique_name) {
+				return;
+			}
+			it = _iu_store.find(update->uid);
+			if (it == _iu_store.end()) {
+				_trigger_resend_request(event);
+				IPAACA_INFO("Using UPDATED message for an IU that we did not fully receive before")
+				return;
+			}
+
+			it->second->_apply_update(update);
+			call_iu_event_handlers(it->second, false, IU_UPDATED, it->second->category() );
+
+		} else if (type == "ipaaca::IULinkUpdate") {
+			boost::shared_ptr<IULinkUpdate> update = boost::static_pointer_cast<IULinkUpdate>(event->getData());
+			if (update->writer_name == _unique_name) {
+				return;
+			}
+			it = _iu_store.find(update->uid);
+			if (it == _iu_store.end()) {
+				_trigger_resend_request(event);
+				IPAACA_INFO("Ignoring LINKSUPDATED message for an IU that we did not fully receive before")
+				return;
+			}
+
+			it->second->_apply_link_update(update);
+			call_iu_event_handlers(it->second, false, IU_LINKSUPDATED, it->second->category() );
+
+		} else if (type == "ipaaca::protobuf::IUCommission") {
+			boost::shared_ptr<protobuf::IUCommission> update = boost::static_pointer_cast<protobuf::IUCommission>(event->getData());
+			if (update->writer_name() == _unique_name) {
+				return;
+			}
+			it = _iu_store.find(update->uid());
+			if (it == _iu_store.end()) {
+				_trigger_resend_request(event);
+				IPAACA_INFO("Ignoring COMMITTED message for an IU that we did not fully receive before")
+				return;
+			}
+			//
+			it->second->_apply_commission();
+			it->second->_revision = update->revision();
+			call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() );
+			//
+			//
+		} else if (type == "ipaaca::protobuf::IURetraction") {
+			boost::shared_ptr<protobuf::IURetraction> update = boost::static_pointer_cast<protobuf::IURetraction>(event->getData());
+			it = _iu_store.find(update->uid());
+			if (it == _iu_store.end()) {
+				_trigger_resend_request(event);
+				IPAACA_INFO("Ignoring RETRACTED message for an IU that we did not fully receive before")
+				return;
+			}
+			//
+			it->second->_revision = update->revision();
+			it->second->_apply_retraction();
+			// remove from InputBuffer     FIXME: this is a crossover between retracted and deleted behavior
+			_iu_store.erase(it->first);
+			// and call the handler. IU reference is still valid for this call, although removed from buffer.
+			call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() );
+			//
+		} else {
+			std::cout << "(Unhandled Event type " << type << " !)" << std::endl;
+			return;
+		}
+		//IPAACA_INFO( "New RemotePushIU state: " << *(it->second) )
+	}
+}
+//}}}
+
+} // of namespace ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc b/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc
index 6430d28e21a26880a7d0960a73db9d6117c69c3b..e08b33ea34b07381ac4b58e5fadced473706f362 100644
--- a/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc
+++ b/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc
@@ -31,7 +31,10 @@
  */
 
 #include <ipaaca/ipaaca.h>
+
+#ifndef WIN32
 #include <getopt.h>
+#endif
 
 namespace ipaaca {
 
@@ -72,6 +75,7 @@ void CommandLineOptions::dump() {
 //
 
 CommandLineParser::CommandLineParser()
+: library_options_handled(true)
 {
 	initialize_parser_defaults();
 }
@@ -82,6 +86,60 @@ void CommandLineParser::initialize_parser_defaults()
 	add_option("verbose",        'v', false, "");
 	add_option("character-name", 'c', true, "UnknownCharacter");
 	add_option("component-name", 'n', true, "UnknownComponent");
+	if (library_options_handled) {
+		add_option("ipaaca-payload-type", 0, true, "JSON");
+		add_option("ipaaca-default-channel", 0, true, "default");
+		add_option("ipaaca-enable-logging", 0, true, "WARNING");
+		add_option("rsb-enable-logging", 0, true, "ERROR");
+	}
+}
+
+bool CommandLineParser::consume_library_option(const std::string& name, bool expect, const char* optarg)
+{
+	if (name=="ipaaca-payload-type") {
+		std::string newtype = optarg;
+		if (newtype=="MAP") newtype="STR";
+		if ((newtype=="JSON") || (newtype=="STR")) {
+			IPAACA_DEBUG("Setting default payload type " << newtype)
+			__ipaaca_static_option_default_payload_type = newtype;
+		} else {
+			IPAACA_WARNING("Ignoring unknown default payload type " << newtype << " - should be one of JSON or STR")
+		}
+	} else if (name=="ipaaca-default-channel") {
+		std::string newch = optarg;
+		IPAACA_DEBUG("Setting default channel " << newch)
+		__ipaaca_static_option_default_channel = newch;
+	} else if (name=="ipaaca-enable-logging") {
+		std::string level(optarg);
+		if ((level=="NONE") || (level=="SILENT")) {
+			IPAACA_DEBUG("Will set log level to NONE")
+			__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_NONE;
+		} else if (level=="DEBUG") {
+			__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_DEBUG;
+			IPAACA_DEBUG("Just set log level to DEBUG")
+		} else if (level=="INFO") {
+			IPAACA_DEBUG("Set log level to INFO")
+			__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_INFO;
+		} else if (level=="WARNING") {
+			IPAACA_DEBUG("Set log level to WARNING")
+			__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_WARNING;
+		} else if (level=="ERROR") {
+			IPAACA_DEBUG("Set log level to ERROR")
+			__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_ERROR;
+		} else if (level=="CRITICAL") {
+			IPAACA_DEBUG("Set log level to CRITICAL")
+			__ipaaca_static_option_log_level = IPAACA_LOG_LEVEL_CRITICAL;
+		} else {
+			IPAACA_WARNING("Unknown log level " << optarg)
+			IPAACA_WARNING("Valid levels are: NONE, DEBUG, INFO, WARNING, ERROR, CRITICAL ")
+		}
+	} else if (name=="rsb-enable-logging") {
+		IPAACA_WARNING("Unimplemented option ignored: " << name)
+		IPAACA_IMPLEMENT_ME
+	} else {
+		return false;
+	}
+	return true;
 }
 
 void CommandLineParser::dump_options()
@@ -114,6 +172,11 @@ void CommandLineParser::add_option(const std::string& optname, char shortoptn, b
 
 CommandLineOptions::ptr CommandLineParser::parse(int argc, char* const* argv)
 {
+#ifdef WIN32
+	LOG_IPAACA_CONSOLE("IMPLEMENT ME: command line parsing for Windows. (req'd: getopt)")
+	throw NotImplementedError();
+#else
+	IPAACA_DEBUG("")
 	int len = options.size();
 	struct option long_options[len+1];
 	int i=0;
@@ -148,19 +211,23 @@ CommandLineOptions::ptr CommandLineParser::parse(int argc, char* const* argv)
 		// Detect the end of the options. 
 		if (c == -1) break;
 		
+		bool do_set_option = false;
+		std::string longname;
+		std::string longoption;
+		bool expect;
 		switch (c)
 		{
 			case 0:
 				{
-				std::string longname = long_options[option_index].name;
+				longname = long_options[option_index].name;
 				if (longname == "help") {
 					std::cout << "Options:" << std::endl;
 					dump_options();
 					exit(0);
 				}
-				std::string longoption = long_options[option_index].name;
-				bool expect = options[longoption];
-				clo->set_option(longoption, expect, optarg);
+				longoption = long_options[option_index].name;
+				expect = options[longoption];
+				do_set_option = true;
 				}
 				break;
 
@@ -170,13 +237,22 @@ CommandLineOptions::ptr CommandLineParser::parse(int argc, char* const* argv)
 			default:
 				std::string s;
 				s += c;
-				std::string longoption = longopt[c];
-				bool expect = options[longoption];
+				longoption = longopt[c];
+				expect = options[longoption];
+				do_set_option = true;
+		}
+		if (do_set_option) {
+			if (library_options_handled) {
+				do_set_option = ! consume_library_option(longoption, expect, optarg );
+			}
+			if (do_set_option) {
 				clo->set_option(longoption, expect, optarg);
+			}
 		}
 	}
 	ensure_defaults_in( clo );
 	return clo;
+#endif
 }
 
 void CommandLineParser::ensure_defaults_in( CommandLineOptions::ptr clo )
diff --git a/ipaacalib/cpp/src/ipaaca-fake.cc b/ipaacalib/cpp/src/ipaaca-fake.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c0d27977a0a6574ae9219a3f733a9f1800d7e9a9
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-fake.cc
@@ -0,0 +1,65 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+IPAACA_EXPORT inline FakeIU::FakeIU() {
+	IPAACA_INFO("")
+}
+IPAACA_EXPORT boost::shared_ptr<FakeIU> FakeIU::create()
+{
+	IPAACA_INFO("");
+	auto iu = boost::shared_ptr<FakeIU>(new FakeIU());
+	iu->_payload.initialize(iu);
+	return iu;
+}
+IPAACA_EXPORT void FakeIU::add_fake_payload_item(const std::string& key, PayloadDocumentEntry::ptr entry)
+{
+	_payload._remotely_enforced_setitem(key, entry);
+}
+IPAACA_EXPORT inline FakeIU::~FakeIU() { }
+IPAACA_EXPORT inline Payload& FakeIU::payload() { return _payload; }
+IPAACA_EXPORT inline const Payload& FakeIU::const_payload() const { return _payload; }
+IPAACA_EXPORT inline void FakeIU::commit() { }
+IPAACA_EXPORT inline void FakeIU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) { }
+IPAACA_EXPORT inline void FakeIU::_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) { }
+IPAACA_EXPORT inline void FakeIU::_apply_update(IUPayloadUpdate::ptr update) { }
+IPAACA_EXPORT inline void FakeIU::_apply_link_update(IULinkUpdate::ptr update) { }
+IPAACA_EXPORT inline void FakeIU::_apply_commission() { }
+IPAACA_EXPORT inline void FakeIU::_apply_retraction() { }
+
+} // of namespace ipaaca
+
+
diff --git a/ipaacalib/cpp/src/ipaaca-internal.cc b/ipaacalib/cpp/src/ipaaca-internal.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1ce8f5f467648919b4728b2ce2e694447c5ba54c
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-internal.cc
@@ -0,0 +1,623 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+// static library Initializer
+IPAACA_EXPORT bool Initializer::_initialized = false;
+IPAACA_EXPORT bool Initializer::initialized() { return _initialized; }
+IPAACA_EXPORT void Initializer::initialize_ipaaca_rsb_if_needed()
+{
+	initialize_backend();
+}
+IPAACA_EXPORT void Initializer::initialize_backend()//{{{
+{
+	if (_initialized) return;
+
+	//IPAACA_INFO("Calling auto_configure_rsb()")
+	auto_configure_rsb();
+
+	// RYT FIXME This configuration stuff has been simply removed in rsb!
+	//ParticipantConfig config = ParticipantConfig::fromConfiguration();
+	//getFactory().setDefaultParticipantConfig(config);
+
+	//IPAACA_INFO("Creating and registering Converters")
+	boost::shared_ptr<IUConverter> iu_converter(new IUConverter());
+	converterRepository<std::string>()->registerConverter(iu_converter);
+
+	boost::shared_ptr<MessageConverter> message_converter(new MessageConverter());
+	converterRepository<std::string>()->registerConverter(message_converter);
+
+	boost::shared_ptr<IUPayloadUpdateConverter> payload_update_converter(new IUPayloadUpdateConverter());
+	converterRepository<std::string>()->registerConverter(payload_update_converter);
+
+	boost::shared_ptr<IULinkUpdateConverter> link_update_converter(new IULinkUpdateConverter());
+	converterRepository<std::string>()->registerConverter(link_update_converter);
+
+	boost::shared_ptr<ProtocolBufferConverter<protobuf::IUCommission> > iu_commission_converter(new ProtocolBufferConverter<protobuf::IUCommission> ());
+	converterRepository<std::string>()->registerConverter(iu_commission_converter);
+
+	// dlw
+	boost::shared_ptr<ProtocolBufferConverter<protobuf::IUResendRequest> > iu_resendrequest_converter(new ProtocolBufferConverter<protobuf::IUResendRequest> ());
+	converterRepository<std::string>()->registerConverter(iu_resendrequest_converter);
+
+	boost::shared_ptr<ProtocolBufferConverter<protobuf::IURetraction> > iu_retraction_converter(new ProtocolBufferConverter<protobuf::IURetraction> ());
+	converterRepository<std::string>()->registerConverter(iu_retraction_converter);
+
+	boost::shared_ptr<IntConverter> int_converter(new IntConverter());
+	converterRepository<std::string>()->registerConverter(int_converter);
+
+	//IPAACA_INFO("Initialization complete.")
+	_initialized = true;
+	//IPAACA_TODO("initialize all converters")
+}//}}}
+IPAACA_EXPORT void Initializer::dump_current_default_config()//{{{
+{
+	IPAACA_INFO("--- Dumping current default participant configuration ---")
+	rsb::ParticipantConfig config = getFactory().getDefaultParticipantConfig();
+	std::set<rsb::ParticipantConfig::Transport> transports = config.getTransports();
+	for (std::set<rsb::ParticipantConfig::Transport>::const_iterator it=transports.begin(); it!=transports.end(); ++it) {
+		IPAACA_INFO( "Active transport: " << it->getName() )
+	}
+	IPAACA_INFO("--- End of configuration dump ---")
+	//ParticipantConfig::Transport inprocess = config.getTransport("inprocess");
+	//inprocess.setEnabled(true);
+	//config.addTransport(inprocess);
+}//}}}
+IPAACA_EXPORT void Initializer::auto_configure_rsb()//{{{
+{
+	// quick hack to iterate through the pwd parents
+	// and find the closest rsb plugin dir
+	//
+	// but only if not yet defined
+	const char* plugin_path = getenv("RSB_PLUGINS_CPP_PATH");
+	if (!plugin_path) {
+#ifdef WIN32
+		LOG_IPAACA_CONSOLE("WARNING: RSB_PLUGINS_CPP_PATH not set - in Windows it has to be specified.")
+		//throw NotImplementedError();
+#else
+		LOG_IPAACA_CONSOLE("RSB_PLUGINS_CPP_PATH not set; looking here and up to 7 dirs up.")
+		std::string pathstr = "./";
+		for (int i=0; i<   8 /* depth EIGHT (totally arbitrary..) */  ; i++) {
+			std::string where_str = pathstr+"deps/lib/rsb*/plugins";
+			const char* where = where_str.c_str();
+			glob_t g;
+			glob(where, 0, NULL, &g);
+			if (g.gl_pathc>0) {
+				const char* found_path = g.gl_pathv[0];
+				LOG_IPAACA_CONSOLE("Found an RSB plugin dir which will be used automatically: " << found_path)
+				setenv("RSB_PLUGINS_CPP_PATH", found_path, 1);
+				break;
+			} // else keep going
+			globfree(&g);
+			pathstr += "../";
+		}
+#endif
+	} else {
+		LOG_IPAACA_CONSOLE("RSB_PLUGINS_CPP_PATH already defined: " << plugin_path)
+	}
+}//}}}
+
+// RSB backend Converters
+// IUConverter//{{{
+
+IPAACA_EXPORT IUConverter::IUConverter()
+: Converter<std::string> (IPAACA_SYSTEM_DEPENDENT_CLASS_NAME("ipaaca::IU"), "ipaaca-iu", true)
+{
+}
+
+IPAACA_EXPORT std::string IUConverter::serialize(const AnnotatedData& data, std::string& wire)
+{
+	//std::cout << "serialize" << std::endl;
+	// Ensure that DATA actually holds a datum of the data-type we expect.
+	assert(data.first == getDataType()); // "ipaaca::IU"
+	// NOTE: a dynamic_pointer_cast cannot be used from void*
+	boost::shared_ptr<const IU> obj = boost::static_pointer_cast<const IU> (data.second);
+	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
+	// transfer obj data to pbo
+	pbo->set_uid(obj->uid());
+	pbo->set_revision(obj->revision());
+	pbo->set_category(obj->category());
+	pbo->set_payload_type(obj->payload_type());
+	pbo->set_owner_name(obj->owner_name());
+	pbo->set_committed(obj->committed());
+	ipaaca::protobuf::IU_AccessMode a_m;
+	switch(obj->access_mode()) {
+		case IU_ACCESS_PUSH:
+			a_m = ipaaca::protobuf::IU_AccessMode_PUSH;
+			break;
+		case IU_ACCESS_REMOTE:
+			a_m = ipaaca::protobuf::IU_AccessMode_REMOTE;
+			break;
+		case IU_ACCESS_MESSAGE:
+			a_m = ipaaca::protobuf::IU_AccessMode_MESSAGE;
+			break;
+	}
+	pbo->set_access_mode(a_m);
+	pbo->set_read_only(obj->read_only());
+	for (auto& kv: obj->_payload._document_store) {
+		protobuf::PayloadItem* item = pbo->add_payload();
+		item->set_key(kv.first);
+		//item->set_value( kv.second->to_json_string_representation() );
+		//item->set_type("JSON");
+		IPAACA_DEBUG("Payload type: " << obj->_payload_type)
+		if (obj->_payload_type=="JSON") {
+			item->set_value( kv.second->to_json_string_representation() );
+			item->set_type("JSON");
+		} else if ((obj->_payload_type=="MAP") || (obj->_payload_type=="STR")) {
+			// legacy mode
+			item->set_value( json_value_cast<std::string>(kv.second->document));
+			item->set_type("STR");
+		}
+	}
+	for (LinkMap::const_iterator it=obj->_links._links.begin(); it!=obj->_links._links.end(); ++it) {
+		protobuf::LinkSet* links = pbo->add_links();
+		links->set_type(it->first);
+		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			links->add_targets(*it2);
+		}
+	}
+	pbo->SerializeToString(&wire);
+	switch(obj->access_mode()) {
+		case IU_ACCESS_PUSH:
+			//std::cout << "Requesting to send as ipaaca-iu" << std::endl;
+			return "ipaaca-iu";
+		case IU_ACCESS_MESSAGE:
+			//std::cout << "Requesting to send as ipaaca-messageiu" << std::endl;
+			return "ipaaca-messageiu";
+		default:
+			//std::cout << "Requesting to send as default" << std::endl;
+			return getWireSchema();
+	}
+
+}
+
+IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
+	//std::cout << "deserialize" << std::endl;
+	assert(wireSchema == getWireSchema()); // "ipaaca-iu"
+	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
+	pbo->ParseFromString(wire);
+	IUAccessMode mode = static_cast<IUAccessMode>(pbo->access_mode());
+	switch(mode) {
+		case IU_ACCESS_PUSH:
+			{
+			// Create a "remote push IU"
+			boost::shared_ptr<RemotePushIU> obj = RemotePushIU::create();
+			// transfer pbo data to obj
+			obj->_uid = pbo->uid();
+			obj->_revision = pbo->revision();
+			obj->_category = pbo->category();
+			obj->_payload_type = pbo->payload_type();
+			obj->_owner_name = pbo->owner_name();
+			obj->_committed = pbo->committed();
+			obj->_read_only = pbo->read_only();
+			obj->_access_mode = IU_ACCESS_PUSH;
+			for (int i=0; i<pbo->payload_size(); i++) {
+				const protobuf::PayloadItem& it = pbo->payload(i);
+				PayloadDocumentEntry::ptr entry;
+				if (it.type() == "JSON") {
+					// fully parse json text
+					entry = PayloadDocumentEntry::from_json_string_representation( it.value() );
+				} else {
+					// assuming 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);
+				LinkSet& ls = obj->_links._links[pls.type()];
+				for (int j=0; j<pls.targets_size(); j++) {
+					ls.insert(pls.targets(j));
+				}
+			}
+			//return std::make_pair(getDataType(), obj);
+			return std::make_pair("ipaaca::RemotePushIU", obj);
+			break;
+			}
+		case IU_ACCESS_MESSAGE:
+			{
+			// Create a "Message-type IU"
+			boost::shared_ptr<RemoteMessage> obj = RemoteMessage::create();
+			//std::cout << "REFCNT after create: " << obj.use_count() << std::endl;
+			// transfer pbo data to obj
+			obj->_uid = pbo->uid();
+			obj->_revision = pbo->revision();
+			obj->_category = pbo->category();
+			obj->_payload_type = pbo->payload_type();
+			obj->_owner_name = pbo->owner_name();
+			obj->_committed = pbo->committed();
+			obj->_read_only = pbo->read_only();
+			obj->_access_mode = IU_ACCESS_MESSAGE;
+			for (int i=0; i<pbo->payload_size(); i++) {
+				const protobuf::PayloadItem& it = pbo->payload(i);
+				PayloadDocumentEntry::ptr entry;
+				if (it.type() == "JSON") {
+					// fully parse json text
+					entry = PayloadDocumentEntry::from_json_string_representation( it.value() );
+				} else {
+					// assuming 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);
+				LinkSet& ls = obj->_links._links[pls.type()];
+				for (int j=0; j<pls.targets_size(); j++) {
+					ls.insert(pls.targets(j));
+				}
+			}
+			//return std::make_pair(getDataType(), obj);
+			return std::make_pair("ipaaca::RemoteMessage", obj);
+			break;
+			}
+		default:
+			// other cases not handled yet! ( TODO )
+			throw NotImplementedError();
+	}
+}
+
+//}}}
+// MessageConverter//{{{
+
+IPAACA_EXPORT MessageConverter::MessageConverter()
+: Converter<std::string> (IPAACA_SYSTEM_DEPENDENT_CLASS_NAME("ipaaca::Message"), "ipaaca-messageiu", true)
+{
+}
+
+IPAACA_EXPORT std::string MessageConverter::serialize(const AnnotatedData& data, std::string& wire)
+{
+	// Ensure that DATA actually holds a datum of the data-type we expect.
+	assert(data.first == getDataType()); // "ipaaca::Message"
+	// NOTE: a dynamic_pointer_cast cannot be used from void*
+	boost::shared_ptr<const Message> obj = boost::static_pointer_cast<const Message> (data.second);
+	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
+	// transfer obj data to pbo
+	pbo->set_uid(obj->uid());
+	pbo->set_revision(obj->revision());
+	pbo->set_category(obj->category());
+	pbo->set_payload_type(obj->payload_type());
+	pbo->set_owner_name(obj->owner_name());
+	pbo->set_committed(obj->committed());
+	ipaaca::protobuf::IU_AccessMode a_m;
+	switch(obj->access_mode()) {
+		case IU_ACCESS_PUSH:
+			a_m = ipaaca::protobuf::IU_AccessMode_PUSH;
+			break;
+		case IU_ACCESS_REMOTE:
+			a_m = ipaaca::protobuf::IU_AccessMode_REMOTE;
+			break;
+		case IU_ACCESS_MESSAGE:
+			a_m = ipaaca::protobuf::IU_AccessMode_MESSAGE;
+			break;
+	}
+	pbo->set_access_mode(a_m);
+	pbo->set_read_only(obj->read_only());
+	for (auto& kv: obj->_payload._document_store) {
+		protobuf::PayloadItem* item = pbo->add_payload();
+		item->set_key(kv.first);
+		//item->set_value( kv.second->to_json_string_representation() );
+		//item->set_type("JSON");
+		if (obj->_payload_type=="JSON") {
+			item->set_value( kv.second->to_json_string_representation() );
+			item->set_type("JSON");
+		} else if ((obj->_payload_type=="MAP") || (obj->_payload_type=="STR")) {
+			// legacy mode
+			item->set_value( json_value_cast<std::string>(kv.second->document));
+			item->set_type("STR");
+		}
+	}
+	for (LinkMap::const_iterator it=obj->_links._links.begin(); it!=obj->_links._links.end(); ++it) {
+		protobuf::LinkSet* links = pbo->add_links();
+		links->set_type(it->first);
+		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			links->add_targets(*it2);
+		}
+	}
+	pbo->SerializeToString(&wire);
+	switch(obj->access_mode()) {
+		case IU_ACCESS_PUSH:
+			return "ipaaca-iu";
+		case IU_ACCESS_MESSAGE:
+			return "ipaaca-messageiu";
+		default:
+			//std::cout << "Requesting to send as default" << std::endl;
+			return getWireSchema();
+	}
+
+}
+
+IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
+	assert(wireSchema == getWireSchema()); // "ipaaca-iu"
+	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
+	pbo->ParseFromString(wire);
+	IUAccessMode mode = static_cast<IUAccessMode>(pbo->access_mode());
+	switch(mode) {
+		case IU_ACCESS_PUSH:
+			{
+			// Create a "remote push IU"
+			boost::shared_ptr<RemotePushIU> obj = RemotePushIU::create();
+			// transfer pbo data to obj
+			obj->_uid = pbo->uid();
+			obj->_revision = pbo->revision();
+			obj->_category = pbo->category();
+			obj->_payload_type = pbo->payload_type();
+			obj->_owner_name = pbo->owner_name();
+			obj->_committed = pbo->committed();
+			obj->_read_only = pbo->read_only();
+			obj->_access_mode = IU_ACCESS_PUSH;
+			for (int i=0; i<pbo->payload_size(); i++) {
+				const protobuf::PayloadItem& it = pbo->payload(i);
+				PayloadDocumentEntry::ptr entry;
+				if (it.type() == "JSON") {
+					// fully parse json text
+					entry = PayloadDocumentEntry::from_json_string_representation( it.value() );
+				} else {
+					// assuming 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);
+				LinkSet& ls = obj->_links._links[pls.type()];
+				for (int j=0; j<pls.targets_size(); j++) {
+					ls.insert(pls.targets(j));
+				}
+			}
+			//return std::make_pair(getDataType(), obj);
+			return std::make_pair("ipaaca::RemotePushIU", obj);
+			break;
+			}
+		case IU_ACCESS_MESSAGE:
+			{
+			// Create a "Message-type IU"
+			boost::shared_ptr<RemoteMessage> obj = RemoteMessage::create();
+			// transfer pbo data to obj
+			obj->_uid = pbo->uid();
+			obj->_revision = pbo->revision();
+			obj->_category = pbo->category();
+			obj->_payload_type = pbo->payload_type();
+			obj->_owner_name = pbo->owner_name();
+			obj->_committed = pbo->committed();
+			obj->_read_only = pbo->read_only();
+			obj->_access_mode = IU_ACCESS_MESSAGE;
+			for (int i=0; i<pbo->payload_size(); i++) {
+				const protobuf::PayloadItem& it = pbo->payload(i);
+				PayloadDocumentEntry::ptr entry;
+				if (it.type() == "JSON") {
+					// fully parse json text
+					entry = PayloadDocumentEntry::from_json_string_representation( it.value() );
+				} else {
+					// assuming 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);
+				LinkSet& ls = obj->_links._links[pls.type()];
+				for (int j=0; j<pls.targets_size(); j++) {
+					ls.insert(pls.targets(j));
+				}
+			}
+			//return std::make_pair(getDataType(), obj);
+			return std::make_pair("ipaaca::RemoteMessage", obj);
+			break;
+			}
+		default:
+			// other cases not handled yet! ( TODO )
+			throw NotImplementedError();
+	}
+}
+
+//}}}
+// IUPayloadUpdateConverter//{{{
+
+IPAACA_EXPORT IUPayloadUpdateConverter::IUPayloadUpdateConverter()
+: Converter<std::string> (IPAACA_SYSTEM_DEPENDENT_CLASS_NAME("ipaaca::IUPayloadUpdate"), "ipaaca-iu-payload-update", true)
+{
+}
+
+IPAACA_EXPORT std::string IUPayloadUpdateConverter::serialize(const AnnotatedData& data, std::string& wire)
+{
+	assert(data.first == getDataType()); // "ipaaca::IUPayloadUpdate"
+	boost::shared_ptr<const IUPayloadUpdate> obj = boost::static_pointer_cast<const IUPayloadUpdate> (data.second);
+	boost::shared_ptr<protobuf::IUPayloadUpdate> pbo(new protobuf::IUPayloadUpdate());
+	// transfer obj data to pbo
+	pbo->set_uid(obj->uid);
+	pbo->set_revision(obj->revision);
+	pbo->set_writer_name(obj->writer_name);
+	pbo->set_is_delta(obj->is_delta);
+	for (auto& kv: obj->new_items) {
+		protobuf::PayloadItem* item = pbo->add_new_items();
+		item->set_key(kv.first);
+		if (obj->payload_type=="JSON") {
+			item->set_value( kv.second->to_json_string_representation() );
+			item->set_type("JSON");
+		} else if ((obj->payload_type=="MAP") || (obj->payload_type=="STR")) {
+			// legacy mode
+			item->set_value( json_value_cast<std::string>(kv.second->document));
+			item->set_type("STR");
+		} else {
+			IPAACA_ERROR("Uninitialized payload update type!")
+			throw NotImplementedError();
+		}
+		IPAACA_DEBUG("Adding updated item (type " << item->type() << "): " << item->key() << " -> " << item->value() )
+	}
+	for (auto& key: obj->keys_to_remove) {
+		pbo->add_keys_to_remove(key);
+		IPAACA_DEBUG("Adding removed key: " << key)
+	}
+	pbo->SerializeToString(&wire);
+	return getWireSchema();
+
+}
+
+AnnotatedData IUPayloadUpdateConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
+	assert(wireSchema == getWireSchema()); // "ipaaca-iu-payload-update"
+	boost::shared_ptr<protobuf::IUPayloadUpdate> pbo(new protobuf::IUPayloadUpdate());
+	pbo->ParseFromString(wire);
+	boost::shared_ptr<IUPayloadUpdate> obj(new IUPayloadUpdate());
+	// transfer pbo data to obj
+	obj->uid = pbo->uid();
+	obj->revision = pbo->revision();
+	obj->writer_name = pbo->writer_name();
+	obj->is_delta = pbo->is_delta();
+	for (int i=0; i<pbo->new_items_size(); i++) {
+		const protobuf::PayloadItem& it = pbo->new_items(i);
+		PayloadDocumentEntry::ptr entry;
+		if (it.type() == "JSON") {
+			// fully parse json text
+			entry = PayloadDocumentEntry::from_json_string_representation( it.value() );
+			IPAACA_INFO("New/updated payload entry: " << it.key() << " -> " << it.value() )
+		} else {
+			// assuming 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;
+	}
+	for (int i=0; i<pbo->keys_to_remove_size(); i++) {
+		obj->keys_to_remove.push_back(pbo->keys_to_remove(i));
+	}
+	return std::make_pair(getDataType(), obj);
+}
+
+//}}}
+// IULinkUpdateConverter//{{{
+
+IPAACA_EXPORT IULinkUpdateConverter::IULinkUpdateConverter()
+: Converter<std::string> (IPAACA_SYSTEM_DEPENDENT_CLASS_NAME("ipaaca::IULinkUpdate"), "ipaaca-iu-link-update", true)
+{
+}
+
+IPAACA_EXPORT std::string IULinkUpdateConverter::serialize(const AnnotatedData& data, std::string& wire)
+{
+	assert(data.first == getDataType()); // "ipaaca::IULinkUpdate"
+	boost::shared_ptr<const IULinkUpdate> obj = boost::static_pointer_cast<const IULinkUpdate> (data.second);
+	boost::shared_ptr<protobuf::IULinkUpdate> pbo(new protobuf::IULinkUpdate());
+	// transfer obj data to pbo
+	pbo->set_uid(obj->uid);
+	pbo->set_revision(obj->revision);
+	pbo->set_writer_name(obj->writer_name);
+	pbo->set_is_delta(obj->is_delta);
+	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj->new_links.begin(); it!=obj->new_links.end(); ++it) {
+		protobuf::LinkSet* links = pbo->add_new_links();
+		links->set_type(it->first);
+		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			links->add_targets(*it2);
+		}
+	}
+	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj->links_to_remove.begin(); it!=obj->links_to_remove.end(); ++it) {
+		protobuf::LinkSet* links = pbo->add_links_to_remove();
+		links->set_type(it->first);
+		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			links->add_targets(*it2);
+		}
+	}
+	pbo->SerializeToString(&wire);
+	return getWireSchema();
+
+}
+
+AnnotatedData IULinkUpdateConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
+	assert(wireSchema == getWireSchema()); // "ipaaca-iu-link-update"
+	boost::shared_ptr<protobuf::IULinkUpdate> pbo(new protobuf::IULinkUpdate());
+	pbo->ParseFromString(wire);
+	boost::shared_ptr<IULinkUpdate> obj(new IULinkUpdate());
+	// transfer pbo data to obj
+	obj->uid = pbo->uid();
+	obj->revision = pbo->revision();
+	obj->writer_name = pbo->writer_name();
+	obj->is_delta = pbo->is_delta();
+	for (int i=0; i<pbo->new_links_size(); ++i) {
+		const protobuf::LinkSet& it = pbo->new_links(i);
+		for (int j=0; j<it.targets_size(); ++j) {
+			obj->new_links[it.type()].insert(it.targets(j)); // = vec;
+		}
+	}
+	for (int i=0; i<pbo->links_to_remove_size(); ++i) {
+		const protobuf::LinkSet& it = pbo->links_to_remove(i);
+		for (int j=0; j<it.targets_size(); ++j) {
+			obj->links_to_remove[it.type()].insert(it.targets(j));
+		}
+	}
+	return std::make_pair(getDataType(), obj);
+}
+
+//}}}
+// IntConverter//{{{
+
+IPAACA_EXPORT IntConverter::IntConverter()
+: Converter<std::string> ("int", "int32", true)
+{
+}
+
+IPAACA_EXPORT std::string IntConverter::serialize(const AnnotatedData& data, std::string& wire)
+{
+	// Ensure that DATA actually holds a datum of the data-type we expect.
+	assert(data.first == getDataType()); // "int"
+	// NOTE: a dynamic_pointer_cast cannot be used from void*
+	boost::shared_ptr<const int> obj = boost::static_pointer_cast<const int> (data.second);
+	boost::shared_ptr<protobuf::IntMessage> pbo(new protobuf::IntMessage());
+	// transfer obj data to pbo
+	pbo->set_value(*obj);
+	pbo->SerializeToString(&wire);
+	return getWireSchema();
+
+}
+
+IPAACA_EXPORT AnnotatedData IntConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
+	assert(wireSchema == getWireSchema()); // "int"
+	boost::shared_ptr<protobuf::IntMessage> pbo(new protobuf::IntMessage());
+	pbo->ParseFromString(wire);
+	boost::shared_ptr<int> obj = boost::shared_ptr<int>(new int(pbo->value()));
+	return std::make_pair("int", obj);
+}
+
+//}}}
+
+} // of namespace ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-iuinterface.cc b/ipaacalib/cpp/src/ipaaca-iuinterface.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2c36848cbc6c29df0fc794e31e2927f6689d289e
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-iuinterface.cc
@@ -0,0 +1,156 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IUInterface& obj)//{{{
+{
+	os << "IUInterface(uid='" << obj.uid() << "'";
+	os << ", category='" << obj.category() << "'";
+	os << ", revision=" << obj.revision();
+	os << ", committed=" << (obj.committed()?"True":"False");
+	os << ", owner_name='" << obj.owner_name() << "'";
+	os << ", payload=";
+	os << obj.const_payload();
+	os << ", links=";
+	os << obj._links;
+	os << ")";
+	return os;
+}
+//}}}
+
+// IUInterface//{{{
+
+IPAACA_EXPORT IUInterface::IUInterface()
+: _buffer(NULL), _committed(false), _retracted(false)
+{
+}
+
+IPAACA_EXPORT void IUInterface::_set_uid(const std::string& uid) {
+	if (_uid != "") {
+		throw IUAlreadyHasAnUIDError();
+	}
+	_uid = uid;
+}
+
+IPAACA_EXPORT void IUInterface::_set_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) {
+	if (_buffer) {
+		throw IUAlreadyInABufferError();
+	}
+	_buffer = buffer;
+
+}
+
+IPAACA_EXPORT void IUInterface::_set_owner_name(const std::string& owner_name) {
+	if (_owner_name != "") {
+		throw IUAlreadyHasAnOwnerNameError();
+	}
+	_owner_name = owner_name;
+}
+
+/// set the buffer pointer and the owner names of IU and Payload
+IPAACA_EXPORT void IUInterface::_associate_with_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) {
+	_set_buffer(buffer); // will throw if already set
+	_set_owner_name(buffer->unique_name());
+	payload()._set_owner_name(buffer->unique_name());
+}
+
+/// C++-specific convenience function to add one single link
+IPAACA_EXPORT void IUInterface::add_link(const std::string& type, const std::string& target, const std::string& writer_name)
+{
+	LinkMap none;
+	LinkMap add;
+	add[type].insert(target);
+	_modify_links(true, add, none, writer_name);
+	_add_and_remove_links(add, none);
+}
+/// C++-specific convenience function to remove one single link
+IPAACA_EXPORT void IUInterface::remove_link(const std::string& type, const std::string& target, const std::string& writer_name)
+{
+	LinkMap none;
+	LinkMap remove;
+	remove[type].insert(target);
+	_modify_links(true, none, remove, writer_name);
+	_add_and_remove_links(none, remove);
+}
+
+IPAACA_EXPORT void IUInterface::add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name)
+{
+	LinkMap none;
+	LinkMap add;
+	add[type] = targets;
+	_modify_links(true, add, none, writer_name);
+	_add_and_remove_links(add, none);
+}
+
+IPAACA_EXPORT void IUInterface::remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name)
+{
+	LinkMap none;
+	LinkMap remove;
+	remove[type] = targets;
+	_modify_links(true, none, remove, writer_name);
+	_add_and_remove_links(none, remove);
+}
+
+IPAACA_EXPORT void IUInterface::modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name)
+{
+	_modify_links(true, add, remove, writer_name);
+	_add_and_remove_links(add, remove);
+}
+
+IPAACA_EXPORT void IUInterface::set_links(const LinkMap& links, const std::string& writer_name)
+{
+	LinkMap none;
+	_modify_links(false, links, none, writer_name);
+	_replace_links(links);
+}
+
+IPAACA_HEADER_EXPORT const std::string& IUInterface::channel()
+{
+	if (_buffer == NULL)
+		throw IUUnpublishedError();
+	else
+		return _buffer->channel();
+
+}
+
+//}}}
+
+} // of namespace ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-ius.cc b/ipaacalib/cpp/src/ipaaca-ius.cc
new file mode 100644
index 0000000000000000000000000000000000000000..07caeb65b2ed42aa132b265f75113c3e8bb6a87a
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-ius.cc
@@ -0,0 +1,370 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+// IU//{{{
+IPAACA_EXPORT IU::ptr IU::create(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
+{
+	return IU::create(category, payload_type, read_only);
+}
+IPAACA_EXPORT IU::ptr IU::create(const std::string& category, const std::string& payload_type, bool read_only)
+{
+	IU::ptr iu = IU::ptr(new IU(category, IU_ACCESS_PUSH, read_only, (payload_type=="")?__ipaaca_static_option_default_payload_type:payload_type)); /* params */ //));
+	iu->_payload.initialize(iu);
+	return iu;
+}
+
+IPAACA_EXPORT IU::IU(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
+{
+	_revision = 1;
+	_uid = ipaaca::generate_uuid_string();
+	_category = category;
+	_payload_type = (payload_type=="")?__ipaaca_static_option_default_payload_type:payload_type;
+	// payload initialization deferred to IU::create(), above
+	_read_only = read_only;
+	_access_mode = access_mode;
+	_committed = false;
+}
+
+IPAACA_EXPORT void IU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
+{
+	_revision_lock.lock();
+	if (_committed) {
+		_revision_lock.unlock();
+		throw IUCommittedError();
+	}
+	_increase_revision_number();
+	if (is_published()) {
+		_buffer->_send_iu_link_update(this, is_delta, _revision, new_links, links_to_remove, writer_name);
+	}
+	_revision_lock.unlock();
+}
+
+
+/*
+ * IPAACA_EXPORT void IU::_publish_resend(IU::ptr iu, const std::string& hidden_scope_name)
+{
+	//_revision_lock.lock();
+	//if (_committed) {
+	//	_revision_lock.unlock();
+	//	throw IUCommittedError();
+	//}
+	//_increase_revision_number();
+	//if (is_published()) {
+	//IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name
+	_buffer->_publish_iu_resend(iu, hidden_scope_name);
+	//}
+	//_revision_lock.unlock();
+}
+*/
+
+
+
+
+IPAACA_EXPORT void IU::_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)
+{
+	IPAACA_INFO("")
+	_revision_lock.lock();
+	if (_committed) {
+		_revision_lock.unlock();
+		throw IUCommittedError();
+	}
+	_increase_revision_number();
+	if (is_published()) {
+		IPAACA_DEBUG("Sending a payload update, new entries:")
+		for (auto& kv: new_items) {
+			IPAACA_DEBUG("  " << kv.first << " -> " << kv.second)
+		}
+		IPAACA_DEBUG("and with removed keys:")
+		for (auto& k: keys_to_remove) {
+			IPAACA_DEBUG("  " << k)
+		}
+		_buffer->_send_iu_payload_update(this, is_delta, _revision, new_items, keys_to_remove, writer_name);
+		IPAACA_DEBUG("... sent.")
+	}
+	_revision_lock.unlock();
+}
+
+IPAACA_EXPORT void IU::commit()
+{
+	_internal_commit();
+}
+
+IPAACA_EXPORT void IU::_internal_commit(const std::string& writer_name)
+{
+	_revision_lock.lock();
+	if (_committed) {
+		_revision_lock.unlock();
+		throw IUCommittedError();
+	}
+	_increase_revision_number();
+	_committed = true;
+	if (is_published()) {
+		_buffer->_send_iu_commission(this, _revision, writer_name);
+	}
+	_revision_lock.unlock();
+}
+//}}}
+// Message//{{{
+Message::ptr Message::create(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
+{
+	return Message::create(category, (payload_type=="")?__ipaaca_static_option_default_payload_type:payload_type);
+}
+Message::ptr Message::create(const std::string& category, const std::string& payload_type)
+{
+	Message::ptr iu = Message::ptr(new Message(category, IU_ACCESS_MESSAGE, true, (payload_type=="")?__ipaaca_static_option_default_payload_type:payload_type)); /* params */ //));
+	iu->_payload.initialize(iu);
+	return iu;
+}
+
+Message::Message(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
+: IU(category, access_mode, read_only, payload_type)
+{
+}
+
+void Message::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
+{
+	if (is_published()) {
+		IPAACA_INFO("Info: modifying a Message after sending has no global effects")
+	}
+}
+void Message::_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)
+{
+	if (is_published()) {
+		IPAACA_INFO("Info: modifying a Message after sending has no global effects")
+	}
+}
+
+void Message::_internal_commit(const std::string& writer_name)
+{
+	if (is_published()) {
+		IPAACA_INFO("Info: committing to a Message after sending has no global effects")
+	}
+
+}
+//}}}
+
+// RemotePushIU//{{{
+
+IPAACA_EXPORT RemotePushIU::ptr RemotePushIU::create()
+{
+	RemotePushIU::ptr iu = RemotePushIU::ptr(new RemotePushIU(/* params */));
+	iu->_payload.initialize(iu);
+	return iu;
+}
+IPAACA_EXPORT RemotePushIU::RemotePushIU()
+{
+	// nothing
+}
+IPAACA_EXPORT void RemotePushIU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
+{
+	if (_committed) {
+		throw IUCommittedError();
+	}
+	if (_read_only) {
+		throw IUReadOnlyError();
+	}
+	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
+	IULinkUpdate::ptr update = IULinkUpdate::ptr(new IULinkUpdate());
+	update->uid = _uid;
+	update->revision = _revision;
+	update->is_delta = is_delta;
+	update->writer_name = _buffer->unique_name();
+	update->new_links = new_links;
+	update->links_to_remove = links_to_remove;
+	boost::shared_ptr<int> result = server->call<int>("updateLinks", update, IPAACA_REMOTE_SERVER_TIMEOUT); // TODO
+	if (*result == 0) {
+		throw IUUpdateFailedError();
+	} else {
+		_revision = *result;
+	}
+}
+IPAACA_EXPORT void RemotePushIU::_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)
+{
+	//std::cout << "-- Sending a modify_payload with " << new_items.size() << " keys to merge." << std::endl;
+	if (_committed) {
+		throw IUCommittedError();
+	}
+	if (_read_only) {
+		throw IUReadOnlyError();
+	}
+	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
+	IUPayloadUpdate::ptr update = IUPayloadUpdate::ptr(new IUPayloadUpdate());
+	update->uid = _uid;
+	update->revision = _revision;
+	update->is_delta = is_delta;
+	update->writer_name = _buffer->unique_name();
+	update->new_items = new_items;
+	update->keys_to_remove = keys_to_remove;
+	update->payload_type = _payload_type;
+	boost::shared_ptr<int> result = server->call<int>("updatePayload", update, IPAACA_REMOTE_SERVER_TIMEOUT); // TODO
+	if (*result == 0) {
+		throw IUUpdateFailedError();
+	} else {
+		_revision = *result;
+	}
+}
+
+IPAACA_EXPORT void RemotePushIU::commit()
+{
+	if (_read_only) {
+		throw IUReadOnlyError();
+	}
+	if (_committed) {
+		// Following python version: ignoring multiple commit
+		return;
+	}
+	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
+	boost::shared_ptr<protobuf::IUCommission> update = boost::shared_ptr<protobuf::IUCommission>(new protobuf::IUCommission());
+	update->set_uid(_uid);
+	update->set_revision(_revision);
+	update->set_writer_name(_buffer->unique_name());
+	boost::shared_ptr<int> result = server->call<int>("commit", update, IPAACA_REMOTE_SERVER_TIMEOUT); // TODO
+	if (*result == 0) {
+		throw IUUpdateFailedError();
+	} else {
+		_revision = *result;
+	}
+}
+
+IPAACA_EXPORT void RemotePushIU::_apply_link_update(IULinkUpdate::ptr update)
+{
+	_revision = update->revision;
+	if (update->is_delta) {
+		_add_and_remove_links(update->new_links, update->links_to_remove);
+	} else {
+		_replace_links(update->new_links);
+	}
+}
+IPAACA_EXPORT void RemotePushIU::_apply_update(IUPayloadUpdate::ptr update)
+{
+	_revision = update->revision;
+	if (update->is_delta) {
+		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
+			_payload._remotely_enforced_delitem(*it);
+		}
+		for (std::map<std::string, PayloadDocumentEntry::ptr>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
+			_payload._remotely_enforced_setitem(it->first, it->second);
+		}
+	} else {
+		_payload._remotely_enforced_wipe();
+		for (std::map<std::string, PayloadDocumentEntry::ptr>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
+			_payload._remotely_enforced_setitem(it->first, it->second);
+		}
+	}
+}
+IPAACA_EXPORT void RemotePushIU::_apply_commission()
+{
+	_committed = true;
+}
+IPAACA_EXPORT void RemotePushIU::_apply_retraction()
+{
+	_retracted = true;
+}
+//}}}
+
+// RemoteMessage//{{{
+
+IPAACA_EXPORT RemoteMessage::ptr RemoteMessage::create()
+{
+	RemoteMessage::ptr iu = RemoteMessage::ptr(new RemoteMessage(/* params */));
+	iu->_payload.initialize(iu);
+	return iu;
+}
+IPAACA_EXPORT RemoteMessage::RemoteMessage()
+{
+	// nothing
+}
+IPAACA_EXPORT void RemoteMessage::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
+{
+	IPAACA_INFO("Info: modifying a RemoteMessage only has local effects")
+}
+IPAACA_EXPORT void RemoteMessage::_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)
+{
+	IPAACA_INFO("Info: modifying a RemoteMessage only has local effects")
+}
+IPAACA_EXPORT void RemoteMessage::commit()
+{
+	IPAACA_INFO("Info: committing to a RemoteMessage only has local effects")
+}
+
+IPAACA_EXPORT void RemoteMessage::_apply_link_update(IULinkUpdate::ptr update)
+{
+	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_link_update")
+	_revision = update->revision;
+	if (update->is_delta) {
+		_add_and_remove_links(update->new_links, update->links_to_remove);
+	} else {
+		_replace_links(update->new_links);
+	}
+}
+IPAACA_EXPORT void RemoteMessage::_apply_update(IUPayloadUpdate::ptr update)
+{
+	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_update")
+	_revision = update->revision;
+	if (update->is_delta) {
+		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
+			_payload._remotely_enforced_delitem(*it);
+		}
+		for (std::map<std::string, PayloadDocumentEntry::ptr>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
+			_payload._remotely_enforced_setitem(it->first, it->second);
+		}
+	} else {
+		_payload._remotely_enforced_wipe();
+		for (std::map<std::string, PayloadDocumentEntry::ptr>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
+			_payload._remotely_enforced_setitem(it->first, it->second);
+		}
+	}
+}
+IPAACA_EXPORT void RemoteMessage::_apply_commission()
+{
+	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_commission")
+	_committed = true;
+}
+IPAACA_EXPORT void RemoteMessage::_apply_retraction()
+{
+	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_retraction")
+	_retracted = true;
+}
+
+//}}}
+
+} // of namespace ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dfdd83ee63adc0603c0f9340cd017d33bd14f9e7
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-json.cc
@@ -0,0 +1,500 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+#include <ipaaca/ipaaca-json.h>
+
+#include <iomanip>
+
+using namespace rapidjson;
+using namespace std;
+
+int batch_update_main(int argc, char** argv)//{{{
+{
+	std::string json_source("[\n\
+	\"old\",\n\
+	[\n\
+		\"str\",\n\
+		null\n\
+	],\n\
+	3,\n\
+	{\n\
+		\"key1\": \"value1\",\n\
+		\"key2\": \"value2\"\n\
+	}\n\
+]");
+	
+	ipaaca::OutputBuffer::ptr ob = ipaaca::OutputBuffer::create("myprog");
+	std::cout << std::endl << "Setting up an IU with initial contents" << std::endl;
+	ipaaca::IU::ptr iu = ipaaca::IU::create("testcategory");
+	iu->payload()["a"] = "OLD: initial contents of payload";
+	iu->payload()["b"] = "OLD: initial value for b";
+	std::cout << std::endl << "Initial contents of payload:" << std::endl;
+	for (auto it: iu->payload()) {
+		std::cout << "  " << it.first << " -> " << it.second << std::endl;
+	}
+	
+	std::cout << std::endl << "Publishing IU (sniffer should receive one ADDED)" << std::endl;
+	ob->add(iu);
+	
+	std::cout << std::endl << "Batch-writing some stuff (sniffer should receive a single UPDATED)" << std::endl;
+	{
+		ipaaca::Locker locker(iu->payload());
+		iu->payload().set(std::map<std::string, std::string>{{"b", "VALUE"}, {"bPrime", "VALUE"}});
+		iu->payload()["a"] = std::map<std::string, long>{{"a", 1},{"b", 2},{"c", 3}};
+		iu->payload()["remove_me"] = "WARNING: this should not be in the payload where an update is received!";
+		iu->payload()["c"] = "WARNING: this should read abc123, not this warning message!";
+		iu->payload()["d"] = 100;
+		iu->payload().remove("d");
+		iu->payload()["d"] = 200;
+		iu->payload()["d"] = 300;
+		iu->payload().remove("d");
+		iu->payload()["d"] = 400;
+		iu->payload()["e"] = "Note: a key 'd' should exist with value 400, and 'b' and 'bPrime' should be equal";
+		iu->payload()["f"] = "12.5000";
+		iu->payload()["g"] = std::vector<std::string>{"g1", "g2"};
+		iu->payload().remove("remove_me");
+		iu->payload()["c"] = "abc123";
+	}
+	
+	std::cout << std::endl << "Adding another key 'XYZ' outside batch mode (sniffer -> UPDATED)" << std::endl;
+	iu->payload()["XYZ"] = "blabla";
+	
+	std::cout << std::endl << "Final batch update, wiping most (sniffer should receive a third UPDATED, with 3 keys remaining in the payload)" << std::endl;
+	{
+		ipaaca::Locker locker(iu->payload());
+		iu->payload()["SHOULD_NOT_EXIST"] = "WARNING: this key should never be visible";
+		iu->payload().set(std::map<std::string, std::string>{{"A", "Final contents (3 entries)"}, {"B", "Final stuff (3 entries)"}});
+		iu->payload()["C"] = std::vector<std::string>{"payload ", "should ", "have ", "three ", "entries, ", "A ", "B ", "and ", "C"};
+	}
+	
+	std::cout << std::endl << "Final contents of payload:" << std::endl;
+	for (auto it: iu->payload()) {
+		std::cout << "  " << it.first << " -> " << it.second << std::endl;
+	}
+	
+	return 0;
+}
+//}}}
+
+int iterators_main(int argc, char** argv)//{{{
+{
+	std::string json_source("[\n\
+	\"old\",\n\
+	[\n\
+		\"str\",\n\
+		null\n\
+	],\n\
+	3,\n\
+	{\n\
+		\"key1\": \"value1\",\n\
+		\"key2\": \"value2\"\n\
+	}\n\
+]");
+	
+	std::cout << "Using this JSON document as initial payload entry 'a':" << std::endl << json_source << std::endl;
+	ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source);
+	
+	std::cout << std::endl << "Setting up payload by adding some additional values" << std::endl;
+	ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create();
+	iu->add_fake_payload_item("a", entry);
+	iu->payload()["b"] = "simpleString";
+	iu->payload()["bPrime"] = "simpleString";
+	iu->payload()["c"] = "anotherSimpleString";
+	iu->payload()["d"] = 100;
+	iu->payload()["e"] = 3l;
+	iu->payload()["f"] = "12.5000";
+	iu->payload()["g"] = std::vector<std::string>{"g1", "g2"};
+	
+	std::cout << std::endl << "Iterate over payload" << std::endl;
+	for (auto it = iu->payload().begin(); it != iu->payload().end(); ++it) {
+		std::cout << "  " << it->first << " -> " << it->second << std::endl;
+	}
+	std::cout << std::endl << "Iterate over payload, range-based" << std::endl;
+	for (auto it: iu->payload()) {
+		std::cout << "  " << it.first << " -> " << it.second << std::endl;
+	}
+	
+	std::cout << std::endl << "Comparisons" << std::endl;
+	bool eq;
+	eq = iu->payload()["a"] == iu->payload()["b"];
+	std::cout << "  a==b ? : " << (eq?"true":"false") << std::endl;
+	eq = iu->payload()["b"] == iu->payload()["bPrime"];
+	std::cout << "  b==bPrime ? : " << (eq?"true":"false") << std::endl;
+	eq = iu->payload()["b"] == "simpleString";
+	std::cout << "  b==\"simpleString\" ? : " << (eq?"true":"false") << std::endl;
+	eq = iu->payload()["b"] == 100;
+	std::cout << "  b==100 ? : " << (eq?"true":"false") << std::endl;
+	eq = iu->payload()["d"] == 100;
+	std::cout << "  d==100 ? : " << (eq?"true":"false") << std::endl;
+	eq = iu->payload()["a"][2] == iu->payload()["e"];
+	std::cout << "  a[2]==e ? : " << (eq?"true":"false") << std::endl;
+	
+	std::cout << std::endl << "Type checks" << std::endl;
+	std::cout << "  a[3] is_null() ? : " << ((iu->payload()["a"][3].is_null())?"true":"false") << std::endl;
+	std::cout << "  a[3] is_string() ? : " << ((iu->payload()["a"][3].is_string())?"true":"false") << std::endl;
+	std::cout << "  a[3] is_number() ? : " << ((iu->payload()["a"][3].is_number())?"true":"false") << std::endl;
+	std::cout << "  a[3] is_list() ? : " << ((iu->payload()["a"][3].is_list())?"true":"false") << std::endl;
+	std::cout << "  a[3] is_map() ? : " << ((iu->payload()["a"][3].is_map())?"true":"false") << std::endl;
+	std::cout << std::endl;
+	std::cout << "  f is_null() ? : " << ((iu->payload()["f"].is_null())?"true":"false") << std::endl;
+	std::cout << "  f is_string() ? : " << ((iu->payload()["f"].is_string())?"true":"false") << std::endl;
+	std::cout << "  f is_number() ? : " << ((iu->payload()["f"].is_number())?"true":"false") << std::endl;
+	std::cout << "  f is_list() ? : " << ((iu->payload()["f"].is_list())?"true":"false") << std::endl;
+	std::cout << "  f is_map() ? : " << ((iu->payload()["f"].is_map())?"true":"false") << std::endl;
+	
+	std::cout << std::endl << "Inner iterators, map (printing values as strings)" << std::endl;
+	try {
+		auto inner = iu->payload()["a"][3];
+		std::cout << "Map iteration over payload['a'][3], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto kv: inner.as_map()) {
+			std::cout << "  \"" << kv.first << "\" -> \"" << kv.second << "\"" << std::endl;
+		}
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	try {
+		auto inner = iu->payload()["a"][2];
+		std::cout << "Map iteration over payload['a'][2], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto kv: inner.as_map()) {
+			std::cout << "  \"" << kv.first << "\" -> \"" << kv.second << "\"" << std::endl;
+		}
+	} catch (ipaaca::PayloadTypeConversionError& ex) {
+		std::cout << "  Failed as expected with " << ex.what() << std::endl;
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	
+	std::cout << std::endl << "Inner iterators, list (printing values as strings)" << std::endl;
+	try {
+		auto inner = iu->payload()["a"][1];
+		std::cout << "List iteration over payload['a'][1], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto proxy: inner.as_list()) {
+			std::cout << "  \"" << proxy << "\"" << std::endl;
+		}
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	try {
+		auto inner = iu->payload()["a"][1][1];
+		std::cout << "List iteration over payload['a'][1][1], which equals " << inner << std::endl;
+		std::cout << "Reported size is " << inner.size() << std::endl;
+		for (auto proxy: inner.as_list()) {
+			std::cout << "  \"" << proxy << "\"" << std::endl;
+		}
+	} catch (ipaaca::PayloadTypeConversionError& ex) {
+		std::cout << "  Failed as expected with " << ex.what() << std::endl;
+	} catch (ipaaca::Exception& ex) {
+		std::cout << "  Unexpected exception: " << ex.what() << std::endl;
+	}
+	
+	std::cout << std::endl << "Appending a string item to the end of payload['a']" << std::endl;
+	iu->payload()["a"].push_back("appended string entry");
+	std::cout << "Resulting entries in payload['a']:" << std::endl;
+	for (auto v: iu->payload()["a"].as_list()) {
+		std::cout << "  " << v << std::endl;
+	}
+	
+	std::cout << std::endl << "Extending payload['a'] by a list of three bools" << std::endl;
+	iu->payload()["a"].extend(std::list<bool>{false, false, true});
+	std::cout << "Resulting entries in payload['a']:" << std::endl;
+	for (auto v: iu->payload()["a"].as_list()) {
+		std::cout << "  " << v << std::endl;
+	}
+	
+	std::cout << std::endl << "Extending payload['a'] by payload['g'] and appending payload['f']" << std::endl;
+	iu->payload()["a"].extend(iu->payload()["g"]);
+	iu->payload()["a"].push_back(iu->payload()["f"]);
+	std::cout << "Resulting entries in payload['a']:" << std::endl;
+	for (auto v: iu->payload()["a"].as_list()) {
+		std::cout << "  " << v << std::endl;
+	}
+	
+	return 0;
+}
+//}}}
+
+int json_testbed_main(int argc, char** argv)//{{{
+{
+	std::string json_source("[\"old\",2,3,4]");
+	ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source);
+	
+	std::string newinner("{\"K\":\"V\"}");
+	ipaaca::PayloadDocumentEntry::ptr entrynew = ipaaca::PayloadDocumentEntry::from_json_string_representation(newinner);
+	
+	ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create();
+	iu->add_fake_payload_item("a", entry);
+	iu->add_fake_payload_item("b", entrynew);
+	iu->payload()["c"] = "simpleString";
+	
+	auto proxy = iu->payload()["a"][3];
+	
+	std::cout << "IU payload before: " << iu->payload() << std::endl;
+	std::cout << "Entry before:      " << entry << std::endl;
+	std::cout << "EntryNew before:   " << entrynew << std::endl;
+	
+	/*
+	proxy.json_value->CopyFrom(entrynew->document, proxy.document_entry->document.GetAllocator());
+	proxy.document_entry->update_json_source();
+	*/
+	proxy = iu->payload()["b"];
+	
+	std::cout << "Newly written part: " << iu->payload()["a"][3] << std::endl;
+	iu->payload()["a"][3]["addkey"] = "addvalue";
+	
+	std::cout << "IU payload after: " << iu->payload() << std::endl;
+	std::cout << "Entry after:      " << entry << std::endl;
+	std::cout << "EntryNew after:   " << entrynew << std::endl;
+	
+	return 0;
+}
+//}}}
+
+int fakeiu_main(int argc, char** argv)//{{{
+{
+	//if (argc<2) {
+	//	std::cout << "Please provide json content as the first argument." << std::endl;
+	//	return 0;
+	//}
+	//
+	std::string json_source("[\"old\",2,3,4]");
+	ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source);
+	
+	ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create();
+	iu->add_fake_payload_item("a", entry);
+	iu->payload()["b"] = "anotherValue";
+	iu->payload()["c"] = "yetAnotherValue";
+
+	auto a = iu->payload()["a"];
+	//auto a0 = a[0];
+	std::cout << "entry as string:       " << (std::string) a << std::endl;
+	std::cout << "entry as long:         " << (long) a << std::endl;
+	std::cout << "entry as double:       " << (double) a << std::endl;
+	std::cout << "entry as bool:         " << ((bool) a?"true":"false") << std::endl;
+	// std::vector
+	std::cout << "entry as vector<string>: ";
+	try {
+		std::vector<std::string> v = a;
+		std::for_each(v.begin(), v.end(), [](std::string& s) {
+				std::cout << s << " ";
+		});
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	std::cout << "entry as vector<long>:   ";
+	try {
+		std::vector<long> v = a;
+		std::for_each(v.begin(), v.end(), [](long& s) {
+				std::cout << s << " ";
+		});
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	std::cout << "entry as vector<bool>:   ";
+	try {
+		std::vector<bool> v = a;
+		std::for_each(v.begin(), v.end(), [](bool s) {
+				std::cout << (s?"true":"false") << " ";
+		});
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	// std::map
+	std::cout << "entry as map<string, string>: ";
+	try {
+		std::map<std::string, std::string> m = a;
+		for (auto it = m.begin(); it != m.end(); ++it) {
+			std::cout << it->first << ":" << it->second << "  ";
+		}
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	std::cout << "entry as map<string, long>: ";
+	try {
+		std::map<std::string, long> m = a;
+		for (auto it = m.begin(); it != m.end(); ++it) {
+			std::cout << it->first << ":" << it->second << "  ";
+		}
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	std::cout << "entry as map<string, double>: ";
+	try {
+		std::map<std::string, double> m = a;
+		for (auto it = m.begin(); it != m.end(); ++it) {
+			std::cout << it->first << ":" << it->second << "  ";
+		}
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	std::cout << "entry as map<string, bool>: ";
+	try {
+		std::map<std::string, bool> m = a;
+		for (auto it = m.begin(); it != m.end(); ++it) {
+			std::cout << it->first << ":" << (it->second?"true":"false") << "  ";
+		}
+		std::cout << std::endl;
+	} catch (...) {
+		std::cout << "(n/a)" << std::endl;
+	}
+	
+	std::cout << "Setting value [0] in the object:" << std::endl;
+	try {
+		iu->payload()["a"][0] = "CHANGED_BY_USER";
+	} catch (ipaaca::PayloadAddressingError& e) {
+		std::cout << "  Error - the provided object was not a suitable array" << std::endl;
+	}
+	//iu->payload()["a"]["A"] = "set by pep::op=";
+	
+	
+	std::cout << "Appending two words to key 'b' the currently wrong way:" << std::endl;
+	auto proxy = iu->payload()["b"];
+	proxy = (std::string) proxy + " WORD1";
+	proxy = (std::string) proxy + " WORD2";
+	
+	std::cout << "Appending two words to key 'c' the compatible way:" << std::endl;
+	iu->payload()["c"] = (std::string) iu->payload()["c"] + " WORD1";
+	iu->payload()["c"] = (std::string) iu->payload()["c"] + " WORD2";
+	
+	std::cout << "Printing final payload using PayloadIterator:" << std::endl;
+	for (auto it = iu->payload().begin(); it != iu->payload().end(); ++it) {
+		std::cout << "  " << std::left << std::setw(15) << ((*it).first+": ") << (*it).second << std::endl;
+	}
+	
+	std::cout << "Final payload (cast to map, printed as strings):" << std::endl;
+	std::map<std::string, std::string> pl_flat = iu->payload();
+	for (auto& kv: pl_flat) {
+		std::cout << "  " << std::left << std::setw(15) << (kv.first+": ") << kv.second << std::endl;
+	}
+	return 0;
+}
+//}}}
+
+int legacy_iu_main(int argc, char** argv)//{{{
+{
+	// produce and fill a new and a legacy IU with identical contents
+	
+	ipaaca::OutputBuffer::ptr ob = ipaaca::OutputBuffer::create("jsonTestSenderLegacy");
+	ob->register_handler([](ipaaca::IUInterface::ptr iu, ipaaca::IUEventType event_type, bool local) {
+		std::cout << "Received remote update, new payload: " << iu->payload() << std::endl;
+	});
+	std::cout << "--- Create IUs with category jsonTest" << std::endl;
+	ipaaca::IU::ptr iu1 = ipaaca::IU::create("jsonTest");
+	ipaaca::IU::ptr iu2 = ipaaca::IU::create("jsonTest", "STR"); // explicity request old payload
+	std::map<std::string, long> newmap = { {"fifty", 50}, {"ninety-nine", 99} };
+	std::cout << "--- Set map" << std::endl;
+	iu1->payload()["map"] = newmap;
+	iu1->payload()["array"] = std::vector<std::string>{"aaa", "bbb", "ccc"};
+	iu2->payload()["map"] = newmap;
+	iu2->payload()["array"] = std::vector<std::string>{"aaa", "bbb", "ccc"};
+	std::cout << "--- Publishing IUs with this payload:" << std::endl;
+	std::cout << iu1->payload() << std::endl;
+	ob->add(iu1);
+	ob->add(iu2);
+	std::cout << "--- Waiting for changes for 5s " << std::endl;
+	sleep(5);
+	return 0;
+}
+//}}}
+
+int iu_main(int argc, char** argv)//{{{
+{
+	ipaaca::InputBuffer::ptr ib = ipaaca::InputBuffer::create("jsonTestReceiver", "jsonTest");
+	ib->register_handler([](ipaaca::IUInterface::ptr iu, ipaaca::IUEventType event_type, bool local) {
+		if (event_type==IU_ADDED) {
+			std::cout << "Received a new IU, payload: " << iu->payload() << std::endl;
+			std::cout << "Will write something." << std::endl;
+			//iu->commit();
+			try {
+				iu->payload()["list"][0] = "Overridden from C++";
+			} catch (ipaaca::PayloadAddressingError& e) {
+				iu->payload()["newKey"] = std::vector<long>{2,4,6,8};
+				std::cout << "  (item ['list'][0] could not be addressed, wrote new key)" << std::endl;
+			}
+		}
+	});
+	std::cout << "--- Waiting for IUs for 10s " << std::endl;
+	sleep(10);
+	return 0;
+	
+	ipaaca::OutputBuffer::ptr ob = ipaaca::OutputBuffer::create("jsonTestSender");
+	ob->register_handler([](ipaaca::IUInterface::ptr iu, ipaaca::IUEventType event_type, bool local) {
+		std::cout << "Received remote update, new payload: " << iu->payload() << std::endl;
+	});
+	std::cout << "--- Create IU with category jsonTest" << std::endl;
+	ipaaca::IU::ptr iu = ipaaca::IU::create("jsonTest");
+	std::map<std::string, long> newmap = { {"fifty", 50}, {"ninety-nine", 99} };
+	std::cout << "--- Set map" << std::endl;
+	iu->payload()["map"] = newmap;
+	std::cout << "--- Publishing IU with this payload:" << std::endl;
+	std::cout << iu->payload() << std::endl;
+	ob->add(iu);
+	std::cout << "--- Waiting for changes for 5s before next write" << std::endl;
+	sleep(5);
+	std::cout << "--- Contents of map after 5s" << std::endl;
+	std::cout << iu->payload()["map"] << std::endl;
+	//
+	std::cout << "--- Creating a list" << std::endl;
+	iu->payload()["list"] = std::vector<long>{1, 0} ;
+	std::cout << "--- Waiting for changes for 5s " << std::endl;
+	sleep(5);
+	std::cout << "--- Final map " << std::endl;
+	std::cout << iu->payload()["map"] << std::endl;
+	std::cout << "--- Final list " << std::endl;
+	std::cout << iu->payload()["list"] << std::endl;
+	std::cout << "--- Terminating " << std::endl;
+	return 0;
+}
+//}}}
+
+int main(int argc, char** argv)
+{
+	ipaaca::CommandLineParser::ptr parser = ipaaca::CommandLineParser::create();
+	ipaaca::CommandLineOptions::ptr options = parser->parse(argc, argv);
+
+	return batch_update_main(argc, argv);
+	//return iterators_main(argc, argv);
+	//return json_testbed_main(argc, argv);
+	//return legacy_iu_main(argc, argv);
+	//return fakeiu_main(argc, argv);
+	//return iu_main(argc, argv);
+}
diff --git a/ipaacalib/cpp/src/ipaaca-links.cc b/ipaacalib/cpp/src/ipaaca-links.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e0a6229068126ee2004768a040a4327efe8a32b4
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-links.cc
@@ -0,0 +1,106 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj)//{{{
+{
+	os << "{";
+	bool first = true;
+	for (LinkMap::const_iterator it=obj._links.begin(); it!=obj._links.end(); ++it) {
+		if (first) { first=false; } else { os << ", "; }
+		os << "'" << it->first << "': [";
+		bool firstinner = true;
+		for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			if (firstinner) { firstinner=false; } else { os << ", "; }
+			os << "'" << *it2 << "'";
+		}
+		os << "]";
+	}
+	os << "}";
+	return os;
+}
+//}}}
+
+// SmartLinkMap//{{{
+
+IPAACA_EXPORT LinkSet SmartLinkMap::empty_link_set;
+IPAACA_EXPORT void SmartLinkMap::_add_and_remove_links(const LinkMap& add, const LinkMap& remove)
+{
+	// remove specified links
+	for (LinkMap::const_iterator it = remove.begin(); it != remove.end(); ++it ) {
+		// if link type exists
+		if (_links.count(it->first) > 0) {
+			// remove one by one
+			for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+				_links[it->first].erase(*it2);
+			}
+			// wipe the type key if no more links are left
+			if (_links[it->first].size() == 0) {
+				_links.erase(it->first);
+			}
+		}
+	}
+	// add specified links
+	for (LinkMap::const_iterator it = add.begin(); it != add.end(); ++it ) {
+		for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
+			_links[it->first].insert(*it2);
+		}
+	}
+}
+IPAACA_EXPORT void SmartLinkMap::_replace_links(const LinkMap& links)
+{
+	//_links.clear();
+	_links=links;
+}
+IPAACA_EXPORT const LinkSet& SmartLinkMap::get_links(const std::string& key)
+{
+	LinkMap::const_iterator it = _links.find(key);
+	if (it==_links.end()) return empty_link_set;
+	return it->second;
+}
+IPAACA_EXPORT const LinkMap& SmartLinkMap::get_all_links()
+{
+	return _links;
+}
+//}}}
+
+} // of namespace ipaaca
+
diff --git a/ipaacalib/cpp/src/ipaaca-locking.cc b/ipaacalib/cpp/src/ipaaca-locking.cc
new file mode 100644
index 0000000000000000000000000000000000000000..96748cd530f19d6e34505050724cf07af4806d80
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-locking.cc
@@ -0,0 +1,43 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+Lock& logger_lock() {
+	static Lock lock;
+	return lock;
+}
+
+} // of namespace ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-payload.cc b/ipaacalib/cpp/src/ipaaca-payload.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4047162a7630dc363318f2b4d62fc008e860fdc3
--- /dev/null
+++ b/ipaacalib/cpp/src/ipaaca-payload.cc
@@ -0,0 +1,990 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <ipaaca/ipaaca.h>
+
+namespace ipaaca {
+
+using namespace rapidjson;
+
+using namespace rsb;
+using namespace rsb::filter;
+using namespace rsb::converter;
+using namespace rsb::patterns;
+
+// temporary helper to show rapidjson internal type
+std::string value_diagnosis(rapidjson::Value* val)
+{
+	if (!val) return "nullptr";
+	if (val->IsNull()) return "null";
+	if (val->IsString()) return "string";
+	if (val->IsNumber()) return "number";
+	if (val->IsBool()) return "bool";
+	if (val->IsArray()) return "array";
+	if (val->IsObject()) return "object";
+	return "other";
+
+}
+
+
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const rapidjson::Value& val)//{{{
+{
+	os << json_value_cast<std::string>(val);
+	return os;
+}
+//}}}
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const PayloadEntryProxy& proxy)//{{{
+{
+	if (proxy.json_value) os << *(proxy.json_value);
+	else os << "null";
+	return os;
+}
+//}}}
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, PayloadDocumentEntry::ptr entry)//{{{
+{
+	os << json_value_cast<std::string>(entry->document);
+	return os;
+}
+//}}}
+
+IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{{
+{
+	os << "{";
+	bool first = true;
+	for (auto& kv: obj._document_store) {
+		if (first) { first=false; } else { os << ", "; }
+		os << "\"" << kv.first << "\":" << kv.second->to_json_string_representation() << "";
+	}
+	os << "}";
+	return os;
+}
+//}}}
+
+double strict_numerical_interpretation(const std::string& str)
+{
+	char* endptr;
+	auto s = str_trim(str);
+	const char* startptr = s.c_str();
+	long l = strtod(startptr, &endptr);
+	if ((*endptr)=='\0') {
+		// everything could be parsed
+		return l;
+	} else {
+		throw PayloadTypeConversionError();
+	}
+}
+
+// json_value_cast//{{{
+IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v)
+{
+	if (v.IsString()) return v.GetString();
+	if (v.IsNull()) return "";
+	rapidjson::StringBuffer buffer;
+	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+	v.Accept(writer);
+	return buffer.GetString();
+}
+IPAACA_EXPORT template<> long json_value_cast(const rapidjson::Value& v)
+{
+	if (v.IsString()) return (long) strict_numerical_interpretation(v.GetString());
+	if (v.IsInt()) return v.GetInt();
+	if (v.IsUint()) return v.GetUint();
+	if (v.IsInt64()) return v.GetInt64();
+	if (v.IsUint64()) return v.GetUint64();
+	if (v.IsDouble()) return (long) v.GetDouble();
+	if (v.IsBool()) return v.GetBool() ? 1l : 0l;
+	if (v.IsNull()) return 0l;
+	// default: return parse of string version (should always be 0 though?)
+	throw PayloadTypeConversionError();
+	/*
+	rapidjson::StringBuffer buffer;
+	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+	v.Accept(writer);
+	return atol(std::string(buffer.GetString()).c_str());
+	*/
+}
+IPAACA_EXPORT template<> int json_value_cast(const rapidjson::Value& v)
+{
+	if (v.IsString()) return (int) strict_numerical_interpretation(v.GetString());
+	if (v.IsInt()) return v.GetInt();
+	if (v.IsUint()) return v.GetUint();
+	if (v.IsInt64()) return v.GetInt64();
+	if (v.IsUint64()) return v.GetUint64();
+	if (v.IsDouble()) return (long) v.GetDouble();
+	if (v.IsBool()) return v.GetBool() ? 1l : 0l;
+	if (v.IsNull()) return 0l;
+	throw PayloadTypeConversionError();
+}
+IPAACA_EXPORT template<> double json_value_cast(const rapidjson::Value& v)
+{
+	if (v.IsString()) return strict_numerical_interpretation(v.GetString());
+	if (v.IsDouble()) return v.GetDouble();
+	if (v.IsInt()) return (double) v.GetInt();
+	if (v.IsUint()) return (double) v.GetUint();
+	if (v.IsInt64()) return (double) v.GetInt64();
+	if (v.IsUint64()) return (double) v.GetUint64();
+	if (v.IsBool()) return v.GetBool() ? 1.0 : 0.0;
+	if (v.IsNull()) return 0.0;
+	throw PayloadTypeConversionError();
+}
+IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
+{
+	if (v.IsString()) {
+		std::string s = v.GetString();
+		return !((s=="")||(s=="false")||(s=="False")||(s=="0"));
+		//return ((s=="1")||(s=="true")||(s=="True"));
+	}
+	if (v.IsBool()) return v.GetBool();
+	if (v.IsNull()) return false;
+	if (v.IsInt()) return v.GetInt() != 0;
+	if (v.IsUint()) return v.GetUint() != 0;
+	if (v.IsInt64()) return v.GetInt64() != 0;
+	if (v.IsUint64()) return v.GetUint64() != 0;
+	if (v.IsDouble()) return v.GetDouble() != 0.0;
+	// default: assume "pointer-like" semantics (i.e. objects are TRUE)
+	return true;
+}
+/*
+ * std::map<std::string, std::string> result;
+	std::for_each(_document_store.begin(), _document_store.end(), [&result](std::pair<std::string, PayloadDocumentEntry::ptr> pair) {
+			result[pair.first] =  pair.second->document.GetString();
+			});
+			*/
+//}}}
+
+IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, int newvalue)
+{
+	valueobject.SetInt(newvalue);
+}
+IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, long newvalue)
+{
+	valueobject.SetInt(newvalue);
+}
+IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, double newvalue)
+{
+	valueobject.SetDouble(newvalue);
+}
+IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, bool newvalue)
+{
+	valueobject.SetBool(newvalue);
+}
+IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::string& newvalue)
+{
+	valueobject.SetString(newvalue.c_str(), allocator);
+}
+IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const char* newvalue)
+{
+	valueobject.SetString(newvalue, allocator);
+}
+/*
+IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::vector<std::string>& newvalue)
+{
+	valueobject.SetArray();
+	for (auto& str: newvalue) {
+		rapidjson::Value sv;
+		sv.SetString(str, allocator);
+		valueobject.PushBack(sv, allocator);
+	}
+}
+IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::list<std::string>& newvalue)
+{
+	IPAACA_IMPLEMENT_ME
+}
+IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::map<std::string, std::string>& newvalue)
+{
+	IPAACA_IMPLEMENT_ME
+}
+*/
+
+// PayloadDocumentEntry//{{{
+IPAACA_EXPORT std::string PayloadDocumentEntry::to_json_string_representation()
+{
+	rapidjson::StringBuffer buffer;
+	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+	document.Accept(writer);
+	return buffer.GetString();
+}
+IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_string_representation(const std::string& json_str)
+{
+	PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
+	if (entry->document.Parse(json_str.c_str()).HasParseError()) {
+		throw JsonParsingError();
+	}
+	//entry->json_source = json_str;
+	return entry;
+}
+IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_unquoted_string_value(const std::string& str)
+{
+	PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
+	entry->document.SetString(str.c_str(), entry->document.GetAllocator());
+	//entry->update_json_source();
+	return entry;
+}
+
+/// update json_source after a write operation (on newly cloned entries)
+/*
+IPAACA_EXPORT void PayloadDocumentEntry::update_json_source()
+{
+	json_source = to_json_string_representation();
+}
+*/
+
+IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null()
+{
+	PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
+	//entry->json_source = "null"; // rapidjson::Document value is also null implicitly
+	return entry;
+}
+IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::clone()
+{
+	//auto entry = PayloadDocumentEntry::from_json_string_representation(this->json_source);
+	auto entry = PayloadDocumentEntry::create_null();
+	entry->document.CopyFrom(this->document, entry->document.GetAllocator());
+	IPAACA_DEBUG("Cloned for copy-on-write, contents: " << entry)
+	return entry;
+}
+IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep)
+{
+	if (!(pep->parent)) {
+		return document;
+	}
+	rapidjson::Value& parent_value = get_or_create_nested_value_from_proxy_path(pep->parent);
+	if (pep->addressed_as_array) {
+		IPAACA_DEBUG("Addressed as array with index " << pep->addressed_index)
+		if (! parent_value.IsArray()) {
+			throw PayloadAddressingError();
+		} else {
+			long idx = pep->addressed_index;
+			long s = parent_value.Size();
+			if (idx<s) {
+				return parent_value[idx];
+			} else {
+				throw PayloadAddressingError();
+			}
+		}
+		// for append / push_back? :
+		/*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 {
+		IPAACA_DEBUG("Addressed as dict with key " << pep->addressed_key)
+		// addressed as object (dict)
+		//rapidjson::Value& parent_value = *(pep->parent->json_value);
+		if (! parent_value.IsObject()) {
+			IPAACA_DEBUG("parent is not of type Object")
+			throw PayloadAddressingError();
+		} else {
+			rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+			//Value key;
+			//key.SetString(pep->addressed_key, allocator);
+			//parent_value.AddMember(key, *json_value, allocator);
+			rapidjson::Value key;
+			key.SetString(pep->addressed_key, allocator);
+			auto it = parent_value.FindMember(key);
+			if (it != parent_value.MemberEnd()) {
+				return parent_value[key];
+			} else {
+				rapidjson::Value val;
+				parent_value.AddMember(key, val, allocator);
+				rapidjson::Value rkey;
+				rkey.SetString(pep->addressed_key, allocator);
+				return parent_value[rkey];
+			}
+		}
+	}
+}
+
+//}}}
+
+// PayloadEntryProxy//{{{
+
+ // only if not top-level
+#if 0
+IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents()
+{
+	rapidjson::Document::AllocatorType& allocator = document_entry->document.GetAllocator();
+	PayloadEntryProxy* pep = this;
+	while (!(pep->existent) && pep->parent) { // only if not top-level
+		if (pep->addressed_as_array) {
+			rapidjson::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)
+			rapidjson::Value& parent_value = *(pep->parent->json_value);
+			if (! parent_value.IsObject()) {
+				throw PayloadAddressingError();
+			} else {
+				Value key;
+				key.SetString(pep->addressed_key, allocator);
+				parent_value.AddMember(key, *json_value, allocator);
+			}
+		}
+		// repeat for next parent in the tree
+		pep = pep->parent;
+	}
+}
+#endif
+
+
+IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key)
+: _payload(payload), _key(key), parent(nullptr)
+{
+	document_entry = _payload->get_entry(key);
+	json_value = &(document_entry->document);
+}
+IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(PayloadEntryProxy* parent_, const std::string& addr_key_)
+: parent(parent_), addressed_key(addr_key_), addressed_as_array(false)
+{
+	_payload = parent->_payload;
+	_key = parent->_key;
+	document_entry = parent->document_entry;
+	auto it = parent->json_value->FindMember(addr_key_.c_str());
+	if (it != parent->json_value->MemberEnd()) {
+		json_value = &(parent->json_value->operator[](addr_key_.c_str()));
+		existent = true;
+	} else {
+		json_value = nullptr; // avoid heap construction here
+		existent = false;
+	}
+}
+IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(PayloadEntryProxy* parent_, size_t addr_idx_)
+: parent(parent_), addressed_index(addr_idx_), addressed_as_array(true)
+{
+	_payload = parent->_payload;
+	_key = parent->_key;
+	document_entry = parent->document_entry;
+	json_value = &(parent->json_value->operator[](addr_idx_));
+	existent = true;
+}
+
+IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const char* addr_key_)
+{
+	return operator[](std::string(addr_key_));
+}
+IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const std::string& addr_key_)
+{
+	if (!json_value) {
+		IPAACA_DEBUG("Invalid json_value!")
+		throw PayloadAddressingError();
+	}
+	if (! json_value->IsObject()) {
+		IPAACA_DEBUG("Expected Object for operator[](string)!")
+		throw PayloadAddressingError();
+	}
+	return PayloadEntryProxy(this, addr_key_);
+}
+IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](size_t addr_idx_)
+{
+	if (!json_value) {
+		IPAACA_DEBUG("Invalid json_value!")
+		throw PayloadAddressingError();
+	}
+	if (! json_value->IsArray()) {
+		IPAACA_DEBUG("Expected Array for operator[](size_t)!")
+		throw PayloadAddressingError();
+	}
+	long s = json_value->Size();
+	if (addr_idx_>=s) {
+		IPAACA_DEBUG("Array out of bounds!")
+		throw PayloadAddressingError();
+	}
+	return PayloadEntryProxy(this, addr_idx_);
+}
+IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](int addr_idx_)
+{
+	if (addr_idx_ < 0) {
+		IPAACA_DEBUG("Negative index!")
+		throw PayloadAddressingError();
+	}
+	return operator[]((size_t) addr_idx_);
+}
+
+IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const PayloadEntryProxy& otherproxy)
+{
+	PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+	rapidjson::Value& newval = new_entry->get_or_create_nested_value_from_proxy_path(this);
+	auto valueptr = otherproxy.json_value;
+	if (valueptr) { // only set if value is valid, keep default null value otherwise
+		newval.CopyFrom(*valueptr, new_entry->document.GetAllocator());
+	}
+	//new_entry->update_json_source();
+	_payload->set(_key, new_entry);
+	return *this;
+}
+
+/*
+IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value)
+{
+	//std::cout << "operator=(string)" << std::endl;
+	IPAACA_IMPLEMENT_ME
+	//_payload->set(_key, value);
+	return *this;
+}
+IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const char* value)
+{
+	//std::cout << "operator=(const char*)" << std::endl;
+	IPAACA_IMPLEMENT_ME
+	//_payload->set(_key, value);
+	return *this;
+}
+IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(double value)
+{
+	//std::cout << "operator=(double)" << std::endl;
+	IPAACA_IMPLEMENT_ME
+	//_payload->set(_key, boost::lexical_cast<std::string>(value));
+	return *this;
+}
+IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(bool value)
+{
+	//std::cout << "operator=(bool)" << std::endl;
+	IPAACA_IMPLEMENT_ME
+	//_payload->set(_key, boost::lexical_cast<std::string>(value));
+	return *this;
+}
+*/
+
+IPAACA_EXPORT PayloadEntryProxy::operator std::string()
+{
+	return json_value_cast<std::string>(json_value);
+	//PayloadEntryProxy::get<std::string>();
+}
+IPAACA_EXPORT PayloadEntryProxy::operator long()
+{
+	return json_value_cast<long>(json_value);
+	//return PayloadEntryProxy::get<long>();
+}
+IPAACA_EXPORT PayloadEntryProxy::operator double()
+{
+	return json_value_cast<double>(json_value);
+	//return PayloadEntryProxy::get<double>();
+}
+IPAACA_EXPORT PayloadEntryProxy::operator bool()
+{
+	return json_value_cast<bool>(json_value);
+	//return PayloadEntryProxy::get<bool>();
+}
+IPAACA_EXPORT std::string PayloadEntryProxy::to_str()
+{
+	return json_value_cast<std::string>(json_value);
+	//return PayloadEntryProxy::get<std::string>(); 
+}
+IPAACA_EXPORT long PayloadEntryProxy::to_long()
+{
+	return json_value_cast<long>(json_value);
+	//return PayloadEntryProxy::get<long>();
+}
+IPAACA_EXPORT double PayloadEntryProxy::to_float()
+{
+	return json_value_cast<double>(json_value);
+	//return PayloadEntryProxy::get<double>();
+}
+IPAACA_EXPORT bool PayloadEntryProxy::to_bool()
+{
+	return json_value_cast<bool>(json_value);
+	//return PayloadEntryProxy::get<bool>();
+}
+
+IPAACA_EXPORT PayloadEntryProxyMapDecorator PayloadEntryProxy::as_map()
+{
+	if (json_value && json_value->IsObject()) return PayloadEntryProxyMapDecorator(this);
+	throw PayloadTypeConversionError();
+}
+
+IPAACA_EXPORT PayloadEntryProxyListDecorator PayloadEntryProxy::as_list()
+{
+	if (json_value && json_value->IsArray()) return PayloadEntryProxyListDecorator(this);
+	throw PayloadTypeConversionError();
+}
+
+IPAACA_EXPORT size_t PayloadEntryProxy::size()
+{
+	if (!json_value) return 0;
+	if (json_value->IsArray()) return json_value->Size();
+	if (json_value->IsObject()) return json_value->MemberCount();
+	return 0;
+}
+IPAACA_EXPORT bool PayloadEntryProxy::is_null()
+{
+	return (!json_value) || json_value->IsNull();
+}
+IPAACA_EXPORT bool PayloadEntryProxy::is_string()
+{
+	return json_value && json_value->IsString();
+}
+/// is_number => whether it is *interpretable* as
+/// a numerical value (i.e. including conversions)
+IPAACA_EXPORT bool PayloadEntryProxy::is_number()
+{
+	if (!json_value) return false;
+	try {
+		double dummy = json_value_cast<double>(*json_value);
+		return true;
+	} catch (PayloadTypeConversionError& ex) {
+		return false;
+	}
+}
+IPAACA_EXPORT bool PayloadEntryProxy::is_list()
+{
+	return json_value && json_value->IsArray();
+}
+IPAACA_EXPORT bool PayloadEntryProxy::is_map()
+{
+	return json_value && json_value->IsObject();
+}
+
+//
+// new stuff for protocol v2
+//
+
+/*
+IPAACA_EXPORT template<> std::string PayloadEntryProxy::get<std::string>()
+{
+	if (!json_value) return "";
+	//IPAACA_INFO( value_diagnosis(json_value) )
+	if (json_value->IsString()) return json_value->GetString();
+	if (json_value->IsNull()) return "";
+	rapidjson::StringBuffer buffer;
+	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+	json_value->Accept(writer);
+	return buffer.GetString();
+	
+	//return _payload->get(_key);
+}
+IPAACA_EXPORT template<> long PayloadEntryProxy::get<long>()
+{
+	return atof(operator std::string().c_str());
+}
+IPAACA_EXPORT template<> double PayloadEntryProxy::get<double>()
+{
+	return atol(operator std::string().c_str());
+}
+IPAACA_EXPORT template<> bool PayloadEntryProxy::get<bool>()
+{
+	std::string s = operator std::string();
+	return ((s=="1")||(s=="true")||(s=="True"));
+}
+// complex types
+IPAACA_EXPORT template<> std::list<std::string> PayloadEntryProxy::get<std::list<std::string> >()
+{
+	std::list<std::string> l;
+	l.push_back(PayloadEntryProxy::get<std::string>());
+	return l;
+}
+IPAACA_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get<std::vector<std::string> >()
+{
+	std::vector<std::string> v;
+	v.push_back(PayloadEntryProxy::get<std::string>());
+	return v;
+}
+IPAACA_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get<std::map<std::string, std::string> >()
+{
+	std::map<std::string, std::string> m;
+	m["__automatic__"] = PayloadEntryProxy::get<std::string>();
+	return m;
+}
+*/
+
+//}}}
+
+// Payload//{{{
+
+IPAACA_EXPORT void Payload::on_lock()
+{
+	Locker locker(_payload_operation_mode_lock);
+	IPAACA_DEBUG("Starting batch update mode ...")
+	_update_on_every_change = false;
+}
+IPAACA_EXPORT void Payload::on_unlock()
+{
+	Locker locker(_payload_operation_mode_lock);
+	IPAACA_DEBUG("... applying batch update with " << _collected_modifications.size() << " modifications and " << _collected_removals.size() << " removals ...")
+	_internal_merge_and_remove(_collected_modifications, _collected_removals, _batch_update_writer_name);
+	_update_on_every_change = true;
+	_batch_update_writer_name = "";
+	_collected_modifications.clear();
+	_collected_removals.clear();
+	IPAACA_DEBUG("... exiting batch update mode.")
+}
+
+IPAACA_EXPORT void Payload::initialize(boost::shared_ptr<IUInterface> iu)
+{
+	_iu = boost::weak_ptr<IUInterface>(iu);
+}
+
+IPAACA_EXPORT PayloadEntryProxy Payload::operator[](const std::string& key)
+{
+	// TODO atomicize
+	//boost::shared_ptr<PayloadEntryProxy> p(new PayloadEntryProxy(this, key));
+	return PayloadEntryProxy(this, key);
+}
+
+IPAACA_EXPORT Payload::operator std::map<std::string, std::string>()
+{
+	std::map<std::string, std::string> result;
+	std::for_each(_document_store.begin(), _document_store.end(), [&result](std::pair<std::string, PayloadDocumentEntry::ptr> pair) {
+			result[pair.first] =  json_value_cast<std::string>(pair.second->document);
+			});
+	return result;
+}
+
+IPAACA_EXPORT void Payload::_internal_set(const std::string& k, PayloadDocumentEntry::ptr v, const std::string& writer_name) {
+	Locker locker(_payload_operation_mode_lock);
+	if (_update_on_every_change) {
+		std::map<std::string, PayloadDocumentEntry::ptr> _new;
+		std::vector<std::string> _remove;
+		_new[k] = v;
+		_iu.lock()->_modify_payload(true, _new, _remove, writer_name );
+		IPAACA_DEBUG(" Setting local payload item \"" << k << "\" to " << v)
+		_document_store[k] = v;
+		mark_revision_change();
+	} else {
+		IPAACA_DEBUG("queueing a payload set operation")
+		_batch_update_writer_name = writer_name;
+		_collected_modifications[k] = v;
+		// revoke deletions of this updated key
+		std::vector<std::string> new_removals;
+		for (auto& rk: _collected_removals) {
+			if (rk!=k) new_removals.push_back(rk);
+		}
+		_collected_removals = new_removals;
+	}
+}
+IPAACA_EXPORT void Payload::_internal_remove(const std::string& k, const std::string& writer_name) {
+	Locker locker(_payload_operation_mode_lock);
+	if (_update_on_every_change) {
+		std::map<std::string, PayloadDocumentEntry::ptr> _new;
+		std::vector<std::string> _remove;
+		_remove.push_back(k);
+		_iu.lock()->_modify_payload(true, _new, _remove, writer_name );
+		_document_store.erase(k);
+		mark_revision_change();
+	} else {
+		IPAACA_DEBUG("queueing a payload remove operation")
+		_batch_update_writer_name = writer_name;
+		_collected_removals.push_back(k);
+		// revoke updates of this deleted key
+		_collected_modifications.erase(k);
+	}
+}
+IPAACA_EXPORT void Payload::_internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name)
+{
+	Locker locker(_payload_operation_mode_lock);
+	if (_update_on_every_change) {
+		std::vector<std::string> _remove;
+		_iu.lock()->_modify_payload(false, new_contents, _remove, writer_name );
+		_document_store = new_contents;
+		mark_revision_change();
+	} else {
+		IPAACA_DEBUG("queueing a payload replace_all operation")
+		_batch_update_writer_name = writer_name;
+		_collected_modifications.clear();
+		for (auto& kv: new_contents) {
+			_collected_modifications[kv.first] = kv.second;
+		}
+		// take all existing keys and flag to remove them, unless overridden in current update
+		for (auto& kv: _document_store) {
+			if (! new_contents.count(kv.first)) {
+				_collected_removals.push_back(kv.first);
+				_collected_modifications.erase(kv.first);
+			}
+		}
+	}
+}
+IPAACA_EXPORT void Payload::_internal_merge(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::string& writer_name)
+{
+	Locker locker(_payload_operation_mode_lock);
+	if (_update_on_every_change) {
+		std::vector<std::string> _remove;
+		_iu.lock()->_modify_payload(true, contents_to_merge, _remove, writer_name );
+		for (auto& kv: contents_to_merge) {
+			_document_store[kv.first] = kv.second;
+		}
+		mark_revision_change();
+	} else {
+		IPAACA_DEBUG("queueing a payload merge operation")
+		std::set<std::string> updated_keys;
+		_batch_update_writer_name = writer_name;
+		for (auto& kv: contents_to_merge) {
+			_collected_modifications[kv.first] = kv.second;
+			updated_keys.insert(kv.first);
+		}
+		// revoke deletions of updated keys
+		std::vector<std::string> new_removals;
+		for (auto& rk: _collected_removals) {
+			if (! updated_keys.count(rk)) new_removals.push_back(rk);
+		}
+		_collected_removals = new_removals;
+	}
+}
+IPAACA_EXPORT void Payload::_internal_merge_and_remove(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::vector<std::string>& keys_to_remove, const std::string& writer_name)
+{
+	// this function is called by exiting the batch update mode only, so no extra locking here
+	_iu.lock()->_modify_payload(true, contents_to_merge, keys_to_remove, writer_name );
+	for (auto& k: keys_to_remove) {
+		_document_store.erase(k);
+	}
+	for (auto& kv: contents_to_merge) {
+		_document_store[kv.first] = kv.second;
+	}
+	mark_revision_change();
+}
+IPAACA_EXPORT PayloadDocumentEntry::ptr Payload::get_entry(const std::string& k) {
+	if (_document_store.count(k)>0) return _document_store[k];
+	else return PayloadDocumentEntry::create_null();  // contains Document with 'null' value
+}
+IPAACA_EXPORT std::string Payload::get(const std::string& k) { // DEPRECATED
+	if (_document_store.count(k)>0) return _document_store[k]->document.GetString();
+	return "";
+}
+
+IPAACA_EXPORT void Payload::set(const std::map<std::string, std::string>& all_elems)
+{
+	std::map<std::string, PayloadDocumentEntry::ptr> newmap;
+	for (auto& kv: all_elems) {
+		/*PayloadDocumentEntry::ptr newit = PayloadDocumentEntry::create_null();
+		newit->document.SetString(kv.second, newit->document.GetAllocator());
+		newit->update_json_source();
+		newmap[kv.first] = newit;*/
+		newmap[kv.first] = PayloadDocumentEntry::from_unquoted_string_value(kv.second);
+	}
+	_internal_replace_all(newmap);
+}
+
+IPAACA_EXPORT void Payload::_remotely_enforced_wipe()
+{
+	_document_store.clear();
+	mark_revision_change();
+}
+IPAACA_EXPORT void Payload::_remotely_enforced_delitem(const std::string& k)
+{
+	_document_store.erase(k);
+	mark_revision_change();
+}
+IPAACA_EXPORT void Payload::_remotely_enforced_setitem(const std::string& k, PayloadDocumentEntry::ptr entry)
+{
+	_document_store[k] = entry;
+	mark_revision_change();
+}
+IPAACA_EXPORT PayloadIterator Payload::begin()
+{
+	return PayloadIterator(this, _document_store.begin());
+}
+IPAACA_EXPORT PayloadIterator Payload::end()
+{
+	return PayloadIterator(this, _document_store.end());
+}
+
+//}}}
+
+// PayloadIterator//{{{
+IPAACA_EXPORT PayloadIterator::PayloadIterator(Payload* payload, PayloadDocumentStore::iterator&& ref_it)
+: _payload(payload), reference_payload_revision(payload->internal_revision), raw_iterator(std::move(ref_it))
+{
+}
+IPAACA_EXPORT PayloadIterator::PayloadIterator(const PayloadIterator& iter)
+: _payload(iter._payload), reference_payload_revision(iter.reference_payload_revision), raw_iterator(iter.raw_iterator)
+{
+}
+
+IPAACA_EXPORT PayloadIterator& PayloadIterator::operator++()
+{
+	if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
+	++raw_iterator;
+	return *this;
+}
+
+IPAACA_EXPORT std::pair<std::string, PayloadEntryProxy> PayloadIterator::operator*()
+{
+	if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
+	if (raw_iterator == _payload->_document_store.end()) throw PayloadIteratorInvalidError();
+	return std::pair<std::string, PayloadEntryProxy>(raw_iterator->first, PayloadEntryProxy(_payload, raw_iterator->first));
+}
+IPAACA_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > PayloadIterator::operator->()
+{
+	if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
+	if (raw_iterator == _payload->_document_store.end()) throw PayloadIteratorInvalidError();
+	return std::make_shared<std::pair<std::string, PayloadEntryProxy> >(raw_iterator->first, PayloadEntryProxy(_payload, raw_iterator->first));
+}
+
+IPAACA_EXPORT bool PayloadIterator::operator==(const PayloadIterator& ref)
+{
+	if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
+	return (raw_iterator==ref.raw_iterator);
+}
+IPAACA_EXPORT bool PayloadIterator::operator!=(const PayloadIterator& ref)
+{
+	if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
+	return (raw_iterator!=ref.raw_iterator);
+}
+//}}}
+
+// PayloadEntryProxyMapIterator//{{{
+IPAACA_EXPORT PayloadEntryProxyMapIterator::PayloadEntryProxyMapIterator(PayloadEntryProxy* proxy_, RawIterator&& raw_iter)
+: proxy(proxy_), raw_iterator(std::move(raw_iter))
+{
+}
+
+IPAACA_EXPORT PayloadEntryProxyMapIterator& PayloadEntryProxyMapIterator::operator++()
+{
+	// prevent increase beyond end() ?
+	raw_iterator++;
+	return *this;
+}
+
+IPAACA_EXPORT std::pair<std::string, PayloadEntryProxy> PayloadEntryProxyMapIterator::operator*()
+{
+	std::string key = raw_iterator->name.GetString();
+	return std::pair<std::string, PayloadEntryProxy>(key, (*proxy)[key] ); // generates child Proxy
+}
+
+IPAACA_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > PayloadEntryProxyMapIterator::operator->()
+{
+	std::string key = raw_iterator->name.GetString();
+	return std::make_shared<std::pair<std::string, PayloadEntryProxy> >(key, (*proxy)[key] ); // generates child Proxy
+}
+IPAACA_EXPORT bool PayloadEntryProxyMapIterator::operator==(const PayloadEntryProxyMapIterator& other_iter)
+{
+	return raw_iterator==other_iter.raw_iterator;
+}
+IPAACA_EXPORT bool PayloadEntryProxyMapIterator::operator!=(const PayloadEntryProxyMapIterator& other_iter)
+{
+	return raw_iterator!=other_iter.raw_iterator;
+}
+//}}}
+// PayloadEntryProxyMapDecorator//{{{
+PayloadEntryProxyMapIterator PayloadEntryProxyMapDecorator::begin()
+{
+	return PayloadEntryProxyMapIterator(proxy, proxy->json_value->MemberBegin());
+}
+PayloadEntryProxyMapIterator PayloadEntryProxyMapDecorator::end()
+{
+	return PayloadEntryProxyMapIterator(proxy, proxy->json_value->MemberEnd());
+}
+//}}}
+
+// PayloadEntryProxyListIterator//{{{
+IPAACA_EXPORT PayloadEntryProxyListIterator::PayloadEntryProxyListIterator(PayloadEntryProxy* proxy_, size_t idx, size_t size_)
+: proxy(proxy_), current_idx(idx), size(size_)
+{
+}
+
+IPAACA_EXPORT PayloadEntryProxyListIterator& PayloadEntryProxyListIterator::operator++()
+{
+	if (current_idx!=size) current_idx++;
+	return *this;
+}
+
+IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxyListIterator::operator*()
+{
+	return (*proxy)[current_idx];
+}
+
+IPAACA_EXPORT std::shared_ptr<PayloadEntryProxy> PayloadEntryProxyListIterator::operator->()
+{
+	return std::make_shared<PayloadEntryProxy>((*proxy)[current_idx]);
+}
+IPAACA_EXPORT bool PayloadEntryProxyListIterator::operator==(const PayloadEntryProxyListIterator& other_iter)
+{
+	return (proxy==other_iter.proxy) && (current_idx==other_iter.current_idx);
+}
+IPAACA_EXPORT bool PayloadEntryProxyListIterator::operator!=(const PayloadEntryProxyListIterator& other_iter)
+{
+	return (current_idx!=other_iter.current_idx) || (proxy!=other_iter.proxy);
+}
+//}}}
+// PayloadEntryProxyListDecorator//{{{
+PayloadEntryProxyListIterator PayloadEntryProxyListDecorator::begin()
+{
+	return PayloadEntryProxyListIterator(proxy, 0, proxy->json_value->Size());
+}
+PayloadEntryProxyListIterator PayloadEntryProxyListDecorator::end()
+{
+	size_t size = proxy->json_value->Size();
+	return PayloadEntryProxyListIterator(proxy, size, size);
+}
+//}}}
+
+} // of namespace ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-string-utils.cc b/ipaacalib/cpp/src/ipaaca-string-utils.cc
index 992d7cd005288caf2e43511133892639663a5b19..d3192fc858aed0814dbde2494ddb822172e98095 100644
--- a/ipaacalib/cpp/src/ipaaca-string-utils.cc
+++ b/ipaacalib/cpp/src/ipaaca-string-utils.cc
@@ -32,8 +32,20 @@
 
 #include <ipaaca/ipaaca.h>
 
+#include <cctype>
+#include <string>
+#include <algorithm>
+
+
 namespace ipaaca {
 
+std::string str_trim(const std::string &s)
+{
+	auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c){ return std::isspace(c); } );
+	auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c){ return std::isspace(c); } ).base();
+	return (wsback<=wsfront ? std::string() : std::string(wsfront, wsback));
+}
+
 std::string str_join(const std::set<std::string>& set,const std::string& sep)
 {
 	if(set.size()==0)
diff --git a/ipaacalib/cpp/src/ipaaca.cc b/ipaacalib/cpp/src/ipaaca.cc
index 32264161d4abf28389ad35163d07530e1e019916..2e7f99510dcb8afda09c5019da4e40c9bce9583a 100644
--- a/ipaacalib/cpp/src/ipaaca.cc
+++ b/ipaacalib/cpp/src/ipaaca.cc
@@ -1,10 +1,11 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".  
+ *   for Artificial Conversational Agents".
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -21,7 +22,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -31,108 +32,49 @@
  */
 
 #include <ipaaca/ipaaca.h>
-#include <cstdlib>
-#include <glob.h>
 
 namespace ipaaca {
 
-using namespace rsb;
-using namespace rsb::filter;
-using namespace rsb::converter;
-using namespace rsb::patterns;
-
-#define VERBOSE_HANDLERS 0
-
-Lock& logger_lock() {
-    static Lock lock;
-    return lock;
-}
-
-// util and init//{{{
-
-bool Initializer::_initialized = false;
-
-//const LinkSet EMPTY_LINK_SET = LinkSet();
-//const std::set<std::string> EMPTY_LINK_SET();
-bool Initializer::initialized() { return _initialized; }
-void Initializer::initialize_ipaaca_rsb_if_needed()
-{
-	if (_initialized) return;
-
-	initialize_updated_default_config();
-
-	// RYT FIXME This configuration stuff has been simply removed in rsb!
-	//ParticipantConfig config = ParticipantConfig::fromConfiguration();
-	//getFactory().setDefaultParticipantConfig(config);
-	
-	boost::shared_ptr<IUConverter> iu_converter(new IUConverter());
-	converterRepository<std::string>()->registerConverter(iu_converter);
-	
-	boost::shared_ptr<MessageConverter> message_converter(new MessageConverter());
-	converterRepository<std::string>()->registerConverter(message_converter);
-	
-	boost::shared_ptr<IUPayloadUpdateConverter> payload_update_converter(new IUPayloadUpdateConverter());
-	converterRepository<std::string>()->registerConverter(payload_update_converter);
-	
-	boost::shared_ptr<IULinkUpdateConverter> link_update_converter(new IULinkUpdateConverter());
-	converterRepository<std::string>()->registerConverter(link_update_converter);
-	
-	boost::shared_ptr<ProtocolBufferConverter<protobuf::IUCommission> > iu_commission_converter(new ProtocolBufferConverter<protobuf::IUCommission> ());
-	converterRepository<std::string>()->registerConverter(iu_commission_converter);
-	
-	boost::shared_ptr<ProtocolBufferConverter<protobuf::IURetraction> > iu_retraction_converter(new ProtocolBufferConverter<protobuf::IURetraction> ());
-	converterRepository<std::string>()->registerConverter(iu_retraction_converter);
-	
-	boost::shared_ptr<IntConverter> int_converter(new IntConverter());
-	converterRepository<std::string>()->registerConverter(int_converter);
-	
-	_initialized = true;
-	//IPAACA_TODO("initialize all converters")
-}
-
-void Initializer::initialize_updated_default_config()
-{
-	// quick hack to iterate through the pwd parents
-	// and find the closest rsb plugin dir
-	//
-	// but only if not yet defined
-	const char* plugin_path = getenv("RSB_PLUGINS_CPP_PATH");
-	if (!plugin_path) {
-		LOG_IPAACA_CONSOLE("RSB_PLUGINS_CPP_PATH not set; looking here and up to 7 dirs up.")
-		std::string pathstr = "./";
-		for (int i=0; i<   8 /* depth EIGHT (totally arbitrary..) */  ; i++) {
-			std::string where_str = pathstr+"deps/lib/rsb*/plugins";
-			const char* where = where_str.c_str();
-			glob_t g;
-			glob(where, 0, NULL, &g);
-			if (g.gl_pathc>0) {
-				const char* found_path = g.gl_pathv[0];
-				LOG_IPAACA_CONSOLE("Found an RSB plugin dir which will be used automatically: " << found_path)
-				setenv("RSB_PLUGINS_CPP_PATH", found_path, 1);
-				break;
-			} // else keep going
-			globfree(&g);
-			pathstr += "../";
+// UUID generation
+IPAACA_EXPORT std::string generate_uuid_string()//{{{
+{
+#ifdef WIN32
+	// Windows
+	UUID uuid;
+	RPC_STATUS stat;
+	stat = UuidCreate(&uuid);
+	if (stat == RPC_S_OK) {
+		unsigned char* uuid_str = NULL;
+		stat = UuidToString(&uuid, &uuid_str);
+		if (stat == RPC_S_OK) {
+			std::string result((const char*) uuid_str, 16);
+			RpcStringFree(&uuid_str);
+			return result;
 		}
 	} else {
-		LOG_IPAACA_CONSOLE("RSB_PLUGINS_CPP_PATH already defined: " << plugin_path)
+		throw UUIDGenerationError();
 	}
-}
-
-std::string generate_uuid_string()
-{
+#else
+	// POSIX
 	uuid_t uuidt;
 	uuid_generate(uuidt);
 #ifdef __MACOSX__
+	//   (Mac)
 	uuid_string_t uuidstr;
 	uuid_unparse_lower(uuidt, uuidstr);
 	return uuidstr;
 #else
+	//   (Linux)
 	char result_c[37];
 	uuid_unparse_lower(uuidt, result_c);
 	return result_c;
 #endif
-}
+#endif
+}//}}}
+
+IPAACA_EXPORT std::string __ipaaca_static_option_default_payload_type("JSON");
+IPAACA_EXPORT std::string __ipaaca_static_option_default_channel("default");
+IPAACA_EXPORT unsigned int __ipaaca_static_option_log_level(IPAACA_LOG_LEVEL_WARNING);
 
 /*
 void init_inprocess_too() {
@@ -144,1565 +86,7 @@ void init_inprocess_too() {
 	getFactory().setDefaultParticipantConfig(config);
 }
 */
-//}}}
-
-std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj)//{{{
-{
-	os << "{";
-	bool first = true;
-	for (LinkMap::const_iterator it=obj._links.begin(); it!=obj._links.end(); ++it) {
-		if (first) { first=false; } else { os << ", "; }
-		os << "'" << it->first << "': [";
-		bool firstinner = true;
-		for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			if (firstinner) { firstinner=false; } else { os << ", "; }
-			os << "'" << *it2 << "'";
-		}
-		os << "]";
-	}
-	os << "}";
-	return os;
-}
-//}}}
-std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{{
-{
-	os << "{";
-	bool first = true;
-	for (std::map<std::string, std::string>::const_iterator it=obj._store.begin(); it!=obj._store.end(); ++it) {
-		if (first) { first=false; } else { os << ", "; }
-		os << "'" << it->first << "':'" << it->second << "'";
-	}
-	os << "}";
-	return os;
-}
-//}}}
-std::ostream& operator<<(std::ostream& os, const IUInterface& obj)//{{{
-{
-	os << "IUInterface(uid='" << obj.uid() << "'";
-	os << ", category='" << obj.category() << "'";
-	os << ", revision=" << obj.revision();
-	os << ", committed=" << (obj.committed()?"True":"False");
-	os << ", owner_name='" << obj.owner_name() << "'";
-	os << ", payload=";
-	os << obj.const_payload();
-	os << ", links=";
-	os << obj._links;
-	os << ")";
-	return os;
-}
-//}}}
-std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj)//{{{
-{
-	os << "PayloadUpdate(uid=" << obj.uid << ", revision=" << obj.revision;
-	os << ", writer_name=" << obj.writer_name << ", is_delta=" << (obj.is_delta?"True":"False");
-	os << ", new_items = {";
-	bool first = true;
-	for (std::map<std::string, std::string>::const_iterator it=obj.new_items.begin(); it!=obj.new_items.end(); ++it) {
-		if (first) { first=false; } else { os << ", "; }
-		os << "'" << it->first << "':'" << it->second << "'";
-	}
-	os << "}, keys_to_remove = [";
-	first = true;
-	for (std::vector<std::string>::const_iterator it=obj.keys_to_remove.begin(); it!=obj.keys_to_remove.end(); ++it) {
-		if (first) { first=false; } else { os << ", "; }
-		os << "'" << *it << "'";
-	}
-	os << "])";
-	return os;
-}
-//}}}
-std::ostream& operator<<(std::ostream& os, const IULinkUpdate& obj)//{{{
-{
-	os << "LinkUpdate(uid=" << obj.uid << ", revision=" << obj.revision;
-	os << ", writer_name=" << obj.writer_name << ", is_delta=" << (obj.is_delta?"True":"False");
-	os << ", new_links = {";
-	bool first = true;
-	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj.new_links.begin(); it!=obj.new_links.end(); ++it) {
-		if (first) { first=false; } else { os << ", "; }
-		os << "'" << it->first << "': [";
-		bool ffirst = true;
-		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			if (ffirst) { ffirst=false; } else { os << ", "; }
-			os << "'" << *it2 << "'";
-		}
-		os << "]";
-	}
-	os << "}, links_to_remove = {";
-	first = true;
-	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj.links_to_remove.begin(); it!=obj.links_to_remove.end(); ++it) {
-		if (first) { first=false; } else { os << ", "; }
-		os << "'" << it->first << "': [";
-		bool ffirst = true;
-		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			if (ffirst) { ffirst=false; } else { os << ", "; }
-			os << "'" << *it2 << "'";
-		}
-		os << "]";
-	}
-	os << "})";
-	return os;
-}
-//}}}
-
-// SmartLinkMap//{{{
-
-LinkSet SmartLinkMap::empty_link_set;
-void SmartLinkMap::_add_and_remove_links(const LinkMap& add, const LinkMap& remove)
-{
-	// remove specified links
-	for (LinkMap::const_iterator it = remove.begin(); it != remove.end(); ++it ) {
-		// if link type exists
-		if (_links.count(it->first) > 0) {
-			// remove one by one
-			for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-				_links[it->first].erase(*it2);
-			}
-			// wipe the type key if no more links are left
-			if (_links[it->first].size() == 0) {
-				_links.erase(it->first);
-			}
-		}
-	}
-	// add specified links
-	for (LinkMap::const_iterator it = add.begin(); it != add.end(); ++it ) {
-		for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			_links[it->first].insert(*it2);
-		}
-	}
-}
-void SmartLinkMap::_replace_links(const LinkMap& links)
-{
-	//_links.clear();
-	_links=links;
-}
-const LinkSet& SmartLinkMap::get_links(const std::string& key)
-{
-	LinkMap::const_iterator it = _links.find(key);
-	if (it==_links.end()) return empty_link_set;
-	return it->second;
-}
-const LinkMap& SmartLinkMap::get_all_links()
-{
-	return _links;
-}
-//}}}
-
-// IUEventHandler//{{{
-IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category)
-: _function(function), _event_mask(event_mask), _for_all_categories(false)
-{
-	if (category=="") {
-		_for_all_categories = true;
-	} else {
-		_categories.insert(category);
-	}
-}
-IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories)
-: _function(function), _event_mask(event_mask), _for_all_categories(false)
-{
-	if (categories.size()==0) {
-		_for_all_categories = true;
-	} else {
-		_categories = categories;
-	}
-}
-void IUEventHandler::call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category)
-{
-	if (_condition_met(event_type, category)) {
-		//IUInterface::ptr iu = buffer->get(uid);
-		//if (iu) {
-#if VERBOSE_HANDLERS == 1
-			std::cout << "[" << pthread_self() << " handler ENTER]" << std::endl;
-#endif
-			_function(iu, event_type, local);
-#if VERBOSE_HANDLERS == 1
-			std::cout << "[" << pthread_self() << " handler EXIT]" << std::endl;
-#endif
-		//}
-	}
-}
-//}}}
-
-// Buffer//{{{
-void Buffer::_allocate_unique_name(const std::string& basename, const std::string& function) {
-	std::string uuid = ipaaca::generate_uuid_string();
-	_basename = basename;
-	_uuid = uuid.substr(0,8);
-	_unique_name = "/ipaaca/component/" + _basename + "ID" + _uuid + "/" + function;
-}
-void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories)
-{
-	IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, categories));
-	_event_handlers.push_back(handler);
-}
-void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category)
-{
-	IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, category));
-	_event_handlers.push_back(handler);
-}
-void Buffer::call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category)
-{
-	//IPAACA_INFO("handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid())
-	for (std::vector<IUEventHandler::ptr>::iterator it = _event_handlers.begin(); it != _event_handlers.end(); ++it) {
-		(*it)->call(this, iu, local, event_type, category);
-	}
-}
-//}}}
-
-// Callbacks for OutputBuffer//{{{
-CallbackIUPayloadUpdate::CallbackIUPayloadUpdate(Buffer* buffer): _buffer(buffer) { }
-CallbackIULinkUpdate::CallbackIULinkUpdate(Buffer* buffer): _buffer(buffer) { }
-CallbackIUCommission::CallbackIUCommission(Buffer* buffer): _buffer(buffer) { }
-
-boost::shared_ptr<int> CallbackIUPayloadUpdate::call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update)
-{
-	//std::cout << "-- Received a modify_payload with " << update->new_items.size() << " keys to merge." << std::endl;
-	IUInterface::ptr iui = _buffer->get(update->uid);
-	if (! iui) {
-		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid)
-		return boost::shared_ptr<int>(new int(0));
-	}
-	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
-	iu->_revision_lock.lock();
-	if ((update->revision != 0) && (update->revision != iu->_revision)) {
-		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid)
-		iu->_revision_lock.unlock();
-		return boost::shared_ptr<int>(new int(0));
-	}
-	if (update->is_delta) {
-		// FIXME FIXME this is an unsolved problem atm: deletes in a delta update are
-		// sent individually. We should have something like _internal_merge_and_remove
-		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
-			iu->payload()._internal_remove(*it, update->writer_name); //_buffer->unique_name());
-		}
-		// but it is solved for pure merges:
-		iu->payload()._internal_merge(update->new_items, update->writer_name);
-	} else {
-		iu->payload()._internal_replace_all(update->new_items, update->writer_name); //_buffer->unique_name());
-	}
-	//std::cout << "-- Calling update handler due to remote write." << std::endl;
-	_buffer->call_iu_event_handlers(iu, true, IU_UPDATED, iu->category());
-	revision_t revision = iu->revision();
-	iu->_revision_lock.unlock();
-	return boost::shared_ptr<int>(new int(revision));
-}
-
-boost::shared_ptr<int> CallbackIULinkUpdate::call(const std::string& methodName, boost::shared_ptr<IULinkUpdate> update)
-{
-	IUInterface::ptr iui = _buffer->get(update->uid);
-	if (! iui) {
-		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid)
-		return boost::shared_ptr<int>(new int(0));
-	}
-	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
-	iu->_revision_lock.lock();
-	if ((update->revision != 0) && (update->revision != iu->_revision)) {
-		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid)
-		iu->_revision_lock.unlock();
-		return boost::shared_ptr<int>(new int(0));
-	}
-	if (update->is_delta) {
-		iu->modify_links(update->new_links, update->links_to_remove, update->writer_name);
-	} else {
-		iu->set_links(update->new_links, update->writer_name);
-	}
-	_buffer->call_iu_event_handlers(iu, true, IU_LINKSUPDATED, iu->category());
-	revision_t revision = iu->revision();
-	iu->_revision_lock.unlock();
-	return boost::shared_ptr<int>(new int(revision));
-}
-boost::shared_ptr<int> CallbackIUCommission::call(const std::string& methodName, boost::shared_ptr<protobuf::IUCommission> update)
-{
-	IUInterface::ptr iui = _buffer->get(update->uid());
-	if (! iui) {
-		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid())
-		return boost::shared_ptr<int>(new int(0));
-	}
-	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
-	iu->_revision_lock.lock();
-	if ((update->revision() != 0) && (update->revision() != iu->_revision)) {
-		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid())
-		iu->_revision_lock.unlock();
-		return boost::shared_ptr<int>(new int(0));
-	}
-	if (iu->committed()) {
-		return boost::shared_ptr<int>(new int(0));
-	} else {
-	}
-	iu->_internal_commit(update->writer_name());
-	_buffer->call_iu_event_handlers(iu, true, IU_LINKSUPDATED, iu->category());
-	revision_t revision = iu->revision();
-	iu->_revision_lock.unlock();
-	return boost::shared_ptr<int>(new int(revision));
-}
-
-//}}}
-
-// OutputBuffer//{{{
-
-OutputBuffer::OutputBuffer(const std::string& basename)
-:Buffer(basename, "OB")
-{
-	_id_prefix = _basename + "-" + _uuid + "-IU-";
-	_initialize_server();
-}
-void OutputBuffer::_initialize_server()
-{
-	_server = getFactory().createServer( Scope( _unique_name ) );
-	_server->registerMethod("updatePayload", Server::CallbackPtr(new CallbackIUPayloadUpdate(this)));
-	_server->registerMethod("updateLinks", Server::CallbackPtr(new CallbackIULinkUpdate(this)));
-	_server->registerMethod("commit", Server::CallbackPtr(new CallbackIUCommission(this)));
-}
-OutputBuffer::ptr OutputBuffer::create(const std::string& basename)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return OutputBuffer::ptr(new OutputBuffer(basename));
-}
-IUInterface::ptr OutputBuffer::get(const std::string& iu_uid)
-{
-	IUStore::iterator it = _iu_store.find(iu_uid);
-	if (it==_iu_store.end()) return IUInterface::ptr();
-	return it->second;
-}
-std::set<IUInterface::ptr> OutputBuffer::get_ius()
-{
-	std::set<IUInterface::ptr> set;
-	for (IUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) set.insert(it->second);
-	return set;
-}
-
-void OutputBuffer::_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)
-{
-	IULinkUpdate* lup = new ipaaca::IULinkUpdate();
-	Informer<ipaaca::IULinkUpdate>::DataPtr ldata(lup);
-	lup->uid = iu->uid();
-	lup->is_delta = is_delta;
-	lup->revision = revision;
-	lup->is_delta = true;
-	lup->new_links = new_links;
-	if (is_delta) lup->links_to_remove = links_to_remove;
-	if (writer_name=="") lup->writer_name = _unique_name;
-	else lup->writer_name = writer_name;
-	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
-	informer->publish(ldata);
-}
-
-void OutputBuffer::_send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, std::string>& 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);
-	pup->uid = iu->uid();
-	pup->is_delta = is_delta;
-	pup->revision = revision;
-	pup->new_items = new_items;
-	if (is_delta) pup->keys_to_remove = keys_to_remove;
-	if (writer_name=="") pup->writer_name = _unique_name;
-	else pup->writer_name = writer_name;
-	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
-	informer->publish(pdata);
-}
-
-void OutputBuffer::_send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name)
-{
-	Informer<protobuf::IUCommission>::DataPtr data(new protobuf::IUCommission());
-	data->set_uid(iu->uid());
-	data->set_revision(revision);
-	if (writer_name=="") data->set_writer_name(_unique_name);
-	else data->set_writer_name(writer_name);
-	
-	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
-	informer->publish(data);
-}
-
-void OutputBuffer::add(IU::ptr iu)
-{
-	if (_iu_store.count(iu->uid()) > 0) {
-		throw IUPublishedError();
-	}
-	if (iu->is_published()) {
-		throw IUPublishedError();
-	}
-	if (iu->access_mode() != IU_ACCESS_MESSAGE) {
-		// (for Message-type IUs: do not actually store them)
-		_iu_store[iu->uid()] = iu;
-	}
-	iu->_associate_with_buffer(this); //shared_from_this());
-	_publish_iu(iu);
-}
-
-void OutputBuffer::_publish_iu(IU::ptr iu)
-{
-	Informer<AnyType>::Ptr informer = _get_informer(iu->_category);
-	Informer<ipaaca::IU>::DataPtr iu_data(iu);
-	informer->publish(iu_data);
-}
-
-Informer<AnyType>::Ptr OutputBuffer::_get_informer(const std::string& category)
-{
-	if (_informer_store.count(category) > 0) {
-		return _informer_store[category];
-	} else {
-		//IPAACA_INFO("Making new informer for category " << category)
-		std::string scope_string = "/ipaaca/category/" + category;
-		Informer<AnyType>::Ptr informer = getFactory().createInformer<AnyType> ( Scope(scope_string));
-		_informer_store[category] = informer;
-		return informer;
-	}
-}
-boost::shared_ptr<IU> OutputBuffer::remove(const std::string& iu_uid)
-{
-	IUStore::iterator it = _iu_store.find(iu_uid);
-	if (it == _iu_store.end()) {
-		IPAACA_WARNING("Removal of IU " << iu_uid << " requested, but not present in our OutputBuffer")
-		//throw IUNotFoundError();
-	}
-	IU::ptr iu = it->second;
-	_retract_iu(iu);
-	_iu_store.erase(iu_uid);
-	return iu;
-}
-boost::shared_ptr<IU> OutputBuffer::remove(IU::ptr iu)
-{
-	return remove(iu->uid()); // to make sure it is in the store
-}
-
-void OutputBuffer::_retract_iu(IU::ptr iu)
-{
-	Informer<protobuf::IURetraction>::DataPtr data(new protobuf::IURetraction());
-	data->set_uid(iu->uid());
-	data->set_revision(iu->revision());
-	Informer<AnyType>::Ptr informer = _get_informer(iu->category());
-	informer->publish(data);
-}
-
-
-//}}}
-
-// InputBuffer//{{{
-InputBuffer::InputBuffer(const std::string& basename, const std::set<std::string>& category_interests)
-:Buffer(basename, "IB")
-{
-	for (std::set<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
-		_create_category_listener_if_needed(*it);
-	}
-}
-InputBuffer::InputBuffer(const std::string& basename, const std::vector<std::string>& category_interests)
-:Buffer(basename, "IB")
-{
-	for (std::vector<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
-		_create_category_listener_if_needed(*it);
-	}
-}
-InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1)
-:Buffer(basename, "IB")
-{
-	_create_category_listener_if_needed(category_interest1);
-}
-InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2)
-:Buffer(basename, "IB")
-{
-	_create_category_listener_if_needed(category_interest1);
-	_create_category_listener_if_needed(category_interest2);
-}
-InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3)
-:Buffer(basename, "IB")
-{
-	_create_category_listener_if_needed(category_interest1);
-	_create_category_listener_if_needed(category_interest2);
-	_create_category_listener_if_needed(category_interest3);
-}
-InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4)
-:Buffer(basename, "IB")
-{
-	_create_category_listener_if_needed(category_interest1);
-	_create_category_listener_if_needed(category_interest2);
-	_create_category_listener_if_needed(category_interest3);
-	_create_category_listener_if_needed(category_interest4);
-}
-
-
-InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::set<std::string>& category_interests)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return InputBuffer::ptr(new InputBuffer(basename, category_interests));
-}
-InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::vector<std::string>& category_interests)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return InputBuffer::ptr(new InputBuffer(basename, category_interests));
-}
-InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return InputBuffer::ptr(new InputBuffer(basename, category_interest1));
-}
-InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2));
-}
-InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3));
-}
-InputBuffer::ptr InputBuffer::create(const std::string& basename, const std::string& category_interest1, const std::string& category_interest2, const std::string& category_interest3, const std::string& category_interest4)
-{
-	Initializer::initialize_ipaaca_rsb_if_needed();
-	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3, category_interest4));
-}
-
-IUInterface::ptr InputBuffer::get(const std::string& iu_uid)
-{
-	RemotePushIUStore::iterator it = _iu_store.find(iu_uid); // TODO genericize
-	if (it==_iu_store.end()) return IUInterface::ptr();
-	return it->second;
-}
-std::set<IUInterface::ptr> InputBuffer::get_ius()
-{
-	std::set<IUInterface::ptr> set;
-	for (RemotePushIUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) set.insert(it->second); // TODO genericize
-	return set;
-}
-
-
-RemoteServerPtr InputBuffer::_get_remote_server(const std::string& unique_server_name)
-{
-	std::map<std::string, RemoteServerPtr>::iterator it = _remote_server_store.find(unique_server_name);
-	if (it!=_remote_server_store.end()) return it->second;
-	RemoteServerPtr remote_server = getFactory().createRemoteServer(Scope(unique_server_name));
-	_remote_server_store[unique_server_name] = remote_server;
-	return remote_server;
-}
-
-ListenerPtr InputBuffer::_create_category_listener_if_needed(const std::string& category)
-{
-	std::map<std::string, ListenerPtr>::iterator it = _listener_store.find(category);
-	if (it!=_listener_store.end()) return it->second;
-	//IPAACA_INFO("Creating a new listener for category " << category)
-	std::string scope_string = "/ipaaca/category/" + category;
-	ListenerPtr listener = getFactory().createListener( Scope(scope_string) );
-	HandlerPtr event_handler = HandlerPtr(
-			new EventFunctionHandler(
-				boost::bind(&InputBuffer::_handle_iu_events, this, _1)
-			)
-		);
-	listener->addHandler(event_handler);
-	_listener_store[category] = listener;
-	return listener;
-	/*
-		'''Return (or create, store and return) a category listener.'''
-		if iu_category in self._listener_store: return self._informer_store[iu_category]
-		cat_listener = rsb.createListener(rsb.Scope("/ipaaca/category/"+str(iu_category)), config=self._participant_config)
-		cat_listener.addHandler(self._handle_iu_events)
-		self._listener_store[iu_category] = cat_listener
-		self._category_interests.append(iu_category)
-		logger.info("Added listener in scope "+"/ipaaca/category/"+iu_category)
-		return cat_listener
-	*/
-}
-void InputBuffer::_handle_iu_events(EventPtr event)
-{
-	std::string type = event->getType();
-	if (type == "ipaaca::RemotePushIU") {
-		boost::shared_ptr<RemotePushIU> iu = boost::static_pointer_cast<RemotePushIU>(event->getData());
-		if (_iu_store.count(iu->category()) > 0) {
-			// already got the IU... ignore
-		} else {
-			_iu_store[iu->uid()] = iu;
-			iu->_set_buffer(this);
-			call_iu_event_handlers(iu, false, IU_ADDED, iu->category() );
-		}
-		//IPAACA_INFO( "New RemotePushIU state: " << (*iu) )
-	} else if (type == "ipaaca::RemoteMessage") {
-		boost::shared_ptr<RemoteMessage> iu = boost::static_pointer_cast<RemoteMessage>(event->getData());
-		//_iu_store[iu->uid()] = iu;
-		//iu->_set_buffer(this);
-		//std::cout << "REFCNT after cast, before calling handlers: " << iu.use_count() << std::endl;
-		call_iu_event_handlers(iu, false, IU_MESSAGE, iu->category() );
-		//_iu_store.erase(iu->uid());
-	} else {
-		RemotePushIUStore::iterator it;
-		if (type == "ipaaca::IUPayloadUpdate") {
-			boost::shared_ptr<IUPayloadUpdate> update = boost::static_pointer_cast<IUPayloadUpdate>(event->getData());
-			//IPAACA_INFO("** writer name: " << update->writer_name)
-			if (update->writer_name == _unique_name) {
-				return;
-			}
-			it = _iu_store.find(update->uid);
-			if (it == _iu_store.end()) {
-				IPAACA_INFO("Ignoring UPDATED message for an IU that we did not fully receive before")
-				return;
-			}
-			//
-			it->second->_apply_update(update);
-			call_iu_event_handlers(it->second, false, IU_UPDATED, it->second->category() );
-			//
-			//
-		} else if (type == "ipaaca::IULinkUpdate") {
-			boost::shared_ptr<IULinkUpdate> update = boost::static_pointer_cast<IULinkUpdate>(event->getData());
-			if (update->writer_name == _unique_name) {
-				return;
-			}
-			it = _iu_store.find(update->uid);
-			if (it == _iu_store.end()) {
-				IPAACA_INFO("Ignoring LINKSUPDATED message for an IU that we did not fully receive before")
-				return;
-			}
-			//
-			it->second->_apply_link_update(update);
-			call_iu_event_handlers(it->second, false, IU_LINKSUPDATED, it->second->category() );
-			//
-			//
-		} else if (type == "ipaaca::protobuf::IUCommission") {
-			boost::shared_ptr<protobuf::IUCommission> update = boost::static_pointer_cast<protobuf::IUCommission>(event->getData());
-			if (update->writer_name() == _unique_name) {
-				return;
-			}
-			it = _iu_store.find(update->uid());
-			if (it == _iu_store.end()) {
-				IPAACA_INFO("Ignoring COMMITTED message for an IU that we did not fully receive before")
-				return;
-			}
-			//
-			it->second->_apply_commission();
-			it->second->_revision = update->revision();
-			call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() );
-			//
-			//
-		} else if (type == "ipaaca::protobuf::IURetraction") {
-			boost::shared_ptr<protobuf::IURetraction> update = boost::static_pointer_cast<protobuf::IURetraction>(event->getData());
-			it = _iu_store.find(update->uid());
-			if (it == _iu_store.end()) {
-				IPAACA_INFO("Ignoring RETRACTED message for an IU that we did not fully receive before")
-				return;
-			}
-			//
-			it->second->_revision = update->revision();
-			it->second->_apply_retraction();
-			// remove from InputBuffer     FIXME: this is a crossover between retracted and deleted behavior
-			_iu_store.erase(it->first);
-			// and call the handler. IU reference is still valid for this call, although removed from buffer.
-			call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() );
-			//
-		} else {
-			std::cout << "(Unhandled Event type " << type << " !)" << std::endl;
-			return;
-		}
-		//IPAACA_INFO( "New RemotePushIU state: " << *(it->second) )
-	}
-}
-
-//}}}
-
-
-
-// IUInterface//{{{
-
-IUInterface::IUInterface()
-: _buffer(NULL), _committed(false), _retracted(false)
-{
-}
-
-void IUInterface::_set_uid(const std::string& uid) {
-	if (_uid != "") {
-		throw IUAlreadyHasAnUIDError();
-	}
-	_uid = uid;
-}
-
-void IUInterface::_set_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) {
-	if (_buffer) {
-		throw IUAlreadyInABufferError();
-	}
-	_buffer = buffer;
-	
-}
-
-void IUInterface::_set_owner_name(const std::string& owner_name) {
-	if (_owner_name != "") {
-		throw IUAlreadyHasAnOwnerNameError();
-	}
-	_owner_name = owner_name;
-}
-
-/// set the buffer pointer and the owner names of IU and Payload
-void IUInterface::_associate_with_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) {
-	_set_buffer(buffer); // will throw if already set
-	_set_owner_name(buffer->unique_name());
-	payload()._set_owner_name(buffer->unique_name());
-}
-
-/// C++-specific convenience function to add one single link
-void IUInterface::add_link(const std::string& type, const std::string& target, const std::string& writer_name)
-{
-	LinkMap none;
-	LinkMap add;
-	add[type].insert(target);
-	_modify_links(true, add, none, writer_name);
-	_add_and_remove_links(add, none);
-}
-/// C++-specific convenience function to remove one single link
-void IUInterface::remove_link(const std::string& type, const std::string& target, const std::string& writer_name)
-{
-	LinkMap none;
-	LinkMap remove;
-	remove[type].insert(target);
-	_modify_links(true, none, remove, writer_name);
-	_add_and_remove_links(none, remove);
-}
-
-void IUInterface::add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name)
-{
-	LinkMap none;
-	LinkMap add;
-	add[type] = targets;
-	_modify_links(true, add, none, writer_name);
-	_add_and_remove_links(add, none);
-}
-
-void IUInterface::remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name)
-{
-	LinkMap none;
-	LinkMap remove;
-	remove[type] = targets;
-	_modify_links(true, none, remove, writer_name);
-	_add_and_remove_links(none, remove);
-}
-
-void IUInterface::modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name)
-{
-	_modify_links(true, add, remove, writer_name);
-	_add_and_remove_links(add, remove);
-}
-
-void IUInterface::set_links(const LinkMap& links, const std::string& writer_name)
-{
-	LinkMap none;
-	_modify_links(false, links, none, writer_name);
-	_replace_links(links);
-}
-
-//}}}
-
-// IU//{{{
-IU::ptr IU::create(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
-{
-	IU::ptr iu = IU::ptr(new IU(category, access_mode, read_only, payload_type)); /* params */ //));
-	iu->_payload.initialize(iu);
-	return iu;
-}
-
-IU::IU(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
-{
-	_revision = 1;
-	_uid = ipaaca::generate_uuid_string();
-	_category = category;
-	_payload_type = payload_type;
-	// payload initialization deferred to IU::create(), above
-	_read_only = read_only;
-	_access_mode = access_mode;
-	_committed = false;
-}
-
-void IU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
-{
-	_revision_lock.lock();
-	if (_committed) {
-		_revision_lock.unlock();
-		throw IUCommittedError();
-	}
-	_increase_revision_number();
-	if (is_published()) {
-		_buffer->_send_iu_link_update(this, is_delta, _revision, new_links, links_to_remove, writer_name);
-	}
-	_revision_lock.unlock();
-}
-void IU::_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)
-{
-	_revision_lock.lock();
-	if (_committed) {
-		_revision_lock.unlock();
-		throw IUCommittedError();
-	}
-	_increase_revision_number();
-	if (is_published()) {
-		//std::cout << "Sending a payload update with " << new_items.size() << " entries to merge." << std::endl;
-		_buffer->_send_iu_payload_update(this, is_delta, _revision, new_items, keys_to_remove, writer_name);
-	}
-	_revision_lock.unlock();
-}
-
-void IU::commit()
-{
-	_internal_commit();
-}
-
-void IU::_internal_commit(const std::string& writer_name)
-{
-	_revision_lock.lock();
-	if (_committed) {
-		_revision_lock.unlock();
-		throw IUCommittedError();
-	}
-	_increase_revision_number();
-	_committed = true;
-	if (is_published()) {
-		_buffer->_send_iu_commission(this, _revision, writer_name);
-	}
-	_revision_lock.unlock();
-}
-//}}}
-// Message//{{{
-Message::ptr Message::create(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
-{
-	Message::ptr iu = Message::ptr(new Message(category, access_mode, read_only, payload_type)); /* params */ //));
-	iu->_payload.initialize(iu);
-	return iu;
-}
-
-Message::Message(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type)
-: IU(category, access_mode, read_only, payload_type)
-{
-}
-
-void Message::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
-{
-	if (is_published()) {
-		IPAACA_INFO("Info: modifying a Message after sending has no global effects")
-	}
-}
-void Message::_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)
-{
-	if (is_published()) {
-		IPAACA_INFO("Info: modifying a Message after sending has no global effects")
-	}
-}
-
-void Message::_internal_commit(const std::string& writer_name)
-{
-	if (is_published()) {
-		IPAACA_INFO("Info: committing to a Message after sending has no global effects")
-	}
-	
-}
-//}}}
-
-// RemotePushIU//{{{
-
-RemotePushIU::ptr RemotePushIU::create()
-{
-	RemotePushIU::ptr iu = RemotePushIU::ptr(new RemotePushIU(/* params */));
-	iu->_payload.initialize(iu);
-	return iu;
-}
-RemotePushIU::RemotePushIU()
-{
-	// nothing
-}
-void RemotePushIU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
-{
-	if (_committed) {
-		throw IUCommittedError();
-	}
-	if (_read_only) {
-		throw IUReadOnlyError();
-	}
-	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
-	IULinkUpdate::ptr update = IULinkUpdate::ptr(new IULinkUpdate());
-	update->uid = _uid;
-	update->revision = _revision;
-	update->is_delta = is_delta;
-	update->writer_name = _buffer->unique_name();
-	update->new_links = new_links;
-	update->links_to_remove = links_to_remove;
-	boost::shared_ptr<int> result = server->call<int>("updateLinks", update, IPAACA_REMOTE_SERVER_TIMEOUT); // TODO
-	if (*result == 0) {
-		throw IUUpdateFailedError();
-	} else {
-		_revision = *result;
-	}
-}
-void RemotePushIU::_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)
-{
-	//std::cout << "-- Sending a modify_payload with " << new_items.size() << " keys to merge." << std::endl;
-	if (_committed) {
-		throw IUCommittedError();
-	}
-	if (_read_only) {
-		throw IUReadOnlyError();
-	}
-	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
-	IUPayloadUpdate::ptr update = IUPayloadUpdate::ptr(new IUPayloadUpdate());
-	update->uid = _uid;
-	update->revision = _revision;
-	update->is_delta = is_delta;
-	update->writer_name = _buffer->unique_name();
-	update->new_items = new_items;
-	update->keys_to_remove = keys_to_remove;
-	boost::shared_ptr<int> result = server->call<int>("updatePayload", update, IPAACA_REMOTE_SERVER_TIMEOUT); // TODO
-	if (*result == 0) {
-		throw IUUpdateFailedError();
-	} else {
-		_revision = *result;
-	}
-}
-
-void RemotePushIU::commit()
-{
-	if (_read_only) {
-		throw IUReadOnlyError();
-	}
-	if (_committed) {
-		// Following python version: ignoring multiple commit
-		return;
-	}
-	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
-	boost::shared_ptr<protobuf::IUCommission> update = boost::shared_ptr<protobuf::IUCommission>(new protobuf::IUCommission());
-	update->set_uid(_uid);
-	update->set_revision(_revision);
-	update->set_writer_name(_buffer->unique_name());
-	boost::shared_ptr<int> result = server->call<int>("commit", update, IPAACA_REMOTE_SERVER_TIMEOUT); // TODO
-	if (*result == 0) {
-		throw IUUpdateFailedError();
-	} else {
-		_revision = *result;
-	}
-}
-
-void RemotePushIU::_apply_link_update(IULinkUpdate::ptr update)
-{
-	_revision = update->revision;
-	if (update->is_delta) {
-		_add_and_remove_links(update->new_links, update->links_to_remove);
-	} else {
-		_replace_links(update->new_links);
-	}
-}
-void RemotePushIU::_apply_update(IUPayloadUpdate::ptr update)
-{
-	_revision = update->revision;
-	if (update->is_delta) {
-		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
-			_payload._remotely_enforced_delitem(*it);
-		}
-		for (std::map<std::string, std::string>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
-			_payload._remotely_enforced_setitem(it->first, it->second);
-		}
-	} else {
-		_payload._remotely_enforced_wipe();
-		for (std::map<std::string, std::string>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
-			_payload._remotely_enforced_setitem(it->first, it->second);
-		}
-	}
-}
-void RemotePushIU::_apply_commission()
-{
-	_committed = true;
-}
-void RemotePushIU::_apply_retraction()
-{
-	_retracted = true;
-}
-//}}}
-
-// RemoteMessage//{{{
-
-RemoteMessage::ptr RemoteMessage::create()
-{
-	RemoteMessage::ptr iu = RemoteMessage::ptr(new RemoteMessage(/* params */));
-	iu->_payload.initialize(iu);
-	return iu;
-}
-RemoteMessage::RemoteMessage()
-{
-	// nothing
-}
-void RemoteMessage::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
-{
-	IPAACA_INFO("Info: modifying a RemoteMessage only has local effects")
-}
-void RemoteMessage::_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)
-{
-	IPAACA_INFO("Info: modifying a RemoteMessage only has local effects")
-}
-void RemoteMessage::commit()
-{
-	IPAACA_INFO("Info: committing to a RemoteMessage only has local effects")
-}
-
-void RemoteMessage::_apply_link_update(IULinkUpdate::ptr update)
-{
-	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_link_update")
-	_revision = update->revision;
-	if (update->is_delta) {
-		_add_and_remove_links(update->new_links, update->links_to_remove);
-	} else {
-		_replace_links(update->new_links);
-	}
-}
-void RemoteMessage::_apply_update(IUPayloadUpdate::ptr update)
-{
-	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_update")
-	_revision = update->revision;
-	if (update->is_delta) {
-		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
-			_payload._remotely_enforced_delitem(*it);
-		}
-		for (std::map<std::string, std::string>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
-			_payload._remotely_enforced_setitem(it->first, it->second);
-		}
-	} else {
-		_payload._remotely_enforced_wipe();
-		for (std::map<std::string, std::string>::const_iterator it=update->new_items.begin(); it!=update->new_items.end(); ++it) {
-			_payload._remotely_enforced_setitem(it->first, it->second);
-		}
-	}
-}
-void RemoteMessage::_apply_commission()
-{
-	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_commission")
-	_committed = true;
-}
-void RemoteMessage::_apply_retraction()
-{
-	IPAACA_WARNING("Warning: should never be called: RemoteMessage::_apply_retraction")
-	_retracted = true;
-}
-
-//}}}
-
-
-
-// PayloadEntryProxy//{{{
-
-PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key)
-: _payload(payload), _key(key)
-{
-}
-PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value)
-{
-	//std::cout << "operator=(string)" << std::endl;
-	_payload->set(_key, value);
-	return *this;
-}
-PayloadEntryProxy& PayloadEntryProxy::operator=(const char* value)
-{
-	//std::cout << "operator=(const char*)" << std::endl;
-	_payload->set(_key, value);
-	return *this;
-}
-PayloadEntryProxy& PayloadEntryProxy::operator=(double value)
-{
-	//std::cout << "operator=(double)" << std::endl;
-	_payload->set(_key, boost::lexical_cast<std::string>(value));
-	return *this;
-}
-PayloadEntryProxy& PayloadEntryProxy::operator=(bool value)
-{
-	//std::cout << "operator=(bool)" << std::endl;
-	_payload->set(_key, boost::lexical_cast<std::string>(value));
-	return *this;
-}
-PayloadEntryProxy::operator std::string()
-{
-	return _payload->get(_key);
-}
-PayloadEntryProxy::operator bool()
-{
-	std::string s = operator std::string();
-	return ((s=="1")||(s=="true")||(s=="True"));
-}
-PayloadEntryProxy::operator long()
-{
-	//return boost::lexical_cast<long>(operator std::string().c_str());
-	return atof(operator std::string().c_str());
-}
-PayloadEntryProxy::operator double()
-{
-	//return boost::lexical_cast<double>(operator std::string().c_str());
-	return atol(operator std::string().c_str());
-}
-//}}}
-
-// Payload//{{{
-
-void Payload::initialize(boost::shared_ptr<IUInterface> iu)
-{
-	_iu = boost::weak_ptr<IUInterface>(iu);
-}
-
-PayloadEntryProxy Payload::operator[](const std::string& key)
-{
-	//boost::shared_ptr<PayloadEntryProxy> p(new PayloadEntryProxy(this, key));
-	return PayloadEntryProxy(this, key);
-}
-Payload::operator std::map<std::string, std::string>()
-{
-	return _store;
-}
-
-inline void Payload::_internal_set(const std::string& k, const std::string& v, const std::string& writer_name) {
-	std::map<std::string, std::string> _new;
-	std::vector<std::string> _remove;
-	_new[k]=v;
-	_iu.lock()->_modify_payload(true, _new, _remove, writer_name );
-	_store[k] = v;
-}
-inline void Payload::_internal_remove(const std::string& k, const std::string& writer_name) {
-	std::map<std::string, std::string> _new;
-	std::vector<std::string> _remove;
-	_remove.push_back(k);
-	_iu.lock()->_modify_payload(true, _new, _remove, writer_name );
-	_store.erase(k);
-}
-void Payload::_internal_replace_all(const std::map<std::string, std::string>& new_contents, const std::string& writer_name)
-{
-	std::vector<std::string> _remove;
-	_iu.lock()->_modify_payload(false, new_contents, _remove, writer_name );
-	_store = new_contents;
-}
-void Payload::_internal_merge(const std::map<std::string, std::string>& contents_to_merge, const std::string& writer_name)
-{
-	std::vector<std::string> _remove;
-	_iu.lock()->_modify_payload(true, contents_to_merge, _remove, writer_name );
-	_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;
-	//}
-}
-inline std::string Payload::get(const std::string& k) {
-	if (_store.count(k)>0) return _store[k];
-	else return IPAACA_PAYLOAD_DEFAULT_STRING_VALUE;
-}
-void Payload::_remotely_enforced_wipe()
-{
-	_store.clear();
-}
-void Payload::_remotely_enforced_delitem(const std::string& k)
-{
-	_store.erase(k);
-}
-void Payload::_remotely_enforced_setitem(const std::string& k, const std::string& v)
-{
-	_store[k] = v;
-}
-
-//}}}
-
-// IUConverter//{{{
-
-IUConverter::IUConverter()
-: Converter<std::string> ("ipaaca::IU", "ipaaca-iu", true)
-{
-}
-
-std::string IUConverter::serialize(const AnnotatedData& data, std::string& wire)
-{
-	//std::cout << "serialize" << std::endl;
-	// Ensure that DATA actually holds a datum of the data-type we expect.
-	assert(data.first == getDataType()); // "ipaaca::IU"
-	// NOTE: a dynamic_pointer_cast cannot be used from void*
-	boost::shared_ptr<const IU> obj = boost::static_pointer_cast<const IU> (data.second);
-	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
-	// transfer obj data to pbo
-	pbo->set_uid(obj->uid());
-	pbo->set_revision(obj->revision());
-	pbo->set_category(obj->category());
-	pbo->set_payload_type(obj->payload_type());
-	pbo->set_owner_name(obj->owner_name());
-	pbo->set_committed(obj->committed());
-	ipaaca::protobuf::IU_AccessMode a_m;
-	switch(obj->access_mode()) {
-		case IU_ACCESS_PUSH:
-			a_m = ipaaca::protobuf::IU_AccessMode_PUSH;
-			break;
-		case IU_ACCESS_REMOTE:
-			a_m = ipaaca::protobuf::IU_AccessMode_REMOTE;
-			break;
-		case IU_ACCESS_MESSAGE:
-			a_m = ipaaca::protobuf::IU_AccessMode_MESSAGE;
-			break;
-	}
-	pbo->set_access_mode(a_m);
-	pbo->set_read_only(obj->read_only());
-	for (std::map<std::string, std::string>::const_iterator it=obj->_payload._store.begin(); it!=obj->_payload._store.end(); ++it) {
-		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)
-	}
-	for (LinkMap::const_iterator it=obj->_links._links.begin(); it!=obj->_links._links.end(); ++it) {
-		protobuf::LinkSet* links = pbo->add_links();
-		links->set_type(it->first);
-		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			links->add_targets(*it2);
-		}
-	}
-	pbo->SerializeToString(&wire);
-	switch(obj->access_mode()) {
-		case IU_ACCESS_PUSH:
-			//std::cout << "Requesting to send as ipaaca-iu" << std::endl;
-			return "ipaaca-iu";
-		case IU_ACCESS_MESSAGE:
-			//std::cout << "Requesting to send as ipaaca-messageiu" << std::endl;
-			return "ipaaca-messageiu";
-		default:
-			//std::cout << "Requesting to send as default" << std::endl;
-			return getWireSchema();
-	}
-
-}
-
-AnnotatedData IUConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
-	//std::cout << "deserialize" << std::endl;
-	assert(wireSchema == getWireSchema()); // "ipaaca-iu"
-	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
-	pbo->ParseFromString(wire);
-	IUAccessMode mode = static_cast<IUAccessMode>(pbo->access_mode());
-	switch(mode) {
-		case IU_ACCESS_PUSH:
-			{
-			// Create a "remote push IU"
-			boost::shared_ptr<RemotePushIU> obj = RemotePushIU::create();
-			// transfer pbo data to obj
-			obj->_uid = pbo->uid();
-			obj->_revision = pbo->revision();
-			obj->_category = pbo->category();
-			obj->_payload_type = pbo->payload_type();
-			obj->_owner_name = pbo->owner_name();
-			obj->_committed = pbo->committed();
-			obj->_read_only = pbo->read_only();
-			obj->_access_mode = IU_ACCESS_PUSH;
-			for (int i=0; i<pbo->payload_size(); i++) {
-				const protobuf::PayloadItem& it = pbo->payload(i);
-				obj->_payload._store[it.key()] = it.value();
-			}
-			for (int i=0; i<pbo->links_size(); i++) {
-				const protobuf::LinkSet& pls = pbo->links(i);
-				LinkSet& ls = obj->_links._links[pls.type()];
-				for (int j=0; j<pls.targets_size(); j++) {
-					ls.insert(pls.targets(j));
-				}
-			}
-			//return std::make_pair(getDataType(), obj);
-			return std::make_pair("ipaaca::RemotePushIU", obj);
-			break;
-			}
-		case IU_ACCESS_MESSAGE:
-			{
-			// Create a "Message-type IU"
-			boost::shared_ptr<RemoteMessage> obj = RemoteMessage::create();
-			//std::cout << "REFCNT after create: " << obj.use_count() << std::endl;
-			// transfer pbo data to obj
-			obj->_uid = pbo->uid();
-			obj->_revision = pbo->revision();
-			obj->_category = pbo->category();
-			obj->_payload_type = pbo->payload_type();
-			obj->_owner_name = pbo->owner_name();
-			obj->_committed = pbo->committed();
-			obj->_read_only = pbo->read_only();
-			obj->_access_mode = IU_ACCESS_MESSAGE;
-			for (int i=0; i<pbo->payload_size(); i++) {
-				const protobuf::PayloadItem& it = pbo->payload(i);
-				obj->_payload._store[it.key()] = it.value();
-			}
-			for (int i=0; i<pbo->links_size(); i++) {
-				const protobuf::LinkSet& pls = pbo->links(i);
-				LinkSet& ls = obj->_links._links[pls.type()];
-				for (int j=0; j<pls.targets_size(); j++) {
-					ls.insert(pls.targets(j));
-				}
-			}
-			//return std::make_pair(getDataType(), obj);
-			return std::make_pair("ipaaca::RemoteMessage", obj);
-			break;
-			} 
-		default:
-			// other cases not handled yet! ( TODO )
-			throw NotImplementedError();
-	}
-}
-
-//}}}
-
-// MessageConverter//{{{
-
-MessageConverter::MessageConverter()
-: Converter<std::string> ("ipaaca::Message", "ipaaca-messageiu", true)
-{
-}
-
-std::string MessageConverter::serialize(const AnnotatedData& data, std::string& wire)
-{
-	// Ensure that DATA actually holds a datum of the data-type we expect.
-	assert(data.first == getDataType()); // "ipaaca::Message"
-	// NOTE: a dynamic_pointer_cast cannot be used from void*
-	boost::shared_ptr<const Message> obj = boost::static_pointer_cast<const Message> (data.second);
-	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
-	// transfer obj data to pbo
-	pbo->set_uid(obj->uid());
-	pbo->set_revision(obj->revision());
-	pbo->set_category(obj->category());
-	pbo->set_payload_type(obj->payload_type());
-	pbo->set_owner_name(obj->owner_name());
-	pbo->set_committed(obj->committed());
-	ipaaca::protobuf::IU_AccessMode a_m;
-	switch(obj->access_mode()) {
-		case IU_ACCESS_PUSH:
-			a_m = ipaaca::protobuf::IU_AccessMode_PUSH;
-			break;
-		case IU_ACCESS_REMOTE:
-			a_m = ipaaca::protobuf::IU_AccessMode_REMOTE;
-			break;
-		case IU_ACCESS_MESSAGE:
-			a_m = ipaaca::protobuf::IU_AccessMode_MESSAGE;
-			break;
-	}
-	pbo->set_access_mode(a_m);
-	pbo->set_read_only(obj->read_only());
-	for (std::map<std::string, std::string>::const_iterator it=obj->_payload._store.begin(); it!=obj->_payload._store.end(); ++it) {
-		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)
-	}
-	for (LinkMap::const_iterator it=obj->_links._links.begin(); it!=obj->_links._links.end(); ++it) {
-		protobuf::LinkSet* links = pbo->add_links();
-		links->set_type(it->first);
-		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			links->add_targets(*it2);
-		}
-	}
-	pbo->SerializeToString(&wire);
-	switch(obj->access_mode()) {
-		case IU_ACCESS_PUSH:
-			return "ipaaca-iu";
-		case IU_ACCESS_MESSAGE:
-			return "ipaaca-messageiu";
-		default:
-			//std::cout << "Requesting to send as default" << std::endl;
-			return getWireSchema();
-	}
-
-}
-
-AnnotatedData MessageConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
-	assert(wireSchema == getWireSchema()); // "ipaaca-iu"
-	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
-	pbo->ParseFromString(wire);
-	IUAccessMode mode = static_cast<IUAccessMode>(pbo->access_mode());
-	switch(mode) {
-		case IU_ACCESS_PUSH:
-			{
-			// Create a "remote push IU"
-			boost::shared_ptr<RemotePushIU> obj = RemotePushIU::create();
-			// transfer pbo data to obj
-			obj->_uid = pbo->uid();
-			obj->_revision = pbo->revision();
-			obj->_category = pbo->category();
-			obj->_payload_type = pbo->payload_type();
-			obj->_owner_name = pbo->owner_name();
-			obj->_committed = pbo->committed();
-			obj->_read_only = pbo->read_only();
-			obj->_access_mode = IU_ACCESS_PUSH;
-			for (int i=0; i<pbo->payload_size(); i++) {
-				const protobuf::PayloadItem& it = pbo->payload(i);
-				obj->_payload._store[it.key()] = it.value();
-			}
-			for (int i=0; i<pbo->links_size(); i++) {
-				const protobuf::LinkSet& pls = pbo->links(i);
-				LinkSet& ls = obj->_links._links[pls.type()];
-				for (int j=0; j<pls.targets_size(); j++) {
-					ls.insert(pls.targets(j));
-				}
-			}
-			//return std::make_pair(getDataType(), obj);
-			return std::make_pair("ipaaca::RemotePushIU", obj);
-			break;
-			}
-		case IU_ACCESS_MESSAGE:
-			{
-			// Create a "Message-type IU"
-			boost::shared_ptr<RemoteMessage> obj = RemoteMessage::create();
-			// transfer pbo data to obj
-			obj->_uid = pbo->uid();
-			obj->_revision = pbo->revision();
-			obj->_category = pbo->category();
-			obj->_payload_type = pbo->payload_type();
-			obj->_owner_name = pbo->owner_name();
-			obj->_committed = pbo->committed();
-			obj->_read_only = pbo->read_only();
-			obj->_access_mode = IU_ACCESS_MESSAGE;
-			for (int i=0; i<pbo->payload_size(); i++) {
-				const protobuf::PayloadItem& it = pbo->payload(i);
-				obj->_payload._store[it.key()] = it.value();
-			}
-			for (int i=0; i<pbo->links_size(); i++) {
-				const protobuf::LinkSet& pls = pbo->links(i);
-				LinkSet& ls = obj->_links._links[pls.type()];
-				for (int j=0; j<pls.targets_size(); j++) {
-					ls.insert(pls.targets(j));
-				}
-			}
-			//return std::make_pair(getDataType(), obj);
-			return std::make_pair("ipaaca::RemoteMessage", obj);
-			break;
-			}
-		default:
-			// other cases not handled yet! ( TODO )
-			throw NotImplementedError();
-	}
-}
-
-//}}}
-
-// IUPayloadUpdateConverter//{{{
-
-IUPayloadUpdateConverter::IUPayloadUpdateConverter()
-: Converter<std::string> ("ipaaca::IUPayloadUpdate", "ipaaca-iu-payload-update", true)
-{
-}
-
-std::string IUPayloadUpdateConverter::serialize(const AnnotatedData& data, std::string& wire)
-{
-	assert(data.first == getDataType()); // "ipaaca::IUPayloadUpdate"
-	boost::shared_ptr<const IUPayloadUpdate> obj = boost::static_pointer_cast<const IUPayloadUpdate> (data.second);
-	boost::shared_ptr<protobuf::IUPayloadUpdate> pbo(new protobuf::IUPayloadUpdate());
-	// transfer obj data to pbo
-	pbo->set_uid(obj->uid);
-	pbo->set_revision(obj->revision);
-	pbo->set_writer_name(obj->writer_name);
-	pbo->set_is_delta(obj->is_delta);
-	for (std::map<std::string, std::string>::const_iterator it=obj->new_items.begin(); it!=obj->new_items.end(); ++it) {
-		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)
-	}
-	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);
-	}
-	pbo->SerializeToString(&wire);
-	return getWireSchema();
-
-}
-
-AnnotatedData IUPayloadUpdateConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
-	assert(wireSchema == getWireSchema()); // "ipaaca-iu-payload-update"
-	boost::shared_ptr<protobuf::IUPayloadUpdate> pbo(new protobuf::IUPayloadUpdate());
-	pbo->ParseFromString(wire);
-	boost::shared_ptr<IUPayloadUpdate> obj(new IUPayloadUpdate());
-	// transfer pbo data to obj
-	obj->uid = pbo->uid();
-	obj->revision = pbo->revision();
-	obj->writer_name = pbo->writer_name();
-	obj->is_delta = pbo->is_delta();
-	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();
-	}
-	for (int i=0; i<pbo->keys_to_remove_size(); i++) {
-		obj->keys_to_remove.push_back(pbo->keys_to_remove(i));
-	}
-	return std::make_pair(getDataType(), obj);
-}
-
-//}}}
-
-// IULinkUpdateConverter//{{{
-
-IULinkUpdateConverter::IULinkUpdateConverter()
-: Converter<std::string> ("ipaaca::IULinkUpdate", "ipaaca-iu-link-update", true)
-{
-}
-
-std::string IULinkUpdateConverter::serialize(const AnnotatedData& data, std::string& wire)
-{
-	assert(data.first == getDataType()); // "ipaaca::IULinkUpdate"
-	boost::shared_ptr<const IULinkUpdate> obj = boost::static_pointer_cast<const IULinkUpdate> (data.second);
-	boost::shared_ptr<protobuf::IULinkUpdate> pbo(new protobuf::IULinkUpdate());
-	// transfer obj data to pbo
-	pbo->set_uid(obj->uid);
-	pbo->set_revision(obj->revision);
-	pbo->set_writer_name(obj->writer_name);
-	pbo->set_is_delta(obj->is_delta);
-	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj->new_links.begin(); it!=obj->new_links.end(); ++it) {
-		protobuf::LinkSet* links = pbo->add_new_links();
-		links->set_type(it->first);
-		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			links->add_targets(*it2);
-		}
-	}
-	for (std::map<std::string, std::set<std::string> >::const_iterator it=obj->links_to_remove.begin(); it!=obj->links_to_remove.end(); ++it) {
-		protobuf::LinkSet* links = pbo->add_links_to_remove();
-		links->set_type(it->first);
-		for (std::set<std::string>::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) {
-			links->add_targets(*it2);
-		}
-	}
-	pbo->SerializeToString(&wire);
-	return getWireSchema();
-
-}
-
-AnnotatedData IULinkUpdateConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
-	assert(wireSchema == getWireSchema()); // "ipaaca-iu-link-update"
-	boost::shared_ptr<protobuf::IULinkUpdate> pbo(new protobuf::IULinkUpdate());
-	pbo->ParseFromString(wire);
-	boost::shared_ptr<IULinkUpdate> obj(new IULinkUpdate());
-	// transfer pbo data to obj
-	obj->uid = pbo->uid();
-	obj->revision = pbo->revision();
-	obj->writer_name = pbo->writer_name();
-	obj->is_delta = pbo->is_delta();
-	for (int i=0; i<pbo->new_links_size(); ++i) {
-		const protobuf::LinkSet& it = pbo->new_links(i);
-		for (int j=0; j<it.targets_size(); ++j) {
-			obj->new_links[it.type()].insert(it.targets(j)); // = vec;
-		}
-	}
-	for (int i=0; i<pbo->links_to_remove_size(); ++i) {
-		const protobuf::LinkSet& it = pbo->links_to_remove(i);
-		for (int j=0; j<it.targets_size(); ++j) {
-			obj->links_to_remove[it.type()].insert(it.targets(j));
-		}
-	}
-	return std::make_pair(getDataType(), obj);
-}
-
-//}}}
-
-// IntConverter//{{{
-
-IntConverter::IntConverter()
-: Converter<std::string> ("int", "int32", true)
-{
-}
-
-std::string IntConverter::serialize(const AnnotatedData& data, std::string& wire)
-{
-	// Ensure that DATA actually holds a datum of the data-type we expect.
-	assert(data.first == getDataType()); // "int"
-	// NOTE: a dynamic_pointer_cast cannot be used from void*
-	boost::shared_ptr<const int> obj = boost::static_pointer_cast<const int> (data.second);
-	boost::shared_ptr<protobuf::IntMessage> pbo(new protobuf::IntMessage());
-	// transfer obj data to pbo
-	pbo->set_value(*obj);
-	pbo->SerializeToString(&wire);
-	return getWireSchema();
-
-}
-
-AnnotatedData IntConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
-	assert(wireSchema == getWireSchema()); // "int"
-	boost::shared_ptr<protobuf::IntMessage> pbo(new protobuf::IntMessage());
-	pbo->ParseFromString(wire);
-	boost::shared_ptr<int> obj = boost::shared_ptr<int>(new int(pbo->value()));
-	return std::make_pair("int", obj);
-}
 
-//}}}
 
 } // of namespace ipaaca
 
diff --git a/ipaacalib/cpp/src/rsb.conf b/ipaacalib/cpp/src/rsb.conf
deleted file mode 100644
index 3fb0a683fded31bf2f123d947dcc6ff6a7bfeea1..0000000000000000000000000000000000000000
--- a/ipaacalib/cpp/src/rsb.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-[transport.spread]
-host = localhost
-port = 4803
-enabled = 1
-
diff --git a/ipaacalib/cpp/test/CMakeLists.txt b/ipaacalib/cpp/test/CMakeLists.txt
index 48a93b3076055ea696023cad76ca03d201e024ab..6a56b612432f325165ffeeb542e002aa06ae4130 100644
--- a/ipaacalib/cpp/test/CMakeLists.txt
+++ b/ipaacalib/cpp/test/CMakeLists.txt
@@ -3,6 +3,9 @@ cmake_minimum_required (VERSION 2.6)
 # project name
 project (ipaaca_cpp_test)
 
+# use C++11 (starting with proto v2 / ipaaca-c++ release 12)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
 ## use the following line to enable console debug messages in ipaaca
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_DEBUG_MESSAGES")
 
diff --git a/ipaacalib/cpp/test/src/Makefile b/ipaacalib/cpp/test/src/Makefile
index 11a2336bdded24ce11d4832b37928f1b9ec3beb3..ff3b45be572668655974721966705405b016ae11 100644
--- a/ipaacalib/cpp/test/src/Makefile
+++ b/ipaacalib/cpp/test/src/Makefile
@@ -2,7 +2,7 @@ CONFIG = -DIPAACA_DEBUG_MESSAGES
 #IPAACASOURCES = ../../src/ipaaca.cc ipaaca.pb.cc
 #TEXTSOURCES = ${IPAACASOURCES} testipaaca.cc
 TEXTSOURCES = testipaaca.cc
-CCFLAGS=-I../../../../deps/include -I../../../../dist/include -I. -I../../src -I/usr/local/include -I/opt/local/include ${CONFIG}
+CCFLAGS=-I../../build -I../../../../deps/include -I../../../../dist/include -I. -I../../src -I/usr/local/include -I/opt/local/include ${CONFIG}
 BOOSTLIBS = -L/opt/local/lib -lboost_regex-mt -lboost_date_time-mt -lboost_thread-mt 
 PROTOLIBS = -L/opt/local/lib -lprotobuf
 #LIBS = ${BOOSTLIBS} ${PROTOLIBS} -L/usr/local/lib -lrsc -lrsbcore
diff --git a/ipaacalib/cpp/src/ipaaca-test-main.cc b/ipaacalib/cpp/test/src/ipaaca-test-main.cc
similarity index 86%
rename from ipaacalib/cpp/src/ipaaca-test-main.cc
rename to ipaacalib/cpp/test/src/ipaaca-test-main.cc
index b6ce132704a81a95ccbe1aba63293ef31bde00f7..46946dbd8698df57e565cd8dec654e0de8e7cb36 100644
--- a/ipaacalib/cpp/src/ipaaca-test-main.cc
+++ b/ipaacalib/cpp/test/src/ipaaca-test-main.cc
@@ -30,7 +30,7 @@
  * Excellence Initiative.
  */
 
-#include <ipaaca.h>
+#include <../include/ipaaca/ipaaca.h>
 #include <typeinfo>
 
 //#include <rsc/logging/Logger.h>
@@ -56,7 +56,7 @@ int main() {
 	try{
 		//initialize_ipaaca_rsb();
 		
-		InputBuffer::ptr ib = InputBuffer::create("Tester", "testcategory");
+		InputBuffer::ptr ib = InputBuffer::create("Tester", "spam");
 		ib->register_handler(my_first_iu_handler);
 		
 		while (true) {
@@ -82,7 +82,7 @@ int main() {
 		ob->register_handler(iu_handler_for_remote_changes);
 		//std::cout << "Buffer: " << ob->unique_name() << std::endl;
 		
-		IU::ptr iu = IU::create("testcategory");
+		IU::ptr iu = IU::create("spam");
 		ob->add(iu);
 		
 		std::cout << "Updating in 1 sec" << std::endl;
@@ -98,11 +98,20 @@ int main() {
 		
 		iu->add_link("grin", "DUMMY_IU_UID_1234efef1234");
 		
-		std::cout << "Interpreted as  long  value: " << iu->_payload["TEST"].to_int() << std::endl;
-		std::cout << "Interpreted as double value: " << iu->_payload["TEST"].to_float() << std::endl;
+		//std::cout << "Interpreted as  long  value: " << iu->_payload["TEST"].to_int() << std::endl;
+		//std::cout << "Interpreted as double value: " << iu->_payload["TEST"].to_float() << std::endl;
 		
 		std::cout << "Committing and quitting in 1 sec" << std::endl;
 		sleep(1);
+		int c = 0;
+		while(true) {
+			std::stringstream ss;
+			ss << c;
+                        iu->_payload["data"] = ss.str();
+			std::cout << "iu->_payload[\"data\"]=" << ss.str() << std::endl;
+			c++;
+			sleep(1);
+		}
 		iu->commit();
 	} catch (ipaaca::Exception& e) {
 		std::cout << "== IPAACA EXCEPTION == " << e.what() << std::endl;
diff --git a/ipaacalib/cpp/test/src/ipaaca-test-resend.cc b/ipaacalib/cpp/test/src/ipaaca-test-resend.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a1af0f572ab7d603932aaa448eae1970f4b6743c
--- /dev/null
+++ b/ipaacalib/cpp/test/src/ipaaca-test-resend.cc
@@ -0,0 +1,63 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".  
+ *
+ * Copyright (c) 2009-2013 Sociable Agents Group
+ *                         CITEC, Bielefeld University   
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+#include <../include/ipaaca/ipaaca.h>
+#include <typeinfo>
+#include <iostream>
+
+using namespace ipaaca;
+
+void my_first_iu_handler(IUInterface::ptr iu, IUEventType type, bool local)
+{
+	std::cout<<"Update!"<<std::endl;	
+}
+
+int main() {
+	try{
+		OutputBuffer::ptr output_buffer = OutputBuffer::create("Tester");
+		IU::ptr iu = IU::create("cat1");
+		output_buffer->add(iu);
+		
+		InputBuffer::ptr input_buffer = InputBuffer::create("InputTester","cat1");
+		input_buffer->set_resend(true);
+		input_buffer->register_handler(my_first_iu_handler);
+		iu->payload()["key"]="Dummy";
+		sleep(1);
+		std::cout<<"Input buffer #of ius: "<<input_buffer->get_ius().size()<<std::endl;
+		
+	} catch (ipaaca::Exception& e) {
+		std::cout << "== IPAACA EXCEPTION == " << e.what() << std::endl;
+	}
+}
+
+
+
diff --git a/ipaacalib/cpp/test/src/testipaaca.cc b/ipaacalib/cpp/test/src/testipaaca.cc
index 0de077af57c46d9bed0a44077c18709d9a9c0873..828136ba81da19eaf49546b225f229788c5ed986 100644
--- a/ipaacalib/cpp/test/src/testipaaca.cc
+++ b/ipaacalib/cpp/test/src/testipaaca.cc
@@ -138,7 +138,7 @@ void TextSender::publish_text_to_print(const std::string& text, const std::strin
 	}
 }
 	
-int old_main() {
+int main() {
 	TextSender sender;
 	sleep(1);
 	sender.publish_text_to_print("(INIT)");
@@ -146,7 +146,7 @@ int old_main() {
 	while (true) sleep(1);
 }
 
-int main() {
+int old_main() {
 	std::cerr << "TODO: implement Ipaaca C++ test cases." << std::endl;
 	return 0;
 }
diff --git a/ipaacalib/java/build.properties b/ipaacalib/java/build.properties
index be895bca6a60f3dace498ccc0d61db2abe088746..9549960d4a1a9ff6ee946360d00244d737171de3 100644
--- a/ipaacalib/java/build.properties
+++ b/ipaacalib/java/build.properties
@@ -6,5 +6,5 @@ run.jvmargs= -Xms128m -Xmx512m  -Xss5M
 rebuild.list=
 publish.resolver=asap.sftp.publish
 dist.dir=../../dist
-javac.source=1.6
-javac.target=1.6
+#javac.source=1.6
+#javac.target=1.6
diff --git a/ipaacalib/java/ivy.xml b/ipaacalib/java/ivy.xml
index 8023c27a1dc4f2f71d0d7cfcebe49d55bd8a2475..e1baa4bdf6aa9cbd3606fabf7e9c053a45c286fa 100644
--- a/ipaacalib/java/ivy.xml
+++ b/ipaacalib/java/ivy.xml
@@ -9,5 +9,6 @@
       <dependency org="google"  name="protobuf-java"          rev="latest.release"  />
       <dependency org="rsb"     name="rsb"                    rev="latest.release"  />
       <dependency org="lombok"  name="lombok"                 rev="latest.release"  />
+      <dependency org="apache"  name="commons-lang"           rev="latest.release"  />
    </dependencies>
 </ivy-module>
diff --git a/ipaacalib/java/src/ipaaca/AbstractIU.java b/ipaacalib/java/src/ipaaca/AbstractIU.java
index 83533c2ca3e67f0c061f7e5c1248ad900a09a6d2..d79f1622871ec4f960781e6630604e9fe3054510 100644
--- a/ipaacalib/java/src/ipaaca/AbstractIU.java
+++ b/ipaacalib/java/src/ipaaca/AbstractIU.java
@@ -231,7 +231,7 @@ public abstract class AbstractIU
         List<PayloadItem> items = new ArrayList<PayloadItem>();
         for (Entry<String, String> entry : newPayload.entrySet())
         {
-            PayloadItem item = PayloadItem.newBuilder().setKey(entry.getKey()).setValue(entry.getValue()).setType("") // TODO:default type?
+            PayloadItem item = PayloadItem.newBuilder().setKey(entry.getKey()).setValue(entry.getValue()).setType("STR")
                     .build();
             items.add(item);
         }
diff --git a/ipaacalib/java/src/ipaaca/Buffer.java b/ipaacalib/java/src/ipaaca/Buffer.java
index 993c2d27fc1c035e474462b7328b3a98fd036c96..02b6b36f7eb190ae64344a53e8a7ce663ca80bad 100644
--- a/ipaacalib/java/src/ipaaca/Buffer.java
+++ b/ipaacalib/java/src/ipaaca/Buffer.java
@@ -1,10 +1,10 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".  
+ *   for Artificial Conversational Agents".
  *
  * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -21,7 +21,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -53,7 +53,7 @@ public abstract class Buffer
     {
     	return owningComponentName + "ID" + uuid;
     }
-    
+
     public String getUniqueName()
     {
         return uniqueName;
@@ -107,25 +107,25 @@ public abstract class Buffer
     {
         eventHandlers.add(handler);
     }
-   
+
     public void registerHandler(HandlerFunctor func) {
     	IUEventHandler handler;
     	handler = new IUEventHandler(func);
     	registerHandler(handler);
     }
-    
+
     public void registerHandler(HandlerFunctor func, Set<String> categories) {
     	IUEventHandler handler;
     	handler = new IUEventHandler(func, categories);
     	registerHandler(handler);
     }
-    
+
     public void registerHandler(HandlerFunctor func, EnumSet<IUEventType> eventTypes) {
     	IUEventHandler handler;
     	handler = new IUEventHandler(func, eventTypes);
     	registerHandler(handler);
     }
-   
+
     public void registerHandler(HandlerFunctor func, EnumSet<IUEventType> eventTypes, Set<String> categories) {
     	IUEventHandler handler;
     	handler = new IUEventHandler(func, eventTypes, categories);
diff --git a/ipaacalib/java/src/ipaaca/BufferConfiguration.java b/ipaacalib/java/src/ipaaca/BufferConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec33e1acb2d5adf6dca5293fe38513e4b95161b6
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/BufferConfiguration.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2013 Sociable Agents Group
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+package ipaaca;
+
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+class BufferConfiguration {
+	String _owningComponentName;
+	Set<String> _category_interests;
+	String _channel;
+	boolean _resendActive;
+	// protected:
+	// 	IPAACA_MEMBER_VAR_EXPORT std::string _basename;
+	// 	IPAACA_MEMBER_VAR_EXPORT std::vector<std::string> _category_interests;
+	// 	IPAACA_MEMBER_VAR_EXPORT std::string _channel;
+
+	public BufferConfiguration(String owningComponentName) {
+		this._owningComponentName = owningComponentName;
+		this._channel = "default";
+		this._resendActive = false;
+		this._category_interests = new HashSet<String>();
+	}
+
+	public String getOwningComponentName() {
+		return this._owningComponentName;
+	}
+
+	public Set<String> getCategoryInterests() {
+		return this._category_interests;
+	}
+
+	public String getChannel() {
+		return this._channel;
+	}
+
+	public boolean getResendActive() {
+		return this._resendActive;
+	}
+	// public:
+	// 	IPAACA_HEADER_EXPORT inline BufferConfiguration(const std::string basename) { _basename = basename; }
+	// 	IPAACA_HEADER_EXPORT const std::string get_basename() const { return _basename; }
+	// 	IPAACA_HEADER_EXPORT const std::vector<std::string> get_category_interests() const { return _category_interests; }
+	// 	IPAACA_HEADER_EXPORT const std::string get_channel() const { return _channel; }
+
+}
diff --git a/ipaacalib/java/src/ipaaca/BufferConfigurationBuilder.java b/ipaacalib/java/src/ipaaca/BufferConfigurationBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f536a6994709d21bf8ed402f2518d94cb9f0e1d
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/BufferConfigurationBuilder.java
@@ -0,0 +1,78 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2013 Sociable Agents Group
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+
+package ipaaca;
+
+public class BufferConfigurationBuilder extends BufferConfiguration {
+
+	public BufferConfigurationBuilder(String owningComponentName) {
+		super(owningComponentName);
+	}
+
+	public void setOwningComponentName(String owningComponentName) {
+		this._owningComponentName = owningComponentName;
+	}
+
+	public void addCategoryInterest(String category) {
+		this._category_interests.add(category);
+	}
+
+	public void setChannel(String channel) {
+		this._channel = channel;
+	}
+
+	public void setResendActive(boolean resendActive) {
+		this._resendActive = resendActive;
+	}
+
+	public BufferConfiguration getBufferConfiguration() {
+		return this;
+	}
+
+	// public:
+	// 	IPAACA_HEADER_EXPORT inline BufferConfigurationBuilder(const std::string basename):BufferConfiguration(basename) {}
+	// 	IPAACA_HEADER_EXPORT inline void set_basename(const std::string& basename)
+	// 	{
+	// 		_basename = basename;
+	// 	}
+	// 	IPAACA_HEADER_EXPORT inline void add_category_interest(const std::string& category)
+	// 	{
+	// 		_category_interests.push_back(category);
+	// 	}
+	// 	IPAACA_HEADER_EXPORT inline void set_channel(const std::string& channel)
+	// 	{
+	// 		_channel = channel;
+	// 	}
+
+	// 	IPAACA_HEADER_EXPORT const BufferConfiguration& get_BufferConfiguration() { return *this; }
+}
diff --git a/ipaacalib/java/src/ipaaca/IUConverter.java b/ipaacalib/java/src/ipaaca/IUConverter.java
index 1b6a3c5768fcd72691658bdab67500daeaae57ad..19f86de7cd2eeb684c6c1c6101b670078cc92760 100644
--- a/ipaacalib/java/src/ipaaca/IUConverter.java
+++ b/ipaacalib/java/src/ipaaca/IUConverter.java
@@ -1,10 +1,10 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".  
+ *   for Artificial Conversational Agents".
  *
  * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -21,7 +21,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -55,7 +55,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
 /**
  * Serializes AbstractIUs into protocolbuffer IUs and vice versa.
  * @author hvanwelbergen
- * 
+ *
  */
 public class IUConverter implements Converter<ByteBuffer>
 {
@@ -79,7 +79,7 @@ public class IUConverter implements Converter<ByteBuffer>
         List<PayloadItem> payloadItems = new ArrayList<PayloadItem>();
         for (Entry<String, String> entry : iua.getPayload().entrySet())
         {
-            payloadItems.add(PayloadItem.newBuilder().setKey(entry.getKey()).setValue(entry.getValue()).setType("").build());
+            payloadItems.add(PayloadItem.newBuilder().setKey(entry.getKey()).setValue(entry.getValue()).setType("STR").build());
         }
 
         List<LinkSet> links = new ArrayList<LinkSet>();
@@ -95,11 +95,12 @@ public class IUConverter implements Converter<ByteBuffer>
         }
         IU iu = IU.newBuilder().setUid(iua.getUid()).setRevision(iua.getRevision()).setCategory(iua.getCategory())
                 .setOwnerName(iua.getOwnerName()).setCommitted(iua.isCommitted()).setAccessMode(accessMode)
-                .setReadOnly(iua.isReadOnly()).setPayloadType("MAP").addAllPayload(payloadItems).addAllLinks(links).build();
-        return new WireContents<ByteBuffer>(ByteBuffer.wrap(iu.toByteArray()), "ipaaca-iu");
+                .setReadOnly(iua.isReadOnly()).setPayloadType("STR").addAllPayload(payloadItems).addAllLinks(links).build();
+        String wireFormat = (accessMode == IU.AccessMode.MESSAGE) ? "ipaaca-messageiu" : "ipaaca-iu";
+        return new WireContents<ByteBuffer>(ByteBuffer.wrap(iu.toByteArray()), wireFormat);
     }
 
-    
+
     @Override
     public UserData<?> deserialize(String wireSchema, ByteBuffer buffer) throws ConversionException
     {
@@ -107,6 +108,12 @@ public class IUConverter implements Converter<ByteBuffer>
         try
         {
             iu = IU.newBuilder().mergeFrom(buffer.array()).build();
+            // If there are rsb buffer read-only issues in some build, use this code instead of the above line:
+            //int size = buffer.capacity();
+            //byte[] array = new byte[size];
+            //buffer.get(array, 0, size);
+            //iu = IU.newBuilder().mergeFrom(array).build();
+
         }
         catch (InvalidProtocolBufferException e)
         {
diff --git a/ipaacalib/java/src/ipaaca/IUResendFailedException.java b/ipaacalib/java/src/ipaaca/IUResendFailedException.java
new file mode 100644
index 0000000000000000000000000000000000000000..04d1a06431552ea060cac8d5f066bc8c5a92a6bc
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/IUResendFailedException.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".  
+ *
+ * Copyright (c) 2009-2013 Sociable Agents Group
+ *                         CITEC, Bielefeld University   
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+package ipaaca;
+
+/**
+ * Error indicating that an IU is immutable because it has been committed to.
+ * @author hvanwelbergen
+ * 
+ */
+public class IUResendFailedException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+    private final AbstractIU iu;
+
+    public AbstractIU getIU()
+    {
+        return iu;
+    }
+
+    public IUResendFailedException(AbstractIU iu)
+    {
+        super("Resending IU " + iu.getUid() + " failed.");
+        this.iu = iu;
+    }
+}
diff --git a/ipaacalib/java/src/ipaaca/IUStore.java b/ipaacalib/java/src/ipaaca/IUStore.java
index 0edc34782123f388d725bd9b304ac324546f65db..a81b9b11530b137bd362c37bb6ae5fe12fa28044 100644
--- a/ipaacalib/java/src/ipaaca/IUStore.java
+++ b/ipaacalib/java/src/ipaaca/IUStore.java
@@ -32,7 +32,7 @@
 
 package ipaaca;
 
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * An IUStore maps an IUid to an IU
@@ -40,7 +40,7 @@ import java.util.HashMap;
  *
  * @param <X> type of AbstractIU stored in the store
  */
-public class IUStore<X extends AbstractIU> extends HashMap<String, X>
+public class IUStore<X extends AbstractIU> extends ConcurrentHashMap<String, X>
 {
     private static final long serialVersionUID = 1L;
 }
diff --git a/ipaacalib/java/src/ipaaca/Initializer.java b/ipaacalib/java/src/ipaaca/Initializer.java
index e835f43456241ced846f580f861a873bd3f9c027..0af784bd8e7051dd1889edb0465ef07add9de566 100644
--- a/ipaacalib/java/src/ipaaca/Initializer.java
+++ b/ipaacalib/java/src/ipaaca/Initializer.java
@@ -33,6 +33,7 @@
 package ipaaca;
 
 import ipaaca.protobuf.Ipaaca.IUCommission;
+import ipaaca.protobuf.Ipaaca.IUResendRequest;
 import rsb.converter.ConverterSignature;
 import rsb.converter.DefaultConverterRepository;
 import rsb.converter.ProtocolBufferConverter;
@@ -55,6 +56,9 @@ public final class Initializer
         DefaultConverterRepository.getDefaultConverterRepository().addConverter(new IntConverter());
         DefaultConverterRepository.getDefaultConverterRepository().addConverter(
                 new ProtocolBufferConverter<IUCommission>(IUCommission.getDefaultInstance()));
+	// dlw
+	DefaultConverterRepository.getDefaultConverterRepository().addConverter(
+                new ProtocolBufferConverter<IUResendRequest>(IUResendRequest.getDefaultInstance()));
 
         DefaultConverterRepository.getDefaultConverterRepository().addConverter(
                 new IUConverter(new ConverterSignature("ipaaca-iu", RemotePushIU.class)));
diff --git a/ipaacalib/java/src/ipaaca/InputBuffer.java b/ipaacalib/java/src/ipaaca/InputBuffer.java
index de2be7281d55a79225b83d513c3e7a46d9ef66a9..ccaabc922935c84a6808678a10c0dad5c0608e05 100644
--- a/ipaacalib/java/src/ipaaca/InputBuffer.java
+++ b/ipaacalib/java/src/ipaaca/InputBuffer.java
@@ -1,10 +1,10 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".  
+ *   for Artificial Conversational Agents".
  *
  * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -21,7 +21,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -33,8 +33,10 @@
 package ipaaca;
 
 import ipaaca.protobuf.Ipaaca.IUCommission;
+import ipaaca.protobuf.Ipaaca.IUResendRequest;
 import ipaaca.protobuf.Ipaaca.IULinkUpdate;
 import ipaaca.protobuf.Ipaaca.IUPayloadUpdate;
+import ipaaca.protobuf.Ipaaca.PayloadItem;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -51,6 +53,10 @@ import rsb.Event;
 import rsb.Factory;
 import rsb.Handler;
 import rsb.InitializeException;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
 import rsb.Listener;
 import rsb.RSBException;
 import rsb.Scope;
@@ -70,6 +76,9 @@ public class InputBuffer extends Buffer
     private IUStore<RemotePushIU> iuStore = new IUStore<RemotePushIU>();
     private IUStore<RemoteMessageIU> messageStore = new IUStore<RemoteMessageIU>();
 
+    private String channel = "default";
+    private boolean resendActive;
+
     public void close()
     {
         for (Listener listener : listenerStore.values())
@@ -121,14 +130,53 @@ public class InputBuffer extends Buffer
     // for cat in category_interests:
     // self._create_category_listener_if_needed(cat)
     public InputBuffer(String owningComponentName, Set<String> categoryInterests)
+    {
+        this(owningComponentName, categoryInterests, "default");
+    }
+
+
+    public InputBuffer(String owningComponentName, Set<String> categoryInterests, String ipaaca_channel)
     {
         super(owningComponentName);
-        uniqueName = "/ipaaca/component/" + getUniqueShortName() + "/IB";
+        resendActive = false;
+        String shortIDName = getUniqueShortName();
+        uniqueName = "/ipaaca/component/" + shortIDName + "/IB";
 
+        this.channel = ipaaca_channel;
+        
         for (String cat : categoryInterests)
         {
             createCategoryListenerIfNeeded(cat);
         }
+
+    // add own uuid as identifier for hidden channel. (dlw)
+    createCategoryListenerIfNeeded(shortIDName);
+    }
+
+    /** Pass resendActive to toggle resendRequest-functionality. */
+    public InputBuffer(BufferConfiguration bufferconfiguration)
+    {
+        super(bufferconfiguration.getOwningComponentName());
+        this.resendActive = bufferconfiguration.getResendActive();
+        String shortIDName = getUniqueShortName();
+        uniqueName = "/ipaaca/component/" + shortIDName + "/IB";
+
+        for (String cat : bufferconfiguration.getCategoryInterests())
+        {
+            createCategoryListenerIfNeeded(cat);
+        }
+        this.channel = bufferconfiguration.getChannel();
+
+        // add own uuid as identifier for hidden channel. (dlw)
+        createCategoryListenerIfNeeded(shortIDName);
+    }
+
+    public boolean isResendActive() {
+        return this.resendActive;
+    }
+
+    public void setResendActive(boolean active) {
+        this.resendActive = active;
     }
 
     // def _get_remote_server(self, iu):
@@ -162,6 +210,30 @@ public class InputBuffer extends Buffer
         return remoteServer;
     }
 
+    protected RemoteServer getRemoteServer(String ownerName)
+    {
+        if (remoteServerStore.containsKey(ownerName))
+        {
+            return remoteServerStore.get(ownerName);
+        }
+        logger.debug("Getting remote server for {}", ownerName);
+        RemoteServer remoteServer = Factory.getInstance().createRemoteServer(new Scope(ownerName));
+        try
+        {
+            remoteServer.activate();
+        }
+        catch (InitializeException e)
+        {
+            throw new RuntimeException(e);
+        }
+        catch (RSBException e)
+        {
+            throw new RuntimeException(e);
+        }
+        remoteServerStore.put(ownerName, remoteServer);
+        return remoteServer;
+    }
+
     // def _create_category_listener_if_needed(self, iu_category):
     // '''Return (or create, store and return) a category listener.'''
     // if iu_category in self._listener_store: return self._informer_store[iu_category]
@@ -180,7 +252,7 @@ public class InputBuffer extends Buffer
         Listener listener;
         try
         {
-            listener = Factory.getInstance().createListener(new Scope("/ipaaca/category/" + category));
+            listener = Factory.getInstance().createListener(new Scope("/ipaaca/channel/" + this.channel + "/category/" + category));
         }
         catch (InitializeException e1)
         {
@@ -222,7 +294,7 @@ public class InputBuffer extends Buffer
         }
 
     }
-
+    
     // def _handle_iu_events(self, event):
     // '''Dispatch incoming IU events.
     //
@@ -269,8 +341,15 @@ public class InputBuffer extends Buffer
         if (event.getData() instanceof RemoteMessageIU)
         {
             RemoteMessageIU rm = (RemoteMessageIU) event.getData();
+            if (messageStore.containsKey(rm.getUid())) {
+                logger.warn("Spurious RemoteMessage event: already got this UID: "+rm.getUid());
+                return;
+            }
+            //logger.info("Adding Message "+rm.getUid());
             messageStore.put(rm.getUid(), rm);
+            //logger.info("Calling handlers for Message "+rm.getUid());
             callIuEventHandlers(rm.getUid(),false, IUEventType.MESSAGE, rm.getCategory());
+            //logger.info("Removing Message "+rm.getUid());
             messageStore.remove(rm.getUid());
         }
         else if (event.getData() instanceof RemotePushIU)
@@ -301,7 +380,12 @@ public class InputBuffer extends Buffer
                 }
                 if (!iuStore.containsKey(iuLinkUpdate.getUid()))
                 {
-                    logger.warn("Link update message for IU which we did not fully receive before.");
+                    if (resendActive)
+                    {
+                        triggerResendRequest(event.getData(), getUniqueShortName());
+                    } else {
+                        logger.warn("Link update message for IU which we did not fully receive before.");
+                    }
                     return;
                 }
                 RemotePushIU iu = this.iuStore.get(iuLinkUpdate.getUid());
@@ -319,7 +403,12 @@ public class InputBuffer extends Buffer
                 }
                 if (!iuStore.containsKey(iuUpdate.getUid()))
                 {
-                    logger.warn("Update message for IU which we did not fully receive before.");
+                    if (resendActive)
+                    {
+                        triggerResendRequest(event.getData(), getUniqueShortName());
+                    } else {
+                        logger.warn("Update message for IU which we did not fully receive before.");
+                    }
                     return;
                 }
                 RemotePushIU iu = this.iuStore.get(iuUpdate.getUid());
@@ -339,7 +428,12 @@ public class InputBuffer extends Buffer
                 }
                 if (!iuStore.containsKey(iuc.getUid()))
                 {
-                    logger.warn("Update message for IU which we did not fully receive before.");
+                    if (resendActive)
+                    {
+                        triggerResendRequest(event.getData(), getUniqueShortName());
+                    } else {
+                        logger.warn("Update message for IU which we did not fully receive before.");
+                    }
                     return;
                 }
                 RemotePushIU iu = this.iuStore.get(iuc.getUid());
@@ -350,6 +444,52 @@ public class InputBuffer extends Buffer
         }
     }
 
+    private void triggerResendRequest(Object aiuObj, String hiddenScopeName)
+    {
+        String uid = null;
+        String writerName = null;
+        if (aiuObj instanceof IULinkUpdate) {
+            IULinkUpdate tmp = (IULinkUpdate)aiuObj;
+            uid = tmp.getUid();
+            writerName = tmp.getWriterName();
+        } else if (aiuObj instanceof IUPayloadUpdate) {
+            IUPayloadUpdate tmp = (IUPayloadUpdate)aiuObj;
+            uid = tmp.getUid();
+            writerName = tmp.getWriterName();
+        } else if (aiuObj instanceof IUCommission) {
+            IUCommission tmp = (IUCommission)aiuObj;
+            uid = tmp.getUid();
+            writerName = tmp.getWriterName();
+        }
+        RemoteServer rServer = null;
+        if (writerName != null)
+            rServer = getRemoteServer(writerName);
+        if ((rServer != null)&&(uid != null)) {
+            IUResendRequest iurr = IUResendRequest.newBuilder().setUid(uid).setHiddenScopeName(hiddenScopeName).build();
+            int rRevision = 0;
+            try
+                {
+                    rRevision = (Integer) rServer.call("resendRequest", iurr);
+                }
+                catch (RSBException e)
+                {
+                    throw new RuntimeException(e);
+                }
+                catch (ExecutionException e)
+                {
+                    throw new RuntimeException(e);
+                }
+                catch (TimeoutException e)
+                {
+                    throw new RuntimeException(e);
+                }
+            if (rRevision == 0)
+            {
+                //throw new IUResendFailedException(aiu); // TODO
+            }
+        }
+    }
+
     public InputBuffer(String owningComponentName)
     {
         super(owningComponentName);
@@ -368,6 +508,14 @@ public class InputBuffer extends Buffer
         }
     }
 
+    public void addCategoryInterest(String... categories)
+    {
+        for(String cat:categories)
+        {
+            createCategoryListenerIfNeeded(cat);
+        }
+    }
+
     public Collection<RemotePushIU> getIUs()
     {
         return iuStore.values();
diff --git a/ipaacalib/java/src/ipaaca/LocalIU.java b/ipaacalib/java/src/ipaaca/LocalIU.java
index 82bf3ad84f1edae232ed1c11579eff7a409f8245..6e87a82484f882a25dddda7e314dfd76ebdb3060 100644
--- a/ipaacalib/java/src/ipaaca/LocalIU.java
+++ b/ipaacalib/java/src/ipaaca/LocalIU.java
@@ -230,7 +230,7 @@ public class LocalIU extends AbstractIU
             if (isPublished())
             {
                 // send update to remote holders
-                PayloadItem newItem = PayloadItem.newBuilder().setKey(key).setValue(value).setType("") // TODO: fix this, default in .proto?
+                PayloadItem newItem = PayloadItem.newBuilder().setKey(key).setValue(value).setType("STR")
                         .build();
                 IUPayloadUpdate update = IUPayloadUpdate.newBuilder().setUid(getUid()).setRevision(getRevision()).setIsDelta(true)
                         .setWriterName(writer == null ? getOwnerName() : writer).addNewItems(newItem).build();
@@ -256,7 +256,7 @@ public class LocalIU extends AbstractIU
                         .setWriterName(writer == null ? getOwnerName() : writer);
             	for (Map.Entry<? extends String, ? extends String> item : newItems.entrySet())
             	{
-            		PayloadItem newItem = PayloadItem.newBuilder().setKey(item.getKey()).setValue(item.getValue()).setType("") // TODO: fix this, default in .proto?
+            		PayloadItem newItem = PayloadItem.newBuilder().setKey(item.getKey()).setValue(item.getValue()).setType("STR")
                             .build();
             		builder.addNewItems(newItem);
             	    
diff --git a/ipaacalib/java/src/ipaaca/OutputBuffer.java b/ipaacalib/java/src/ipaaca/OutputBuffer.java
index 35bdae69e8eb5917791cda1ff811869fecfe2820..818621b07d24b974f7928e3d30fa59126caa5fd7 100644
--- a/ipaacalib/java/src/ipaaca/OutputBuffer.java
+++ b/ipaacalib/java/src/ipaaca/OutputBuffer.java
@@ -1,10 +1,10 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".  
+ *   for Artificial Conversational Agents".
  *
  * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -21,7 +21,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -34,6 +34,7 @@ package ipaaca;
 
 import ipaaca.protobuf.Ipaaca;
 import ipaaca.protobuf.Ipaaca.IUCommission;
+import ipaaca.protobuf.Ipaaca.IUResendRequest;
 import ipaaca.protobuf.Ipaaca.IULinkUpdate;
 import ipaaca.protobuf.Ipaaca.IUPayloadUpdate;
 import ipaaca.protobuf.Ipaaca.LinkSet;
@@ -69,6 +70,7 @@ public class OutputBuffer extends Buffer
     private Map<String, Informer<Object>> informerStore = new HashMap<String, Informer<Object>>(); // category -> informer map
     private final static Logger logger = LoggerFactory.getLogger(OutputBuffer.class.getName());
     private IUStore<LocalIU> iuStore = new IUStore<LocalIU>();
+    private String channel = "default";
 
     // def __init__(self, owning_component_name, participant_config=None):
     // '''Create an Output Buffer.
@@ -90,6 +92,16 @@ public class OutputBuffer extends Buffer
      * @param owningComponentName name of the entity that own this buffer
      */
     public OutputBuffer(String owningComponentName)
+    {
+        this(owningComponentName, "default");
+
+    }
+
+    /**
+     * @param owningComponentName name of the entity that own this buffer
+     * @param channel name of the ipaaca channel this buffer is using
+     */
+    public OutputBuffer(String owningComponentName, String ipaaca_channel)
     {
         super(owningComponentName);
 
@@ -101,6 +113,8 @@ public class OutputBuffer extends Buffer
             server.addMethod("updatePayload", new RemoteUpdatePayload());
             server.addMethod("updateLinks", new RemoteUpdateLinks());
             server.addMethod("commit", new RemoteCommit());
+	    // add method to trigger a resend request. (dlw)
+	    server.addMethod("resendRequest", new RemoteResendRequest());
             server.activate();
         }
         catch (InitializeException e)
@@ -112,6 +126,7 @@ public class OutputBuffer extends Buffer
             throw new RuntimeException(e);
         }
 
+        this.channel = ipaaca_channel;
     }
 
     private final class RemoteUpdatePayload extends DataCallback<Integer, IUPayloadUpdate>
@@ -147,6 +162,17 @@ public class OutputBuffer extends Buffer
 
     }
 
+    private final class RemoteResendRequest extends DataCallback<Integer, IUResendRequest>
+    {
+        @Override
+        public Integer invoke(IUResendRequest data) throws Throwable
+        {
+            logger.debug("remoteResendRequest");
+            return remoteResendRequest(data);
+        }
+
+    }
+
     // def _remote_update_payload(self, update):
     // '''Apply a remotely requested update to one of the stored IUs.'''
     // if update.uid not in self._iu_store:
@@ -192,7 +218,7 @@ public class OutputBuffer extends Buffer
             {
                 iu.getPayload().remove(k, update.getWriterName());
             }
-            if (update.getNewItemsList().size() > 0) 
+            if (update.getNewItemsList().size() > 0)
             {
             	HashMap<String, String> payloadUpdate = new HashMap<String, String>();
 
@@ -305,6 +331,35 @@ public class OutputBuffer extends Buffer
         }
     }
 
+    /*
+     * Resend an requested iu over the specific hidden channel. (dlw) TODO
+     */
+    private int remoteResendRequest(IUResendRequest iu_resend_request_pack)
+    {
+        if (!iuStore.containsKey(iu_resend_request_pack.getUid()))
+        {
+            logger.warn("Remote InBuffer tried to spuriously write non-existent IU {}", iu_resend_request_pack.getUid());
+            return 0;
+        }
+        AbstractIU iu = iuStore.get(iu_resend_request_pack.getUid());
+        if ((iu_resend_request_pack.hasHiddenScopeName() == true)&&(!iu_resend_request_pack.getHiddenScopeName().equals("")))
+        {
+	    Informer<Object> informer = getInformer(iu_resend_request_pack.getHiddenScopeName());
+            try
+            {
+                informer.send(iu);
+            }
+            catch (RSBException e)
+            {
+                throw new RuntimeException(e);
+            }
+            return iu.getRevision();
+        } else
+        {
+            return 0;
+        }
+    }
+
     // def _get_informer(self, iu_category):
     // '''Return (or create, store and return) an informer object for IUs of the specified category.'''
     // if iu_category in self._informer_store:
@@ -329,7 +384,7 @@ public class OutputBuffer extends Buffer
         Informer<Object> informer;
         try
         {
-            informer = Factory.getInstance().createInformer("/ipaaca/category/" + category);
+            informer = Factory.getInstance().createInformer("/ipaaca/channel/" + this.channel + "/category/" + category);
         }
         catch (InitializeException e1)
         {
@@ -337,7 +392,7 @@ public class OutputBuffer extends Buffer
         }
 
         informerStore.put(category, informer);
-        logger.info("Added informer on " + category);
+        logger.info("Added informer on channel " + this.channel + " and category " + category);
 
         try
         {
diff --git a/ipaacalib/java/src/ipaaca/Payload.java b/ipaacalib/java/src/ipaaca/Payload.java
index 5dc056b67f4fe60b949b90802c86c8a67b80ccee..5d1ed1d61a36cfd11e687b5904706e629adcf253 100644
--- a/ipaacalib/java/src/ipaaca/Payload.java
+++ b/ipaacalib/java/src/ipaaca/Payload.java
@@ -34,6 +34,8 @@ package ipaaca;
 
 import ipaaca.protobuf.Ipaaca.PayloadItem;
 
+import org.apache.commons.lang.StringEscapeUtils;
+
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -55,18 +57,6 @@ public class Payload implements Map<String, String>
         this.iu = iu;
     }
 
-    // def __init__(self, remote_push_iu, new_payload):
-    // """Create remote payload object.
-    //
-    // Keyword arguments:
-    // remote_push_iu -- remote IU holding this payload
-    // new_payload -- payload dict to initialise this remote payload with
-    // """
-    // super(RemotePushPayload, self).__init__()
-    // self._remote_push_iu = remote_push_iu
-    // if new_payload is not None:
-    // for k,v in new_payload.items():
-    // dict.__setitem__(self, k, v)
     public Payload(AbstractIU iu, List<PayloadItem> payloadItems)
     {
         this(iu, payloadItems, null);
@@ -102,21 +92,29 @@ public class Payload implements Map<String, String>
         map.clear();
         for (PayloadItem item : newPayload)
         {
-            map.put(item.getKey(), item.getValue());
+            map.put(item.getKey(), pseudoConvertFromJSON(item.getValue(), item.getType()));
+        }
+    }
+
+    public String pseudoConvertFromJSON(String value, String type) {
+        if (type.equals("JSON")) {
+            if (value.startsWith("\"")) {
+                //return value.replaceAll("\\\"", "");
+                return StringEscapeUtils.unescapeJava(value.substring(1, value.length() - 1));
+            } else if (value.startsWith("{") || value.startsWith("[") || value.matches("true") || value.matches("false") || value.matches("-?[0-9]*[.,]?[0-9][0-9]*.*")) { 
+                return value;
+            } else if (value.equals("null")) {
+                return "";
+            }
         }
+        return value;
     }
 
-    // def _remotely_enforced_setitem(self, k, v):
-    // """Sets an item when requested remotely."""
-    // return dict.__setitem__(self, k, v)
     void enforcedSetItem(String key, String value)
     {
         map.put(key, value);
     }
 
-    // def _remotely_enforced_delitem(self, k):
-    // """Deletes an item when requested remotely."""
-    // return dict.__delitem__(self, k)
     void enforcedRemoveItem(String key)
     {
         map.remove(key);
@@ -168,31 +166,6 @@ public class Payload implements Map<String, String>
         return map.keySet();
     }
 
-    // def __setitem__(self, k, v):
-    // """Set item in this payload.
-    //
-    // Requests item setting from the OutputBuffer holding the local version
-    // of this IU. Returns when permission is granted and item is set;
-    // otherwise raises an IUUpdateFailedError.
-    // """
-    // if self._remote_push_iu.committed:
-    // raise IUCommittedError(self._remote_push_iu)
-    // if self._remote_push_iu.read_only:
-    // raise IUReadOnlyError(self._remote_push_iu)
-    // requested_update = IUPayloadUpdate(
-    // uid=self._remote_push_iu.uid,
-    // revision=self._remote_push_iu.revision,
-    // is_delta=True,
-    // writer_name=self._remote_push_iu.buffer.unique_name,
-    // new_items={k:v},
-    // keys_to_remove=[])
-    // remote_server = self._remote_push_iu.buffer._get_remote_server(self._remote_push_iu)
-    // new_revision = remote_server.updatePayload(requested_update)
-    // if new_revision == 0:
-    // raise IUUpdateFailedError(self._remote_push_iu)
-    // else:
-    // self._remote_push_iu._revision = new_revision
-    // dict.__setitem__(self, k, v)
     /**
      * Set item in this payload.
      * Requests item setting from the OutputBuffer holding the local version
@@ -205,32 +178,6 @@ public class Payload implements Map<String, String>
         return map.put(key, value);
     }
 
-    //
-    // def __delitem__(self, k):
-    // """Delete item in this payload.
-    //
-    // Requests item deletion from the OutputBuffer holding the local version
-    // of this IU. Returns when permission is granted and item is deleted;
-    // otherwise raises an IUUpdateFailedError.
-    // """
-    // if self._remote_push_iu.committed:
-    // raise IUCommittedError(self._remote_push_iu)
-    // if self._remote_push_iu.read_only:
-    // raise IUReadOnlyError(self._remote_push_iu)
-    // requested_update = IUPayloadUpdate(
-    // uid=self._remote_push_iu.uid,
-    // revision=self._remote_push_iu.revision,
-    // is_delta=True,
-    // writer_name=self._remote_push_iu.buffer.unique_name,
-    // new_items={},
-    // keys_to_remove=[k])
-    // remote_server = self._remote_push_iu.buffer._get_remote_server(self._remote_push_iu)
-    // new_revision = remote_server.updatePayload(requested_update)
-    // if new_revision == 0:
-    // raise IUUpdateFailedError(self._remote_push_iu)
-    // else:
-    // self._remote_push_iu._revision = new_revision
-    // dict.__delitem__(self, k)
     /**
      * Delete item in this payload.//
      * Requests item deletion from the OutputBuffer holding the local version
@@ -251,7 +198,7 @@ public class Payload implements Map<String, String>
     
     public void putAll(Map<? extends String, ? extends String> newItems)
     {
-        putAll(newItems);
+        putAll(newItems, null);
     }
 
     public void putAll(Map<? extends String, ? extends String> newItems, String writer)
diff --git a/ipaacalib/java/src/ipaaca/RemotePushIU.java b/ipaacalib/java/src/ipaaca/RemotePushIU.java
index 45af9e8096ac38160dcddb42124cf3fb85515d7f..bfb8060403c42031dfbf70c7b8c55eadaf72b334 100644
--- a/ipaacalib/java/src/ipaaca/RemotePushIU.java
+++ b/ipaacalib/java/src/ipaaca/RemotePushIU.java
@@ -71,14 +71,6 @@ public class RemotePushIU extends AbstractIU
         return inputBuffer;
     }
 
-    // def __init__(self, uid, revision, read_only, owner_name, category, type, committed, payload):
-    // super(RemotePushIU, self).__init__(uid=uid, access_mode=IUAccessMode.PUSH, read_only=read_only)
-    // self._revision = revision
-    // self._category = category
-    // self.owner_name = owner_name
-    // self._type = type
-    // self._committed = committed
-    // self._payload = RemotePushPayload(remote_push_iu=self, new_payload=payload)
     public RemotePushIU(String uid)
     {
         super(uid);
@@ -107,7 +99,7 @@ public class RemotePushIU extends AbstractIU
         {
             throw new IUReadOnlyException(this);
         }
-        PayloadItem newItem = PayloadItem.newBuilder().setKey(key).setValue(value).setType("").build();// TODO use default type in .proto
+        PayloadItem newItem = PayloadItem.newBuilder().setKey(key).setValue(value).setType("STR").build();
         IUPayloadUpdate update = IUPayloadUpdate.newBuilder().setIsDelta(true).setUid(getUid()).setRevision(getRevision())
                 .setWriterName(getBuffer().getUniqueName()).addNewItems(newItem).build();
 
@@ -152,7 +144,7 @@ public class RemotePushIU extends AbstractIU
                 .setWriterName(getBuffer().getUniqueName());
         for (Map.Entry<? extends String, ? extends String> item : newItems.entrySet())
         {
-            PayloadItem newItem = PayloadItem.newBuilder().setKey(item.getKey()).setValue(item.getValue()).setType("") // TODO: fix this, default in .proto?
+            PayloadItem newItem = PayloadItem.newBuilder().setKey(item.getKey()).setValue(item.getValue()).setType("STR")
                     .build();
             builder.addNewItems(newItem);
 
@@ -187,25 +179,6 @@ public class RemotePushIU extends AbstractIU
         setRevision(newRevision);
     }
 
-    // def commit(self):
-    // """Commit to this IU."""
-    // if self.read_only:
-    // raise IUReadOnlyError(self)
-    // if self._committed:
-    // # ignore commit requests when already committed
-    // return
-    // else:
-    // commission_request = iuProtoBuf_pb2.IUCommission()
-    // commission_request.uid = self.uid
-    // commission_request.revision = self.revision
-    // commission_request.writer_name = self.buffer.unique_name
-    // remote_server = self.buffer._get_remote_server(self)
-    // new_revision = remote_server.commit(commission_request)
-    // if new_revision == 0:
-    // raise IUUpdateFailedError(self)
-    // else:
-    // self._revision = new_revision
-    // self._committed = True
     @Override
     public void commit(String writerName)
     {
@@ -251,17 +224,6 @@ public class RemotePushIU extends AbstractIU
         }
     }
 
-    // def __str__(self):
-    // s = "RemotePushIU{ "
-    // s += "uid="+self._uid+" "
-    // s += "(buffer="+(self.buffer.unique_name if self.buffer is not None else "<None>")+") "
-    // s += "owner_name=" + ("<None>" if self.owner_name is None else self.owner_name) + " "
-    // s += "payload={ "
-    // for k,v in self.payload.items():
-    // s += k+":'"+v+"', "
-    // s += "} "
-    // s += "}"
-    // return s
     @Override
     public String toString()
     {
@@ -280,37 +242,11 @@ public class RemotePushIU extends AbstractIU
         return b.toString();
     }
 
-    //
-    // def _get_payload(self):
-    // return self._payload
     public Payload getPayload()
     {
         return payload;
     }
 
-    // def _set_payload(self, new_pl):
-    // if self.committed:
-    // raise IUCommittedError(self)
-    // if self.read_only:
-    // raise IUReadOnlyError(self)
-    // requested_update = IUPayloadUpdate(
-    // uid=self.uid,
-    // revision=self.revision,
-    // is_delta=False,
-    // writer_name=self.buffer.unique_name,
-    // new_items=new_pl,
-    // keys_to_remove=[])
-    // remote_server = self.buffer._get_remote_server(self)
-    // new_revision = remote_server.updatePayload(requested_update)
-    // if new_revision == 0:
-    // raise IUUpdateFailedError(self)
-    // else:
-    // self._revision = new_revision
-    // self._payload = RemotePushPayload(remote_push_iu=self, new_payload=new_pl)
-    // payload = property(
-    // fget=_get_payload,
-    // fset=_set_payload,
-    // doc='Payload dictionary of the IU.')
     @Override
     public void setPayload(List<PayloadItem> newItems, String writerName)
     {
@@ -354,37 +290,33 @@ public class RemotePushIU extends AbstractIU
         }
     }
 
-    // def _apply_update(self, update):
-    // """Apply a IUPayloadUpdate to the IU."""
-    // self._revision = update.revision
-    // if update.is_delta:
-    // for k in update.keys_to_remove: self.payload._remotely_enforced_delitem(k)
-    // for k, v in update.new_items.items(): self.payload._remotely_enforced_setitem(k, v)
-    // else:
-    // # using '_payload' to circumvent the local writing methods
-    // self._payload = RemotePushPayload(remote_push_iu=self, new_payload=update.new_items)
     /**
      * Apply a IUPayloadUpdate to the IU.
      * @param update
      */
-    public void applyUpdate(IUPayloadUpdate update)
-    {
-        revision = update.getRevision();
-        if (update.getIsDelta())
-        {
-            for (String key : update.getKeysToRemoveList())
-            {
-                payload.enforcedRemoveItem(key);
-            }
-            for (PayloadItem item : update.getNewItemsList())
-            {
-                payload.enforcedSetItem(item.getKey(), item.getValue());
-            }
-        }
-        else
-        {
-            payload = new Payload(this, update.getNewItemsList());
-        }
+    public void applyUpdate(IUPayloadUpdate update) {
+    	revision = update.getRevision();
+    	if (update.getIsDelta()) {
+    		for (String key : update.getKeysToRemoveList()) {
+    			payload.enforcedRemoveItem(key);
+    		}
+    		for (PayloadItem item : update.getNewItemsList()) {
+    			if (item.getType().equals("STR")) {
+    				payload.enforcedSetItem(item.getKey(), item.getValue());
+    			} else if (item.getType().equals("JSON")) {
+    				String value = item.getValue();
+    				if (value.startsWith("\"")) {
+    					payload.enforcedSetItem(item.getKey(), value.replaceAll("\\\"", ""));
+    				} else if (value.startsWith("{") || value.startsWith("[") || value.matches("true") || value.matches("false") || value.matches("-?[0-9]*[.,]?[0-9][0-9]*.*")) { 
+    					payload.enforcedSetItem(item.getKey(), value);
+    				} else if (value.equals("null")) {
+    					payload.enforcedSetItem(item.getKey(), "");
+    				}
+    			}
+    		}
+    	} else {
+    		payload = new Payload(this, update.getNewItemsList());
+    	}
     }
 
     public void applyLinkUpdate(IULinkUpdate update)
@@ -420,9 +352,6 @@ public class RemotePushIU extends AbstractIU
 
     }
 
-    // def _apply_commission(self):
-    // """Apply commission to the IU"""
-    // self._committed = True
     public void applyCommmision()
     {
         committed = true;
@@ -466,25 +395,7 @@ public class RemotePushIU extends AbstractIU
         setRevision(newRevision);
     }
 
-    // def _modify_payload(self, payload, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
-    // """Modify the payload: add or remove item from this payload remotely and send update."""
-    // if self.committed:
-    // raise IUCommittedError(self)
-    // if self.read_only:
-    // raise IUReadOnlyError(self)
-    // requested_update = IUPayloadUpdate(
-    // uid=self.uid,
-    // revision=self.revision,
-    // is_delta=is_delta,
-    // writer_name=self.buffer.unique_name,
-    // new_items=new_items,
-    // keys_to_remove=keys_to_remove)
-    // remote_server = self.buffer._get_remote_server(self)
-    // new_revision = remote_server.updatePayload(requested_update)
-    // if new_revision == 0:
-    // raise IUUpdateFailedError(self)
-    // else:
-    // self._revision = new_revision
+
     @Override
     void modifyLinks(boolean isDelta, SetMultimap<String, String> linksToAdd, SetMultimap<String, String> linksToRemove, String writerName)
     {
diff --git a/ipaacalib/java/src/ipaaca/util/Blackboard.java b/ipaacalib/java/src/ipaaca/util/Blackboard.java
new file mode 100644
index 0000000000000000000000000000000000000000..789182b44e2174812921d6b3eadf2384f986ed8e
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/util/Blackboard.java
@@ -0,0 +1,129 @@
+package ipaaca.util;
+
+import ipaaca.AbstractIU;
+import ipaaca.HandlerFunctor;
+import ipaaca.IUEventType;
+import ipaaca.InputBuffer;
+import ipaaca.LocalIU;
+import ipaaca.OutputBuffer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A simple key-value blackboard
+ * @author hvanwelbergen
+ */
+public class Blackboard
+{
+    private final OutputBuffer outBuffer;
+    private final InputBuffer inBuffer;
+    private final LocalIU iu;
+    private final ComponentNotifier notifier;
+    private static final String DUMMY_KEY = "DUMMY_KEY";
+    public static final String MESSAGE_SUFFIX = "MESSAGE";
+    private int dummyValue = 0;
+    private List<BlackboardUpdateListener> listeners = Collections.synchronizedList(new ArrayList<BlackboardUpdateListener>());
+
+    public Blackboard(String id, String category)
+    {
+        this(id, category, "default");
+    }
+
+    private void updateListeners()
+    {
+        synchronized (listeners)
+        {
+            for (BlackboardUpdateListener listener : listeners)
+            {
+                listener.update();
+            }
+        }
+    }
+    public Blackboard(String id, String category, String channel)
+    {
+        outBuffer = new OutputBuffer(id, channel);
+        iu = new LocalIU(category);
+        outBuffer.add(iu);
+        outBuffer.registerHandler(new HandlerFunctor()
+        {
+            @Override
+            public void handle(AbstractIU iu, IUEventType type, boolean local)
+            {
+                updateListeners();
+            }
+        });
+        inBuffer = new InputBuffer(id, ImmutableSet.of(ComponentNotifier.NOTIFY_CATEGORY, category + MESSAGE_SUFFIX), channel);
+        notifier = new ComponentNotifier(id, category, ImmutableSet.of(category), new HashSet<String>(), outBuffer, inBuffer);
+        notifier.addNotificationHandler(new HandlerFunctor()
+        {
+            @Override
+            public void handle(AbstractIU iuNotify, IUEventType type, boolean local)
+            {
+                dummyValue++;
+                iu.getPayload().put(DUMMY_KEY, "" + dummyValue);
+            }
+        });
+        notifier.initialize();
+        inBuffer.registerHandler(new HandlerFunctor()
+        {
+            @Override
+            public void handle(AbstractIU iuMessage, IUEventType type, boolean local)
+            {
+                iu.getPayload().putAll(iuMessage.getPayload());
+                updateListeners();
+            }
+        }, ImmutableSet.of(category + MESSAGE_SUFFIX));
+    }
+
+    public String put(String key, String value)
+    {
+        return iu.getPayload().put(key, value);
+    }
+
+    public void putAll(Map<String, String> newItems)
+    {
+        iu.getPayload().putAll(newItems);
+    }
+
+    /**
+     * Get the value corresponding to the key, or null if it is not available
+     */
+    public String get(String key)
+    {
+        return iu.getPayload().get(key);
+    }
+
+    public void addUpdateListener(BlackboardUpdateListener listener)
+    {
+        listeners.add(listener);
+    }
+
+    public Set<String> keySet()
+    {
+        return iu.getPayload().keySet();
+    }
+
+    public Set<Map.Entry<String, String>> entrySet()
+    {
+        return iu.getPayload().entrySet();
+    }
+
+    public Collection<String> values()
+    {
+        return iu.getPayload().values();
+    }
+
+    public void close()
+    {
+        outBuffer.close();
+        inBuffer.close();
+    }
+}
diff --git a/ipaacalib/java/src/ipaaca/util/BlackboardClient.java b/ipaacalib/java/src/ipaaca/util/BlackboardClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f70e78f922a289a29e2214b3861a0466755a063
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/util/BlackboardClient.java
@@ -0,0 +1,129 @@
+package ipaaca.util;
+
+import ipaaca.AbstractIU;
+import ipaaca.HandlerFunctor;
+import ipaaca.IUEventType;
+import ipaaca.InputBuffer;
+import ipaaca.LocalMessageIU;
+import ipaaca.OutputBuffer;
+import ipaaca.protobuf.Ipaaca.IU;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Client to get/set key value pairs on a Blackboard
+ * @author hvanwelbergen
+ *
+ */
+public class BlackboardClient
+{
+    private final InputBuffer inBuffer;
+    private final OutputBuffer outBuffer;
+    private List<BlackboardUpdateListener> listeners = Collections.synchronizedList(new ArrayList<BlackboardUpdateListener>());
+    private final String category;
+    
+    public BlackboardClient(String id, String category)
+    {
+        this(id, category, "default");
+    }
+
+    public BlackboardClient(String id, String category, String channel)
+    {
+        this.category = category;
+        inBuffer = new InputBuffer(id, ImmutableSet.of(category, ComponentNotifier.NOTIFY_CATEGORY), channel);
+        inBuffer.setResendActive(true);
+        inBuffer.registerHandler(new HandlerFunctor()
+        {
+            @Override
+            public void handle(AbstractIU iu, IUEventType type, boolean local)
+            {
+                synchronized (listeners)
+                {
+                    for (BlackboardUpdateListener listener : listeners)
+                    {
+                        listener.update();
+                    }
+                }
+            }
+        }, ImmutableSet.of(category));
+        outBuffer = new OutputBuffer(id);
+        ComponentNotifier notifier = new ComponentNotifier(id, category, new HashSet<String>(), ImmutableSet.of(category),
+                outBuffer, inBuffer);
+        notifier.initialize();
+    }
+
+    public void close()
+    {
+        inBuffer.close();
+        outBuffer.close();
+    }
+    
+    public void waitForBlackboardConnection()
+    {
+        while(inBuffer.getIUs().isEmpty());        
+    }
+    
+    public String get(String key)
+    {
+        if (inBuffer.getIUs().isEmpty())
+        {
+            return null;
+        }
+        return inBuffer.getIUs().iterator().next().getPayload().get(key);
+    }
+
+    public void put(String key, String value)
+    {
+        LocalMessageIU iu = new LocalMessageIU(category+Blackboard.MESSAGE_SUFFIX);
+        iu.getPayload().put(key,value);
+        outBuffer.add(iu);
+    }
+    
+    public void putAll(Map<String,String> values)
+    {
+        LocalMessageIU iu = new LocalMessageIU(category+Blackboard.MESSAGE_SUFFIX);
+        iu.getPayload().putAll(values);
+        outBuffer.add(iu);
+    }
+    
+    private boolean hasIU()
+    {
+        return !inBuffer.getIUs().isEmpty();
+    }
+    
+    private AbstractIU getIU()
+    {
+        return inBuffer.getIUs().iterator().next();
+    }
+    
+    public Set<String> keySet()
+    {
+        if(!hasIU())return new HashSet<>();
+        return getIU().getPayload().keySet();
+    }
+
+    public Set<Map.Entry<String, String>> entrySet()
+    {
+        if(!hasIU())return new HashSet<>();
+        return getIU().getPayload().entrySet();
+    }
+
+    public Collection<String> values()
+    {
+        if(!hasIU())return new HashSet<>();
+        return getIU().getPayload().values();
+    }
+    
+    public void addUpdateListener(BlackboardUpdateListener listener)
+    {
+        listeners.add(listener);
+    }
+}
diff --git a/ipaacalib/java/src/ipaaca/util/BlackboardUpdateListener.java b/ipaacalib/java/src/ipaaca/util/BlackboardUpdateListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1ebdde021533542463fdea4e5a3a20534d0fba4
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/util/BlackboardUpdateListener.java
@@ -0,0 +1,6 @@
+package ipaaca.util;
+
+public interface BlackboardUpdateListener
+{
+    void update();
+}
diff --git a/ipaacalib/java/src/ipaacademo/TestListener.java b/ipaacalib/java/src/ipaacademo/TestListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..4759207badc3fc5c609ca5f9c61949af0c4c3d7c
--- /dev/null
+++ b/ipaacalib/java/src/ipaacademo/TestListener.java
@@ -0,0 +1,125 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2013 Sociable Agents Group
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+package ipaacademo;
+
+import ipaaca.AbstractIU;
+import ipaaca.HandlerFunctor;
+import ipaaca.IUEventHandler;
+import ipaaca.IUEventType;
+import ipaaca.Initializer;
+import ipaaca.InputBuffer;
+import ipaaca.OutputBuffer;
+import ipaaca.RemotePushIU;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+
+import com.google.common.collect.ImmutableSet;
+
+public class TestListener
+{
+
+    private static final class MyEventHandler implements HandlerFunctor
+    {
+        @Override
+        public void handle(AbstractIU iu, IUEventType type, boolean local)
+        {
+            switch(type)
+            {
+            case ADDED:  System.out.println("IU added "+iu.getPayload().get("CONTENT"));  break;
+            case COMMITTED: System.out.println("IU committed");  break;
+            case UPDATED: System.out.println("IU updated "+iu.getPayload()); break;
+            case LINKSUPDATED: System.out.println("IU links updated"); break;
+            case RETRACTED: break;
+            case DELETED: break;
+            }
+        }
+
+    }
+
+    static
+    {
+        Initializer.initializeIpaacaRsb();
+    }
+
+    private static final String CATEGORY = "spam";
+    private static final double RATE = 0.5;
+    private UpdateThread updateThread;
+
+    public TestListener()
+    {
+        Set<String> categories = new ImmutableSet.Builder<String>().add(CATEGORY).build();
+        JLabel label = new JLabel("");
+
+        updateThread = new UpdateThread(new InputBuffer("TestListener", categories),label);
+    }
+
+    public void start()
+    {
+        updateThread.start();
+    }
+
+    private static class UpdateThread extends Thread
+    {
+        private InputBuffer inBuffer;
+        private JLabel label;
+
+        public UpdateThread(InputBuffer inBuffer, JLabel label)
+        {
+            this.inBuffer = inBuffer;
+            this.label = label;
+
+            EnumSet<IUEventType> types = EnumSet.of(IUEventType.ADDED,IUEventType.COMMITTED,IUEventType.UPDATED,IUEventType.LINKSUPDATED);
+            Set<String> categories = new ImmutableSet.Builder<String>().add(CATEGORY).build();
+            MyEventHandler printingEventHandler;
+            printingEventHandler = new MyEventHandler();
+            this.inBuffer.registerHandler(new IUEventHandler(printingEventHandler,types,categories));
+        }
+
+        @Override
+        public void run()
+        {
+        	System.out.println("Starting!");
+        }
+
+    }
+
+    public static void main(String args[])
+    {
+        TestListener tl = new TestListener();
+        tl.start();
+    }
+}
diff --git a/ipaacalib/java/src/ipaacademo/TextPrinter.java b/ipaacalib/java/src/ipaacademo/TextPrinter.java
index 13ef1a1fd287649b1d82c211eb910cca308f00dd..5161ad3b7eb1c91ea02e23f4c0f6ccb4399ef500 100644
--- a/ipaacalib/java/src/ipaacademo/TextPrinter.java
+++ b/ipaacalib/java/src/ipaacademo/TextPrinter.java
@@ -222,7 +222,8 @@ public class TextPrinter
         TextPrinter tp = new TextPrinter();        
         
         
-        OutputBuffer outBuffer = new OutputBuffer("componentX");
+        //OutputBuffer outBuffer = new OutputBuffer("componentX");
+
         /*String[] inputString = {"h","e","l","l","o"," ","w","o","r","l","d","!"};
         LocalIU predIU = null;        
         for(String str:inputString)
diff --git a/ipaacalib/java/test/src/ipaaca/InputBufferTest.java b/ipaacalib/java/test/src/ipaaca/InputBufferTest.java
index d0ff20a710a44ca5da7b8cce805cc7e86f9223d8..420a3687480cc2f0a2dbc2f425ac83f163858907 100644
--- a/ipaacalib/java/test/src/ipaaca/InputBufferTest.java
+++ b/ipaacalib/java/test/src/ipaaca/InputBufferTest.java
@@ -22,7 +22,7 @@ import com.google.common.collect.ImmutableSet;
 public class InputBufferTest
 {
     private static final String COMPID = "Comp1";
-    private static final String CATEGORY = "category1";
+    private static final String CATEGORY = "testcat";
     private InputBuffer inBuffer;
 
 
@@ -47,10 +47,10 @@ public class InputBufferTest
     @Test
     public void testHandleRemotePushEvent() throws RSBException, InterruptedException
     {
-        Informer<Object> informer = Factory.getInstance().createInformer("/ipaaca/category/"+CATEGORY);
+        Informer<Object> informer = Factory.getInstance().createInformer("/ipaaca/channel/default/category/"+CATEGORY);
         informer.activate();
         RemotePushIU iu = new RemotePushIU("uid1");
-        iu.setCategory("/ipaaca/category/"+CATEGORY);
+        iu.setCategory("/ipaaca/channel/default/category/"+CATEGORY);
         iu.setOwnerName("owner");
         iu.setReadOnly(false);
         iu.setRevision(1);
diff --git a/ipaacalib/java/test/src/ipaaca/util/BlackboardIntegrationTest.java b/ipaacalib/java/test/src/ipaaca/util/BlackboardIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..afd10b00ea0b3b18536bdfa6430c40d3f2bdd48a
--- /dev/null
+++ b/ipaacalib/java/test/src/ipaaca/util/BlackboardIntegrationTest.java
@@ -0,0 +1,129 @@
+package ipaaca.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import ipaaca.Initializer;
+
+import org.junit.After;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Integration tests for the blackboard
+ * @author hvanwelbergen
+ */
+public class BlackboardIntegrationTest
+{
+    static
+    {
+        Initializer.initializeIpaacaRsb();
+    }
+    
+    private Blackboard bb = new Blackboard("myblackboard","blackboardx");
+    private BlackboardClient bbc;
+    
+    @After
+    public void after()
+    {
+        bb.close();
+        if(bbc!=null)
+        {
+            bbc.close();
+        }
+    }
+    
+    @Test
+    public void testGetValueFromBlackboardBeforeConnection()
+    {
+        bb.put("key1","value1");
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        assertEquals("value1", bbc.get("key1"));        
+    }
+    
+    @Test
+    public void testGetValueFromBlackboardAfterConnection() throws InterruptedException
+    {
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        bb.put("key1","value1");
+        Thread.sleep(200);
+        assertEquals("value1", bbc.get("key1"));        
+    }
+    
+    @Test
+    public void testSetValueOnBlackboard() throws InterruptedException
+    {
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        bbc.put("key2","value2");
+        Thread.sleep(300);
+        assertEquals("value2", bb.get("key2"));        
+    }
+    
+    @Test
+    public void testBlackboardUpdateHandler()throws InterruptedException
+    {
+        BlackboardUpdateListener mockListener = mock(BlackboardUpdateListener.class);
+        bb.addUpdateListener(mockListener);
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        bbc.put("key2","value2");
+        Thread.sleep(200);
+        bb.put("key2","value3");
+        verify(mockListener,times(1)).update();
+    }
+    
+    @Test
+    public void testBlackboardClientUpdateHandler() throws InterruptedException
+    {
+        BlackboardUpdateListener mockListener = mock(BlackboardUpdateListener.class);
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        bbc.addUpdateListener(mockListener);
+        bb.put("key3","value3");
+        Thread.sleep(200);
+        bbc.put("key3","value4");
+        verify(mockListener,times(2)).update();
+    }
+    
+    @Test
+    public void testSetManyValuesOnBlackboard() throws InterruptedException
+    {
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        for(int i=0;i<100;i++)
+        {
+            bbc.put("key"+i,"value"+i);
+            bb.put("key"+i,"value"+i);
+        }
+        Thread.sleep(300);
+        assertEquals("value2", bb.get("key2"));        
+        assertEquals("value3", bb.get("key3"));
+    }
+    
+    @Test
+    public void testSetValuesOnClient() throws InterruptedException
+    {
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        bbc.putAll(ImmutableMap.of("key1","value1","key2","value2"));
+        Thread.sleep(200);
+        assertEquals("value1", bb.get("key1"));        
+        assertEquals("value2", bb.get("key2"));
+    }
+    
+    @Test
+    public void testSetValuesOnBlackBoard() throws InterruptedException
+    {
+        bbc = new BlackboardClient("myblackboardclient","blackboardx");
+        bbc.waitForBlackboardConnection();
+        bb.putAll(ImmutableMap.of("key1","value1","key2","value2"));
+        Thread.sleep(200);
+        assertEquals("value1", bbc.get("key1"));        
+        assertEquals("value2", bbc.get("key2"));
+    }
+}
diff --git a/ipaacalib/java/test/src/ipaaca/util/ComponentNotifierIntegrationTest.java b/ipaacalib/java/test/src/ipaaca/util/ComponentNotifierIntegrationTest.java
index aef0e5ae662d6c3b16c384b2980e6b41bb7013b3..5acbed6b861d6ae736a65ac4d01702d25e0cb1af 100644
--- a/ipaacalib/java/test/src/ipaaca/util/ComponentNotifierIntegrationTest.java
+++ b/ipaacalib/java/test/src/ipaaca/util/ComponentNotifierIntegrationTest.java
@@ -1,21 +1,22 @@
 package ipaaca.util;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import ipaaca.AbstractIU;
 import ipaaca.HandlerFunctor;
 import ipaaca.IUEventType;
 import ipaaca.Initializer;
 import ipaaca.InputBuffer;
+import ipaaca.LocalIU;
 import ipaaca.OutputBuffer;
-import ipaaca.util.ComponentNotifier;
 
 import java.util.Set;
 
+import lombok.Getter;
+
 import org.junit.After;
 import org.junit.Test;
 
-import lombok.Getter;
-
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -29,7 +30,7 @@ public class ComponentNotifierIntegrationTest
     private ComponentNotifier notifier2;
     private InputBuffer inBuffer;
     private OutputBuffer outBuffer;
-
+    private static final String OTHER_CATEGORY="OTHER";
     static
     {
         Initializer.initializeIpaacaRsb();
@@ -67,6 +68,13 @@ public class ComponentNotifierIntegrationTest
         return new ComponentNotifier(id, "test", ImmutableSet.copyOf(sendList), ImmutableSet.copyOf(recvList), outBuffer, inBuffer);
     }
 
+    private ComponentNotifier setupCompNotifierWithOtherCategoryInputBuffer(String id, Set<String> sendList, Set<String> recvList)
+    {
+        inBuffer = new InputBuffer(id + "in", ImmutableSet.of(ComponentNotifier.NOTIFY_CATEGORY, OTHER_CATEGORY));
+        outBuffer = new OutputBuffer(id + "out");
+        return new ComponentNotifier(id, "test", ImmutableSet.copyOf(sendList), ImmutableSet.copyOf(recvList), outBuffer, inBuffer);
+    }
+    
     @Test
     public void testSelf() throws InterruptedException
     {
@@ -97,4 +105,19 @@ public class ComponentNotifierIntegrationTest
         assertEquals(1, h1.getNumCalled());
         assertEquals(1, h2.getNumCalled());
     }
+    
+    @Test
+    public void testOtherCategoryInInputBuffer() throws InterruptedException
+    {
+        notifier1 = setupCompNotifierWithOtherCategoryInputBuffer("not1", ImmutableSet.of("a1", "b1"), ImmutableSet.of("a3", "b1"));
+        MyHandlerFunctor h1 = new MyHandlerFunctor();
+        notifier1.addNotificationHandler(h1);
+        
+        OutputBuffer out = new OutputBuffer("out");
+        LocalIU iu = new LocalIU(OTHER_CATEGORY);
+        out.add(iu);
+        Thread.sleep(500);
+        assertEquals(0, h1.getNumCalled());
+        assertNotNull(inBuffer.getIU(iu.getUid()));
+    }
 }
diff --git a/ipaacalib/proto/ipaaca.proto b/ipaacalib/proto/ipaaca.proto
index 7288dc84a0f8dcef4689166b26571c2d936c6200..c0e1d1d196c31a34d05aaf18996bc7c1f9480d6d 100755
--- a/ipaacalib/proto/ipaaca.proto
+++ b/ipaacalib/proto/ipaaca.proto
@@ -2,7 +2,7 @@
 //  "Incremental Processing Architecture
 //   for Artificial Conversational Agents".	
 //
-// Copyright (c) 2009-2013 Sociable Agents Group
+// Copyright (c) 2009-2014 Social Cognitive Systems Group
 //                         CITEC, Bielefeld University	
 //
 // http://opensource.cit-ec.de/projects/ipaaca/
@@ -84,6 +84,11 @@ message IUCommission {
 	required string writer_name = 3;
 }
 
+message IUResendRequest {
+	required string uid = 1;
+	required string hidden_scope_name = 2;
+}
+
 message IULinkUpdate {
 	required string uid = 1;
 	required uint32 revision = 2;
@@ -92,5 +97,3 @@ message IULinkUpdate {
 	required bool is_delta = 5 [default = false];
 	required string writer_name = 6;
 }
-
-
diff --git a/ipaacalib/python/ivy.xml b/ipaacalib/python/ivy.xml
index 1b948cd692f7b7df1b4aeaf22f200435e5f498b5..e559706ba1ca9a0010dc3d0d75e8218907fe1278 100644
--- a/ipaacalib/python/ivy.xml
+++ b/ipaacalib/python/ivy.xml
@@ -10,3 +10,4 @@
    </dependencies>
 
 </ivy-module>
+
diff --git a/ipaacalib/python/src/ipaaca/__init__.py b/ipaacalib/python/src/ipaaca/__init__.py
index db2f873b9ca7f6405ba6ba4ba8a27b61f0a3f29d..09321c0bd26070239ee9a44f354e62d5f40eeaff 100755
--- a/ipaacalib/python/src/ipaaca/__init__.py
+++ b/ipaacalib/python/src/ipaaca/__init__.py
@@ -2,10 +2,10 @@
 
 # This file is part of IPAACA, the
 #  "Incremental Processing Architecture
-#   for Artificial Conversational Agents".	
+#   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2013 Sociable Agents Group
-#                         CITEC, Bielefeld University	
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
 # http://purl.org/net/ipaaca
@@ -22,7 +22,7 @@
 # You should have received a copy of the LGPL along with this
 # program. If not, go to http://www.gnu.org/licenses/lgpl.html
 # or write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.	
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #
 # The development of this software was supported by the
 # Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -30,1590 +30,60 @@
 # Forschungsgemeinschaft (DFG) in the context of the German
 # Excellence Initiative.
 
-from __future__ import print_function, division
-
-import logging
-import sys
-import threading
-import uuid
-import collections
-import copy
-import time
+from __future__ import division, print_function
 
 import rsb
 import rsb.converter
 
 import ipaaca_pb2
+import ipaaca.converter
+from ipaaca.buffer import InputBuffer, OutputBuffer
+from ipaaca.exception import *
+from ipaaca.iu import IU, Message, IUAccessMode, IUEventType 
+from ipaaca.misc import enable_logging, IpaacaArgumentParser
+from ipaaca.payload import Payload
 
-_DEFAULT_PAYLOAD_UPDATE_TIMEOUT = 0.1
-
-# IDEAS
-#  We should think about relaying the update event (or at least the
-#  affected keys in the payload / links) to the event handlers!
-
-# THOUGHTS
-#  Output buffers could generate UIDs for IUs on request, without
-#  publishing them at that time. Then UID could then be used
-#  for internal links etc. The IU may be published later through
-#  the same buffer that allocated the UID.
-
-# WARNINGS
-#  category is now the FIRST argument for IU constructors
-
-__all__ = [
-	'IUEventType',
-	'IUAccessMode',
-	'InputBuffer', 'OutputBuffer',
-	'IU',
-	'IUPublishedError', 'IUUpdateFailedError', 'IUCommittedError', 'IUReadOnlyError', 'IUNotFoundError',
-	'logger'
-]
-
-
-## --- Utilities -------------------------------------------------------------
-
-
-def enum(*sequential, **named):
-	"""Create an enum type.
-	
-	Based on suggestion of Alec Thomas on stackoverflow.com:
-	http://stackoverflow.com/questions/36932/
-		whats-the-best-way-to-implement-an-enum-in-python/1695250#1695250
-	"""
-	enums = dict(zip(sequential, range(len(sequential))), **named)
-	return type('Enum', (), enums)
-
-
-def pack_typed_payload_item(protobuf_object, key, value):
-	protobuf_object.key = key
-	protobuf_object.value = value
-	protobuf_object.type = 'str' # TODO: more types
-
-
-def unpack_typed_payload_item(protobuf_object):
-	# TODO: more types
-	return (protobuf_object.key, protobuf_object.value)
-
-
-class IpaacaLoggingHandler(logging.Handler):
-	
-	def __init__(self, level=logging.DEBUG):
-		logging.Handler.__init__(self, level)
-	
-	def emit(self, record):
-		meta = '[ipaaca] (' + str(record.levelname) + ') ' 
-		msg = str(record.msg.format(record.args))
-		print(meta + msg)
-
-
-## --- Global Definitions ----------------------------------------------------
-
-
-IUEventType = enum(
-	ADDED = 'ADDED',
-	COMMITTED = 'COMMITTED',
-	DELETED = 'DELETED',
-	RETRACTED = 'RETRACTED',
-	UPDATED = 'UPDATED',
-	LINKSUPDATED = 'LINKSUPDATED',
-	MESSAGE = 'MESSAGE'
-)
-
-
-IUAccessMode = enum(
-	"PUSH",
-	"REMOTE",
-	"MESSAGE"
-)
-
-
-## --- Errors and Exceptions -------------------------------------------------
-
-
-class IUPublishedError(Exception):
-	"""Error publishing of an IU failed since it is already in the buffer."""
-	def __init__(self, iu):
-		super(IUPublishedError, self).__init__('IU ' + str(iu.uid) + ' is already present in the output buffer.')
-
-
-class IUUpdateFailedError(Exception):
-	"""Error indicating that a remote IU update failed."""
-	def __init__(self, iu):
-		super(IUUpdateFailedError, self).__init__('Remote update failed for IU ' + str(iu.uid) + '.')
-
-
-class IUCommittedError(Exception):
-	"""Error indicating that an IU is immutable because it has been committed to."""
-	def __init__(self, iu):
-		super(IUCommittedError, self).__init__('Writing to IU ' + str(iu.uid) + ' failed -- it has been committed to.')
-
-
-class IUReadOnlyError(Exception):
-	"""Error indicating that an IU is immutable because it is 'read only'."""
-	def __init__(self, iu):
-		super(IUReadOnlyError, self).__init__('Writing to IU ' + str(iu.uid) + ' failed -- it is read-only.')
-
-class IUNotFoundError(Exception):
-	"""Error indicating that an IU UID was unexpectedly not found in an internal store."""
-	def __init__(self, iu_uid):
-		super(IUNotFoundError, self).__init__('Lookup of IU ' + str(iu_uid) + ' failed.')
-
-class IUPayloadLockTimeoutError(Exception):
-	"""Error indicating that exclusive access to the Payload could not be obtained in time."""
-	def __init__(self, iu):
-		super(IUPayloadLockTimeoutError, self).__init__('Timeout while accessing payload of IU ' + str(iu.uid) + '.')
-
-class IUPayloadLockedError(Exception):
-	"""Error indicating that exclusive access to the Payload could not be obtained because someone actually locked it."""
-	def __init__(self, iu):
-		super(IUPayloadLockedError, self).__init__('IU '+str(iu.uid)+' was locked during access attempt.')
-
-
-## --- Generation Architecture -----------------------------------------------
-
-class Payload(dict):
-	def __init__(self, iu, writer_name=None, new_payload=None, omit_init_update_message=False, update_timeout=_DEFAULT_PAYLOAD_UPDATE_TIMEOUT):
-		self.iu = iu
-		pl1 = {} if new_payload is None else new_payload
-		pl = {}
-		for k,v in pl1.items():
-			if type(k)==str:
-				k=unicode(k,'utf8')
-			if type(v)==str:
-				v=unicode(v,'utf8')
-			pl[k] = v
-		# NOTE omit_init_update_message is necessary to prevent checking for
-		#   exceptions and sending updates in the case where we just receive
-		#   a whole new payload from the remote side and overwrite it locally.
-		for k, v in pl.items():
-			dict.__setitem__(self, k, v)
-		if (not omit_init_update_message) and (self.iu.buffer is not None):
-			self.iu._modify_payload(is_delta=False, new_items=pl, keys_to_remove=[], writer_name=writer_name)
-		self._update_on_every_change = True
-		self._collected_modifications = {}
-		self._collected_removals = []
-		self._update_timeout = update_timeout
-		self._batch_update_writer_name = None  # name of remote buffer or None
-		self._batch_update_lock = threading.RLock()
-		self._batch_update_cond = threading.Condition(threading.RLock())
-
-	def merge(self, payload, writer_name=None):
-		self._batch_update_lock.acquire(True)
-		#if not self._batch_update_lock.acquire(False):
-		#	print('Someone failed a lock trying to merge '+str(payload.keys()))
-		#	raise IUPayloadLockedError(self.iu)
-		#print("Payload.merge() IN, Merging "+str(payload.keys()))
-		for k, v in payload.items():
-			if type(k)==str:
-				k=unicode(k,'utf8')
-			if type(v)==str:
-				v=unicode(v,'utf8')
-		self.iu._modify_payload(is_delta=True, new_items=payload, keys_to_remove=[], writer_name=writer_name)
-		r = dict.update(payload) # batch update
-		#print("Payload.merge() OUT")
-		self._batch_update_lock.release()
-		return r
-
-	def __setitem__(self, k, v, writer_name=None):
-		self._batch_update_lock.acquire(True)
-		#if not self._batch_update_lock.acquire(False):
-		#	print('Someone failed a lock trying to set '+k+' to '+v)
-		#	raise IUPayloadLockedError(self.iu)
-		#print("Payload.__setitem__() IN, Setting "+k+' to '+v)
-		#print("  by writer "+str(writer_name))
-		if type(k)==str:
-			k=unicode(k,'utf8')
-		if type(v)==str:
-			v=unicode(v,'utf8')
-		if self._update_on_every_change:
-			#print("  running _modify_payload with writer name "+str(writer_name))
-			self.iu._modify_payload(is_delta=True, new_items={k:v}, keys_to_remove=[], writer_name=writer_name)
-		else: # Collect additions/modifications
-			self._batch_update_writer_name = writer_name
-			self._collected_modifications[k] = v
-		r = dict.__setitem__(self, k, v)
-		#print("Payload.__setitem__() OUT")
-		self._batch_update_lock.release()
-		return r
-
-	def __delitem__(self, k, writer_name=None):
-		self._batch_update_lock.acquire(True)
-		#if not self._batch_update_lock.acquire(False):
-		#	print('Someone failed a lock trying to del '+k)
-		#	raise IUPayloadLockedError(self.iu)
-		#print("Payload.__delitem__() IN, Deleting "+k)
-		if type(k)==str:
-			k=unicode(k,'utf8')
-		if self._update_on_every_change:
-			self.iu._modify_payload(is_delta=True, new_items={}, keys_to_remove=[k], writer_name=writer_name)
-		else: # Collect additions/modifications
-			self._batch_update_writer_name = writer_name
-			self._collected_removals.append(k)
-		r = dict.__delitem__(self, k)
-		#print("Payload.__delitem__() OUT")
-		self._batch_update_lock.release()
-		return r
-	
-	# Context-manager based batch updates, not yet thread-safe (on remote updates)	
-	def __enter__(self):
-		#print('running Payload.__enter__()')
-		self._wait_batch_update_lock(self._update_timeout)
-		self._update_on_every_change = False
-	
-	def __exit__(self, type, value, traceback):
-		#print('running Payload.__exit__()')
-		self.iu._modify_payload(is_delta=True, new_items=self._collected_modifications, keys_to_remove=self._collected_removals, writer_name=self._batch_update_writer_name)
-		self._collected_modifications = {}
-		self._collected_removals = []
-		self._update_on_every_change = True
-		self._batch_update_writer_name = None
-		self._batch_update_lock.release()
-
-	def _remotely_enforced_setitem(self, k, v):
-		"""Sets an item when requested remotely."""
-		return dict.__setitem__(self, k, v)
-
-	def _remotely_enforced_delitem(self, k):
-		"""Deletes an item when requested remotely."""
-		return dict.__delitem__(self, k)
-
-	def _wait_batch_update_lock(self, timeout):
-		# wait lock with time-out http://stackoverflow.com/a/8393033
-		with self._batch_update_cond:
-			current_time = start_time = time.time()
-			while current_time < start_time + timeout:
-				if self._batch_update_lock.acquire(False):
-					return True
-				else:
-					self._batch_update_cond.wait(timeout - current_time + start_time)
-					current_time = time.time()
-		raise IUPayloadLockTimeoutError(self.iu)
-
-
-class IUInterface(object): #{{{
-	
-	"""Base class of all specialised IU classes."""
-	
-	def __init__(self, uid, access_mode=IUAccessMode.PUSH, read_only=False):
-		"""Creates an IU.
-		
-		Keyword arguments:
-		uid -- unique ID of this IU
-		access_mode -- access mode of this IU
-		read_only -- flag indicating whether this IU is read_only or not
-		"""
-		self._uid = uid
-		self._revision = None
-		self._category = None
-		self._payload_type = None
-		self._owner_name = None
-		self._committed = False
-		self._retracted = False
-		self._access_mode = access_mode
-		self._read_only = read_only
-		self._buffer = None
-		# payload is not present here
-		self._links = collections.defaultdict(set)
-	
-	def __str__(self):
-		s = unicode(self.__class__)+"{ "
-		s += "category="+("<None>" if self._category is None else self._category)+" "
-		s += "uid="+self._uid+" "
-		s += "(buffer="+(self.buffer.unique_name if self.buffer is not None else "<None>")+") "
-		s += "owner_name=" + ("<None>" if self.owner_name is None else self.owner_name) + " "
-		s += "payload={ "
-		for k,v in self.payload.items():
-			s += k+":'"+v+"', "
-		s += "} "
-		s += "links={ "
-		for t,ids in self.get_all_links().items():
-			s += t+":'"+str(ids)+"', "
-		s += "} "
-		s += "}"
-		return s
-	
-	
-	def _add_and_remove_links(self, add, remove):
-		'''Just add and remove the new links in our links set, do not send an update here'''
-		'''Note: Also used for remotely enforced links updates.'''
-		for type in remove.keys(): self._links[type] -= set(remove[type])
-		for type in add.keys(): self._links[type] |= set(add[type])
-	def _replace_links(self, links):
-		'''Just wipe and replace our links set, do not send an update here'''
-		'''Note: Also used for remotely enforced links updates.'''
-		self._links = collections.defaultdict(set)
-		for type in links.keys(): self._links[type] |= set(links[type])
-		
-	def add_links(self, type, targets, writer_name=None):
-		'''Attempt to add links if the conditions are met
-		and send an update message. Then call the local setter.'''
-		if not hasattr(targets, '__iter__'): targets=[targets]
-		self._modify_links(is_delta=True, new_links={type:targets}, links_to_remove={}, writer_name=writer_name)
-		self._add_and_remove_links( add={type:targets}, remove={} )
-	def remove_links(self, type, targets, writer_name=None):
-		'''Attempt to remove links if the conditions are met
-		and send an update message. Then call the local setter.'''
-		if not hasattr(targets, '__iter__'): targets=[targets]
-		self._modify_links(is_delta=True, new_links={}, links_to_remove={type:targets}, writer_name=writer_name)
-		self._add_and_remove_links( add={}, remove={type:targets} )
-	def modify_links(self, add, remove, writer_name=None):
-		'''Attempt to modify links if the conditions are met
-		and send an update message. Then call the local setter.'''
-		self._modify_links(is_delta=True, new_links=add, links_to_remove=remove, writer_name=writer_name)
-		self._add_and_remove_links( add=add, remove=remove )
-	def set_links(self, links, writer_name=None):
-		'''Attempt to set (replace) links if the conditions are met
-		and send an update message. Then call the local setter.'''
-		self._modify_links(is_delta=False, new_links=links, links_to_remove={}, writer_name=writer_name)
-		self._replace_links( links=links )
-	def get_links(self, type):
-		return set(self._links[type])
-	def get_all_links(self):
-		return copy.deepcopy(self._links)
-	
-	def _get_revision(self):
-		return self._revision
-	revision = property(fget=_get_revision, doc='Revision number of the IU.')
-	
-	def _get_category(self):
-		return self._category
-	category = property(fget=_get_category, doc='Category of the IU.')
-	
-	def _get_payload_type(self):
-		return self._payload_type
-	payload_type = property(fget=_get_payload_type, doc='Type of the IU payload')
-	
-	def _get_committed(self):
-		return self._committed
-	committed = property(
-			fget=_get_committed,
-			doc='Flag indicating whether this IU has been committed to.')
-	
-	def _get_retracted(self):
-		return self._retracted
-	retracted = property(
-			fget=_get_retracted,
-			doc='Flag indicating whether this IU has been retracted.')
-	
-	def _get_uid(self):
-		return self._uid
-	uid = property(fget=_get_uid, doc='Unique ID of the IU.')
-	
-	def _get_access_mode(self):
-		return self._access_mode
-	access_mode = property(fget=_get_access_mode, doc='Access mode of the IU.')
-	
-	def _get_read_only(self):
-		return self._read_only
-	read_only = property(
-			fget=_get_read_only, 
-			doc='Flag indicating whether this IU is read only.')
-	
-	def _get_buffer(self):
-		return self._buffer
-	def _set_buffer(self, buffer):
-		if self._buffer is not None:
-			raise Exception('The IU is already in a buffer, cannot move it.')
-		self._buffer = buffer
-	buffer = property(
-			fget=_get_buffer,
-			fset=_set_buffer, 
-			doc='Buffer this IU is held in.')
-	
-	def _get_owner_name(self):
-		return self._owner_name
-	def _set_owner_name(self, owner_name):
-		if self._owner_name is not None:
-			raise Exception('The IU already has an owner name, cannot change it.')
-		self._owner_name = owner_name
-	owner_name = property(
-			fget=_get_owner_name,
-			fset=_set_owner_name,
-			doc="The IU's owner's name.")
-#}}}
-
-class IU(IUInterface):#{{{
-
-	"""A local IU."""
-
-	def __init__(self, category='undef', access_mode=IUAccessMode.PUSH, read_only=False, _payload_type='MAP'):
-		super(IU, self).__init__(uid=None, access_mode=access_mode, read_only=read_only)
-		self._revision = 1
-		self.uid = str(uuid.uuid4())
-		self._category = category
-		self._payload_type = _payload_type
-		self.revision_lock = threading.RLock()
-		self._payload = Payload(iu=self)
-	
-	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
-		if self.committed:
-			raise IUCommittedError(self)
-		with self.revision_lock:
-			# modify links locally
-			self._increase_revision_number()
-			if self.is_published:
-				# send update to remote holders
-				self.buffer._send_iu_link_update(
-						self,
-						revision=self.revision,
-						is_delta=is_delta,
-						new_links=new_links,
-						links_to_remove=links_to_remove,
-						writer_name=self.owner_name if writer_name is None else writer_name)
-	
-	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
-		"""Modify the payload: add or remove items from this payload locally and send update."""
-		if self.committed:
-			raise IUCommittedError(self)
-		with self.revision_lock:
-			# set item locally
-			# FIXME: Is it actually set locally?
-			self._increase_revision_number()
-			if self.is_published:
-				#print('  _modify_payload: running send_iu_pl_upd with writer name '+str(writer_name))
-				# send update to remote holders
-				self.buffer._send_iu_payload_update(
-						self,
-						revision=self.revision,
-						is_delta=is_delta,
-						new_items=new_items,
-						keys_to_remove=keys_to_remove,
-						writer_name=self.owner_name if writer_name is None else writer_name)
-	
-	def _increase_revision_number(self):
-		self._revision += 1
-	
-	def _internal_commit(self, writer_name=None):
-		if self.committed:
-			raise IUCommittedError(self)
-		with self.revision_lock:
-			if not self._committed:
-				self._increase_revision_number()
-				self._committed = True
-				if self.buffer is not None:
-					self.buffer._send_iu_commission(self, writer_name=writer_name)
-	
-	def commit(self):
-		"""Commit to this IU."""
-		return self._internal_commit()
-	
-	def _get_payload(self):
-		return self._payload
-	def _set_payload(self, new_pl, writer_name=None):
-		if self.committed:
-			raise IUCommittedError(self)
-		with self.revision_lock:
-			self._increase_revision_number()
-			self._payload = Payload(
-					iu=self,
-					writer_name=None if self.buffer is None else (self.buffer.unique_name if writer_name is None else writer_name),
-					new_payload=new_pl)
-	payload = property(
-			fget=_get_payload,
-			fset=_set_payload,
-			doc='Payload dictionary of this IU.')
-	
-	def _get_is_published(self):
-		return self.buffer is not None
-	is_published = property(
-			fget=_get_is_published, 
-			doc='Flag indicating whether this IU has been published or not.')
-	
-	def _set_buffer(self, buffer):
-		if self._buffer is not None:
-			raise Exception('The IU is already in a buffer, cannot move it.')
-		self._buffer = buffer
-		self.owner_name = buffer.unique_name
-		self._payload.owner_name = buffer.unique_name
-	buffer = property(
-			fget=IUInterface._get_buffer,
-			fset=_set_buffer,
-			doc='Buffer this IU is held in.')
-	
-	def _set_uid(self, uid):
-		if self._uid is not None:
-			raise AttributeError('The uid of IU ' + self.uid + ' has already been set, cannot change it.')
-		self._uid = uid
-	uid = property(
-			fget=IUInterface._get_uid,
-			fset=_set_uid,
-			doc='Unique ID of the IU.')
 
-#}}}
-
-class Message(IU):#{{{
-	"""Local IU of Message sub-type. Can be handled like a normal IU, but on the remote side it is only existent during the handler calls."""
-	def __init__(self, category='undef', access_mode=IUAccessMode.MESSAGE, read_only=True, _payload_type='MAP'):
-		super(Message, self).__init__(category=category, access_mode=access_mode, read_only=read_only, _payload_type=_payload_type)
-	
-	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
-		if self.is_published:
-			logger.info('Info: modifying a Message after sending has no global effects')
-	
-	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
-		if self.is_published:
-			logger.info('Info: modifying a Message after sending has no global effects')
-	
-	def _increase_revision_number(self):
-		self._revision += 1
-	
-	def _internal_commit(self, writer_name=None):
-		if self.is_published:
-			logger.info('Info: committing to a Message after sending has no global effects')
-	
-	def commit(self):
-		return self._internal_commit()
-	
-	def _get_payload(self):
-		return self._payload
-	def _set_payload(self, new_pl, writer_name=None):
-		if self.is_published:
-			logger.info('Info: modifying a Message after sending has no global effects')
-		else:
-			if self.committed:
-				raise IUCommittedError(self)
-			with self.revision_lock:
-				self._increase_revision_number()
-				self._payload = Payload(
-						iu=self,
-						writer_name=None if self.buffer is None else (self.buffer.unique_name if writer_name is None else writer_name),
-						new_payload=new_pl)
-	payload = property(
-			fget=_get_payload,
-			fset=_set_payload,
-			doc='Payload dictionary of this IU.')
-	
-	def _get_is_published(self):
-		return self.buffer is not None
-	is_published = property(
-			fget=_get_is_published, 
-			doc='Flag indicating whether this IU has been published or not.')
-	
-	def _set_buffer(self, buffer):
-		if self._buffer is not None:
-			raise Exception('The IU is already in a buffer, cannot move it.')
-		self._buffer = buffer
-		self.owner_name = buffer.unique_name
-		self._payload.owner_name = buffer.unique_name
-	buffer = property(
-			fget=IUInterface._get_buffer,
-			fset=_set_buffer,
-			doc='Buffer this IU is held in.')
-	
-	def _set_uid(self, uid):
-		if self._uid is not None:
-			raise AttributeError('The uid of IU ' + self.uid + ' has already been set, cannot change it.')
-		self._uid = uid
-	uid = property(
-			fget=IUInterface._get_uid,
-			fset=_set_uid,
-			doc='Unique ID of the IU.')
-#}}}
-
-class RemoteMessage(IUInterface):#{{{
-	
-	"""A remote IU with access mode 'MESSAGE'."""
-	
-	def __init__(self, uid, revision, read_only, owner_name, category, payload_type, committed, payload, links):
-		super(RemoteMessage, self).__init__(uid=uid, access_mode=IUAccessMode.PUSH, read_only=read_only)
-		self._revision = revision
-		self._category = category
-		self.owner_name = owner_name
-		self._payload_type = payload_type
-		self._committed = committed
-		self._retracted = False
-		# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
-		#  don't try to invoke any modification checks or network updates ourselves either.
-		#  We are just receiving it here and applying the new data.
-		self._payload = Payload(iu=self, new_payload=payload, omit_init_update_message=True)
-		self._links = links
-	
-	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
-		logger.info('Info: modifying a RemoteMessage only has local effects')
-	
-	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
-		logger.info('Info: modifying a RemoteMessage only has local effects')
-
-	def commit(self):
-		logger.info('Info: committing to a RemoteMessage only has local effects')
-
-	def _get_payload(self):
-		return self._payload
-	def _set_payload(self, new_pl):
-		logger.info('Info: modifying a RemoteMessage only has local effects')
-		self._payload = Payload(iu=self, new_payload=new_pl, omit_init_update_message=True)
-	payload = property(
-			fget=_get_payload,
-			fset=_set_payload,
-			doc='Payload dictionary of the IU.')
-
-	def _apply_link_update(self, update):
-		"""Apply a IULinkUpdate to the IU."""
-		logger.warning('Warning: should never be called: RemoteMessage._apply_link_update')
-		self._revision = update.revision
-		if update.is_delta:
-			self._add_and_remove_links(add=update.new_links, remove=update.links_to_remove)
-		else:
-			self._replace_links(links=update.new_links)
-	
-	def _apply_update(self, update):
-		"""Apply a IUPayloadUpdate to the IU."""
-		logger.warning('Warning: should never be called: RemoteMessage._apply_update')
-		self._revision = update.revision
-		if update.is_delta:
-			for k in update.keys_to_remove: self.payload._remotely_enforced_delitem(k)
-			for k, v in update.new_items.items(): self.payload._remotely_enforced_setitem(k, v)
-		else:
-			# NOTE Please read the comment in the constructor
-			self._payload = Payload(iu=self, new_payload=update.new_items, omit_init_update_message=True)
-	
-	def _apply_commission(self):
-		"""Apply commission to the IU"""
-		logger.warning('Warning: should never be called: RemoteMessage._apply_commission')
-		self._committed = True
-	
-	def _apply_retraction(self):
-		"""Apply retraction to the IU"""
-		logger.warning('Warning: should never be called: RemoteMessage._apply_retraction')
-		self._retracted = True
-#}}}
-
-class RemotePushIU(IUInterface):#{{{
-	
-	"""A remote IU with access mode 'PUSH'."""
-	
-	def __init__(self, uid, revision, read_only, owner_name, category, payload_type, committed, payload, links):
-		super(RemotePushIU, self).__init__(uid=uid, access_mode=IUAccessMode.PUSH, read_only=read_only)
-		self._revision = revision
-		self._category = category
-		self.owner_name = owner_name
-		self._payload_type = payload_type
-		self._committed = committed
-		self._retracted = False
-		# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
-		#  don't try to invoke any modification checks or network updates ourselves either.
-		#  We are just receiving it here and applying the new data.
-		self._payload = Payload(iu=self, new_payload=payload, omit_init_update_message=True)
-		self._links = links
-	
-	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
-		"""Modify the links: add or remove item from this payload remotely and send update."""
-		if self.committed:
-			raise IUCommittedError(self)
-		if self.read_only:
-			raise IUReadOnlyError(self)
-		requested_update = IULinkUpdate(
-				uid=self.uid,
-				revision=self.revision,
-				is_delta=is_delta,
-				writer_name=self.buffer.unique_name,
-				new_links=new_links,
-				links_to_remove=links_to_remove)
-		remote_server = self.buffer._get_remote_server(self)
-		new_revision = remote_server.updateLinks(requested_update)
-		if new_revision == 0:
-			raise IUUpdateFailedError(self)
-		else:
-			self._revision = new_revision
-	
-	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
-		"""Modify the payload: add or remove item from this payload remotely and send update."""
-		if self.committed:
-			raise IUCommittedError(self)
-		if self.read_only:
-			raise IUReadOnlyError(self)
-		requested_update = IUPayloadUpdate(
-				uid=self.uid,
-				revision=self.revision,
-				is_delta=is_delta,
-				writer_name=self.buffer.unique_name,
-				new_items=new_items,
-				keys_to_remove=keys_to_remove)
-		remote_server = self.buffer._get_remote_server(self)
-		new_revision = remote_server.updatePayload(requested_update)
-		if new_revision == 0:
-			raise IUUpdateFailedError(self)
-		else:
-			self._revision = new_revision
-
-	def commit(self):
-		"""Commit to this IU."""
-		if self.read_only:
-			raise IUReadOnlyError(self)
-		if self._committed:
-			# ignore commit requests when already committed
-			return
-		else:
-			commission_request = ipaaca_pb2.IUCommission()
-			commission_request.uid = self.uid
-			commission_request.revision = self.revision
-			commission_request.writer_name = self.buffer.unique_name
-			remote_server = self.buffer._get_remote_server(self)
-			new_revision = remote_server.commit(commission_request)
-			if new_revision == 0:
-				raise IUUpdateFailedError(self)
-			else:
-				self._revision = new_revision
-				self._committed = True
-
-	def _get_payload(self):
-		return self._payload
-	def _set_payload(self, new_pl):
-		if self.committed:
-			raise IUCommittedError(self)
-		if self.read_only:
-			raise IUReadOnlyError(self)
-		requested_update = IUPayloadUpdate(
-				uid=self.uid,
-				revision=self.revision,
-				is_delta=False,
-				writer_name=self.buffer.unique_name,
-				new_items=new_pl,
-				keys_to_remove=[])
-		remote_server = self.buffer._get_remote_server(self)
-		new_revision = remote_server.updatePayload(requested_update)
-		if new_revision == 0:
-			raise IUUpdateFailedError(self)
-		else:
-			self._revision = new_revision
-			# NOTE Please read the comment in the constructor
-			self._payload = Payload(iu=self, new_payload=new_pl, omit_init_update_message=True)
-	payload = property(
-			fget=_get_payload,
-			fset=_set_payload,
-			doc='Payload dictionary of the IU.')
-
-	def _apply_link_update(self, update):
-		"""Apply a IULinkUpdate to the IU."""
-		self._revision = update.revision
-		if update.is_delta:
-			self._add_and_remove_links(add=update.new_links, remove=update.links_to_remove)
-		else:
-			self._replace_links(links=update.new_links)
-	
-	def _apply_update(self, update):
-		"""Apply a IUPayloadUpdate to the IU."""
-		self._revision = update.revision
-		if update.is_delta:
-			for k in update.keys_to_remove: self.payload._remotely_enforced_delitem(k)
-			for k, v in update.new_items.items(): self.payload._remotely_enforced_setitem(k, v)
-		else:
-			# NOTE Please read the comment in the constructor
-			self._payload = Payload(iu=self, new_payload=update.new_items, omit_init_update_message=True)
-	
-	def _apply_commission(self):
-		"""Apply commission to the IU"""
-		self._committed = True
-	
-	def _apply_retraction(self):
-		"""Apply retraction to the IU"""
-		self._retracted = True
-#}}}
-
-
-class IntConverter(rsb.converter.Converter):#{{{
-	"""Convert Python int objects to Protobuf ints and vice versa."""
-	def __init__(self, wireSchema="int", dataType=int):
-		super(IntConverter, self).__init__(bytearray, dataType, wireSchema)
-	
-	def serialize(self, value):
-		pbo = ipaaca_pb2.IntMessage()
-		pbo.value = value
-		return bytearray(pbo.SerializeToString()), self.wireSchema
-	
-	def deserialize(self, byte_stream, ws):
-		pbo = ipaaca_pb2.IntMessage()
-		pbo.ParseFromString( str(byte_stream) )
-		return pbo.value
-#}}}
-
-
-class IUConverter(rsb.converter.Converter):#{{{
-	'''
-	Converter class for Full IU representations
-	wire:bytearray <-> wire-schema:ipaaca-full-iu <-> class ipaacaRSB.IU
-	'''
-	def __init__(self, wireSchema="ipaaca-iu", dataType=IU):
-		super(IUConverter, self).__init__(bytearray, dataType, wireSchema)
-	
-	def serialize(self, iu):
-		pbo = ipaaca_pb2.IU()
-		pbo.uid = iu._uid
-		pbo.revision = iu._revision
-		pbo.category = iu._category
-		pbo.payload_type = iu._payload_type
-		pbo.owner_name = iu._owner_name
-		pbo.committed = iu._committed
-		am=ipaaca_pb2.IU.PUSH #default
-		if iu._access_mode == IUAccessMode.MESSAGE:
-			am=ipaaca_pb2.IU.MESSAGE
-		# TODO add other types later
-		pbo.access_mode = am
-		pbo.read_only = iu._read_only
-		for k,v in iu._payload.items():
-			entry = pbo.payload.add()
-			pack_typed_payload_item(entry, k, v)
-		for type_ in iu._links.keys():
-			linkset = pbo.links.add()
-			linkset.type = type_
-			linkset.targets.extend(iu._links[type_])
-		ws = "ipaaca-messageiu" if iu._access_mode == IUAccessMode.MESSAGE else self.wireSchema
-		return bytearray(pbo.SerializeToString()), ws
-	
-	def deserialize(self, byte_stream, ws):
-		type = self.getDataType()
-		#print('IUConverter.deserialize got a '+str(type)+' over wireSchema '+ws)
-		if type == IU or type == Message:
-			pbo = ipaaca_pb2.IU()
-			pbo.ParseFromString( str(byte_stream) )
-			if pbo.access_mode ==  ipaaca_pb2.IU.PUSH:
-				_payload = {}
-				for entry in pbo.payload:
-					k, v = unpack_typed_payload_item(entry)
-					_payload[k] = v
-				_links = collections.defaultdict(set)
-				for linkset in pbo.links:
-					for target_uid in linkset.targets:
-						_links[linkset.type].add(target_uid)
-				remote_push_iu = RemotePushIU(
-						uid=pbo.uid,
-						revision=pbo.revision,
-						read_only = pbo.read_only,
-						owner_name = pbo.owner_name,
-						category = pbo.category,
-						payload_type = pbo.payload_type,
-						committed = pbo.committed,
-						payload=_payload,
-						links=_links
-					)
-				return remote_push_iu
-			elif pbo.access_mode ==  ipaaca_pb2.IU.MESSAGE:
-				_payload = {}
-				for entry in pbo.payload:
-					k, v = unpack_typed_payload_item(entry)
-					_payload[k] = v
-				_links = collections.defaultdict(set)
-				for linkset in pbo.links:
-					for target_uid in linkset.targets:
-						_links[linkset.type].add(target_uid)
-				remote_message = RemoteMessage(
-						uid=pbo.uid,
-						revision=pbo.revision,
-						read_only = pbo.read_only,
-						owner_name = pbo.owner_name,
-						category = pbo.category,
-						payload_type = pbo.payload_type,
-						committed = pbo.committed,
-						payload=_payload,
-						links=_links
-					)
-				return remote_message
-			else:
-				raise Exception("We can only handle IUs with access mode 'PUSH' or 'MESSAGE' for now!")
-		else:
-			raise ValueError("Inacceptable dataType %s" % type)
-#}}}
-
-class MessageConverter(rsb.converter.Converter):#{{{
-	'''
-	Converter class for Full IU representations
-	wire:bytearray <-> wire-schema:ipaaca-full-iu <-> class ipaacaRSB.IU
-	'''
-	def __init__(self, wireSchema="ipaaca-messageiu", dataType=Message):
-		super(IUConverter, self).__init__(bytearray, dataType, wireSchema)
-	
-	def serialize(self, iu):
-		pbo = ipaaca_pb2.IU()
-		pbo.uid = iu._uid
-		pbo.revision = iu._revision
-		pbo.category = iu._category
-		pbo.payload_type = iu._payload_type
-		pbo.owner_name = iu._owner_name
-		pbo.committed = iu._committed
-		am=ipaaca_pb2.IU.PUSH #default
-		if iu._access_mode == IUAccessMode.MESSAGE:
-			am=ipaaca_pb2.IU.MESSAGE
-		# TODO add other types later
-		pbo.access_mode = am
-		pbo.read_only = iu._read_only
-		for k,v in iu._payload.items():
-			entry = pbo.payload.add()
-			pack_typed_payload_item(entry, k, v)
-		for type_ in iu._links.keys():
-			linkset = pbo.links.add()
-			linkset.type = type_
-			linkset.targets.extend(iu._links[type_])
-		ws = "ipaaca-messageiu" if iu._access_mode == IUAccessMode.MESSAGE else self.wireSchema
-		return bytearray(pbo.SerializeToString()), ws
-	
-	def deserialize(self, byte_stream, ws):
-		type = self.getDataType()
-		#print('MessageConverter.deserialize got a '+str(type)+' over wireSchema '+ws)
-		if type == IU or type == Message:
-			pbo = ipaaca_pb2.IU()
-			pbo.ParseFromString( str(byte_stream) )
-			if pbo.access_mode ==  ipaaca_pb2.IU.PUSH:
-				_payload = {}
-				for entry in pbo.payload:
-					k, v = unpack_typed_payload_item(entry)
-					_payload[k] = v
-				_links = collections.defaultdict(set)
-				for linkset in pbo.links:
-					for target_uid in linkset.targets:
-						_links[linkset.type].add(target_uid)
-				remote_push_iu = RemotePushIU(
-						uid=pbo.uid,
-						revision=pbo.revision,
-						read_only = pbo.read_only,
-						owner_name = pbo.owner_name,
-						category = pbo.category,
-						payload_type = pbo.payload_type,
-						committed = pbo.committed,
-						payload=_payload,
-						links=_links
-					)
-				return remote_push_iu
-			elif pbo.access_mode ==  ipaaca_pb2.IU.MESSAGE:
-				_payload = {}
-				for entry in pbo.payload:
-					k, v = unpack_typed_payload_item(entry)
-					_payload[k] = v
-				_links = collections.defaultdict(set)
-				for linkset in pbo.links:
-					for target_uid in linkset.targets:
-						_links[linkset.type].add(target_uid)
-				remote_message = RemoteMessage(
-						uid=pbo.uid,
-						revision=pbo.revision,
-						read_only = pbo.read_only,
-						owner_name = pbo.owner_name,
-						category = pbo.category,
-						payload_type = pbo.payload_type,
-						committed = pbo.committed,
-						payload=_payload,
-						links=_links
-					)
-				return remote_message
-			else:
-				raise Exception("We can only handle IUs with access mode 'PUSH' or 'MESSAGE' for now!")
-		else:
-			raise ValueError("Inacceptable dataType %s" % type)
-#}}}
-
-
-class IULinkUpdate(object):#{{{
-	
-	def __init__(self, uid, revision, is_delta, writer_name="undef", new_links=None, links_to_remove=None):
-		super(IULinkUpdate, self).__init__()
-		self.uid = uid
-		self.revision = revision
-		self.writer_name = writer_name
-		self.is_delta = is_delta
-		self.new_links = collections.defaultdict(set) if new_links is None else collections.defaultdict(set, new_links)
-		self.links_to_remove = collections.defaultdict(set) if links_to_remove is None else collections.defaultdict(set, links_to_remove)
-	
-	def __str__(self):
-		s =  'LinkUpdate(' + 'uid=' + self.uid + ', '
-		s += 'revision='+str(self.revision)+', '
-		s += 'writer_name='+str(self.writer_name)+', '
-		s += 'is_delta='+str(self.is_delta)+', '
-		s += 'new_links = '+str(self.new_links)+', '
-		s += 'links_to_remove = '+str(self.links_to_remove)+')'
-		return s
-#}}}
-
-class IUPayloadUpdate(object):#{{{
-	
-	def __init__(self, uid, revision, is_delta, writer_name="undef", new_items=None, keys_to_remove=None):
-		super(IUPayloadUpdate, self).__init__()
-		self.uid = uid
-		self.revision = revision
-		self.writer_name = writer_name
-		self.is_delta = is_delta
-		self.new_items = {} if new_items is None else new_items
-		self.keys_to_remove = [] if keys_to_remove is None else keys_to_remove
-	
-	def __str__(self):
-		s =  'PayloadUpdate(' + 'uid=' + self.uid + ', '
-		s += 'revision='+str(self.revision)+', '
-		s += 'writer_name='+str(self.writer_name)+', '
-		s += 'is_delta='+str(self.is_delta)+', '
-		s += 'new_items = '+str(self.new_items)+', '
-		s += 'keys_to_remove = '+str(self.keys_to_remove)+')'
-		return s
-#}}}
-
-class IULinkUpdateConverter(rsb.converter.Converter):#{{{
-	def __init__(self, wireSchema="ipaaca-iu-link-update", dataType=IULinkUpdate):
-		super(IULinkUpdateConverter, self).__init__(bytearray, dataType, wireSchema)
-	
-	def serialize(self, iu_link_update):
-		pbo = ipaaca_pb2.IULinkUpdate()
-		pbo.uid = iu_link_update.uid
-		pbo.writer_name = iu_link_update.writer_name
-		pbo.revision = iu_link_update.revision
-		for type_ in iu_link_update.new_links.keys():
-			linkset = pbo.new_links.add()
-			linkset.type = type_
-			linkset.targets.extend(iu_link_update.new_links[type_])
-		for type_ in iu_link_update.links_to_remove.keys():
-			linkset = pbo.links_to_remove.add()
-			linkset.type = type_
-			linkset.targets.extend(iu_link_update.links_to_remove[type_])
-		pbo.is_delta = iu_link_update.is_delta
-		return bytearray(pbo.SerializeToString()), self.wireSchema
-	
-	def deserialize(self, byte_stream, ws):
-		type = self.getDataType()
-		if type == IULinkUpdate:
-			pbo = ipaaca_pb2.IULinkUpdate()
-			pbo.ParseFromString( str(byte_stream) )
-			logger.debug('received an IULinkUpdate for revision '+str(pbo.revision))
-			iu_link_up = IULinkUpdate( uid=pbo.uid, revision=pbo.revision, writer_name=pbo.writer_name, is_delta=pbo.is_delta)
-			for entry in pbo.new_links:
-				iu_link_up.new_links[str(entry.type)] = set(entry.targets)
-			for entry in pbo.links_to_remove:
-				iu_link_up.links_to_remove[str(entry.type)] = set(entry.targets)
-			return iu_link_up
-		else:
-			raise ValueError("Inacceptable dataType %s" % type)
-#}}}
-
-class IUPayloadUpdateConverter(rsb.converter.Converter):#{{{
-	def __init__(self, wireSchema="ipaaca-iu-payload-update", dataType=IUPayloadUpdate):
-		super(IUPayloadUpdateConverter, self).__init__(bytearray, dataType, wireSchema)
-	
-	def serialize(self, iu_payload_update):
-		pbo = ipaaca_pb2.IUPayloadUpdate()
-		pbo.uid = iu_payload_update.uid
-		pbo.writer_name = iu_payload_update.writer_name
-		pbo.revision = iu_payload_update.revision
-		for k,v in iu_payload_update.new_items.items():
-			entry = pbo.new_items.add()
-			pack_typed_payload_item(entry, k, v)
-		pbo.keys_to_remove.extend(iu_payload_update.keys_to_remove)
-		pbo.is_delta = iu_payload_update.is_delta
-		return bytearray(pbo.SerializeToString()), self.wireSchema
-	
-	def deserialize(self, byte_stream, ws):
-		type = self.getDataType()
-		if type == IUPayloadUpdate:
-			pbo = ipaaca_pb2.IUPayloadUpdate()
-			pbo.ParseFromString( str(byte_stream) )
-			logger.debug('received an IUPayloadUpdate for revision '+str(pbo.revision))
-			iu_up = IUPayloadUpdate( uid=pbo.uid, revision=pbo.revision, writer_name=pbo.writer_name, is_delta=pbo.is_delta)
-			for entry in pbo.new_items:
-				k, v = unpack_typed_payload_item(entry)
-				iu_up.new_items[k] = v
-			iu_up.keys_to_remove = pbo.keys_to_remove[:]
-			return iu_up
-		else:
-			raise ValueError("Inacceptable dataType %s" % type)
-#}}}
-
-
-class IUStore(dict):
-	"""A dictionary storing IUs."""
-	def __init__(self):
-		super(IUStore, self).__init__()
-
-class FrozenIUStore(IUStore):
-	"""A read-only version of a dictionary storing IUs. (TODO: might be slow)"""
-	def __init__(self, original_iu_store):
-		super(FrozenIUStore, self).__init__()
-		map(lambda p: super(FrozenIUStore, self).__setitem__(p[0], p[1]), original_iu_store.items())
-	def __delitem__(self, k):
-		raise AttributeError()
-	def __setitem__(self, k, v):
-		raise AttributeError()
-
-class IUEventHandler(object):
-	
-	"""Wrapper for IU event handling functions."""
-	
-	def __init__(self, handler_function, for_event_types=None, for_categories=None):
-		"""Create an IUEventHandler.
-		
-		Keyword arguments:
-		handler_function -- the handler function with the signature
-			(IU, event_type, local)
-		for_event_types -- a list of event types or None if handler should
-			be called for all event types
-		for_categories -- a list of category names or None if handler should
-			be called for all categoires
-		"""
-		super(IUEventHandler, self).__init__()
-		self._handler_function = handler_function
-		self._for_event_types = (
-			None if for_event_types is None else
-			(for_event_types[:] if hasattr(for_event_types, '__iter__') else [for_event_types]))
-		self._for_categories = (
-			None if for_categories is None else
-			(for_categories[:] if hasattr(for_categories, '__iter__') else [for_categories]))
-	
-	def condition_met(self, event_type, category):
-		"""Check whether this IUEventHandler should be called.
-		
-		Keyword arguments:
-		event_type -- type of the IU event
-		category -- category of the IU which triggered the event
-		"""
-		type_condition_met = (self._for_event_types is None or event_type in self._for_event_types)
-		cat_condition_met = (self._for_categories is None or category in self._for_categories)
-		return type_condition_met and cat_condition_met
-	
-	def call(self, buffer, iu_uid, local, event_type, category):
-		"""Call this IUEventHandler's function, if it applies.
-		
-		Keyword arguments:
-		buffer -- the buffer in which the IU is stored
-		iu_uid -- the uid of the IU
-		local -- is the IU local or remote to this component? @RAMIN: Is this correct?
-		event_type -- IU event type
-		category -- category of the IU
-		"""
-		if self.condition_met(event_type, category):
-			iu = buffer._iu_store[iu_uid]
-			self._handler_function(iu, event_type, local)
-
-
-class Buffer(object):
-	
-	"""Base class for InputBuffer and OutputBuffer."""
-	
-	def __init__(self, owning_component_name, participant_config=None):
-		'''Create a Buffer.
-		
-		Keyword arguments:
-		owning_compontent_name -- name of the entity that owns this Buffer
-		participant_config -- RSB configuration
-		'''
-		super(Buffer, self).__init__()
-		self._owning_component_name = owning_component_name
-		self._participant_config = rsb.ParticipantConfig.fromDefaultSources() if participant_config is None else participant_config
-		self._uuid = str(uuid.uuid4())[0:8]
-		# Initialise with a temporary, but already unique, name
-		self._unique_name = "undef-"+self._uuid
-		self._iu_store = IUStore()
-		self._iu_event_handlers = []
-	
-	def _get_frozen_iu_store(self):
-		return FrozenIUStore(original_iu_store = self._iu_store)
-	iu_store = property(fget=_get_frozen_iu_store, doc='Copy-on-read version of the internal IU store')
-	
-	def register_handler(self, handler_function, for_event_types=None, for_categories=None):
-		"""Register a new IU event handler function.
-		
-		Keyword arguments:
-		handler_function -- a function with the signature (IU, event_type, local)
-		for_event_types -- a list of event types or None if handler should
-			be called for all event types
-		for_categories -- a list of category names or None if handler should
-			be called for all categories
-		
-		 """
-		handler = IUEventHandler(handler_function=handler_function, for_event_types=for_event_types, for_categories=for_categories)
-		self._iu_event_handlers.append(handler)
-	
-	def call_iu_event_handlers(self, uid, local, event_type, category):
-		"""Call registered IU event handler functions registered for this event_type and category."""
-		for h in self._iu_event_handlers:
-			h.call(self, uid, local=local, event_type=event_type, category=category)
-	
-	def _get_owning_component_name(self):
-		"""Return the name of this Buffer's owning component"""
-		return self._owning_component_name
-	owning_component_name = property(_get_owning_component_name)
-	
-	def _get_unique_name(self):
-		"""Return the Buffer's unique name."""
-		return self._unique_name
-	unique_name = property(_get_unique_name)
-	
-
-
-class InputBuffer(Buffer):
-	
-	"""An InputBuffer that holds remote IUs."""
-	
-	def __init__(self, owning_component_name, category_interests=None, participant_config=None):
-		'''Create an InputBuffer.
-		
-		Keyword arguments:
-		owning_compontent_name -- name of the entity that owns this InputBuffer
-		category_interests -- list of IU categories this Buffer is interested in
-		participant_config = RSB configuration
-		'''
-		super(InputBuffer, self).__init__(owning_component_name, participant_config)
-		self._unique_name = '/ipaaca/component/'+str(owning_component_name)+'ID'+self._uuid+'/IB'
-		self._listener_store = {} # one per IU category
-		self._remote_server_store = {} # one per remote-IU-owning Component
-		self._category_interests = []
-		if category_interests is not None:
-			for cat in category_interests:
-				self._add_category_listener(cat)
-	
-	def _get_remote_server(self, iu):
-		'''Return (or create, store and return) a remote server.'''
-		if iu.owner_name in self._remote_server_store:
-			return self._remote_server_store[iu.owner_name]
-		#  TODO remove the str() when unicode is supported (issue #490)
-		remote_server = rsb.createRemoteServer(rsb.Scope(str(iu.owner_name)))
-		self._remote_server_store[iu.owner_name] = remote_server
-		return remote_server
-	
-	def _add_category_listener(self, iu_category):
-		'''Return (or create, store and return) a category listener.'''
-		if iu_category not in self._listener_store: 
-			cat_listener = rsb.createListener(rsb.Scope("/ipaaca/category/"+str(iu_category)), config=self._participant_config)
-			cat_listener.addHandler(self._handle_iu_events)
-			self._listener_store[iu_category] = cat_listener
-			self._category_interests.append(iu_category)
-			logger.info("Added listener in scope "+"/ipaaca/category/"+iu_category)
-	
-	def _handle_iu_events(self, event):
-		'''Dispatch incoming IU events.
-		
-		Adds incoming IU's to the store, applies payload and commit updates to
-		IU, calls IU event handlers.'
-		
-		Keyword arguments:
-		event -- a converted RSB event
-		'''
-		type_ = type(event.data)
-		if type_ is RemotePushIU:
-			# a new IU
-			if event.data.uid in self._iu_store:
-				# already in our store
-				pass
-			else:
-				self._iu_store[ event.data.uid ] = event.data
-				event.data.buffer = self
-				self.call_iu_event_handlers(event.data.uid, local=False, event_type=IUEventType.ADDED, category=event.data.category)
-		elif type_ is RemoteMessage:
-			# a new Message, an ephemeral IU that is removed after calling handlers
-			self._iu_store[ event.data.uid ] = event.data
-			event.data.buffer = self
-			self.call_iu_event_handlers(event.data.uid, local=False, event_type=IUEventType.MESSAGE, category=event.data.category)
-			del self._iu_store[ event.data.uid ]
-		else:
-			# an update to an existing IU
-			if event.data.uid not in self._iu_store:
-				# TODO: we should request the IU's owner to send us the IU
-				logger.warning("Update message for IU which we did not fully receive before.")
-				return
-			if type_ is ipaaca_pb2.IURetraction:
-				# IU retraction (cannot be triggered remotely)
-				iu = self._iu_store[event.data.uid]
-				iu._revision = event.data.revision
-				iu._apply_retraction() # for now - just sets the _rectracted flag.
-				self.call_iu_event_handlers(event.data.uid, local=False, event_type=IUEventType.RETRACTED, category=iu.category)
-				# SPECIAL CASE: allow the handlers (which will need to find the IU
-				#  in the buffer) to operate on the IU - then delete it afterwards!
-				# FIXME: for now: retracted == deleted! Think about this later
-				del(self._iu_store[iu.uid])
-			else:
-				if event.data.writer_name == self.unique_name:
-					# Notify only for remotely triggered events;
-					# Discard updates that originate from this buffer
-					return
-				#else:
-				#	print('Got update written by buffer '+str(event.data.writer_name))
-					
-				if type_ is ipaaca_pb2.IUCommission:
-					# IU commit
-					iu = self._iu_store[event.data.uid]
-					iu._apply_commission()
-					iu._revision = event.data.revision
-					self.call_iu_event_handlers(event.data.uid, local=False, event_type=IUEventType.COMMITTED, category=iu.category)
-				elif type_ is IUPayloadUpdate:
-					# IU payload update
-					iu = self._iu_store[event.data.uid]
-					iu._apply_update(event.data)
-					self.call_iu_event_handlers(event.data.uid, local=False, event_type=IUEventType.UPDATED, category=iu.category)
-				elif type_ is IULinkUpdate:
-					# IU link update
-					iu = self._iu_store[event.data.uid]
-					iu._apply_link_update(event.data)
-					self.call_iu_event_handlers(event.data.uid, local=False, event_type=IUEventType.LINKSUPDATED, category=iu.category)
-				else:
-					logger.warning('Warning: _handle_iu_events failed to handle an object of type '+str(type_))
-
-	def add_category_interests(self, category_interests):
-		for interest in category_interests:
-			self._add_category_listener(interest)
-
-
-class OutputBuffer(Buffer):
-	
-	"""An OutputBuffer that holds local IUs."""
-	
-	def __init__(self, owning_component_name, participant_config=None):
-		'''Create an Output Buffer.
-		
-		Keyword arguments:
-		owning_component_name -- name of the entity that own this buffer
-		participant_config -- RSB configuration
-		'''
-		super(OutputBuffer, self).__init__(owning_component_name, participant_config)
-		self._unique_name = '/ipaaca/component/' + str(owning_component_name) + 'ID' + self._uuid + '/OB'
-		self._server = rsb.createServer(rsb.Scope(self._unique_name))
-		self._server.addMethod('updateLinks', self._remote_update_links, IULinkUpdate, int)
-		self._server.addMethod('updatePayload', self._remote_update_payload, IUPayloadUpdate, int)
-		self._server.addMethod('commit', self._remote_commit, ipaaca_pb2.IUCommission, int)
-		self._informer_store = {}
-		self._id_prefix = str(owning_component_name)+'-'+str(self._uuid)+'-IU-'
-		self.__iu_id_counter_lock = threading.Lock()
-		#self.__iu_id_counter = 0 # hbuschme: IUs now have their Ids assigned on creation
-	
-	def _create_own_name_listener(self, iu_category):
-		# FIXME replace this
-		'''Create an own name listener.'''
-		#if iu_category in self._listener_store: return self._informer_store[iu_category]
-		#cat_listener = rsb.createListener(rsb.Scope("/ipaaca/category/"+str(iu_category)), config=self._participant_config)
-		#cat_listener.addHandler(self._handle_iu_events)
-		#self._listener_store[iu_category] = cat_listener
-		#self._category_interests.append(iu_category)
-		#logger.info("Added category listener for "+iu_category)
-		#return cat_listener
-		pass
-	
-	# hbuschme: IUs now have their Ids assigned on creation
-	#def _generate_iu_uid(self):
-	#	'''Generate a unique IU id of the form ????'''
-	#	with self.__iu_id_counter_lock:
-	#		self.__iu_id_counter += 1
-	#		number = self.__iu_id_counter
-	#	return self._id_prefix + str(number)
-
-	def _remote_update_links(self, update):
-		'''Apply a remotely requested update to one of the stored IU's links.'''
-		if update.uid not in self._iu_store:
-			logger.warning("Remote InBuffer tried to spuriously write non-existent IU "+str(update.uid))
-			return 0
-		iu = self._iu_store[update.uid]
-		with iu.revision_lock:
-			if (update.revision != 0) and (update.revision != iu.revision):
-				# (0 means "do not pay attention to the revision number" -> "force update")
-				logger.warning("Remote write operation failed because request was out of date; IU "+str(update.uid))
-				return 0
-			if update.is_delta:
-				iu.modify_links(add=update.new_links, remove=update.links_to_remove, writer_name=update.writer_name)
-			else:
-				iu.set_links(links=update.new_links, writer_name=update.writer_name)
-			self.call_iu_event_handlers(update.uid, local=True, event_type=IUEventType.LINKSUPDATED, category=iu.category)
-			return iu.revision
-	
-	def _remote_update_payload(self, update):
-		'''Apply a remotely requested update to one of the stored IU's payload.'''
-		if update.uid not in self._iu_store:
-			logger.warning("Remote InBuffer tried to spuriously write non-existent IU "+str(update.uid))
-			return 0
-		iu = self._iu_store[update.uid]
-		with iu.revision_lock:
-			if (update.revision != 0) and (update.revision != iu.revision):
-				# (0 means "do not pay attention to the revision number" -> "force update")
-				logger.warning(u"Remote update_payload operation failed because request was out of date; IU "+str(update.uid))
-				logger.warning(u"  Writer was: "+update.writer_name)
-				logger.warning(u"  Requested update was: (New keys:) "+','.join(update.new_items.keys())+'  (Removed keys:) '+','.join(update.keys_to_remove))
-				logger.warning(u"  Referred-to revision was "+str(update.revision)+' while local revision is '+str(iu.revision))
-				return 0
-			if update.is_delta:
-				#print('Writing delta update by '+str(update.writer_name))
-				with iu.payload:
-					for k in update.keys_to_remove:
-						iu.payload.__delitem__(k, writer_name=update.writer_name)
-					for k,v in update.new_items.items():
-						iu.payload.__setitem__(k, v, writer_name=update.writer_name)
-			else:
-				#print('Writing non-incr update by '+str(update.writer_name))
-				iu._set_payload(update.new_items, writer_name=update.writer_name)
-				# _set_payload etc. have also incremented the revision number
-			self.call_iu_event_handlers(update.uid, local=True, event_type=IUEventType.UPDATED, category=iu.category)
-			return iu.revision
-	
-	def _remote_commit(self, iu_commission):
-		'''Apply a remotely requested commit to one of the stored IUs.'''
-		if iu_commission.uid not in self._iu_store:
-			logger.warning("Remote InBuffer tried to spuriously write non-existent IU "+str(iu_commission.uid))
-			return 0
-		iu = self._iu_store[iu_commission.uid]
-		with iu.revision_lock:
-			if (iu_commission.revision != 0) and (iu_commission.revision != iu.revision):
-				# (0 means "do not pay attention to the revision number" -> "force update")
-				logger.warning("Remote write operation failed because request was out of date; IU "+str(iu_commission.uid))
-				return 0
-			if iu.committed:
-				return 0
-			else:
-				iu._internal_commit(writer_name=iu_commission.writer_name)
-				self.call_iu_event_handlers(iu_commission.uid, local=True, event_type=IUEventType.COMMITTED, category=iu.category)
-				return iu.revision
-	
-	def _get_informer(self, iu_category):
-		'''Return (or create, store and return) an informer object for IUs of the specified category.'''
-		if iu_category in self._informer_store:
-			logger.info("Returning informer on scope "+"/ipaaca/category/"+str(iu_category))
-			return self._informer_store[iu_category]
-		informer_iu = rsb.createInformer(
-				rsb.Scope("/ipaaca/category/"+str(iu_category)),
-				config=self._participant_config,
-				dataType=object)
-		self._informer_store[iu_category] = informer_iu #new_tuple
-		logger.info("Returning NEW informer on scope "+"/ipaaca/category/"+str(iu_category))
-		return informer_iu #return new_tuple
-	
-	def add(self, iu):
-		'''Add an IU to the IU store, assign an ID and publish it.'''
-		# hbuschme: IUs now have their Ids assigned on creation
-		#if iu._uid is not None:
-		#	raise IUPublishedError(iu)
-		#iu.uid = self._generate_iu_uid()
-		if iu.uid in self._iu_store:
-			raise IUPublishedError(iu)
-		if iu.buffer is not None:
-			raise IUPublishedError(iu)
-		if iu.access_mode != IUAccessMode.MESSAGE:
-			# Messages are not really stored in the OutputBuffer
-			self._iu_store[iu.uid] = iu
-		iu.buffer = self
-		self._publish_iu(iu)
-	
-	def remove(self, iu=None, iu_uid=None):
-		'''Remove the iu or an IU corresponding to iu_uid from the OutputBuffer, retracting it from the system.'''
-		if iu is None:
-			if iu_uid is None:
-				return None
-			else:
-				if iu_uid not in self. _iu_store:
-					raise IUNotFoundError(iu_uid)
-				iu = self._iu_store[iu_uid]
-		# unpublish the IU
-		self._retract_iu(iu)
-		del self._iu_store[iu.uid]
-		return iu
-	
-	def _publish_iu(self, iu):
-		'''Publish an IU.'''
-		informer = self._get_informer(iu._category)
-		informer.publishData(iu)
-	
-	def _retract_iu(self, iu):
-		'''Retract (unpublish) an IU.'''
-		iu_retraction = ipaaca_pb2.IURetraction()
-		iu_retraction.uid = iu.uid
-		iu_retraction.revision = iu.revision
-		informer = self._get_informer(iu._category)
-		informer.publishData(iu_retraction)
-	
-	def _send_iu_commission(self, iu, writer_name):
-		'''Send IU commission.
-		
-		Keyword arguments:
-		iu -- the IU that has been committed to
-		writer_name -- name of the Buffer that initiated this commit, necessary
-			to enable remote components to filter out updates that originated
-			from their own operations
-		'''
-		# a raw Protobuf object for IUCommission is produced
-		# (unlike updates, where we have an intermediate class)
-		iu_commission = ipaaca_pb2.IUCommission()
-		iu_commission.uid = iu.uid
-		iu_commission.revision = iu.revision
-		iu_commission.writer_name = iu.owner_name if writer_name is None else writer_name
-		informer = self._get_informer(iu._category)
-		informer.publishData(iu_commission)
-	
-	def _send_iu_link_update(self, iu, is_delta, revision, new_links=None, links_to_remove=None, writer_name="undef"):
-		'''Send an IU link update.
-		
-		Keyword arguments:
-		iu -- the IU being updated
-		is_delta -- whether this is an incremental update or a replacement
-			the whole link dictionary
-		revision -- the new revision number
-		new_links -- a dictionary of new link sets
-		links_to_remove -- a dict of the link sets that shall be removed
-		writer_name -- name of the Buffer that initiated this update, necessary
-			to enable remote components to filter out updates that originate d
-			from their own operations
-		'''
-		if new_links is None:
-			new_links = {}
-		if links_to_remove is None:
-			links_to_remove = {}
-		link_update = IULinkUpdate(iu._uid, is_delta=is_delta, revision=revision)
-		link_update.new_links = new_links
-		if is_delta:
-			link_update.links_to_remove = links_to_remove
-		link_update.writer_name = writer_name
-		informer = self._get_informer(iu._category)
-		informer.publishData(link_update)
-		# FIXME send the notification to the target, if the target is not the writer_name
-	
-	def _send_iu_payload_update(self, iu, is_delta, revision, new_items=None, keys_to_remove=None, writer_name="undef"):
-		'''Send an IU payload update.
-		
-		Keyword arguments:
-		iu -- the IU being updated
-		is_delta -- whether this is an incremental update or a replacement
-		revision -- the new revision number
-		new_items -- a dictionary of new payload items
-		keys_to_remove -- a list of the keys that shall be removed from the
-		 	payload
-		writer_name -- name of the Buffer that initiated this update, necessary
-			to enable remote components to filter out updates that originate d
-			from their own operations
-		'''
-		if new_items is None:
-			new_items = {}
-		if keys_to_remove is None:
-			keys_to_remove = []
-		payload_update = IUPayloadUpdate(iu._uid, is_delta=is_delta, revision=revision)
-		payload_update.new_items = new_items
-		if is_delta:
-			payload_update.keys_to_remove = keys_to_remove
-		payload_update.writer_name = writer_name
-		informer = self._get_informer(iu._category)
-		informer.publishData(payload_update)
-		#print("  -- Sent update with writer name "+str(writer_name))
-
-
-## --- RSB -------------------------------------------------------------------
-
-
-def initialize_ipaaca_rsb():#{{{
+def initialize_ipaaca_rsb():
+	''''Register own RSB Converters and initialise RSB from default config file.'''
 	rsb.converter.registerGlobalConverter(
-		IntConverter(wireSchema="int32", dataType=int))
+		ipaaca.converter.IntConverter(
+			wireSchema="int32",
+			dataType=int))
+
 	rsb.converter.registerGlobalConverter(
-		IUConverter(wireSchema="ipaaca-iu", dataType=IU))
+		ipaaca.converter.IUConverter(
+			wireSchema="ipaaca-iu",
+			dataType=IU))
+
 	rsb.converter.registerGlobalConverter(
-		IUConverter(wireSchema="ipaaca-messageiu", dataType=Message))
+		ipaaca.converter.MessageConverter(
+			wireSchema="ipaaca-messageiu",
+			dataType=Message))
+
 	rsb.converter.registerGlobalConverter(
-		IULinkUpdateConverter(
+		ipaaca.converter.IULinkUpdateConverter(
 			wireSchema="ipaaca-iu-link-update",
-			dataType=IULinkUpdate))
+			dataType=converter.IULinkUpdate))
+
 	rsb.converter.registerGlobalConverter(
-		IUPayloadUpdateConverter(
+		ipaaca.converter.IUPayloadUpdateConverter(
 			wireSchema="ipaaca-iu-payload-update",
-			dataType=IUPayloadUpdate))
+			dataType=converter.IUPayloadUpdate))
+
 	rsb.converter.registerGlobalConverter(
 		rsb.converter.ProtocolBufferConverter(
 			messageClass=ipaaca_pb2.IUCommission))
+
 	rsb.converter.registerGlobalConverter(
 		rsb.converter.ProtocolBufferConverter(
-			messageClass=ipaaca_pb2.IURetraction))
-	rsb.__defaultParticipantConfig = rsb.ParticipantConfig.fromDefaultSources()
-	#t = rsb.ParticipantConfig.Transport('spread', {'enabled':'true'})
-	#rsb.__defaultParticipantConfig = rsb.ParticipantConfig.fromFile('rsb.cfg')
-#}}}
+			messageClass=ipaaca_pb2.IUResendRequest))
 
+	rsb.converter.registerGlobalConverter(
+		rsb.converter.ProtocolBufferConverter(
+			messageClass=ipaaca_pb2.IURetraction))
 
-## --- Module initialisation -------------------------------------------------
+	rsb.__defaultParticipantConfig = rsb.ParticipantConfig.fromDefaultSources()
 
-# register our own RSB Converters
+# Initialise module
 initialize_ipaaca_rsb()
-
-# Create a global logger for this module
-logger = logging.getLogger('ipaaca')
-logger.addHandler(IpaacaLoggingHandler(level=logging.INFO))
diff --git a/ipaacalib/python/src/ipaaca/buffer.py b/ipaacalib/python/src/ipaaca/buffer.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4b75a4450cbd1301717caf94fa36dfb46e8b2f1
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/buffer.py
@@ -0,0 +1,588 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+
+import threading
+import uuid
+import traceback
+
+import rsb
+
+import ipaaca_pb2
+import ipaaca.defaults
+import ipaaca.exception
+import ipaaca.converter
+import ipaaca.iu
+
+
+
+__all__ = [
+	'InputBuffer',
+	'OutputBuffer',
+]
+
+LOGGER = ipaaca.misc.get_library_logger()
+
+class IUStore(dict):
+	"""A dictionary storing IUs."""
+	def __init__(self):
+		super(IUStore, self).__init__()
+
+
+class FrozenIUStore(IUStore):
+	"""A read-only version of a dictionary storing IUs. (TODO: might be slow)"""
+	def __init__(self, original_iu_store):
+		super(FrozenIUStore, self).__init__()
+		map(lambda p: super(FrozenIUStore, self).__setitem__(p[0], p[1]), original_iu_store.items())
+	def __delitem__(self, k):
+		raise AttributeError()
+	def __setitem__(self, k, v):
+		raise AttributeError()
+
+
+class IUEventHandler(object):
+
+	"""Wrapper for IU event handling functions."""
+
+	def __init__(self, handler_function, for_event_types=None, for_categories=None):
+		"""Create an IUEventHandler.
+
+		Keyword arguments:
+		handler_function -- the handler function with the signature
+			(IU, event_type, local)
+		for_event_types -- a list of event types or None if handler should
+			be called for all event types
+		for_categories -- a list of category names or None if handler should
+			be called for all categoires
+		"""
+		super(IUEventHandler, self).__init__()
+		self._handler_function = handler_function
+		self._for_event_types = (
+			None if for_event_types is None else
+			(for_event_types[:] if hasattr(for_event_types, '__iter__') else [for_event_types]))
+		self._for_categories = (
+			None if for_categories is None else
+			(for_categories[:] if hasattr(for_categories, '__iter__') else [for_categories]))
+
+	def condition_met(self, event_type, category):
+		"""Check whether this IUEventHandler should be called.
+
+		Keyword arguments:
+		event_type -- type of the IU event
+		category -- category of the IU which triggered the event
+		"""
+		type_condition_met = (self._for_event_types is None or event_type in self._for_event_types)
+		cat_condition_met = (self._for_categories is None or category in self._for_categories)
+		return type_condition_met and cat_condition_met
+
+	def call(self, buffer, iu_uid, local, event_type, category):
+		"""Call this IUEventHandler's function, if it applies.
+
+		Keyword arguments:
+		buffer -- the buffer in which the IU is stored
+		iu_uid -- the uid of the IU
+		local -- is the IU local or remote to this component? @RAMIN: Is this correct?
+		event_type -- IU event type
+		category -- category of the IU
+		"""
+		if self.condition_met(event_type, category):
+			iu = buffer._iu_store[iu_uid]
+			self._handler_function(iu, event_type, local)
+
+
+class Buffer(object):
+
+	"""Base class for InputBuffer and OutputBuffer."""
+
+	def __init__(self, owning_component_name, channel=None, participant_config=None):
+		'''Create a Buffer.
+
+		Keyword arguments:
+		owning_compontent_name -- name of the entity that owns this Buffer
+		participant_config -- RSB configuration
+		'''
+		super(Buffer, self).__init__()
+		self._owning_component_name = owning_component_name
+		self._channel = channel if channel is not None else ipaaca.defaults.IPAACA_DEFAULT_CHANNEL
+		self._participant_config = rsb.ParticipantConfig.fromDefaultSources() if participant_config is None else participant_config
+		self._uuid = str(uuid.uuid4())[0:8]
+		# Initialise with a temporary, but already unique, name
+		self._unique_name = "undef-"+self._uuid
+		self._iu_store = IUStore()
+		self._iu_event_handlers = []
+
+	def _get_frozen_iu_store(self):
+		return FrozenIUStore(original_iu_store = self._iu_store)
+	iu_store = property(fget=_get_frozen_iu_store, doc='Copy-on-read version of the internal IU store')
+
+	def register_handler(self, handler_function, for_event_types=None, for_categories=None):
+		"""Register a new IU event handler function.
+
+		Keyword arguments:
+		handler_function -- a function with the signature (IU, event_type, local)
+		for_event_types -- a list of event types or None if handler should
+			be called for all event types
+		for_categories -- a list of category names or None if handler should
+			be called for all categories
+		"""
+		if handler_function in [h._handler_function for h in self._iu_event_handlers]:
+			LOGGER.warn("The handler function '" + handler_function.__name__ + '" has been registered before.')
+		handler = IUEventHandler(handler_function=handler_function, for_event_types=for_event_types, for_categories=for_categories)
+		self._iu_event_handlers.append(handler)
+		return handler
+
+	def call_iu_event_handlers(self, uid, local, event_type, category):
+		"""Call registered IU event handler functions registered for this event_type and category."""
+		for h in self._iu_event_handlers:
+			try:
+				h.call(self, uid, local=local, event_type=event_type, category=category)
+			except Exception as e:
+				if local:
+					LOGGER.error('Local IU handler raised an exception upon remote write.' + unicode(e))
+				else:
+					print(unicode(traceback.format_exc()))
+					raise e
+	
+	def _get_owning_component_name(self):
+		"""Return the name of this Buffer's owning component"""
+		return self._owning_component_name
+	owning_component_name = property(_get_owning_component_name)
+
+	def _get_unique_name(self):
+		"""Return the Buffer's unique name."""
+		return self._unique_name
+	unique_name = property(_get_unique_name)
+
+
+class InputBuffer(Buffer):
+
+	"""An InputBuffer that holds remote IUs."""
+
+	def __init__(self, owning_component_name, category_interests=None, channel=None, participant_config=None, resend_active=False):
+		'''Create an InputBuffer.
+
+		Keyword arguments:
+		owning_compontent_name -- name of the entity that owns this InputBuffer
+		category_interests -- list of IU categories this Buffer is interested in
+		participant_config = RSB configuration
+		'''
+		super(InputBuffer, self).__init__(owning_component_name, channel, participant_config)
+		self._unique_name = '/ipaaca/component/'+str(owning_component_name)+'ID'+self._uuid+'/IB'
+		self._resend_active = resend_active
+		self._listener_store = {} # one per IU category
+		self._remote_server_store = {} # one per remote-IU-owning Component
+		self._category_interests = []
+		# add own uuid as identifier for hidden category.
+		self._add_category_listener(str(self._uuid))
+		if category_interests is not None:
+			self.add_category_interests(category_interests)
+
+	def _get_remote_server(self, iu):
+		'''Return (or create, store and return) a remote server.'''
+		_owner = None
+		if hasattr(iu,'owner_name'):
+			_owner = iu.owner_name
+		elif hasattr(iu,'writer_name'):
+			_owner = iu.writer_name
+		if _owner is not None:
+			if _owner in self._remote_server_store:
+				return self._remote_server_store[_owner]
+			#  TODO remove the str() when unicode is supported (issue #490)
+			remote_server = rsb.createRemoteServer(rsb.Scope(str(_owner)))
+			self._remote_server_store[_owner] = remote_server
+		return remote_server
+
+	def _add_category_listener(self, iu_category):
+		'''Create and store a listener on a specific category.'''
+		if iu_category not in self._listener_store:
+			cat_listener = rsb.createListener(rsb.Scope("/ipaaca/channel/"+str(self._channel)+"/category/"+str(iu_category)), config=self._participant_config)
+			cat_listener.addHandler(self._handle_iu_events)
+			self._listener_store[iu_category] = cat_listener
+			self._category_interests.append(iu_category)
+			LOGGER.info("Added listener in scope /ipaaca/channel/" + str(self._channel) + "/category/" + iu_category)
+
+	def _remove_category_listener(self, iu_category):
+		'''Remove the listener for a specific category.'''
+		if iu_category in self._listener_store and iu_category in self._category_interests:
+			del self._listener_store[iu_category]
+			self._category_interests.remove(iu_category)
+			LOGGER.info("Removed listener in scope /ipaaca/channel/" + str(self._channel) + "/category/ " + iu_category)
+
+	def _handle_iu_events(self, event):
+		'''Dispatch incoming IU events.
+
+		Adds incoming IU's to the store, applies payload and commit updates to
+		IU, calls IU event handlers.'
+
+		Keyword arguments:
+		event -- a converted RSB event
+		'''
+		type_ = type(event.data)
+		if type_ is ipaaca.iu.RemotePushIU:
+			# a new IU
+			if event.data.uid not in self._iu_store:
+				self._iu_store[event.data.uid] = event.data
+				event.data.buffer = self
+				self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.ADDED, category=event.data.category)
+			else:
+				# IU already in our store, overwrite local IU, but do not call
+				# event handler. This functionality is necessary to undo 
+				# destructive changes after a failing remote updates (undo is
+				# done via the resend request mechanism).
+				self._iu_store[event.data.uid] = event.data
+				event.data.buffer = self
+		elif type_ is ipaaca.iu.RemoteMessage:
+			# a new Message, an ephemeral IU that is removed after calling handlers
+			self._iu_store[ event.data.uid ] = event.data
+			event.data.buffer = self
+			self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.MESSAGE, category=event.data.category)
+			del self._iu_store[ event.data.uid ]
+		else:
+			if event.data.uid not in self._iu_store:
+				if self._resend_active:
+					# send resend request to remote server
+					self._request_remote_resend(event.data)
+				else:
+					LOGGER.warning("Received an update for an IU which we did not receive before.")
+				return
+			# an update to an existing IU
+			if type_ is ipaaca_pb2.IURetraction:
+				# IU retraction (cannot be triggered remotely)
+				iu = self._iu_store[event.data.uid]
+				iu._revision = event.data.revision
+				iu._apply_retraction() # for now - just sets the _rectracted flag.
+				self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.RETRACTED, category=iu.category)
+				# SPECIAL CASE: allow the handlers (which will need to find the IU
+				#  in the buffer) to operate on the IU - then delete it afterwards!
+				# FIXME: for now: retracted == deleted! Think about this later
+				del(self._iu_store[iu.uid])
+			else:
+				if event.data.writer_name == self.unique_name:
+					# Notify only for remotely triggered events;
+					# Discard updates that originate from this buffer
+					return
+				if type_ is ipaaca_pb2.IUCommission:
+					# IU commit
+					iu = self._iu_store[event.data.uid]
+					iu._apply_commission()
+					iu._revision = event.data.revision
+					self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.COMMITTED, category=iu.category)
+				elif type_ is ipaaca.converter.IUPayloadUpdate:
+					# IU payload update
+					iu = self._iu_store[event.data.uid]
+					iu._apply_update(event.data)
+					self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.UPDATED, category=iu.category)
+				elif type_ is ipaaca.converter.IULinkUpdate:
+					# IU link update
+					iu = self._iu_store[event.data.uid]
+					iu._apply_link_update(event.data)
+					self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.LINKSUPDATED, category=iu.category)
+				else:
+					LOGGER.warning('Warning: _handle_iu_events failed to handle an object of type '+str(type_))
+
+	def add_category_interests(self, category_interests):
+		if hasattr(category_interests, '__iter__'):
+			for interest in category_interests:
+				self._add_category_listener(interest)
+		else:
+			self._add_category_listener(category_interests)
+
+	def remove_category_interests(self, category_interests):
+		if hasattr(category_interests, '__iter__'):
+			for interest in category_interests:
+				self._remove_category_listener(interest)
+		else:
+			self._remove_category_listener(category_interests)
+
+	def _request_remote_resend(self, iu):
+		remote_server = self._get_remote_server(iu)
+		resend_request = ipaaca_pb2.IUResendRequest()
+		resend_request.uid = iu.uid # target iu
+		resend_request.hidden_scope_name = str(self._uuid) # hidden category name
+		remote_revision = remote_server.requestResend(resend_request)
+		if remote_revision == 0:
+			raise ipaaca.exception.IUResendRequestFailedError()
+
+	def register_handler(self, handler_function, for_event_types=None, for_categories=None):
+		"""Register a new IU event handler function.
+
+		Keyword arguments:
+		handler_function -- a function with the signature (IU, event_type, local)
+		for_event_types -- a list of event types or None if handler should
+			be called for all event types
+		for_categories -- a list of category names or None if handler should
+			be called for all categories
+		"""
+		handler = super(InputBuffer, self).register_handler(handler_function, for_event_types, for_categories)
+		try:
+			for category in handler._for_categories:
+				self.add_category_interests(category)
+		except TypeError:
+			# i.e., None was provided to the handler
+			pass
+		return handler
+
+	def is_resend_active(self):
+		return self._resend_active
+
+	def set_resend_active(self, active=True):
+		self._resend_active = active
+
+
+class OutputBuffer(Buffer):
+
+	"""An OutputBuffer that holds local IUs."""
+
+	def __init__(self, owning_component_name, channel=None, participant_config=None):
+		'''Create an Output Buffer.
+
+		Keyword arguments:
+		owning_component_name -- name of the entity that own this buffer
+		participant_config -- RSB configuration
+		'''
+		super(OutputBuffer, self).__init__(owning_component_name, channel, participant_config)
+		self._unique_name = '/ipaaca/component/' + str(owning_component_name) + 'ID' + self._uuid + '/OB'
+		self._server = rsb.createLocalServer(rsb.Scope(self._unique_name))
+		self._server.addMethod('updateLinks', self._remote_update_links, ipaaca.converter.IULinkUpdate, int)
+		self._server.addMethod('updatePayload', self._remote_update_payload, ipaaca.converter.IUPayloadUpdate, int)
+		self._server.addMethod('commit', self._remote_commit, ipaaca_pb2.IUCommission, int)
+		self._server.addMethod('requestResend', self._remote_request_resend, ipaaca_pb2.IUResendRequest, int)
+		self._informer_store = {}
+		self._id_prefix = str(owning_component_name)+'-'+str(self._uuid)+'-IU-'
+		self.__iu_id_counter_lock = threading.Lock()
+
+	def _remote_update_links(self, update):
+		'''Apply a remotely requested update to one of the stored IU's links.'''
+		if update.uid not in self._iu_store:
+			LOGGER.warning("Remote InBuffer tried to spuriously write non-existent IU "+str(update.uid))
+			return 0
+		iu = self._iu_store[update.uid]
+		with iu.revision_lock:
+			if (update.revision != 0) and (update.revision != iu.revision):
+				# (0 means "do not pay attention to the revision number" -> "force update")
+				LOGGER.warning("Remote write operation failed because request was out of date; IU "+str(update.uid))
+				return 0
+			if update.is_delta:
+				iu.modify_links(add=update.new_links, remove=update.links_to_remove, writer_name=update.writer_name)
+			else:
+				iu.set_links(links=update.new_links, writer_name=update.writer_name)
+			self.call_iu_event_handlers(update.uid, local=True, event_type=ipaaca.iu.IUEventType.LINKSUPDATED, category=iu.category)
+			return iu.revision
+
+	def _remote_update_payload(self, update):
+		'''Apply a remotely requested update to one of the stored IU's payload.'''
+		if update.uid not in self._iu_store:
+			LOGGER.warning("Remote InBuffer tried to spuriously write non-existent IU "+str(update.uid))
+			return 0
+		iu = self._iu_store[update.uid]
+		with iu.revision_lock:
+			if (update.revision != 0) and (update.revision != iu.revision):
+				# (0 means "do not pay attention to the revision number" -> "force update")
+				LOGGER.warning(u"Remote update_payload operation failed because request was out of date; IU "+str(update.uid))
+				LOGGER.warning(u"  Writer was: "+update.writer_name)
+				LOGGER.warning(u"  Requested update was: (New keys:) "+','.join(update.new_items.keys())+'  (Removed keys:) '+','.join(update.keys_to_remove))
+				LOGGER.warning(u"  Referred-to revision was "+str(update.revision)+' while local revision is '+str(iu.revision))
+				return 0
+			if update.is_delta:
+				#print('Writing delta update by '+str(update.writer_name))
+				with iu.payload:
+					for k in update.keys_to_remove:
+						iu.payload.__delitem__(k, writer_name=update.writer_name)
+					for k,v in update.new_items.items():
+						iu.payload.__setitem__(k, v, writer_name=update.writer_name)
+			else:
+				#print('Writing non-incr update by '+str(update.writer_name))
+				iu._set_payload(update.new_items, writer_name=update.writer_name)
+				# _set_payload etc. have also incremented the revision number
+			self.call_iu_event_handlers(update.uid, local=True, event_type=ipaaca.iu.IUEventType.UPDATED, category=iu.category)
+			return iu.revision
+
+	def _remote_request_resend(self, iu_resend_request_pack):
+		''' Resend a requested IU over the specific hidden category.'''
+		if iu_resend_request_pack.uid not in self._iu_store:
+			LOGGER.warning("Remote side requested resending of non-existent IU "+str(iu_resend_request_pack.uid))
+			return 0
+		iu = self._iu_store[iu_resend_request_pack.uid]
+		with iu.revision_lock:
+			if iu_resend_request_pack.hidden_scope_name is not None and iu_resend_request_pack.hidden_scope_name is not '':
+				informer = self._get_informer(iu_resend_request_pack.hidden_scope_name)
+				informer.publishData(iu)
+				return iu.revision
+			else:
+				return 0
+
+	def _remote_commit(self, iu_commission):
+		'''Apply a remotely requested commit to one of the stored IUs.'''
+		if iu_commission.uid not in self._iu_store:
+			LOGGER.warning("Remote InBuffer tried to spuriously write non-existent IU "+str(iu_commission.uid))
+			return 0
+		iu = self._iu_store[iu_commission.uid]
+		with iu.revision_lock:
+			if (iu_commission.revision != 0) and (iu_commission.revision != iu.revision):
+				# (0 means "do not pay attention to the revision number" -> "force update")
+				LOGGER.warning("Remote write operation failed because request was out of date; IU "+str(iu_commission.uid))
+				return 0
+			if iu.committed:
+				return 0
+			else:
+				iu._internal_commit(writer_name=iu_commission.writer_name)
+				self.call_iu_event_handlers(iu_commission.uid, local=True, event_type=ipaaca.iu.IUEventType.COMMITTED, category=iu.category)
+				return iu.revision
+
+	def _get_informer(self, iu_category):
+		'''Return (or create, store and return) an informer object for IUs of the specified category.'''
+		if iu_category in self._informer_store:
+			LOGGER.info("Returning informer on scope "+"/ipaaca/channel/"+str(self._channel)+"/category/"+str(iu_category))
+			return self._informer_store[iu_category]
+		informer_iu = rsb.createInformer(
+				rsb.Scope("/ipaaca/channel/"+str(self._channel)+"/category/"+str(iu_category)),
+				config=self._participant_config,
+				dataType=object)
+		self._informer_store[iu_category] = informer_iu #new_tuple
+		LOGGER.info("Returning NEW informer on scope "+"/ipaaca/channel/"+str(self._channel)+"/category/"+str(iu_category))
+		return informer_iu #return new_tuple
+
+	def add(self, iu):
+		'''Add an IU to the IU store, assign an ID and publish it.'''
+		if iu.uid in self._iu_store:
+			raise ipaaca.exception.IUPublishedError(iu)
+		if iu.buffer is not None:
+			raise ipaaca.exception.IUPublishedError(iu)
+		if iu.access_mode != ipaaca.iu.IUAccessMode.MESSAGE:
+			# Messages are not really stored in the OutputBuffer
+			self._iu_store[iu.uid] = iu
+		iu.buffer = self
+		self._publish_iu(iu)
+
+	def remove(self, iu=None, iu_uid=None):
+		'''Remove the iu or an IU corresponding to iu_uid from the OutputBuffer, retracting it from the system.'''
+		if iu is None:
+			if iu_uid is None:
+				return None
+			else:
+				if iu_uid not in self. _iu_store:
+					raise ipaaca.exception.IUNotFoundError(iu_uid)
+				iu = self._iu_store[iu_uid]
+		# unpublish the IU
+		self._retract_iu(iu)
+		del self._iu_store[iu.uid]
+		return iu
+
+	def _publish_iu(self, iu):
+		'''Publish an IU.'''
+		informer = self._get_informer(iu._category)
+		informer.publishData(iu)
+
+	def _retract_iu(self, iu):
+		'''Retract (unpublish) an IU.'''
+		iu_retraction = ipaaca_pb2.IURetraction()
+		iu_retraction.uid = iu.uid
+		iu_retraction.revision = iu.revision
+		informer = self._get_informer(iu._category)
+		informer.publishData(iu_retraction)
+
+	def _send_iu_commission(self, iu, writer_name):
+		'''Send IU commission.
+
+		Keyword arguments:
+		iu -- the IU that has been committed to
+		writer_name -- name of the Buffer that initiated this commit, necessary
+			to enable remote components to filter out updates that originated
+			from their own operations
+		'''
+		# a raw Protobuf object for IUCommission is produced
+		# (unlike updates, where we have an intermediate class)
+		iu_commission = ipaaca_pb2.IUCommission()
+		iu_commission.uid = iu.uid
+		iu_commission.revision = iu.revision
+		iu_commission.writer_name = iu.owner_name if writer_name is None else writer_name
+		informer = self._get_informer(iu._category)
+		informer.publishData(iu_commission)
+
+	def _send_iu_link_update(self, iu, is_delta, revision, new_links=None, links_to_remove=None, writer_name="undef"):
+		'''Send an IU link update.
+
+		Keyword arguments:
+		iu -- the IU being updated
+		is_delta -- whether this is an incremental update or a replacement
+			the whole link dictionary
+		revision -- the new revision number
+		new_links -- a dictionary of new link sets
+		links_to_remove -- a dict of the link sets that shall be removed
+		writer_name -- name of the Buffer that initiated this update, necessary
+			to enable remote components to filter out updates that originate d
+			from their own operations
+		'''
+		if new_links is None:
+			new_links = {}
+		if links_to_remove is None:
+			links_to_remove = {}
+		link_update = ipaaca.converter.IULinkUpdate(iu._uid, is_delta=is_delta, revision=revision)
+		link_update.new_links = new_links
+		if is_delta:
+			link_update.links_to_remove = links_to_remove
+		link_update.writer_name = writer_name
+		informer = self._get_informer(iu._category)
+		informer.publishData(link_update)
+		# FIXME send the notification to the target, if the target is not the writer_name
+
+	def _send_iu_payload_update(self, iu, is_delta, revision, new_items=None, keys_to_remove=None, writer_name="undef"):
+		'''Send an IU payload update.
+
+		Keyword arguments:
+		iu -- the IU being updated
+		is_delta -- whether this is an incremental update or a replacement
+		revision -- the new revision number
+		new_items -- a dictionary of new payload items
+		keys_to_remove -- a list of the keys that shall be removed from the
+		 	payload
+		writer_name -- name of the Buffer that initiated this update, necessary
+			to enable remote components to filter out updates that originate d
+			from their own operations
+		'''
+		if new_items is None:
+			new_items = {}
+		if keys_to_remove is None:
+			keys_to_remove = []
+		payload_update = ipaaca.converter.IUPayloadUpdate(
+			uid=iu._uid,
+			revision=revision,
+			is_delta=is_delta,
+			payload_type=iu.payload_type)
+		payload_update.new_items = new_items 
+		if is_delta:
+			payload_update.keys_to_remove = keys_to_remove
+		payload_update.writer_name = writer_name
+		informer = self._get_informer(iu._category)
+		informer.publishData(payload_update)
diff --git a/ipaacalib/python/src/ipaaca/converter.py b/ipaacalib/python/src/ipaaca/converter.py
new file mode 100644
index 0000000000000000000000000000000000000000..2bd3e690e32cf404a94070ed541e0e975e74c513
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/converter.py
@@ -0,0 +1,274 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import collections
+
+import rsb.converter
+
+import ipaaca_pb2
+import ipaaca.defaults
+import ipaaca.exception
+import ipaaca.iu
+import ipaaca.misc
+
+LOGGER = ipaaca.misc.get_library_logger()
+
+try:
+	import simplejson as json
+except ImportError:
+	import json
+	LOGGER.warn('INFO: Using module "json" instead of "simplejson". Install "simplejson" for better performance.')
+
+
+__all__ = [
+	'IntConverter',
+	'IUConverter',
+	'IULinkUpdate',
+	'IULinkUpdateConverter',
+	'IUPayloadUpdate',
+	'IUPayloadUpdateConverter',
+	'MessageConverter',
+]
+
+
+class IntConverter(rsb.converter.Converter):
+	"""Convert Python int objects to Protobuf ints and vice versa."""
+	def __init__(self, wireSchema="int", dataType=int):
+		super(IntConverter, self).__init__(bytearray, dataType, wireSchema)
+
+	def serialize(self, value):
+		pbo = ipaaca_pb2.IntMessage()
+		pbo.value = value
+		return bytearray(pbo.SerializeToString()), self.wireSchema
+
+	def deserialize(self, byte_stream, ws):
+		pbo = ipaaca_pb2.IntMessage()
+		pbo.ParseFromString( str(byte_stream) )
+		return pbo.value
+
+
+def pack_payload_entry(entry, key, value, _type=ipaaca.iu.IUPayloadType.JSON):
+	entry.key = key
+	if _type == ipaaca.iu.IUPayloadType.JSON: 
+		entry.value = json.dumps(value)
+	elif _type == ipaaca.iu.IUPayloadType.STR or _type == 'MAP':
+		entry.value = str(value)
+	else:
+		raise ipaaca.exception.IpaacaException('Asked to send payload entry with unsupported type "' +  _type + '".')
+	entry.type = _type
+
+
+def unpack_payload_entry(entry):
+	# We assume that the only transfer types are 'STR' or 'JSON'. Both are transparently handled by json.loads
+	if entry.type == ipaaca.iu.IUPayloadType.JSON:
+		return json.loads(entry.value)
+	elif entry.type == ipaaca.iu.IUPayloadType.STR or entry.type == 'str':
+		return entry.value
+	else:
+		LOGGER.warn('Received payload entry with unsupported type "' + entry.type + '".')
+		return entry.value
+
+
+class IUConverter(rsb.converter.Converter):
+	'''
+	Converter class for Full IU representations
+	wire:bytearray <-> wire-schema:ipaaca-full-iu <-> class ipaacaRSB.IU
+	'''
+	def __init__(self, wireSchema="ipaaca-iu", dataType=ipaaca.iu.IU):
+		super(IUConverter, self).__init__(bytearray, dataType, wireSchema)
+		self._access_mode = ipaaca_pb2.IU.PUSH
+		self._remote_data_type = ipaaca.iu.RemotePushIU
+
+	def serialize(self, iu):
+		pbo = ipaaca_pb2.IU()
+		pbo.access_mode = self._access_mode
+		pbo.uid = iu._uid
+		pbo.revision = iu._revision
+		pbo.category = iu._category
+		pbo.payload_type = iu._payload_type
+		pbo.owner_name = iu._owner_name
+		pbo.committed = iu._committed
+		pbo.read_only = iu._read_only
+		for k, v in iu._payload.iteritems():
+			entry = pbo.payload.add()
+			pack_payload_entry(entry, k, v, iu.payload_type)
+		for type_ in iu._links.keys():
+			linkset = pbo.links.add()
+			linkset.type = type_
+			linkset.targets.extend(iu._links[type_])
+		return bytearray(pbo.SerializeToString()), self.wireSchema
+
+	def deserialize(self, byte_stream, ws):
+		pbo = ipaaca_pb2.IU()
+		pbo.ParseFromString(str(byte_stream))
+		_payload = {}
+		for entry in pbo.payload:
+			_payload[entry.key] = unpack_payload_entry(entry)
+		_links = collections.defaultdict(set)
+		for linkset in pbo.links:
+			for target_uid in linkset.targets:
+				_links[linkset.type].add(target_uid)
+		return self._remote_data_type(
+			uid=pbo.uid,
+			revision=pbo.revision,
+			read_only = pbo.read_only,
+			owner_name = pbo.owner_name,
+			category = pbo.category,
+			payload_type = 'str' if pbo.payload_type is 'MAP' else pbo.payload_type,
+			committed = pbo.committed,
+			payload=_payload,
+			links=_links)
+
+
+class MessageConverter(IUConverter):
+	'''
+	Converter class for Full IU representations
+	wire:bytearray <-> wire-schema:ipaaca-full-iu <-> class ipaacaRSB.IU
+	'''
+	def __init__(self, wireSchema="ipaaca-messageiu", dataType=ipaaca.iu.Message):
+		super(MessageConverter, self).__init__(wireSchema, dataType)
+		self._access_mode = ipaaca_pb2.IU.MESSAGE
+		self._remote_data_type = ipaaca.iu.RemoteMessage
+
+
+class IULinkUpdate(object):
+
+	def __init__(self, uid, revision, is_delta, writer_name="undef", new_links=None, links_to_remove=None):
+		super(IULinkUpdate, self).__init__()
+		self.uid = uid
+		self.revision = revision
+		self.writer_name = writer_name
+		self.is_delta = is_delta
+		self.new_links = collections.defaultdict(set) if new_links is None else collections.defaultdict(set, new_links)
+		self.links_to_remove = collections.defaultdict(set) if links_to_remove is None else collections.defaultdict(set, links_to_remove)
+
+	def __str__(self):
+		s =  'LinkUpdate(' + 'uid=' + self.uid + ', '
+		s += 'revision='+str(self.revision)+', '
+		s += 'writer_name='+str(self.writer_name)+', '
+		s += 'is_delta='+str(self.is_delta)+', '
+		s += 'new_links = '+str(self.new_links)+', '
+		s += 'links_to_remove = '+str(self.links_to_remove)+')'
+		return s
+
+
+class IULinkUpdateConverter(rsb.converter.Converter):
+	
+	def __init__(self, wireSchema="ipaaca-iu-link-update", dataType=IULinkUpdate):
+		super(IULinkUpdateConverter, self).__init__(bytearray, dataType, wireSchema)
+
+	def serialize(self, iu_link_update):
+		pbo = ipaaca_pb2.IULinkUpdate()
+		pbo.uid = iu_link_update.uid
+		pbo.writer_name = iu_link_update.writer_name
+		pbo.revision = iu_link_update.revision
+		for type_ in iu_link_update.new_links.keys():
+			linkset = pbo.new_links.add()
+			linkset.type = type_
+			linkset.targets.extend(iu_link_update.new_links[type_])
+		for type_ in iu_link_update.links_to_remove.keys():
+			linkset = pbo.links_to_remove.add()
+			linkset.type = type_
+			linkset.targets.extend(iu_link_update.links_to_remove[type_])
+		pbo.is_delta = iu_link_update.is_delta
+		return bytearray(pbo.SerializeToString()), self.wireSchema
+
+	def deserialize(self, byte_stream, ws):
+		type = self.getDataType()
+		if type == IULinkUpdate:
+			pbo = ipaaca_pb2.IULinkUpdate()
+			pbo.ParseFromString( str(byte_stream) )
+			LOGGER.debug('received an IULinkUpdate for revision '+str(pbo.revision))
+			iu_link_up = IULinkUpdate( uid=pbo.uid, revision=pbo.revision, writer_name=pbo.writer_name, is_delta=pbo.is_delta)
+			for entry in pbo.new_links:
+				iu_link_up.new_links[str(entry.type)] = set(entry.targets)
+			for entry in pbo.links_to_remove:
+				iu_link_up.links_to_remove[str(entry.type)] = set(entry.targets)
+			return iu_link_up
+		else:
+			raise ValueError("Inacceptable dataType %s" % type)
+
+
+class IUPayloadUpdate(object):
+
+	def __init__(self, uid, revision, is_delta, payload_type, writer_name="undef", new_items=None, keys_to_remove=None):
+		super(IUPayloadUpdate, self).__init__()
+		self.uid = uid
+		self.revision = revision
+		self.payload_type = payload_type
+		self.writer_name = writer_name
+		self.is_delta = is_delta
+		self.new_items = {} if new_items is None else new_items
+		self.keys_to_remove = [] if keys_to_remove is None else keys_to_remove
+
+	def __str__(self):
+		s =  'PayloadUpdate(' + 'uid=' + self.uid + ', '
+		s += 'revision='+str(self.revision)+', '
+		s += 'writer_name='+str(self.writer_name)+', '
+		s += 'payload_type='+str(self.payload_type)+', '
+		s += 'is_delta='+str(self.is_delta)+', '
+		s += 'new_items = '+str(self.new_items)+', '
+		s += 'keys_to_remove = '+str(self.keys_to_remove)+')'
+		return s
+
+
+class IUPayloadUpdateConverter(rsb.converter.Converter):
+	def __init__(self, wireSchema="ipaaca-iu-payload-update", dataType=IUPayloadUpdate):
+		super(IUPayloadUpdateConverter, self).__init__(bytearray, dataType, wireSchema)
+
+	def serialize(self, iu_payload_update):
+		pbo = ipaaca_pb2.IUPayloadUpdate()
+		pbo.uid = iu_payload_update.uid
+		pbo.writer_name = iu_payload_update.writer_name
+		pbo.revision = iu_payload_update.revision
+		for k, v in iu_payload_update.new_items.items():
+			entry = pbo.new_items.add()
+			pack_payload_entry(entry, k, v, iu_payload_update.payload_type)
+		pbo.keys_to_remove.extend(iu_payload_update.keys_to_remove)
+		pbo.is_delta = iu_payload_update.is_delta
+		return bytearray(pbo.SerializeToString()), self.wireSchema
+
+	def deserialize(self, byte_stream, ws):
+		type = self.getDataType()
+		if type == IUPayloadUpdate:
+			pbo = ipaaca_pb2.IUPayloadUpdate()
+			pbo.ParseFromString( str(byte_stream) )
+			LOGGER.debug('received an IUPayloadUpdate for revision '+str(pbo.revision))
+			iu_up = IUPayloadUpdate( uid=pbo.uid, revision=pbo.revision, payload_type=None, writer_name=pbo.writer_name, is_delta=pbo.is_delta)
+			for entry in pbo.new_items:
+				iu_up.new_items[entry.key] = unpack_payload_entry(entry)
+			iu_up.keys_to_remove = pbo.keys_to_remove[:]
+			return iu_up
+		else:
+			raise ValueError("Inacceptable dataType %s" % type)
diff --git a/ipaacalib/python/src/ipaaca/defaults.py b/ipaacalib/python/src/ipaaca/defaults.py
new file mode 100644
index 0000000000000000000000000000000000000000..706c714b1d270838f04a84f3cd20dffe432d747c
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/defaults.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+IPAACA_DEFAULT_CHANNEL = 'default'
+
+IPAACA_LOGGER_NAME = 'ipaaca'
+IPAACA_DEFAULT_LOGGING_LEVEL = 'WARNING'
+
+IPAACA_DEFAULT_IU_PAYLOAD_TYPE = 'JSON' # one of ipaaca.iu.IUPayloadType
diff --git a/ipaacalib/python/src/ipaaca/exception.py b/ipaacalib/python/src/ipaaca/exception.py
new file mode 100644
index 0000000000000000000000000000000000000000..f90a6756ef4f2935004e2b60fd76e14c612f60f4
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/exception.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+
+__all__ = [
+	'IpaacaError',
+	'IUCommittedError',
+	'IUNotFoundError',
+	'IUPayloadLockedError',
+	'IUPayloadLockTimeoutError',
+	'IUPublishedError',
+	'IUReadOnlyError',
+	'IUResendRequestFailedError',
+	'IUUpdateFailedError',
+]
+
+
+class IpaacaError(Exception): pass
+
+
+class IUCommittedError(IpaacaError):
+	"""Error indicating that an IU is immutable because it has been committed to."""
+	def __init__(self, iu):
+		super(IUCommittedError, self).__init__('Writing to IU ' + str(iu.uid) + ' failed -- it has been committed to.')
+
+
+class IUNotFoundError(IpaacaError):
+	"""Error indicating that an IU UID was unexpectedly not found in an internal store."""
+	def __init__(self, iu_uid):
+		super(IUNotFoundError, self).__init__('Lookup of IU ' + str(iu_uid) + ' failed.')
+
+
+class IUPayloadLockTimeoutError(IpaacaError):
+	"""Error indicating that exclusive access to the Payload could not be obtained in time."""
+	def __init__(self, iu):
+		super(IUPayloadLockTimeoutError, self).__init__('Timeout while accessing payload of IU ' + str(iu.uid) + '.')
+
+
+class IUPayloadLockedError(IpaacaError):
+	"""Error indicating that exclusive access to the Payload could not be obtained because someone actually locked it."""
+	def __init__(self, iu):
+		super(IUPayloadLockedError, self).__init__('IU '+str(iu.uid)+' was locked during access attempt.')
+
+
+class IUPublishedError(IpaacaError):
+	"""Error publishing of an IU failed since it is already in the buffer."""
+	def __init__(self, iu):
+		super(IUPublishedError, self).__init__('IU ' + str(iu.uid) + ' is already present in the output buffer.')
+
+
+class IUReadOnlyError(IpaacaError):
+	"""Error indicating that an IU is immutable because it is 'read only'."""
+	def __init__(self, iu):
+		super(IUReadOnlyError, self).__init__('Writing to IU ' + str(iu.uid) + ' failed -- it is read-only.')
+
+
+class IUResendRequestFailedError(IpaacaError):
+	"""Error indicating that a remote IU resend failed."""
+	def __init__(self, iu):
+		super(IUResendFailedError, self).__init__('Remote resend failed for IU ' + str(iu.uid) + '.')
+
+
+class IUUpdateFailedError(IpaacaError):
+	"""Error indicating that a remote IU update failed."""
+	def __init__(self, iu):
+		super(IUUpdateFailedError, self).__init__('Remote update failed for IU ' + str(iu.uid) + '.')
diff --git a/ipaacalib/python/src/ipaaca/iu.py b/ipaacalib/python/src/ipaaca/iu.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd55bd78a3dc7b15ae248432cbce202331d8323e
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/iu.py
@@ -0,0 +1,604 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import collections
+import copy
+import threading
+import uuid
+
+import ipaaca_pb2
+import ipaaca.converter
+import ipaaca.exception
+import ipaaca.misc
+import ipaaca.payload
+
+
+__all__ = [
+	'IUAccessMode',
+	'IUEventType',
+	'IUPayloadType',
+	'IU',
+	'Message',
+]
+
+LOGGER = ipaaca.misc.get_library_logger()
+
+IUAccessMode = ipaaca.misc.enum(
+	PUSH = 'PUSH',
+	REMOTE = 'REMOTE',
+	MESSAGE = 'MESSAGE'
+)
+
+
+IUEventType = ipaaca.misc.enum(
+	ADDED = 'ADDED',
+	COMMITTED = 'COMMITTED',
+	DELETED = 'DELETED',
+	RETRACTED = 'RETRACTED',
+	UPDATED = 'UPDATED',
+	LINKSUPDATED = 'LINKSUPDATED',
+	MESSAGE = 'MESSAGE'
+)
+
+
+IUPayloadType = ipaaca.misc.enum(
+	JSON = 'JSON',
+	STR = 'STR'
+)
+
+
+class IUInterface(object):
+
+	"""Base class of all specialised IU classes."""
+
+	def __init__(self, uid, access_mode=IUAccessMode.PUSH, read_only=False, payload_type=None):
+		"""Creates an IU.
+
+		Keyword arguments:
+		uid -- unique ID of this IU
+		access_mode -- access mode of this IU
+		read_only -- flag indicating whether this IU is read_only or not
+		"""
+		self._uid = uid
+		self._revision = None
+		self._category = None
+		self._owner_name = None
+		self._committed = False
+		self._retracted = False
+		self._access_mode = access_mode
+		self._read_only = read_only
+		self._payload_type = payload_type if payload_type is not None else ipaaca.defaults.IPAACA_DEFAULT_IU_PAYLOAD_TYPE
+		self._buffer = None
+		# payload is not present here
+		self._links = collections.defaultdict(set)
+
+	def __str__(self):
+		s = unicode(self.__class__)+"{ "
+		s += "category="+("<None>" if self._category is None else self._category)+" "
+		s += "uid="+self._uid+" "
+		s += "(buffer="+(self.buffer.unique_name if self.buffer is not None else "<None>")+") "
+		s += "owner_name=" + ("<None>" if self.owner_name is None else self.owner_name) + " "
+		s += "payload={ "
+		for k,v in self.payload.items():
+			s += k+":'"+unicode(v)+"', "
+		s += "} "
+		s += "links={ "
+		for t,ids in self.get_all_links().items():
+			s += t+":'"+unicode(ids)+"', "
+		s += "} "
+		s += "}"
+		return s
+
+
+	def _add_and_remove_links(self, add, remove):
+		'''Just add and remove the new links in our links set, do not send an update here'''
+		'''Note: Also used for remotely enforced links updates.'''
+		for type in remove.keys(): self._links[type] -= set(remove[type])
+		for type in add.keys(): self._links[type] |= set(add[type])
+	def _replace_links(self, links):
+		'''Just wipe and replace our links set, do not send an update here'''
+		'''Note: Also used for remotely enforced links updates.'''
+		self._links = collections.defaultdict(set)
+		for type in links.keys(): self._links[type] |= set(links[type])
+
+	def add_links(self, type, targets, writer_name=None):
+		'''Attempt to add links if the conditions are met
+		and send an update message. Then call the local setter.'''
+		if not hasattr(targets, '__iter__'): targets=[targets]
+		self._modify_links(is_delta=True, new_links={type:targets}, links_to_remove={}, writer_name=writer_name)
+		self._add_and_remove_links( add={type:targets}, remove={} )
+	def remove_links(self, type, targets, writer_name=None):
+		'''Attempt to remove links if the conditions are met
+		and send an update message. Then call the local setter.'''
+		if not hasattr(targets, '__iter__'): targets=[targets]
+		self._modify_links(is_delta=True, new_links={}, links_to_remove={type:targets}, writer_name=writer_name)
+		self._add_and_remove_links( add={}, remove={type:targets} )
+	def modify_links(self, add, remove, writer_name=None):
+		'''Attempt to modify links if the conditions are met
+		and send an update message. Then call the local setter.'''
+		self._modify_links(is_delta=True, new_links=add, links_to_remove=remove, writer_name=writer_name)
+		self._add_and_remove_links( add=add, remove=remove )
+	def set_links(self, links, writer_name=None):
+		'''Attempt to set (replace) links if the conditions are met
+		and send an update message. Then call the local setter.'''
+		self._modify_links(is_delta=False, new_links=links, links_to_remove={}, writer_name=writer_name)
+		self._replace_links( links=links )
+	def get_links(self, type):
+		return set(self._links[type])
+	def get_all_links(self):
+		return copy.deepcopy(self._links)
+
+	def _get_revision(self):
+		return self._revision
+	revision = property(fget=_get_revision, doc='Revision number of the IU.')
+
+	def _get_category(self):
+		return self._category
+	category = property(fget=_get_category, doc='Category of the IU.')
+
+	def _get_payload_type(self):
+		return self._payload_type
+	def _set_payload_type(self, type):
+		if self._buffer is None:
+			self._payload_type = type
+		else:
+			raise IpaacaException('The IU is already in a buffer, cannot change payload type anymore.')
+	payload_type = property(
+		fget=_get_payload_type, 
+		fset=_set_payload_type,
+		 doc='Type of the IU payload')
+
+	def _get_committed(self):
+		return self._committed
+	committed = property(
+			fget=_get_committed,
+			doc='Flag indicating whether this IU has been committed to.')
+
+	def _get_retracted(self):
+		return self._retracted
+	retracted = property(
+			fget=_get_retracted,
+			doc='Flag indicating whether this IU has been retracted.')
+
+	def _get_uid(self):
+		return self._uid
+	uid = property(fget=_get_uid, doc='Unique ID of the IU.')
+
+	def _get_access_mode(self):
+		return self._access_mode
+	access_mode = property(fget=_get_access_mode, doc='Access mode of the IU.')
+
+	def _get_read_only(self):
+		return self._read_only
+	read_only = property(
+			fget=_get_read_only,
+			doc='Flag indicating whether this IU is read only.')
+
+	def _get_buffer(self):
+		return self._buffer
+	def _set_buffer(self, buffer):
+		if self._buffer is not None:
+			raise IpaacaException('The IU is already in a buffer, cannot move it.')
+		self._buffer = buffer
+	buffer = property(
+			fget=_get_buffer,
+			fset=_set_buffer,
+			doc='Buffer this IU is held in.')
+
+	def _get_owner_name(self):
+		return self._owner_name
+	def _set_owner_name(self, owner_name):
+		if self._owner_name is not None:
+			raise Exception('The IU already has an owner name, cannot change it.')
+		self._owner_name = owner_name
+	owner_name = property(
+			fget=_get_owner_name,
+			fset=_set_owner_name,
+			doc="The IU's owner's name.")
+
+
+class IU(IUInterface):
+
+	"""A local IU."""
+
+	def __init__(self, category='undef', access_mode=IUAccessMode.PUSH, read_only=False, payload_type=None):
+		super(IU, self).__init__(uid=None, access_mode=access_mode, read_only=read_only, payload_type=payload_type)
+		self._revision = 1
+		self.uid = str(uuid.uuid4())
+		self._category = str(category)
+		self.revision_lock = threading.RLock()
+		self._payload = ipaaca.payload.Payload(iu=self)
+
+	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		with self.revision_lock:
+			# modify links locally
+			self._increase_revision_number()
+			if self.is_published:
+				# send update to remote holders
+				self.buffer._send_iu_link_update(
+						self,
+						revision=self.revision,
+						is_delta=is_delta,
+						new_links=new_links,
+						links_to_remove=links_to_remove,
+						writer_name=self.owner_name if writer_name is None else writer_name)
+
+	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
+		"""Modify the payload: add or remove items from this payload locally and send update."""
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		with self.revision_lock:
+			# set item locally
+			# FIXME: Is it actually set locally?
+			self._increase_revision_number()
+			if self.is_published:
+				#print('  _modify_payload: running send_iu_pl_upd with writer name '+str(writer_name))
+				# send update to remote holders
+				self.buffer._send_iu_payload_update(
+						self,
+						revision=self.revision,
+						is_delta=is_delta,
+						new_items=new_items,
+						keys_to_remove=keys_to_remove,
+						writer_name=self.owner_name if writer_name is None else writer_name)
+
+	def _increase_revision_number(self):
+		self._revision += 1
+
+	def _internal_commit(self, writer_name=None):
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		with self.revision_lock:
+			if not self._committed:
+				self._increase_revision_number()
+				self._committed = True
+				if self.buffer is not None:
+					self.buffer._send_iu_commission(self, writer_name=writer_name)
+
+	def commit(self):
+		"""Commit to this IU."""
+		return self._internal_commit()
+
+	def _get_payload(self):
+		return self._payload
+	def _set_payload(self, new_pl, writer_name=None):
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		with self.revision_lock:
+			self._increase_revision_number()
+			self._payload = ipaaca.payload.Payload(
+					iu=self,
+					writer_name=None if self.buffer is None else (self.buffer.unique_name if writer_name is None else writer_name),
+					new_payload=new_pl)
+	payload = property(
+			fget=_get_payload,
+			fset=_set_payload,
+			doc='Payload dictionary of this IU.')
+
+	def _get_is_published(self):
+		return self.buffer is not None
+	is_published = property(
+			fget=_get_is_published,
+			doc='Flag indicating whether this IU has been published or not.')
+
+	def _set_buffer(self, buffer):
+		if self._buffer is not None:
+			raise Exception('The IU is already in a buffer, cannot move it.')
+		self._buffer = buffer
+		self.owner_name = buffer.unique_name
+		self._payload.owner_name = buffer.unique_name
+	buffer = property(
+			fget=IUInterface._get_buffer,
+			fset=_set_buffer,
+			doc='Buffer this IU is held in.')
+
+	def _set_uid(self, uid):
+		if self._uid is not None:
+			raise AttributeError('The uid of IU ' + self.uid + ' has already been set, cannot change it.')
+		self._uid = uid
+	uid = property(
+			fget=IUInterface._get_uid,
+			fset=_set_uid,
+			doc='Unique ID of the IU.')
+
+
+class Message(IU):
+	"""Local IU of Message sub-type. Can be handled like a normal IU, but on the remote side it is only existent during the handler calls."""
+	def __init__(self, category='undef', access_mode=IUAccessMode.MESSAGE, read_only=True, payload_type=None):
+		super(Message, self).__init__(category=str(category), access_mode=access_mode, read_only=read_only, payload_type=payload_type)
+
+	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
+		if self.is_published:
+			LOGGER.info('Info: modifying a Message after sending has no global effects')
+
+	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
+		if self.is_published:
+			LOGGER.info('Info: modifying a Message after sending has no global effects')
+
+	def _increase_revision_number(self):
+		self._revision += 1
+
+	def _internal_commit(self, writer_name=None):
+		if self.is_published:
+			LOGGER.info('Info: committing to a Message after sending has no global effects')
+
+	def commit(self):
+		return self._internal_commit()
+
+	def _get_payload(self):
+		return self._payload
+	def _set_payload(self, new_pl, writer_name=None):
+		if self.is_published:
+			LOGGER.info('Info: modifying a Message after sending has no global effects')
+		else:
+			if self.committed:
+				raise ipaaca.exception.IUCommittedError(self)
+			with self.revision_lock:
+				self._increase_revision_number()
+				self._payload = ipaaca.payload.Payload(
+						iu=self,
+						writer_name=None if self.buffer is None else (self.buffer.unique_name if writer_name is None else writer_name),
+						new_payload=new_pl)
+	payload = property(
+			fget=_get_payload,
+			fset=_set_payload,
+			doc='Payload dictionary of this IU.')
+
+	def _get_is_published(self):
+		return self.buffer is not None
+	is_published = property(
+			fget=_get_is_published,
+			doc='Flag indicating whether this IU has been published or not.')
+
+	def _set_buffer(self, buffer):
+		if self._buffer is not None:
+			raise Exception('The IU is already in a buffer, cannot move it.')
+		self._buffer = buffer
+		self.owner_name = buffer.unique_name
+		self._payload.owner_name = buffer.unique_name
+	buffer = property(
+			fget=IUInterface._get_buffer,
+			fset=_set_buffer,
+			doc='Buffer this IU is held in.')
+
+	def _set_uid(self, uid):
+		if self._uid is not None:
+			raise AttributeError('The uid of IU ' + self.uid + ' has already been set, cannot change it.')
+		self._uid = uid
+	uid = property(
+			fget=IUInterface._get_uid,
+			fset=_set_uid,
+			doc='Unique ID of the IU.')
+
+
+class RemoteMessage(IUInterface):
+
+	"""A remote IU with access mode 'MESSAGE'."""
+
+	def __init__(self, uid, revision, read_only, owner_name, category, payload_type, committed, payload, links):
+		super(RemoteMessage, self).__init__(uid=uid, access_mode=IUAccessMode.PUSH, read_only=read_only, payload_type=payload_type)
+		self._revision = revision
+		self._category = category
+		self.owner_name = owner_name
+		self._committed = committed
+		self._retracted = False
+		# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
+		#  don't try to invoke any modification checks or network updates ourselves either.
+		#  We are just receiving it here and applying the new data.
+		self._payload = ipaaca.payload.Payload(iu=self, new_payload=payload, omit_init_update_message=True)
+		self._links = links
+
+	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
+		LOGGER.info('Info: modifying a RemoteMessage only has local effects')
+
+	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
+		LOGGER.info('Info: modifying a RemoteMessage only has local effects')
+
+	def commit(self):
+		LOGGER.info('Info: committing to a RemoteMessage only has local effects')
+
+	def _get_payload(self):
+		return self._payload
+	def _set_payload(self, new_pl):
+		LOGGER.info('Info: modifying a RemoteMessage only has local effects')
+		self._payload = ipaaca.payload.Payload(iu=self, new_payload=new_pl, omit_init_update_message=True)
+	payload = property(
+			fget=_get_payload,
+			fset=_set_payload,
+			doc='Payload dictionary of the IU.')
+
+	def _apply_link_update(self, update):
+		"""Apply a IULinkUpdate to the IU."""
+		LOGGER.warning('Warning: should never be called: RemoteMessage._apply_link_update')
+		self._revision = update.revision
+		if update.is_delta:
+			self._add_and_remove_links(add=update.new_links, remove=update.links_to_remove)
+		else:
+			self._replace_links(links=update.new_links)
+
+	def _apply_update(self, update):
+		"""Apply a IUPayloadUpdate to the IU."""
+		LOGGER.warning('Warning: should never be called: RemoteMessage._apply_update')
+		self._revision = update.revision
+		if update.is_delta:
+			for k in update.keys_to_remove: self.payload._remotely_enforced_delitem(k)
+			for k, v in update.new_items.items(): self.payload._remotely_enforced_setitem(k, v)
+		else:
+			# NOTE Please read the comment in the constructor
+			self._payload = ipaaca.payload.Payload(iu=self, new_payload=update.new_items, omit_init_update_message=True)
+
+	def _apply_commission(self):
+		"""Apply commission to the IU"""
+		LOGGER.warning('Warning: should never be called: RemoteMessage._apply_commission')
+		self._committed = True
+
+	def _apply_retraction(self):
+		"""Apply retraction to the IU"""
+		LOGGER.warning('Warning: should never be called: RemoteMessage._apply_retraction')
+		self._retracted = True
+
+
+class RemotePushIU(IUInterface):
+
+	"""A remote IU with access mode 'PUSH'."""
+
+	def __init__(self, uid, revision, read_only, owner_name, category, payload_type, committed, payload, links):
+		super(RemotePushIU, self).__init__(uid=uid, access_mode=IUAccessMode.PUSH, read_only=read_only, payload_type=payload_type)
+		self._revision = revision
+		self._category = category
+		self.owner_name = owner_name
+		self._committed = committed
+		self._retracted = False
+		# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
+		#  don't try to invoke any modification checks or network updates ourselves either.
+		#  We are just receiving it here and applying the new data.
+		self._payload = ipaaca.payload.Payload(iu=self, new_payload=payload, omit_init_update_message=True)
+		self._links = links
+
+	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
+		"""Modify the links: add or remove item from this payload remotely and send update."""
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		if self.read_only:
+			raise ipaaca.exception.IUReadOnlyError(self)
+		requested_update = ipaaca.converter.IULinkUpdate(
+				uid=self.uid,
+				revision=self.revision,
+				is_delta=is_delta,
+				writer_name=self.buffer.unique_name,
+				new_links=new_links,
+				links_to_remove=links_to_remove)
+		remote_server = self.buffer._get_remote_server(self)
+		new_revision = remote_server.updateLinks(requested_update)
+		if new_revision == 0:
+			raise ipaaca.exception.IUUpdateFailedError(self)
+		else:
+			self._revision = new_revision
+
+	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
+		"""Modify the payload: add or remove item from this payload remotely and send update."""
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		if self.read_only:
+			raise ipaaca.exception.IUReadOnlyError(self)
+		requested_update = ipaaca.converter.IUPayloadUpdate(
+				uid=self.uid,
+				revision=self.revision,
+				payload_type=self.payload_type,
+				is_delta=is_delta,
+				writer_name=self.buffer.unique_name,
+				new_items=new_items,
+				keys_to_remove=keys_to_remove)
+		remote_server = self.buffer._get_remote_server(self)
+		new_revision = remote_server.updatePayload(requested_update)
+		if new_revision == 0:
+			raise ipaaca.exception.IUUpdateFailedError(self)
+		else:
+			self._revision = new_revision
+
+	def commit(self):
+		"""Commit to this IU."""
+		if self.read_only:
+			raise ipaaca.exception.IUReadOnlyError(self)
+		if self._committed:
+			# ignore commit requests when already committed
+			return
+		else:
+			commission_request = ipaaca_pb2.IUCommission()
+			commission_request.uid = self.uid
+			commission_request.revision = self.revision
+			commission_request.writer_name = self.buffer.unique_name
+			remote_server = self.buffer._get_remote_server(self)
+			new_revision = remote_server.commit(commission_request)
+			if new_revision == 0:
+				raise ipaaca.exception.IUUpdateFailedError(self)
+			else:
+				self._revision = new_revision
+				self._committed = True
+
+	def _get_payload(self):
+		return self._payload
+	def _set_payload(self, new_pl):
+		if self.committed:
+			raise ipaaca.exception.IUCommittedError(self)
+		if self.read_only:
+			raise ipaaca.exception.IUReadOnlyError(self)
+		requested_update = ipaaca.converter.IUPayloadUpdate(
+				uid=self.uid,
+				revision=self.revision,
+				payload_type=self.payload_type,
+				is_delta=False,
+				writer_name=self.buffer.unique_name,
+				new_items=new_pl,
+				keys_to_remove=[])
+		remote_server = self.buffer._get_remote_server(self)
+		new_revision = remote_server.updatePayload(requested_update)
+		if new_revision == 0:
+			raise ipaaca.exception.IUUpdateFailedError(self)
+		else:
+			self._revision = new_revision
+			# NOTE Please read the comment in the constructor
+			self._payload = ipaaca.payload.Payload(iu=self, new_payload=new_pl, omit_init_update_message=True)
+	payload = property(
+			fget=_get_payload,
+			fset=_set_payload,
+			doc='Payload dictionary of the IU.')
+
+	def _apply_link_update(self, update):
+		"""Apply a IULinkUpdate to the IU."""
+		self._revision = update.revision
+		if update.is_delta:
+			self._add_and_remove_links(add=update.new_links, remove=update.links_to_remove)
+		else:
+			self._replace_links(links=update.new_links)
+
+	def _apply_update(self, update):
+		"""Apply a IUPayloadUpdate to the IU."""
+		self._revision = update.revision
+		if update.is_delta:
+			for k in update.keys_to_remove: self.payload._remotely_enforced_delitem(k)
+			for k, v in update.new_items.items(): self.payload._remotely_enforced_setitem(k, v)
+		else:
+			# NOTE Please read the comment in the constructor
+			self._payload = ipaaca.payload.Payload(iu=self, new_payload=update.new_items, omit_init_update_message=True)
+
+	def _apply_commission(self):
+		"""Apply commission to the IU"""
+		self._committed = True
+
+	def _apply_retraction(self):
+		"""Apply retraction to the IU"""
+		self._retracted = True
diff --git a/ipaacalib/python/src/ipaaca/misc.py b/ipaacalib/python/src/ipaaca/misc.py
new file mode 100644
index 0000000000000000000000000000000000000000..44932d5f47442df1b4ce44c5399a31433a374431
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/misc.py
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+
+import argparse
+import logging
+
+import ipaaca.defaults
+
+
+__all__ = [
+	'enum',
+	'IpaacaArgumentParser',
+]
+
+
+def enum(*sequential, **named):
+	"""Create an enum type.
+
+	Based on suggestion of Alec Thomas on stackoverflow.com:
+	http://stackoverflow.com/questions/36932/
+		whats-the-best-way-to-implement-an-enum-in-python/1695250#1695250
+	"""
+	enums = dict(zip(sequential, range(len(sequential))), **named)
+	enums['_choices'] = enums.keys()
+	return type('Enum', (object,), enums)
+
+
+class IpaacaLoggingHandler(logging.Handler):
+	'''A logging handler that prints to stdout.'''
+
+	def __init__(self, prefix='IPAACA', level=logging.NOTSET):
+		logging.Handler.__init__(self, level)
+		self._prefix = prefix
+
+	def emit(self, record):
+		meta = '[%s: %s] ' % (self._prefix, str(record.levelname))
+		msg = str(record.msg.format(record.args))
+		print(meta + msg)
+
+
+class GenericNoLoggingHandler(logging.Handler):
+	'''A logging handler that produces no output'''
+	def emit(self, record): pass
+
+
+def get_library_logger():
+	'''Get ipaaca's library-wide logger object.'''
+	return logging.getLogger(ipaaca.defaults.IPAACA_LOGGER_NAME)
+
+
+__IPAACA_LOGGING_HANDLER = IpaacaLoggingHandler('IPAACA')
+__GENERIC_NO_LOG_HANDLER = GenericNoLoggingHandler()
+
+# By default, suppress library logging
+# - for IPAACA
+get_library_logger().addHandler(__GENERIC_NO_LOG_HANDLER)
+# - for RSB
+logging.getLogger('rsb').addHandler(__GENERIC_NO_LOG_HANDLER)
+
+
+def enable_logging(level=None):
+	'''Enable ipaaca's 'library-wide logging.'''
+	ipaaca_logger = get_library_logger()
+	ipaaca_logger.addHandler(__IPAACA_LOGGING_HANDLER)
+	ipaaca_logger.removeHandler(__GENERIC_NO_LOG_HANDLER)
+	ipaaca_logger.setLevel(level=level if level is not None else
+		ipaaca.defaults.IPAACA_DEFAULT_LOGGING_LEVEL)
+
+
+class IpaacaArgumentParser(argparse.ArgumentParser):
+
+	class IpaacaDefaultChannelAction(argparse.Action):
+
+		def __call__(self, parser, namespace, values, option_string=None):
+			ipaaca.defaults.IPAACA_DEFAULT_CHANNEL = values
+
+	class IpaacaPayloadTypeAction(argparse.Action):
+
+		def __call__(self, parser, namespace, values, option_string=None):
+			ipaaca.defaults.IPAACA_DEFAULT_IU_PAYLOAD_TYPE = values
+
+	class IpaacaLoggingLevelAction(argparse.Action):
+
+		def __call__(self, parser, namespace, values, option_string=None):
+			enable_logging(values)
+
+	class IpaacaRSBLoggingLevelAction(argparse.Action):
+
+		def __call__(self, parser, namespace, values, option_string=None):
+			rsb_logger = logging.getLogger('rsb')
+			rsb_logger.addHandler(IpaacaLoggingHandler('RSB'))
+			rsb_logger.removeHandler(__GENERIC_NO_LOG_HANDLER)
+			rsb_logger.setLevel(level=values)
+
+	def __init__(self, prog=None, usage=None, description=None, epilog=None,
+			parents=[], formatter_class=argparse.HelpFormatter,
+			prefix_chars='-', fromfile_prefix_chars=None, 
+			argument_default=None, conflict_handler='error', add_help=True):
+		super(IpaacaArgumentParser, self).__init__(prog=prog, usage=usage,
+			description=description, epilog=epilog, parents=parents,
+			formatter_class=formatter_class, prefix_chars=prefix_chars,
+			fromfile_prefix_chars=fromfile_prefix_chars,
+			argument_default=argument_default, 
+			conflict_handler=conflict_handler, add_help=add_help)
+
+	def _add_ipaaca_lib_arguments(self):
+		ipaacalib_group = self.add_argument_group('IPAACA library arguments')
+		ipaacalib_group.add_argument(
+			'--ipaaca-payload-type', 
+			action=self.IpaacaPayloadTypeAction,
+			choices=['JSON', 'STR'], # one of ipaaca.iu.IUPayloadTypes
+			dest='_ipaaca_payload_type_',
+			default='JSON',
+			help="specify payload type (default: 'JSON')")
+		ipaacalib_group.add_argument(
+			'--ipaaca-default-channel', 
+			action=self.IpaacaDefaultChannelAction,
+			default='default',
+			metavar='NAME',
+			dest='_ipaaca_default_channel_',
+			help="specify default IPAACA channel name (default: 'default')")
+		ipaacalib_group.add_argument(
+			'--ipaaca-enable-logging', 
+			action=self.IpaacaLoggingLevelAction,
+			choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
+			dest='_ipaaca_logging_level_',
+			help="enable IPAACA logging with threshold")
+		rsblib_group = self.add_argument_group('RSB library arguments')
+		rsblib_group.add_argument(
+			'--rsb-enable-logging', 
+			action=self.IpaacaRSBLoggingLevelAction,
+			choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
+			dest='_ipaaca_rsb_enable_logging_',
+			help="enable RSB logging with threshold")
+
+	def parse_args(self, args=None, namespace=None):
+		self._add_ipaaca_lib_arguments() # Add ipaaca-args just before parsing
+		result = super(IpaacaArgumentParser, self).parse_args(args, namespace)
+		# Delete ipaaca specific arguments (beginning with '_ipaaca' and 
+		# ending with an underscore) from the resulting Namespace object.
+		for item in dir(result):
+			if item.startswith('_ipaaca') and item.endswith('_'):
+				delattr(result, item)
+		return result
diff --git a/ipaacalib/python/src/ipaaca/payload.py b/ipaacalib/python/src/ipaaca/payload.py
new file mode 100644
index 0000000000000000000000000000000000000000..13a5e36524e380954f3cb4ba0bb0f2ced624e54c
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/payload.py
@@ -0,0 +1,296 @@
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import threading
+import time
+
+import ipaaca.exception
+
+
+__all__ = [
+	'Payload',
+	'PayloadItemDictProxy',
+	'PayloadItemListProxy',
+]
+
+
+_DEFAULT_PAYLOAD_UPDATE_TIMEOUT = 0.1
+
+
+class Payload(dict):
+
+	def __init__(self, iu, writer_name=None, new_payload=None, omit_init_update_message=False, update_timeout=_DEFAULT_PAYLOAD_UPDATE_TIMEOUT):
+		self.iu = iu
+		_pl = {}
+		for k, v in ({} if new_payload is None else new_payload).iteritems():
+			_pl[unicode(k, 'utf8') if type(k) == str else k] = unicode(v, 'utf8') if type(v) == str else v
+		# NOTE omit_init_update_message is necessary to prevent checking for
+		#   exceptions and sending updates in the case where we just receive
+		#   a whole new payload from the remote side and overwrite it locally.
+		for k, v in _pl.iteritems():
+			dict.__setitem__(self, k, v)
+		if (not omit_init_update_message) and (self.iu.buffer is not None):
+			self.iu._modify_payload(
+				is_delta=False,
+				new_items=_pl,
+				keys_to_remove=[],
+				writer_name=writer_name)
+		self._update_on_every_change = True
+		self._update_timeout = update_timeout
+		self._collected_modifications = {}
+		self._collected_removals = []
+		self._batch_update_writer_name = None  # name of remote buffer or None
+		self._batch_update_lock = threading.RLock()
+		self._batch_update_cond = threading.Condition(threading.RLock())
+
+	def __getitem__(self, k):
+		value = dict.__getitem__(self, k)
+		if isinstance(value, dict):
+			return PayloadItemDictProxy(value, self, k)
+		elif isinstance(value, list):
+			return PayloadItemListProxy(value, self, k)
+		else:
+			return value
+
+	def __setitem__(self, k, v, writer_name=None):
+		with self._batch_update_lock:
+			k = unicode(k, 'utf8') if type(k) == str else k
+			v = unicode(v, 'utf8') if type(v) == str else v
+			if self._update_on_every_change:
+				self.iu._modify_payload(
+					is_delta=True,
+					new_items={k:v},
+					keys_to_remove=[],
+					writer_name=writer_name)
+			else: # Collect additions/modifications
+				self._batch_update_writer_name = writer_name
+				self._collected_modifications[k] = v
+				# revoke deletion of item since a new version has been added
+				self._collected_removals = [i for i in self._collected_removals if i!=k]
+			return dict.__setitem__(self, k, v)
+
+	def __delitem__(self, k, writer_name=None):
+		with self._batch_update_lock:
+			k = unicode(k, 'utf8') if type(k) == str else k
+			if self._update_on_every_change:
+				self.iu._modify_payload(
+					is_delta=True,
+					new_items={},
+					keys_to_remove=[k],
+					writer_name=writer_name)
+			else: # Collect additions/modifications
+				self._batch_update_writer_name = writer_name
+				self._collected_removals.append(k)
+				# revoke older update of item since more recent changes take precedence
+				if k in self._collected_modifications: del self._collected_modifications[k]
+			return dict.__delitem__(self, k)
+
+	# Context-manager based batch updates, not thread-safe (on remote updates)
+	def __enter__(self):
+		self._wait_batch_update_lock(self._update_timeout)
+		self._update_on_every_change = False
+
+	# Context-manager based batch updates, not thread-safe (on remote updates)
+	def __exit__(self, type, value, traceback):
+		self.iu._modify_payload(
+			is_delta=True,
+			new_items=self._collected_modifications,
+			keys_to_remove=self._collected_removals,
+			writer_name=self._batch_update_writer_name)
+		self._collected_modifications = {}
+		self._collected_removals = []
+		self._update_on_every_change = True
+		self._batch_update_writer_name = None
+		self._batch_update_lock.release()
+
+	def merge(self, payload, writer_name=None):
+		with self._batch_update_lock:
+			for k, v in payload.iteritems():
+				k = unicode(k, 'utf8') if type(k) == str else k
+				v = unicode(v, 'utf8') if type(v) == str else v
+			self.iu._modify_payload(
+				is_delta=True,
+				new_items=payload,
+				keys_to_remove=[],
+				writer_name=writer_name)
+			return dict.update(self, payload) # batch update
+
+	def _remotely_enforced_setitem(self, k, v):
+		"""Sets an item when requested remotely."""
+		dict.__setitem__(self, k, v)
+
+	def _remotely_enforced_delitem(self, k):
+		"""Deletes an item when requested remotely."""
+		if k in self: dict.__delitem__(self, k)
+
+	def _wait_batch_update_lock(self, timeout):
+		# wait lock with time-out http://stackoverflow.com/a/8393033
+		with self._batch_update_cond:
+			current_time = start_time = time.time()
+			while current_time < start_time + timeout:
+				if self._batch_update_lock.acquire(False):
+					return True
+				else:
+					self._batch_update_cond.wait(timeout - current_time + start_time)
+					current_time = time.time()
+		raise ipaaca.exception.IUPayloadLockTimeoutError(self.iu)
+
+
+class PayloadItemProxy(object):
+
+	def __init__(self, content, payload, identifier_in_payload):
+		self.payload = payload
+		self.content = content
+		self.identifier_in_payload = identifier_in_payload
+
+	def _notify_payload(self):
+		try:
+			self.payload[self.identifier_in_payload] = self.content
+		except ipaaca.exception.IUUpdateFailedError as e:
+			# IU update failed. Use the ResendRequest mechanism
+			# to replace the altered RemotePushIU with the unchanged
+			# payload from its OutputBuffer.''
+			iu = self.payload.iu
+			iu.buffer._request_remote_resend(iu)
+			raise e # re-raise IUUpdateFailedError from aboves
+
+	def _create_proxy(self, obj, identifier_in_payload):
+		if isinstance(obj, dict):
+			return PayloadItemDictProxy(obj, self.payload, identifier_in_payload)
+		elif isinstance(obj, list):
+			return PayloadItemListProxy(obj, self.payload, identifier_in_payload)
+		else:
+			return obj
+
+	def __setitem__(self, k, v):
+		self.content.__setitem__(k,v)
+		self._notify_payload()
+
+	def __getitem__(self, k):
+		item = self.content.__getitem__(k)
+		return self._create_proxy(item, k)
+
+	def __delitem__(self, k):
+		self.content.__delitem__(k)
+		self._notify_payload()
+
+
+class PayloadItemDictProxy(PayloadItemProxy, dict):
+
+	def __init__(self, content, payload, identifier_in_payload):
+		dict.__init__(self, content)
+		PayloadItemProxy.__init__(self, content, payload, identifier_in_payload)
+
+	def clear(self):
+		self.content.clear()
+		self._notify_payload()
+
+	def get(self, key, default=None):
+		value = self.content.get(key, default)
+		return self._create_proxy(value, key)
+
+	def items(self):
+		return [(key, value) for key, value in self.iteritems()]
+
+	def iteritems(self):
+		for key, value in self.content.iteritems():
+			yield key, self._create_proxy(value, key)
+
+	def values(self):
+		return [value for value in self.itervalues()]
+
+	def itervalues(self):
+		for key, value in self.content.iteritems():
+			yield self._create_proxy(value, key)
+
+	def pop(self, key, *args):
+		x = self.content.pop(key, *args)
+		self._notify_payload()
+		return x
+
+	def popitem(self):
+		x = self.content.popitem()
+		self._notify_payload()
+		return x
+
+	def setdefault(self, key, default=None):
+		notification_necessary = not key in self.content
+		x = self.content.setdefault(key, default)
+		if notification_necessary:
+			self._notify_payload()
+		return x
+
+	def update(self, *args, **kwargs):
+		self.content.update(*args, **kwargs)
+		self._notify_payload()
+
+
+class PayloadItemListProxy(PayloadItemProxy, list):
+
+	def __init__(self, content, payload, identifier_in_payload):
+		list.__init__(self, content)
+		PayloadItemProxy.__init__(self, content, payload, identifier_in_payload)
+
+	def __iter__(self):
+		for index, item in enumerate(self.content):
+			yield self._create_proxy(item, index)
+
+	def append(self, x):
+		self.content.append(x)
+		self._notify_payload()
+
+	def extend(self, l):
+		self.content.extend(l)
+		self._notify_payload()
+
+	def insert(self, i, x):
+		self.content.insert(i, x)
+		self._notify_payload()
+
+	def remove(self, x):
+		self.content.remove(x)
+		self._notify_payload()
+
+	def pop(self, *args, **kwargs):
+		x = self.content.pop(*args, **kwargs)
+		self._notify_payload()
+		return x
+
+	def sort(self, cmp=None, key=None, reverse=False):
+		self.content.sort(cmp, key, reverse)
+		self._notify_payload()
+
+	def reverse(self):
+		self.content.reverse()
+		self._notify_payload()
diff --git a/ipaacalib/python/src/ipaaca/util/__init__.py b/ipaacalib/python/src/ipaaca/util/__init__.py
index 199d379b66d80b4e2f7a9c375d9e4aa7c53bef7a..c6727687b13273ea1f6fcb0acfe369ae90d2b213 100644
--- a/ipaacalib/python/src/ipaaca/util/__init__.py
+++ b/ipaacalib/python/src/ipaaca/util/__init__.py
@@ -1,9 +1,11 @@
+# -*- coding: utf-8 -*-
+
 # This file is part of IPAACA, the
 #  "Incremental Processing Architecture
-#   for Artificial Conversational Agents".	
+#   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2013 Sociable Agents Group
-#                         CITEC, Bielefeld University	
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
 # http://purl.org/net/ipaaca
@@ -20,7 +22,7 @@
 # You should have received a copy of the LGPL along with this
 # program. If not, go to http://www.gnu.org/licenses/lgpl.html
 # or write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.	
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #
 # The development of this software was supported by the
 # Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -28,4 +30,6 @@
 # Forschungsgemeinschaft (DFG) in the context of the German
 # Excellence Initiative.
 
+from __future__ import division, print_function
+
 from notifier import ComponentNotifier
diff --git a/ipaacalib/python/src/ipaaca/util/notifier.py b/ipaacalib/python/src/ipaaca/util/notifier.py
index 1ee991e833af8a776b8c040ac8fc2d68e687b7b0..750d39affd5b657cf6c761d2a919d96fbbda9f8c 100644
--- a/ipaacalib/python/src/ipaaca/util/notifier.py
+++ b/ipaacalib/python/src/ipaaca/util/notifier.py
@@ -2,10 +2,10 @@
 
 # This file is part of IPAACA, the
 #  "Incremental Processing Architecture
-#   for Artificial Conversational Agents".  
+#   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2013 Sociable Agents Group
-#                         CITEC, Bielefeld University   
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
 # http://purl.org/net/ipaaca
@@ -22,7 +22,7 @@
 # You should have received a copy of the LGPL along with this
 # program. If not, go to http://www.gnu.org/licenses/lgpl.html
 # or write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #
 # The development of this software was supported by the
 # Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -30,23 +30,37 @@
 # Forschungsgemeinschaft (DFG) in the context of the German
 # Excellence Initiative.
 
-from __future__ import print_function, with_statement
+
+from __future__ import division, print_function
 
 import threading
 
-import ipaaca
-from ipaaca.util.timesync import *
 
-NotificationState = ipaaca.enum(
-		NEW = 'new',
-		OLD = 'old',
-		DOWN = 'down'
-		)
+import ipaaca.buffer
+import ipaaca.iu
+import ipaaca.misc
+import ipaaca.util.timesync
+
+
+__all__ = [
+	'NotificationState',
+	'ComponentError',
+	'ComponentNotifier'
+]
+
+
+NotificationState = ipaaca.misc.enum(
+	NEW = 'new',
+	OLD = 'old',
+	DOWN = 'down'
+)
+
 
 class ComponentError(Exception):
 	def __init__(self, msg):
 		super(ComponentError, self).__init__(msg)
 
+
 class ComponentNotifier(object):
 
 	NOTIFY_CATEGORY = "componentNotify"
@@ -61,8 +75,8 @@ class ComponentNotifier(object):
 		self.component_function = component_function
 		self.send_categories = frozenset(send_categories)
 		self.receive_categories = frozenset(receive_categories)
-		self.in_buffer = in_buffer if in_buffer is not None else ipaaca.InputBuffer(component_name + 'Notifier')
-		self.out_buffer = out_buffer if out_buffer is not None else ipaaca.OutputBuffer(component_name + 'Notifier')
+		self.in_buffer = in_buffer if in_buffer is not None else ipaaca.buffer.InputBuffer(component_name + 'Notifier')
+		self.out_buffer = out_buffer if out_buffer is not None else ipaaca.buffer.OutputBuffer(component_name + 'Notifier')
 		self.terminated = False
 		self.initialized = False
 		self.notification_handlers = []
@@ -77,28 +91,28 @@ class ComponentNotifier(object):
 
 	def _submit_notify(self, is_new):
 		with self.submit_lock:
-			notify_iu = ipaaca.Message(ComponentNotifier.NOTIFY_CATEGORY)
+			notify_iu = ipaaca.iu.Message(ComponentNotifier.NOTIFY_CATEGORY)
 			notify_iu.payload = {
 					ComponentNotifier.NAME: self.component_name,
 					ComponentNotifier.FUNCTION: self.component_function,
 					ComponentNotifier.SEND_CATEGORIES: ",".join(self.send_categories),
 					ComponentNotifier.RECEIVE_CATEGORIES:  ",".join(self.receive_categories),
 					ComponentNotifier.STATE: NotificationState.NEW if is_new else NotificationState.OLD,
-					}          
+					}
 			self.out_buffer.add(notify_iu)
-	
+
 	def terminate(self):
 		with self.submit_lock:
 			if self.terminated: return
 			self.terminated = True
-			notify_iu = ipaaca.Message(ComponentNotifier.NOTIFY_CATEGORY)
+			notify_iu = ipaaca.iu.Message(ComponentNotifier.NOTIFY_CATEGORY)
 			notify_iu.payload = {
 					ComponentNotifier.NAME: self.component_name,
 					ComponentNotifier.FUNCTION: self.component_function,
 					ComponentNotifier.SEND_CATEGORIES: ",".join(self.send_categories),
 					ComponentNotifier.RECEIVE_CATEGORIES:  ",".join(self.receive_categories),
 					ComponentNotifier.STATE: NotificationState.DOWN,
-					}          
+					}
 			self.out_buffer.add(notify_iu)
 
 	def _handle_iu_event(self, iu, event_type, local):
@@ -125,30 +139,28 @@ class ComponentNotifier(object):
 
 	def add_timesync_slave_handler(self, handler):
 		self.timesync_slave_handlers.append(handler)
-	
+
 	def add_timesync_master_handler(self, handler):
 		self.timesync_master_handlers.append(handler)
-	
+
 	def send_master_timesync(self):
 		#if len(self.timesync_master_handlers)==0:
 		#	print('Warning: Sending a master timesync without a registered result callback.')
 		self.timesync_master.send_master_timesync()
-	
+
 	def initialize(self):
 		with self.initialize_lock:
 			if self.terminated:
 				raise ComponentError('Attempted to reinitialize component '+component_name+' after termination')
 			if (not self.initialized):
-				self.timesync_slave = TimesyncSlave(component_name=self.component_name, timing_handler=self.launch_timesync_slave_handlers)
-				self.timesync_master = TimesyncMaster(component_name=self.component_name, timing_handler=self.launch_timesync_master_handlers)
-				self.in_buffer.register_handler(self._handle_iu_event, ipaaca.IUEventType.MESSAGE, ComponentNotifier.NOTIFY_CATEGORY)
+				self.timesync_slave = ipaaca.util.timesync.TimesyncSlave(component_name=self.component_name, timing_handler=self.launch_timesync_slave_handlers)
+				self.timesync_master = ipaaca.util.timesync.TimesyncMaster(component_name=self.component_name, timing_handler=self.launch_timesync_master_handlers)
+				self.in_buffer.register_handler(self._handle_iu_event, ipaaca.iu.IUEventType.MESSAGE, ComponentNotifier.NOTIFY_CATEGORY)
 				self._submit_notify(True)
 				self.initialized = True
-	
+
 	def __enter__(self):
 		self.initialize()
-	
+
 	def __exit__(self, t, v, tb):
 		self.terminate()
-
-
diff --git a/ipaacalib/python/src/ipaaca/util/timesync.py b/ipaacalib/python/src/ipaaca/util/timesync.py
index e3ec33e58398d37eb2b714c8625bbd3af22d1107..950a50f1cce1929f89d6701d20b1d9dfe62db120 100644
--- a/ipaacalib/python/src/ipaaca/util/timesync.py
+++ b/ipaacalib/python/src/ipaaca/util/timesync.py
@@ -1,13 +1,47 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-import ipaaca
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2014 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
 import time
 
+import ipaaca.buffer
+import ipaaca.iu
+
+
 class TimesyncMaster(object):
 	def __init__(self, component_name=None, timing_handler=None, debug_offset=0):
-		self.ob = ipaaca.OutputBuffer(('' if component_name is None else component_name)+'TimesyncMaster')
-		self.ib = ipaaca.InputBuffer(('' if component_name is None else component_name)+'TimesyncMaster', ['timesyncReply'])
+		self.ob = ipaaca.buffer.OutputBuffer(('' if component_name is None else component_name)+'TimesyncMaster')
+		self.ib = ipaaca.buffer.InputBuffer(('' if component_name is None else component_name)+'TimesyncMaster', ['timesyncReply'])
 		# component name to report (None => use buffer name)
 		self.component_name = component_name if component_name is not None else self.ob.unique_name
 		#
@@ -29,7 +63,7 @@ class TimesyncMaster(object):
 		self.timing_handler = timing_handler
 	
 	def send_master_timesync(self):
-		iu = ipaaca.IU('timesyncRequest')
+		iu = ipaaca.iu.IU('timesyncRequest')
 		self.master_t1 = self.get_time()
 		iu.payload = {
 				'stage':'0',
@@ -85,8 +119,8 @@ class TimesyncMaster(object):
 
 class TimesyncSlave(object):
 	def __init__(self, component_name=None, timing_handler=None, debug_offset=0):
-		self.ob = ipaaca.OutputBuffer(('' if component_name is None else component_name)+'TimesyncSlave')
-		self.ib = ipaaca.InputBuffer(('' if component_name is None else component_name)+'TimesyncSlave', ['timesyncRequest'])
+		self.ob = ipaaca.buffer.OutputBuffer(('' if component_name is None else component_name)+'TimesyncSlave')
+		self.ib = ipaaca.buffer.InputBuffer(('' if component_name is None else component_name)+'TimesyncSlave', ['timesyncRequest'])
 		# component name to report (None => use buffer name)
 		self.component_name = component_name if component_name is not None else self.ib.unique_name
 		self.ob.register_handler(self.handle_timesync_slave)
@@ -113,7 +147,7 @@ class TimesyncSlave(object):
 				if stage=='0':
 					#print('Received stage 0 from master '+master)
 					# initial reply to master
-					self.my_iu = ipaaca.IU('timesyncReply')
+					self.my_iu = ipaaca.iu.IU('timesyncReply')
 					# TODO: add grounded_in link too?
 					t1 = self.get_time()
 					self.my_iu.payload = iu.payload
@@ -146,5 +180,3 @@ class TimesyncSlave(object):
 						self.timing_handler(master, self.component_name, latency, offset)
 	def get_time(self):
 		return time.time() + self.debug_offset
-
-
diff --git a/ipaacalib/python/test/ivy.xml b/ipaacalib/python/test/ivy.xml
index 9912781fe761ded2dc8e8bf0da44981473a56ed2..03db403ef45bbe4494c7fa1838a7d91ba1fc3f5f 100644
--- a/ipaacalib/python/test/ivy.xml
+++ b/ipaacalib/python/test/ivy.xml
@@ -6,3 +6,4 @@
         <dependency org="nose" name="nose"  rev="latest.release" />
    </dependencies>
 </ivy-module>
+
diff --git a/ipaacasoa/cpp/CMakeLists.txt b/ipaacasoa/cpp/CMakeLists.txt
index 9830e75d75edd7b6322c9bdaf7e1b59d942a70a9..1e5ddebc00ad53984cb295b1b5da40d8f2c2eb75 100644
--- a/ipaacasoa/cpp/CMakeLists.txt
+++ b/ipaacasoa/cpp/CMakeLists.txt
@@ -5,7 +5,7 @@ project (ipaaca_soa_cpp)
 
 install(
 	DIRECTORY include
-	DESTINATION /
+	DESTINATION .
 	FILES_MATCHING PATTERN "*.h" PATTERN "*.hh" PATTERN "*.hpp" PATTERN "*.inl"
 	)
 
diff --git a/ipaacatools/scripts/ipaaca-iu-injector b/ipaacatools/scripts/ipaaca-iu-injector
new file mode 100755
index 0000000000000000000000000000000000000000..5f464da52355b3b3cc6bdf8c975282c758a6bc97
--- /dev/null
+++ b/ipaacatools/scripts/ipaaca-iu-injector
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import itertools
+import os
+import platform
+import sys
+import time
+
+import ipaaca
+
+
+def iu_update_handler(iu, event_type, local):
+	try:
+		print(event_type + ': ' + unicode(iu))
+	except:
+		print(u"An error occurred printing an IU for an event of type "+event_type)
+
+
+parser = ipaaca.IpaacaArgumentParser(description='Ipaaca IU Injector -- Sent ipaaca messages or IUs from the command line')
+parser.add_argument(
+	'-t', '--type',
+	default='Message',
+	dest='iu_type',
+	choices = ['Message', 'IU'],
+	help="choose IU type to be send (default: 'Message')")
+parser.add_argument(
+	'-k', '--keep-alive',
+	default=3.0,
+	dest='keep_alive',
+	metavar='SECONDS',
+	type=float,
+	help='set time in seconds to wait for potential IU updates (default: 3.0)')
+parser.add_argument(
+	'-j', '--json-payload',
+	dest='json_payload',
+	action='store_true',
+	help='allow structured data to be sent (treats payload VALUE arguments as Python expressions)')
+parser.add_argument(
+	'-c', '--category',
+	dest='category',
+	metavar='CATEGORY',
+	required=True,
+	help='set Message/IU category')
+parser.add_argument(
+	'-p', '--payload',
+	default=[],
+	dest='payload',
+	metavar='KEY VALUE',
+	nargs='+',
+	help='set Message/IU payload ')
+
+
+if __name__ == '__main__':
+	arguments = parser.parse_args()
+
+	ob = ipaaca.OutputBuffer('IpaacaIUInjector')
+	ob.register_handler(iu_update_handler)
+	iu = ipaaca.Message(arguments.category) if arguments.iu_type == 'Message' else ipaaca.IU(arguments.category)
+	if arguments.json_payload:
+		# Treat payload values as Python expressions
+		iu.payload = {k: eval(v) for (k, v) in itertools.izip_longest(arguments.payload[::2],	arguments.payload[1::2])}
+	else:
+		iu.payload = {k: v for (k, v) in itertools.izip_longest(arguments.payload[::2],	arguments.payload[1::2])}
+	ob.add(iu)
+
+	print(
+		u'Sent {iu_type} with category "{category}" and payload {{'.format(**vars(arguments)),
+		end='\n' if len(iu.payload) > 0 else '')
+	for k, v in iu.payload.items():
+		print(u"  '{key}': {value},".format(key=k, value=v))
+	print(u'}.')
+	
+	# Wait for updates to the IU
+	try:
+		if arguments.iu_type == 'IU':
+			print('Waiting %s s for the IU to be updated.' % arguments.keep_alive)
+			time.sleep(arguments.keep_alive)
+		else:
+			time.sleep(0.1)
+	except KeyboardInterrupt:
+		pass
+
+	if platform.system() == 'Windows':
+		os._exit(0)
+	else:
+		sys.exit(0)
diff --git a/ipaacatools/scripts/ipaaca-iu-injector.py b/ipaacatools/scripts/ipaaca-iu-injector.py
deleted file mode 100755
index b6a56de5658860b3a469d6a6f328d9c34d7ab41f..0000000000000000000000000000000000000000
--- a/ipaacatools/scripts/ipaaca-iu-injector.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env python
-
-# This file is part of IPAACA, the
-#  "Incremental Processing Architecture
-#   for Artificial Conversational Agents".	
-#
-# Copyright (c) 2009-2013 Sociable Agents Group
-#                         CITEC, Bielefeld University	
-#
-# http://opensource.cit-ec.de/projects/ipaaca/
-# http://purl.org/net/ipaaca
-#
-# This file may be licensed under the terms of of the
-# GNU Lesser General Public License Version 3 (the ``LGPL''),
-# or (at your option) any later version.
-#
-# Software distributed under the License is distributed
-# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
-# express or implied. See the LGPL for the specific language
-# governing rights and limitations.
-#
-# You should have received a copy of the LGPL along with this
-# program. If not, go to http://www.gnu.org/licenses/lgpl.html
-# or write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.	
-#
-# The development of this software was supported by the
-# Excellence Cluster EXC 277 Cognitive Interaction Technology.
-# The Excellence Cluster EXC 277 is a grant of the Deutsche
-# Forschungsgemeinschaft (DFG) in the context of the German
-# Excellence Initiative.
-
-import logging
-import sys
-import time
-
-import ipaaca
-
-def my_update_handler(iu, event_type, local):
-	print(event_type+': '+str(iu))
-
-if len(sys.argv)<2:
-	print "Please use the program as follows:"
-	print " "+sys.argv[0]+" [--class IU|Message] [--timeout <sec>] <categoryname> [<payloadkey> <payloadvalue>] [<k2> <v2>] ..."
-	sys.exit(1)
-
-iu_class = 'Message'
-timeout = 3.0
-idx = 1
-keep_going = True
-while keep_going:
-	keep_going = False
-	if sys.argv[idx]=='--class':
-		t = sys.argv[idx+1]
-		if t in ['Message', 'IU']:
-			iu_class = t
-		else:
-			print "Unknown IU class: "+t
-			sys.exit(1)
-		idx += 2
-		keep_going = True
-	elif sys.argv[idx]=='--timeout':
-		timeout = float(sys.argv[idx+1])
-		idx += 2
-		keep_going = True
-
-cate = sys.argv[idx]
-idx += 1
-pl={}
-while len(sys.argv)>idx+1:
-	pl[sys.argv[idx]] = sys.argv[idx+1]
-	idx+=2
-
-print "Sending "+iu_class+" of category "+cate
-print " with payload "+str(pl)
-
-ob = ipaaca.OutputBuffer('IUInjector')
-ob.register_handler(my_update_handler)
-iu_top = ipaaca.IU(cate)
-iu_top.payload = pl
-ob.add(iu_top)
-print iu_class+" sent."
-
-if iu_class=="IU":
-	print "Waiting "+str(timeout)+" sec for remote modifications..."
-	time.sleep(timeout)
-else:
-	time.sleep(0.1)
-print "done."
-
diff --git a/ipaacatools/scripts/ipaaca-iu-sniffer b/ipaacatools/scripts/ipaaca-iu-sniffer
new file mode 100755
index 0000000000000000000000000000000000000000..a4db5847098f8a1078cf50d4051719a84642f8f6
--- /dev/null
+++ b/ipaacatools/scripts/ipaaca-iu-sniffer
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import logging
+import os
+import platform
+import re
+import sys
+import time
+
+import ipaaca
+
+
+def event_type_color(typ):
+	colors = {
+		'ADDED': '32;1',
+		'RETRACTED': '31;1',
+		'UPDATED': '33;1',
+		'MESSAGE': '34;1',
+		'COMMITTED': '35;1',
+		'LINKSUPDATED': '36;1',
+		'RETRACTED': '37;1',
+	}
+	return colors.get(typ, '1')
+
+def highlight_if_color(s, c='1'):
+	return s if not arguments.color else '[' + c + 'm' + s +''
+
+def pretty_printed_dict(d):
+	s='{\n'
+	for k, v in d.items():
+		if isinstance(v, unicode) or isinstance(v, str):
+			v = "'"+unicode(v)+"'"
+		else:
+			v = unicode(v)
+		v2 = v if len(v) <= arguments.max_size else v[:arguments.max_size] + '<excess length omitted>'
+		v2.replace('\\','\\\\').replace('\n', highlight_if_color('\\n'))
+		s += "\t '%s': %s,\n" % (highlight_if_color(unicode(k),'1'), unicode(v2))
+	s+='}'
+	return s
+
+def pretty_printed_iu_event(iu, event_type, local):
+	s = ''
+	t = time.time()
+	lt = time.localtime(t)
+	s += highlight_if_color('%.3f' % t, '1')
+	s += ' %02d:%02d:%02d' % (lt.tm_hour, lt.tm_min, lt.tm_sec)
+	s += ' ' + highlight_if_color('%-9s' % event_type, event_type_color(event_type))
+	s += ' category=' + highlight_if_color(iu.category,event_type_color(event_type))
+	s += ' channel=' + iu.buffer._channel
+	s += ' uid=' + iu.uid
+	s += ' owner=' + iu.owner_name
+	if event_type is not 'MESSAGE':
+		s += '\nlinks=' + pretty_printed_dict(iu.get_all_links())
+	s += '\npayload=' + pretty_printed_dict(iu.payload)
+	return s
+
+def my_update_handler(iu, event_type, local):
+	if arguments.regex:
+		for cat in arguments.categories: # actually now regexs, not categories
+			if re.match(cat, iu.category):
+				break
+		else:
+			return
+	print(pretty_printed_iu_event(iu, event_type, local), end='\n\n')
+
+
+
+parser = ipaaca.IpaacaArgumentParser(description='Ipaaca IU Sniffer -- Selectively listen to IPAACA traffic')
+parser.add_argument(
+	'-r', '--regex',
+	action='store_true',
+	dest='regex',
+	help='match categories by regular expressions')
+parser.add_argument(
+	'-c', '--color',
+	action='store_true',
+	dest='color',
+	help='colorize output')
+parser.add_argument(
+	'--channels',
+	dest='channels',
+	default=['default'],
+	metavar='CHANNEL',
+	nargs='+',
+	help="set the channels to listen on (otherwise 'default')")
+parser.add_argument(
+	'--categories',
+	default=[''],
+	dest='categories',
+	metavar='CATEGORY',
+	nargs='+',
+	help='set categories (or regex patterns) to be matched')
+parser.add_argument(
+	'--size-limit',
+	default=2048,
+	dest='max_size',
+	metavar='LIMIT',
+	type=int,
+	help='limit payload display chars (default: 2048)')
+
+
+if __name__ == '__main__':
+	arguments = parser.parse_args()
+
+	buffers = {}
+	for channel in arguments.channels:
+		buffers[channel] = ipaaca.InputBuffer(
+			'IpaacaIUSniffer',
+			category_interests=arguments.categories if not arguments.regex else [''],
+			channel=channel,
+			resend_active=True)
+		buffers[channel].register_handler(my_update_handler)
+
+	channellist = 's ' if len(arguments.channels) > 1 else ' '
+	channellist += ', '.join(arguments.channels)
+	
+	print('Listening on channel' + channellist + ' for IU events of ', end='')
+	if arguments.categories == ['']:
+		print('any category ...')
+	else:
+		if arguments.regex:
+			print('whose category matches one of the regexes:')
+		else:
+			print('categories:')
+		print('\t' + ', '.join(arguments.categories))
+	print('')
+	try:
+		while True:
+			time.sleep(1)
+	except KeyboardInterrupt:
+		pass
+	
+	if platform.system() == 'Windows':
+		os._exit(0)
+	else:
+		sys.exit(0)
+	
diff --git a/ipaacatools/scripts/ipaaca-iu-sniffer.py b/ipaacatools/scripts/ipaaca-iu-sniffer.py
deleted file mode 100755
index c7034c1d7a49e872946efd13848bf271f0e9fbe0..0000000000000000000000000000000000000000
--- a/ipaacatools/scripts/ipaaca-iu-sniffer.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python
-
-# This file is part of IPAACA, the
-#  "Incremental Processing Architecture
-#   for Artificial Conversational Agents".	
-#
-# Copyright (c) 2009-2013 Sociable Agents Group
-#                         CITEC, Bielefeld University	
-#
-# http://opensource.cit-ec.de/projects/ipaaca/
-# http://purl.org/net/ipaaca
-#
-# This file may be licensed under the terms of of the
-# GNU Lesser General Public License Version 3 (the ``LGPL''),
-# or (at your option) any later version.
-#
-# Software distributed under the License is distributed
-# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
-# express or implied. See the LGPL for the specific language
-# governing rights and limitations.
-#
-# You should have received a copy of the LGPL along with this
-# program. If not, go to http://www.gnu.org/licenses/lgpl.html
-# or write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.	
-#
-# The development of this software was supported by the
-# Excellence Cluster EXC 277 Cognitive Interaction Technology.
-# The Excellence Cluster EXC 277 is a grant of the Deutsche
-# Forschungsgemeinschaft (DFG) in the context of the German
-# Excellence Initiative.
-
-import logging
-import sys
-import time
-import ipaaca
-
-color = False
-max_size = 2048
-
-def highlight_if_color(s, c='1'):
-	return s if not color else '['+c+'m'+s+''
-
-def pretty_printed_iu_payload(iu):
-	s='{ '
-	for k,v in iu.payload.items():
-		v2 = (('\''+v+'\'') if len(v)<=max_size else ('\''+v[:max_size]+'\'<excess length omitted>')).replace('\\','\\\\').replace('\n',highlight_if_color('\\n'))
-		s += '\n' + '\t\t\'' + highlight_if_color(unicode(k),'1')+'\': '+unicode(v2)+', '
-	s+=' }'
-	return s
-
-def event_type_color(typ):
-	colors={'ADDED':'32;1', 'RETRACTED':'31;1', 'UPDATED':'33;1', 'MESSAGE':'34;1'}
-	return '1' if typ not in colors else colors[typ]
-
-def pretty_printed_iu_event(iu, event_type, local):
-	s=''
-	t=time.time()
-	lt=time.localtime(t)
-	s += highlight_if_color('%.3f'%t, '1')+' '+"%02d:%02d:%02d"%(lt.tm_hour, lt.tm_min, lt.tm_sec)
-	s += ' '+highlight_if_color('%-9s'%event_type,event_type_color(event_type))+' category='+highlight_if_color(iu.category,event_type_color(event_type))+' uid='+iu.uid+' owner='+iu.owner_name+' payload='+pretty_printed_iu_payload(iu)
-	return s
-
-def my_update_handler(iu, event_type, local):
-	t=time.localtime()
-	print pretty_printed_iu_event(iu, event_type, local)
-
-cats = []
-
-keep_going=True
-idx = 1
-while keep_going:
-	opt = sys.argv[idx] if idx<len(sys.argv) else None
-	if opt=='--help':
-		print('IU sniffer - usage:')
-		print('  '+sys.argv[0]+' [--options] [<category1> [<category2 ...]]')
-		print('         Listen to specified categories (default: all)')
-		print('         Option --color : colorize output')
-		print('         Option --size-limit <size> : limit payload display, chars (def: 2048)')
-		sys.exit(0)
-	elif opt=='--color':
-		color = True
-		idx += 1
-	elif opt=='--size-limit':
-		if len(sys.argv)<idx+2:
-			print('Please specify a max size')
-			sys.exit(1)
-		max_size = int(sys.argv[idx+1])
-		idx += 2
-	else:
-		cats = sys.argv[idx:]
-		keep_going = False
-
-ib = ipaaca.InputBuffer('SnifferIn', [''] if len(cats)==0 else cats)
-ib.register_handler(my_update_handler)
-
-print('')
-print('Ipaaca IU Sniffer - run with --help to see options')
-print('Listening for IU events of '+('any category...' if len(cats)==0 else 'categories: '+' '.join(cats)))
-print('')
-while True:
-	time.sleep(1)
-