{"action":"created","comment":{"url":"https://api.github.com/repos/kaaproject/kaa/pulls/comments/72620327","id":72620327,"diff_hunk":"@@ -437,312 +544,383 @@ The base schema is obtained by transforming the configuration schema, as follows\n }\n ```\n \n-### Updating configuration data\n+## Updating configuration data\n \n-The Kaa Control server exposes API for loading configuration data into the \"all\" group. To introduce the configuration update, the new data set must be supplied in the Avro binary or Avro JSON format and correspond to the base schema version specified in the API call. As a result, all the endpoints under the application will assume the new configuration.\n+The Kaa Control service exposes API for loading configuration data into the \"all\" group. To introduce the configuration update, the new data set must be\n+supplied in the Avro binary or Avro JSON format and correspond to the base schema version specified in the API call. As a result, all the endpoints under\n+the application will assume the new configuration.\n \n The following rules apply during the update:\n \n-* When loading the new data set, Kaa persists the existing UUIDs for all [addressable]() records, thus ignoring the corresponding values supplied with the new configuration.\n-* In case of unions that assumes that the record types in the old configuration and in the new configuration match. If they don't, Kaa generates a new UUID value for the replacement record.\n-* In case of non-addressable records (those directly or indirectly contained in the arrays), Kaa performs record instances matching by comparing the UUID values in the old and the new configuration.\n+* When loading the new data set, Kaa persists the existing UUIDs for all [addressable](#addressing) records, thus ignoring the corresponding values supplied\n+with the new configuration.\n+* In case of unions that assumes that the record types in the old configuration and in the new configuration match.\n+If they don't, Kaa generates a new UUID value for the replacement record.\n+* In case of non-addressable records (those directly or indirectly contained in the arrays), Kaa performs record instances matching by comparing\n+the UUID values in the old and the new configuration.\n \n-### UUID validation\n+## UUID validation\n \n-Kaa performs UUID validation to prevent corruption of configuration data when the API user or Kaa administrator loads a new version of the configuration data to the server. In this case, Kaa inspects the UUIDs of the newly introduced configuration data and validates them against the UUIDs in the previous version of the configuration data.\n+Kaa performs UUID validation to prevent corruption of configuration data when the API user or Kaa administrator loads a new version of the configuration data\n+to the server. In this case, Kaa inspects the UUIDs of the newly introduced configuration data and validates them against the UUIDs in the previous version\n+of the configuration data.\n \n UUID validation is performed in the following two cases: updating an existing object or creating a new object.\n \n-#### Updating an existing object (there is a UUID in the previous version of the configuration)\n+### Updating an existing object (there is a UUID in the previous version of the configuration)\n \n The following rules apply for the object update.\n \n * If the resolved UUID remains the same, the new configuration is stored with the existing UUID.\n-* If the resolved UUID is null or unknown and the object is a record, Kaa does a search throughout the existing base schema to find the object in question and obtain its existing UUID; after the search is complete, the new configuration is stored with the existing UUID.\n+* If the resolved UUID is null or unknown and the object is a record, Kaa does a search throughout the existing base schema to find the object in question and\n+obtain its existing UUID; after the search is complete, the new configuration is stored with the existing UUID.\n * If the resolved UUID is null or unknown and the object is an array, Kaa generates a new UUID for the new configuration.\n \n-#### Creating a new object (there is no UUID in previous version of the configuration)\n+### Creating a new object (there is no UUID in previous version of the configuration)\n \n The following rules apply for object creation.\n \n * If the resolved UUID is null, Kaa generates a new UUID for the object and stores it in the database.\n-* If the resolved UUID is equal to some other UUID which is already in use or to unknown value, Kaa generates a new UUID for the object and stores it in the database.\n-\n-## Group-specific configuration management\n+* If the resolved UUID is equal to some other UUID which is already in use or to unknown value, Kaa generates a new UUID for the object and stores it in the\n+database.\n \n-Kaa allows updating configuration data for a specific endpoint group under the application, which is a more targeted approach than that described in [Schema-specific configuration management]() for the \"all\" group. To implement such a modification, Kaa distributes _configuration override data_ to the endpoint group. The structure of the configuration override data is specified by the _override schema_, which is derived from the configuration schema used by the target endpoint group. As different from the base schema, the override schema allows updating fields selectively, leaving some of them without any change if necessary (using the org.kaaproject.configuration.unchangedT type).\n+## Override schema\n \n-### Override schema\n+The override schema is obtained by transforming the configuration schema and looks very similar to the base schema. The difference is that when constructing\n+an override schema, Kaa adds ```org.kaaproject.configuration.unchangedT``` to every field type definition (converting them into union types, if necessary).\n+Thus, all mandatory fields become union types with either their original type (if there is any data change) or the ```org.kaaproject.configuration.unchangedT```\n+ type (if there is no data change). When org.kaaproject.configuration.unchangedT appears in the data, it indicates that the corresponding field value remains\n+without the change during the update.\n \n-The override schema is obtained by transforming the configuration schema and looks very similar to the base schema. The difference is that when constructing an override schema, Kaa adds org.kaaproject.configuration.unchangedT to every field type definition (converting them into union types, if necessary). Thus, all mandatory fields become union types with either their original type (if there is any data change) or the org.kaaproject.configuration.unchangedT type (if there is no data change). When org.kaaproject.configuration.unchangedT appears in the data, it indicates that the corresponding field value remains without the change during the update.\n As an example, consider how mandatory and optional fields are converted from the configuration schema to the override schema.\n \n-{% include csv-table.html csv_path='compare-configuration-override.csv' table_id='compare-configuration-override' width='100%' %}\n+Mandatory field in the **configuration schema**:\n \n-Loading the override data into the endpoint groups is similar to [loading base data into group \"all\"](). Among other parameters, the group ID must be passed to the API call to indicate the group to which the new data should be applied. The loading algorithm processes the record UUID values identically to how it is done for the \"all\" group, persisting the UUID values that already existed in the previous version of the data in the processed group. Loading is done for the group in question independently of any other groups and without any cross-group data lookups.\n+```json\n+{\n+    \"name\":\"stringField\",\n+    \"type\":\"string\",\n+    \"by_default\":\"default string value\"\n+}\n+```\n \n-### Override algorithm\n+Mandatory field in the **override schema**:\n \n-To define and apply the resulting configuration update for the endpoint, the Operations server proceeds as follows:\n+```json\n+{\n+    \"name\":\"stringField\",\n+    \"type\":[\n+        \"string\",\n+        {\n+            \"name\":\"unchangedT\",\n+            \"namespace\":\"org.kaaproject.configuration\",\n+            \"type\":\"enum\",\n+            \"symbols\":[\n+                \"unchanged\"\n+            ]\n+        }\n+    ],\n+    \"by_default\":\"default string value\"\n+}\n+```\n \n-1. Evaluates the endpoint group membership according to the endpoint profile.\n-Merges all configuration data sets assigned to the groups the endpoint belongs to, starting with the one that has the lowest weight (which is always group \"all\" with the 0 weight).\n+Optional field in the **configuration schema**:\n \n-2. In case of the conflicting field values, the field is set with the the value from the group with the highest weight.\n+```json\n+{\n+    \"name\":\"optionalBytesField\",\n+    \"type\":[\n+        \"null\",\n+        \"bytes\"\n+    ],\n+    \"optional\":true\n+}\n+```\n \n-**NOTE:**\n-In case of the arrays, the **overrideStrategy** field in the configuration schema defines the way in which the arrays are merged.\n-Record UUID fields never change from the values in the lowest weight group they were first encountered in.\n-Both profile schema and configuration schema versions the endpoint supports are taken into account during the merge.\n+Optional field in the **override schema**:\n \n-## User-specific configuration management\n+```json\n+{\n+    \"name\":\"optionalBytesField\",\n+    \"type\":[\n+        \"null\",\n+        \"bytes\",\n+        \"org.kaaproject.configuration.unchangedT\"\n+    ],\n+    \"optional\":true\n+}\n+```\n \n-The user-specific configuration management allows updating configuration data for the specific user under the application. The user-specific configuration management implements the same approach as in [Group-specific configuration]() management, based on the override schema and override algorithm.\n+Loading the override data into the endpoint groups is similar to [loading base data into group \"all\"](#updating-configuration-data).\n+Among other parameters, the group ID must be passed to the API call to indicate the group to which the new data should be applied. The loading\n+algorithm processes the record UUID values identically to how it is done for the \"all\" group, persisting the UUID values that already existed in the\n+previous version of the data in the processed group. Loading is done for the group in question independently of any other groups and without any\n+cross-group data lookups.\n \n-**NOTE:**\n-Since each endpoint belongs to only one user at a time, the override algorithm does not support data set merges as in the group-specific configuration management.  \n-The override algorithm applies user-specific overrides only after all group-specific overrides have been applied.\n+## Override algorithm\n \n-## Endpoint data synchronization\n+To define and apply the resulting configuration update for the endpoint, the Operations service proceeds as follows:\n \n-After calculating the up-to-date configuration for the endpoint, the Operations server constructs a delta update based on the knowledge of the prior configuration of that endpoint. In certain cases, the delta update can contain a complete endpoint configuration.\n+1. Evaluates the endpoint group membership according to the endpoint profile.\n+2. Merges all configuration data sets assigned to the groups the endpoint belongs to, starting with the one that has the lowest weight\n+(which is always group \"all\" with the 0 weight). <br/>\n+In case of the conflicting field alues, the field is set with the value from the group with the highest weight.\n \n-Having received the delta update, the endpoint merges it with the existing configuration data, notifies the client application about the update, and persists the resulting configuration. The data storage location is set as an abstraction in the endpoint, therefore the concrete location for persisting the data is defined in the client implementation.\n+>**NOTE:**\n+> In case of the arrays, the ```overrideStrategy``` field in the configuration schema defines the way in which the arrays are merged. <br/>\n+Record UUID fields never change from the values in the lowest weight group they were first encountered in. <br/>\n+Both profile schema and configuration schema versions the endpoint supports are taken into account during the merge. <br/>\n \n-By delivering configuration deltas instead of full configuration sets each time the endpoint needs to be reconfigured, the Kaa server significantly reduces a traffic load in the available data channels.\n+# Endpoint data synchronization\n \n-Data consistency is ensured by the hash comparison between the endpoint and the server.\n+After receiving configuration update for the endpoint group, the Operations service calculates and delivers the up-to-date configuration for all affected endpoints. \n \n-### Protocol schema\n+Having received the update, the endpoint notifies the client application about the update and\n+persists the resulting configuration. The data storage location is set as an abstraction in the endpoint, therefore the concrete location for\n+persisting the data is defined in the client implementation.\n \n-A _protocol schema_ determines the structure of the data updates that Kaa server sends to the endpoints and possible update actions (change, add, reset, and leave unchanged). The protocol schema is automatically generated by the Control server for each configuration schema (when the configuration schema is loaded by the user).\n+Data consistency is ensured by the configuration hash comparison between the endpoint and the server.\n \n-The updates may carry either a full set of data (full sync) or a partial update (configuration delta). Full sync is used in exceptional situations (e.g., a hash mismatch), with the corresponding protocol schema being very similar to the [base schema]().\n+![Configuration management overview](attach/configuration.png)\n \n-The schema generator performs the following transformations to convert the configuration schema to the protocol schema.\n+# Configuration management SDK API\n \n-* The \\__uuid field of the org.kaaproject.configuration.uuidT type is added to every addressable record. Having a UUID ensures that the record becomes addressable and the Kaa server can send partial updates on such records.\n+The configuration management API varies depending on the target SDK platform. However, the general approach is the same.\n \n-* Optional fields are transformed into unions with either the original field type, null type or org.kaaproject.configuration.unchangedT type. (\\*TODO* is this only for optional or for any unions with null?)\n-The org.kaaproject.configuration.unchangedT type is used for a simple enum that indicates that there is no change for the field in the current update. It has the following structure.\n+The Kaa client application should use the following code.\n \n-```json\n-{\n-    \"name\": \"unchangedT\",\n-    \"namespace\": \"org.kaaproject.configuration\",\n-    \"type\": \"enum\",\n-    \"symbols\": [\"unchanged\"]\n-}\n+<ul class=\"nav nav-tabs\">\n+  <li class=\"active\"><a data-toggle=\"tab\" href=\"#Java-1\">Java</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C_plus_plus-1\">C++</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C-1\">C</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#Objective-C-1\">Objective-C</a></li>\n+</ul>\n \n-```\n+<div class=\"tab-content\">\n+<div id=\"Java-1\" class=\"tab-pane fade in active\" markdown=\"1\" >\n \n-* Mandatory fields are transformed into unions with either the original field type or the org.kaaproject.configuration.unchangedT type.\n+```java\n \n-* Array fields are transformed into unions, as follows:\n-   * an array of:\n-       * the original array item type to add new items to the array\n-       * the org.kaaproject.configuration.uuidT type if the original item type is a UUID-addressable record\n-   * the org.kaaproject.configuration.unchangedT type to indicate no changes to the array contents\n-   * the org.kaaproject.configuration.resetT type to purge the array contents. Similarly to org.kaaproject.configuration.unchangedT, org.kaaproject.configuration.resetT is a simple enum, as follows:\n+import org.kaaproject.kaa.client.DesktopKaaPlatformContext;\n+import org.kaaproject.kaa.client.Kaa;\n+import org.kaaproject.kaa.client.KaaClient;\n+import org.kaaproject.kaa.client.SimpleKaaClientStateListener;\n+import org.kaaproject.kaa.client.configuration.base.ConfigurationListener;\n+import org.kaaproject.kaa.client.configuration.base.SimpleConfigurationStorage;\n \n-```json\n-{\n-    \"name\": \"resetT\",\n-    \"namespace\": \"org.kaaproject.configuration\",\n-    \"type\": \"enum\",\n-    \"symbols\": [\"reset\"]\n+public static void main(String[] args) {\n+    // Create the Kaa desktop context for the application.\n+    DesktopKaaPlatformContext desktopKaaPlatformContext = new DesktopKaaPlatformContext();\n+    \n+    // Create a Kaa client and add a listener which displays the Kaa client configuration \n+    // as soon as the Kaa client is started. \n+    kaaClient = Kaa.newClient(desktopKaaPlatformContext, new SimpleKaaClientStateListener() {\n+    @Override\n+    public void onStarted() {\n+        super.onStarted();\n+        printConfiguration(kaaClient.getConfiguration());\n+    }\n+    });\n+    \n+    // Persist configuration in a local storage to avoid downloading it each time the Kaa client is started.\n+    kaaClient.setConfigurationStorage(new SimpleConfigurationStorage(desktopKaaPlatformContext, \"saved_config.cfg\"));\n+    \n+    // Add a listener which displays the Kaa client configuration each time it is updated.\n+    kaaClient.addConfigurationListener(new ConfigurationListener() {\n+    @Override\n+    public void onConfigurationUpdate(SampleConfiguration sampleConfiguration) {\n+        printConfiguration(sampleConfiguration);\n+    }\n+    });\n+        \n+    // Start the Kaa client and connect it to the Kaa server.\n+    kaaClient.start();\n+    ...\n }\n+\n+private static void printConfiguration(SampleConfiguration sampleConfiguration) {\n+    LOG.info(\"Current configuration: {}\", sampleConfiguration);\n+}\n+\n ```\n \n-* The root record schema is wrapped into an array of org.kaaproject.configuration.deltaT records. The org.kaaproject.configuration.deltaT record contains the only one field, which is called delta. The delta field is a union of the transformed data root record schema and every UUID-addressable record type encountered in the root record schema. Such a structure allows encoding delta updates to every UUID-addressable record in the schema, including the root record.\n+</div>\n+<div id=\"C_plus_plus-1\" class=\"tab-pane fade\" markdown=\"1\" >\n \n-```json\n+```c++\n+#include <memory>\n+#include <iostream>\n+ \n+#include <kaa/Kaa.hpp>\n+#include <kaa/event/registration/SimpleUserAttachCallback.hpp>\n+ \n+using namespace kaa;\n+\n+const char savedConfig[] = \"saved_config.cfg\";\n+\n+class UserConfigurationReceiver : public IConfigurationReceiver {\n+public:\n+    void printConfiguration(const KaaRootConfiguration &configuration)\n+    {\n+        std::cout << \"Current configuration: \" << configuration << std::endl;\n+    }\n+    virtual void onConfigurationUpdated(const KaaRootConfiguration &configuration)\n+    {\n+        printConfiguration(configuration);\n+    }\n+};\n+\n+int main()\n {\n-    \"type\": \"array\"\n-    \"items\": {\n-        \"name\": \"deltaT\",\n-        \"namespace\": \"org.kaaproject.configuration\"\n-        \"type\": \"record\",\n-        \"fields\": [\n-            {\n-                \"name\": \"delta\",\n-                \"type\": [\n-                    <root record schema>,\n-                    <list of addressable record types>\n-                ]\n-            }\n-        ],\n-    },\n+    // Initialize the Kaa endpoint.\n+    auto kaaClient = Kaa::newClient();\n+\n+    // Set up a configuration subsystem.\n+    IConfigurationStoragePtr storage(std::make_shared<FileConfigurationStorage>(savedConfig));\n+    kaaClient->setConfigurationStorage(storage);\n+\n+    // Set configuration update receiver.\n+    UserConfigurationReceiver receiver;\n+    kaaClient->addConfigurationListener(receiver);\n+\n+    // Run the Kaa endpoint.\n+    kaaClient->start();\n+\n+    // Wait for the Enter key before exiting.\n+    std::cin.get();\n+    \n }\n+\n ```\n \n-As an example, consider transformation of the following record.\n+</div>\n+<div id=\"C-1\" class=\"tab-pane fade\" markdown=\"1\" >\n \n-{% include csv-table.html csv_path='record-trasformation.csv' table_id='record-trasformation' width='100%' %}\n \n+```c\n+#include <target.h>\n \n-<br/>**Note:**\n+#include <kaa/kaa_error.h>\n+#include <kaa/kaa_context.h>\n+#include <kaa/platform/kaa_client.h>\n+#include <kaa/utilities/kaa_log.h>\n+#include <kaa_configuration_manager.h>\n+ \n+static kaa_client_t *kaa_client = NULL;\n \n-* The \\__uuid field was added to org.kaaproject.sample.addressableRecordT, but not to org.kaaproject.sample.primitiveRecordT.\n-* There is a reference to org.kaaproject.sample.addressableRecordT in the union definition for the delta field of the org.kaaproject.configuration.deltaT type.\n-* org.kaaproject.configuration.uuidT is used in a union to indicate the removal of UUID-addressable records in /arrayOfRecords, but not in /arrayOfPrimitives.\n+void print_configuration(\n+        const kaa_root_configuration_t *configuration) {\n+        printf(\"Current configuration: \" configuration);\n+}\n \n-### Delta calculation algorithm\n+kaa_error_t kaa_demo_configuration_receiver(void *context,\n+                                            const kaa_root_configuration_t *configuration) {\n+    (void) context;\n+    printf(\"Received configuration data\\r\\n\");\n+    print_configuration(configuration);\n+    kaa_client_stop(kaa_client);\n+    return KAA_ERR_NONE;\n+}\n \n-The delta calculation algorithm is executed by the Operations server to discover and represent via the [protocol schema]() the difference between the newly required configuration and the current one in regard to the specific endpoint. This difference is represented according to the corresponding [protocol schema]() and then supplied to the endpoint as the _delta configuration data_ (other accepted terms for which are delta, delta update, delta record). Note that both configurations should conform to the same configuration schema version.\n+int main(/*int argc, char *argv[]*/) {\n \n-To keep track of the current endpoint configuration, the Kaa server maintains a hash look-up table that contains the configuration SHA-1 hash, as well as the configuration data itself. Whenever the Operations server calculates a configuration with the unique hash, it adds that configuration to the table which is persisted in the database and shared across the Operations servers. The endpoint submits the hash of the last known configuration to Operations server for the table lookup.\n+    //Initialize Kaa client.\n+    kaa_error_t error_code = kaa_client_create(&kaa_client, NULL);\n+    if (error_code) {\n+        printf(\"Failed create Kaa client\\r\\n\");\n+        return 2;\n+    }\n \n-Having found the current endpoint configuration via the hash look-up, the Operations server starts comparing the current configuration set with the new one to detect any discrepancies between the two. Once all the differences are found, the Operations server looks up the nearest UUID-addressable record in the [addressing hierarchy]() and creates a delta record for it. After that, the algorithm proceeds to comparing the corresponding records in the two data sets and filling in the delta record. In case some field has the same value in both configuration sets, this field is assigned the unchanged type value (\"unchangedT\") in the delta record to indicate so. Otherwise, the value from the new configuration set is copied into the delta record.\n+    kaa_configuration_root_receiver_t receiver = {\n+            NULL,","path":"doc/Programming-guide/Key-platform-features/Configuration-management/index.md","position":1110,"original_position":1110,"commit_id":"6fbe735764df37a50fb1dd2867f3723d1f6441d4","original_commit_id":"6fbe735764df37a50fb1dd2867f3723d1f6441d4","user":{"login":"forGGe","id":5261821,"avatar_url":"https://avatars.githubusercontent.com/u/5261821?v=3","gravatar_id":"","url":"https://api.github.com/users/forGGe","html_url":"https://github.com/forGGe","followers_url":"https://api.github.com/users/forGGe/followers","following_url":"https://api.github.com/users/forGGe/following{/other_user}","gists_url":"https://api.github.com/users/forGGe/gists{/gist_id}","starred_url":"https://api.github.com/users/forGGe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/forGGe/subscriptions","organizations_url":"https://api.github.com/users/forGGe/orgs","repos_url":"https://api.github.com/users/forGGe/repos","events_url":"https://api.github.com/users/forGGe/events{/privacy}","received_events_url":"https://api.github.com/users/forGGe/received_events","type":"User","site_admin":false},"body":"Use designated initializer for structure element initialization.","created_at":"2016-07-28T13:22:56Z","updated_at":"2016-07-28T13:22:57Z","html_url":"https://github.com/kaaproject/kaa/pull/864#discussion_r72620327","pull_request_url":"https://api.github.com/repos/kaaproject/kaa/pulls/864","_links":{"self":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/comments/72620327"},"html":{"href":"https://github.com/kaaproject/kaa/pull/864#discussion_r72620327"},"pull_request":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/864"}}},"pull_request":{"url":"https://api.github.com/repos/kaaproject/kaa/pulls/864","id":77263373,"html_url":"https://github.com/kaaproject/kaa/pull/864","diff_url":"https://github.com/kaaproject/kaa/pull/864.diff","patch_url":"https://github.com/kaaproject/kaa/pull/864.patch","issue_url":"https://api.github.com/repos/kaaproject/kaa/issues/864","number":864,"state":"closed","locked":false,"title":"KAA-1166: Add a page on configuration management","user":{"login":"chv348","id":12833314,"avatar_url":"https://avatars.githubusercontent.com/u/12833314?v=3","gravatar_id":"","url":"https://api.github.com/users/chv348","html_url":"https://github.com/chv348","followers_url":"https://api.github.com/users/chv348/followers","following_url":"https://api.github.com/users/chv348/following{/other_user}","gists_url":"https://api.github.com/users/chv348/gists{/gist_id}","starred_url":"https://api.github.com/users/chv348/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chv348/subscriptions","organizations_url":"https://api.github.com/users/chv348/orgs","repos_url":"https://api.github.com/users/chv348/repos","events_url":"https://api.github.com/users/chv348/events{/privacy}","received_events_url":"https://api.github.com/users/chv348/received_events","type":"User","site_admin":false},"body":"Page of 'Configuration management' fixed.","created_at":"2016-07-13T10:13:58Z","updated_at":"2016-07-28T13:22:57Z","closed_at":"2016-07-21T11:11:13Z","merged_at":"2016-07-21T11:11:13Z","merge_commit_sha":"3180339effd542f37ece065e67fc3a23459ae5ca","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/kaaproject/kaa/pulls/864/commits","review_comments_url":"https://api.github.com/repos/kaaproject/kaa/pulls/864/comments","review_comment_url":"https://api.github.com/repos/kaaproject/kaa/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kaaproject/kaa/issues/864/comments","statuses_url":"https://api.github.com/repos/kaaproject/kaa/statuses/6fbe735764df37a50fb1dd2867f3723d1f6441d4","head":{"label":"chv348:KAA-1166","ref":"KAA-1166","sha":"6fbe735764df37a50fb1dd2867f3723d1f6441d4","user":{"login":"chv348","id":12833314,"avatar_url":"https://avatars.githubusercontent.com/u/12833314?v=3","gravatar_id":"","url":"https://api.github.com/users/chv348","html_url":"https://github.com/chv348","followers_url":"https://api.github.com/users/chv348/followers","following_url":"https://api.github.com/users/chv348/following{/other_user}","gists_url":"https://api.github.com/users/chv348/gists{/gist_id}","starred_url":"https://api.github.com/users/chv348/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chv348/subscriptions","organizations_url":"https://api.github.com/users/chv348/orgs","repos_url":"https://api.github.com/users/chv348/repos","events_url":"https://api.github.com/users/chv348/events{/privacy}","received_events_url":"https://api.github.com/users/chv348/received_events","type":"User","site_admin":false},"repo":{"id":62781543,"name":"kaa","full_name":"chv348/kaa","owner":{"login":"chv348","id":12833314,"avatar_url":"https://avatars.githubusercontent.com/u/12833314?v=3","gravatar_id":"","url":"https://api.github.com/users/chv348","html_url":"https://github.com/chv348","followers_url":"https://api.github.com/users/chv348/followers","following_url":"https://api.github.com/users/chv348/following{/other_user}","gists_url":"https://api.github.com/users/chv348/gists{/gist_id}","starred_url":"https://api.github.com/users/chv348/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chv348/subscriptions","organizations_url":"https://api.github.com/users/chv348/orgs","repos_url":"https://api.github.com/users/chv348/repos","events_url":"https://api.github.com/users/chv348/events{/privacy}","received_events_url":"https://api.github.com/users/chv348/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/chv348/kaa","description":"Kaa open-source middleware platform for building, managing, and integrating connected products with the Internet of Everything.","fork":true,"url":"https://api.github.com/repos/chv348/kaa","forks_url":"https://api.github.com/repos/chv348/kaa/forks","keys_url":"https://api.github.com/repos/chv348/kaa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/chv348/kaa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/chv348/kaa/teams","hooks_url":"https://api.github.com/repos/chv348/kaa/hooks","issue_events_url":"https://api.github.com/repos/chv348/kaa/issues/events{/number}","events_url":"https://api.github.com/repos/chv348/kaa/events","assignees_url":"https://api.github.com/repos/chv348/kaa/assignees{/user}","branches_url":"https://api.github.com/repos/chv348/kaa/branches{/branch}","tags_url":"https://api.github.com/repos/chv348/kaa/tags","blobs_url":"https://api.github.com/repos/chv348/kaa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/chv348/kaa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/chv348/kaa/git/refs{/sha}","trees_url":"https://api.github.com/repos/chv348/kaa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/chv348/kaa/statuses/{sha}","languages_url":"https://api.github.com/repos/chv348/kaa/languages","stargazers_url":"https://api.github.com/repos/chv348/kaa/stargazers","contributors_url":"https://api.github.com/repos/chv348/kaa/contributors","subscribers_url":"https://api.github.com/repos/chv348/kaa/subscribers","subscription_url":"https://api.github.com/repos/chv348/kaa/subscription","commits_url":"https://api.github.com/repos/chv348/kaa/commits{/sha}","git_commits_url":"https://api.github.com/repos/chv348/kaa/git/commits{/sha}","comments_url":"https://api.github.com/repos/chv348/kaa/comments{/number}","issue_comment_url":"https://api.github.com/repos/chv348/kaa/issues/comments{/number}","contents_url":"https://api.github.com/repos/chv348/kaa/contents/{+path}","compare_url":"https://api.github.com/repos/chv348/kaa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/chv348/kaa/merges","archive_url":"https://api.github.com/repos/chv348/kaa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/chv348/kaa/downloads","issues_url":"https://api.github.com/repos/chv348/kaa/issues{/number}","pulls_url":"https://api.github.com/repos/chv348/kaa/pulls{/number}","milestones_url":"https://api.github.com/repos/chv348/kaa/milestones{/number}","notifications_url":"https://api.github.com/repos/chv348/kaa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/chv348/kaa/labels{/name}","releases_url":"https://api.github.com/repos/chv348/kaa/releases{/id}","deployments_url":"https://api.github.com/repos/chv348/kaa/deployments","created_at":"2016-07-07T06:40:55Z","updated_at":"2016-07-07T06:41:05Z","pushed_at":"2016-07-27T12:18:54Z","git_url":"git://github.com/chv348/kaa.git","ssh_url":"git@github.com:chv348/kaa.git","clone_url":"https://github.com/chv348/kaa.git","svn_url":"https://github.com/chv348/kaa","homepage":"http://www.kaaproject.org","size":138455,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"kaaproject:develop","ref":"develop","sha":"1b57c090d96859d5dded89b5782782f191a1b211","user":{"login":"kaaproject","id":6984613,"avatar_url":"https://avatars.githubusercontent.com/u/6984613?v=3","gravatar_id":"","url":"https://api.github.com/users/kaaproject","html_url":"https://github.com/kaaproject","followers_url":"https://api.github.com/users/kaaproject/followers","following_url":"https://api.github.com/users/kaaproject/following{/other_user}","gists_url":"https://api.github.com/users/kaaproject/gists{/gist_id}","starred_url":"https://api.github.com/users/kaaproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaaproject/subscriptions","organizations_url":"https://api.github.com/users/kaaproject/orgs","repos_url":"https://api.github.com/users/kaaproject/repos","events_url":"https://api.github.com/users/kaaproject/events{/privacy}","received_events_url":"https://api.github.com/users/kaaproject/received_events","type":"Organization","site_admin":false},"repo":{"id":17839346,"name":"kaa","full_name":"kaaproject/kaa","owner":{"login":"kaaproject","id":6984613,"avatar_url":"https://avatars.githubusercontent.com/u/6984613?v=3","gravatar_id":"","url":"https://api.github.com/users/kaaproject","html_url":"https://github.com/kaaproject","followers_url":"https://api.github.com/users/kaaproject/followers","following_url":"https://api.github.com/users/kaaproject/following{/other_user}","gists_url":"https://api.github.com/users/kaaproject/gists{/gist_id}","starred_url":"https://api.github.com/users/kaaproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaaproject/subscriptions","organizations_url":"https://api.github.com/users/kaaproject/orgs","repos_url":"https://api.github.com/users/kaaproject/repos","events_url":"https://api.github.com/users/kaaproject/events{/privacy}","received_events_url":"https://api.github.com/users/kaaproject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kaaproject/kaa","description":"Kaa open-source middleware platform for building, managing, and integrating connected products with the Internet of Everything.","fork":false,"url":"https://api.github.com/repos/kaaproject/kaa","forks_url":"https://api.github.com/repos/kaaproject/kaa/forks","keys_url":"https://api.github.com/repos/kaaproject/kaa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kaaproject/kaa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kaaproject/kaa/teams","hooks_url":"https://api.github.com/repos/kaaproject/kaa/hooks","issue_events_url":"https://api.github.com/repos/kaaproject/kaa/issues/events{/number}","events_url":"https://api.github.com/repos/kaaproject/kaa/events","assignees_url":"https://api.github.com/repos/kaaproject/kaa/assignees{/user}","branches_url":"https://api.github.com/repos/kaaproject/kaa/branches{/branch}","tags_url":"https://api.github.com/repos/kaaproject/kaa/tags","blobs_url":"https://api.github.com/repos/kaaproject/kaa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kaaproject/kaa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kaaproject/kaa/git/refs{/sha}","trees_url":"https://api.github.com/repos/kaaproject/kaa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kaaproject/kaa/statuses/{sha}","languages_url":"https://api.github.com/repos/kaaproject/kaa/languages","stargazers_url":"https://api.github.com/repos/kaaproject/kaa/stargazers","contributors_url":"https://api.github.com/repos/kaaproject/kaa/contributors","subscribers_url":"https://api.github.com/repos/kaaproject/kaa/subscribers","subscription_url":"https://api.github.com/repos/kaaproject/kaa/subscription","commits_url":"https://api.github.com/repos/kaaproject/kaa/commits{/sha}","git_commits_url":"https://api.github.com/repos/kaaproject/kaa/git/commits{/sha}","comments_url":"https://api.github.com/repos/kaaproject/kaa/comments{/number}","issue_comment_url":"https://api.github.com/repos/kaaproject/kaa/issues/comments{/number}","contents_url":"https://api.github.com/repos/kaaproject/kaa/contents/{+path}","compare_url":"https://api.github.com/repos/kaaproject/kaa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kaaproject/kaa/merges","archive_url":"https://api.github.com/repos/kaaproject/kaa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kaaproject/kaa/downloads","issues_url":"https://api.github.com/repos/kaaproject/kaa/issues{/number}","pulls_url":"https://api.github.com/repos/kaaproject/kaa/pulls{/number}","milestones_url":"https://api.github.com/repos/kaaproject/kaa/milestones{/number}","notifications_url":"https://api.github.com/repos/kaaproject/kaa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kaaproject/kaa/labels{/name}","releases_url":"https://api.github.com/repos/kaaproject/kaa/releases{/id}","deployments_url":"https://api.github.com/repos/kaaproject/kaa/deployments","created_at":"2014-03-17T18:48:31Z","updated_at":"2016-07-28T11:00:15Z","pushed_at":"2016-07-28T12:18:22Z","git_url":"git://github.com/kaaproject/kaa.git","ssh_url":"git@github.com:kaaproject/kaa.git","clone_url":"https://github.com/kaaproject/kaa.git","svn_url":"https://github.com/kaaproject/kaa","homepage":"http://www.kaaproject.org","size":148210,"stargazers_count":345,"watchers_count":345,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":133,"mirror_url":null,"open_issues_count":41,"forks":133,"open_issues":41,"watchers":345,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/864"},"html":{"href":"https://github.com/kaaproject/kaa/pull/864"},"issue":{"href":"https://api.github.com/repos/kaaproject/kaa/issues/864"},"comments":{"href":"https://api.github.com/repos/kaaproject/kaa/issues/864/comments"},"review_comments":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/864/comments"},"review_comment":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/864/commits"},"statuses":{"href":"https://api.github.com/repos/kaaproject/kaa/statuses/6fbe735764df37a50fb1dd2867f3723d1f6441d4"}}}}
{"actor":{"display_login":"forGGe"}}