IGNITE-7777: Implemented Ignite NodeJs thin client

Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c56d16fb
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c56d16fb
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c56d16fb

Branch: refs/heads/ignite-8900-repro
Commit: c56d16fb741703aac2bc72a6267c35f78084be30
Parents: e1a3398
Author: Igor Sapego <isap...@gridgain.com>
Authored: Thu Jun 28 17:40:25 2018 +0300
Committer: Igor Sapego <isap...@gridgain.com>
Committed: Thu Jun 28 17:40:25 2018 +0300

----------------------------------------------------------------------
 modules/platforms/nodejs/README.md              |  615 ++
 .../platforms/nodejs/api_spec/BinaryObject.html | 1847 ++++
 .../nodejs/api_spec/BinaryObject.js.html        |  549 ++
 .../platforms/nodejs/api_spec/CacheClient.html  | 4867 ++++++++++
 .../nodejs/api_spec/CacheClient.js.html         |  812 ++
 .../nodejs/api_spec/CacheConfiguration.html     | 8527 ++++++++++++++++++
 .../nodejs/api_spec/CacheConfiguration.js.html  | 1784 ++++
 .../platforms/nodejs/api_spec/CacheEntry.html   |  468 +
 .../nodejs/api_spec/CacheKeyConfiguration.html  |  796 ++
 .../nodejs/api_spec/CollectionObjectType.html   |  524 ++
 .../nodejs/api_spec/ComplexObjectType.html      |  526 ++
 .../nodejs/api_spec/CompositeType.html          |  170 +
 modules/platforms/nodejs/api_spec/Cursor.html   |  588 ++
 .../platforms/nodejs/api_spec/Cursor.js.html    |  360 +
 modules/platforms/nodejs/api_spec/EnumItem.html | 1431 +++
 .../platforms/nodejs/api_spec/EnumItem.js.html  |  255 +
 .../platforms/nodejs/api_spec/Errors.js.html    |  172 +
 .../platforms/nodejs/api_spec/IgniteClient.html | 2368 +++++
 .../nodejs/api_spec/IgniteClient.js.html        |  343 +
 .../api_spec/IgniteClientConfiguration.html     |  846 ++
 .../api_spec/IgniteClientConfiguration.js.html  |  163 +
 .../nodejs/api_spec/IgniteClientError.html      |  168 +
 .../nodejs/api_spec/IllegalStateError.html      |  179 +
 .../nodejs/api_spec/LostConnectionError.html    |  179 +
 .../nodejs/api_spec/MapObjectType.html          |  485 +
 .../nodejs/api_spec/ObjectArrayType.html        |  265 +
 .../platforms/nodejs/api_spec/ObjectType.html   | 1126 +++
 .../nodejs/api_spec/ObjectType.js.html          |  651 ++
 .../nodejs/api_spec/OperationError.html         |  179 +
 modules/platforms/nodejs/api_spec/Query.html    |  481 +
 modules/platforms/nodejs/api_spec/Query.js.html |  559 ++
 .../platforms/nodejs/api_spec/QueryEntity.html  | 2218 +++++
 .../platforms/nodejs/api_spec/QueryField.html   | 2211 +++++
 .../platforms/nodejs/api_spec/QueryIndex.html   | 1480 +++
 .../platforms/nodejs/api_spec/ScanQuery.html    |  686 ++
 .../nodejs/api_spec/SqlFieldsCursor.html        |  915 ++
 .../nodejs/api_spec/SqlFieldsQuery.html         | 3036 +++++++
 modules/platforms/nodejs/api_spec/SqlQuery.html | 1755 ++++
 .../platforms/nodejs/api_spec/Timestamp.html    |  566 ++
 .../platforms/nodejs/api_spec/Timestamp.js.html |  127 +
 modules/platforms/nodejs/api_spec/conf.json     |   12 +
 .../api_spec/fonts/OpenSans-Bold-webfont.eot    |  Bin 0 -> 19544 bytes
 .../api_spec/fonts/OpenSans-Bold-webfont.svg    | 1830 ++++
 .../api_spec/fonts/OpenSans-Bold-webfont.woff   |  Bin 0 -> 22432 bytes
 .../fonts/OpenSans-BoldItalic-webfont.eot       |  Bin 0 -> 20133 bytes
 .../fonts/OpenSans-BoldItalic-webfont.svg       | 1830 ++++
 .../fonts/OpenSans-BoldItalic-webfont.woff      |  Bin 0 -> 23048 bytes
 .../api_spec/fonts/OpenSans-Italic-webfont.eot  |  Bin 0 -> 20265 bytes
 .../api_spec/fonts/OpenSans-Italic-webfont.svg  | 1830 ++++
 .../api_spec/fonts/OpenSans-Italic-webfont.woff |  Bin 0 -> 23188 bytes
 .../api_spec/fonts/OpenSans-Light-webfont.eot   |  Bin 0 -> 19514 bytes
 .../api_spec/fonts/OpenSans-Light-webfont.svg   | 1831 ++++
 .../api_spec/fonts/OpenSans-Light-webfont.woff  |  Bin 0 -> 22248 bytes
 .../fonts/OpenSans-LightItalic-webfont.eot      |  Bin 0 -> 20535 bytes
 .../fonts/OpenSans-LightItalic-webfont.svg      | 1835 ++++
 .../fonts/OpenSans-LightItalic-webfont.woff     |  Bin 0 -> 23400 bytes
 .../api_spec/fonts/OpenSans-Regular-webfont.eot |  Bin 0 -> 19836 bytes
 .../api_spec/fonts/OpenSans-Regular-webfont.svg | 1831 ++++
 .../fonts/OpenSans-Regular-webfont.woff         |  Bin 0 -> 22660 bytes
 modules/platforms/nodejs/api_spec/index.html    |   65 +
 .../nodejs/api_spec/scripts/linenumber.js       |   25 +
 .../scripts/prettify/Apache-License-2.0.txt     |  202 +
 .../api_spec/scripts/prettify/lang-css.js       |    2 +
 .../api_spec/scripts/prettify/prettify.js       |   28 +
 .../nodejs/api_spec/styles/jsdoc-default.css    |  358 +
 .../nodejs/api_spec/styles/prettify-jsdoc.css   |  111 +
 .../api_spec/styles/prettify-tomorrow.css       |  132 +
 .../platforms/nodejs/examples/AuthTlsExample.js |  128 +
 .../nodejs/examples/CachePutGetExample.js       |  186 +
 .../nodejs/examples/FailoverExample.js          |   59 +
 modules/platforms/nodejs/examples/README.md     |  128 +
 modules/platforms/nodejs/examples/SqlExample.js |  242 +
 .../nodejs/examples/SqlQueryEntriesExample.js   |  136 +
 modules/platforms/nodejs/examples/certs/ca.crt  |   32 +
 .../platforms/nodejs/examples/certs/client.crt  |   30 +
 .../platforms/nodejs/examples/certs/client.key  |   51 +
 .../nodejs/examples/certs/keystore.jks          |  Bin 0 -> 3828 bytes
 .../nodejs/examples/certs/truststore.jks        |  Bin 0 -> 1477 bytes
 modules/platforms/nodejs/index.js               |   43 +
 modules/platforms/nodejs/lib/BinaryObject.js    |  498 +
 modules/platforms/nodejs/lib/CacheClient.js     |  761 ++
 .../platforms/nodejs/lib/CacheConfiguration.js  | 1733 ++++
 modules/platforms/nodejs/lib/Cursor.js          |  309 +
 modules/platforms/nodejs/lib/EnumItem.js        |  204 +
 modules/platforms/nodejs/lib/Errors.js          |  121 +
 modules/platforms/nodejs/lib/IgniteClient.js    |  292 +
 .../nodejs/lib/IgniteClientConfiguration.js     |  112 +
 modules/platforms/nodejs/lib/ObjectType.js      |  600 ++
 modules/platforms/nodejs/lib/Query.js           |  508 ++
 modules/platforms/nodejs/lib/Timestamp.js       |   76 +
 .../nodejs/lib/internal/ArgumentChecker.js      |   83 +
 .../nodejs/lib/internal/BinaryReader.js         |  197 +
 .../platforms/nodejs/lib/internal/BinaryType.js |  472 +
 .../nodejs/lib/internal/BinaryTypeStorage.js    |  112 +
 .../nodejs/lib/internal/BinaryUtils.js          |  598 ++
 .../nodejs/lib/internal/BinaryWriter.js         |  210 +
 .../nodejs/lib/internal/ClientFailoverSocket.js |  134 +
 .../nodejs/lib/internal/ClientSocket.js         |  434 +
 modules/platforms/nodejs/lib/internal/Logger.js |   45 +
 .../nodejs/lib/internal/MessageBuffer.js        |  272 +
 modules/platforms/nodejs/package-lock.json      |  168 +
 modules/platforms/nodejs/package.json           |   25 +
 .../platforms/nodejs/spec/ExamplesExecutor.js   |   11 +
 modules/platforms/nodejs/spec/README.md         |   42 +
 modules/platforms/nodejs/spec/TestingHelper.js  |  384 +
 .../nodejs/spec/cache/BinaryObject.spec.js      |  176 +
 .../platforms/nodejs/spec/cache/Cache.spec.js   |  262 +
 .../nodejs/spec/cache/CacheKeyValueOps.spec.js  | 1022 +++
 .../spec/cache/CachePutGetDiffTypes.spec.js     |  647 ++
 .../nodejs/spec/cache/ComplexObject.spec.js     |  464 +
 modules/platforms/nodejs/spec/config.js         |   27 +
 .../nodejs/spec/examples/AuthExample.spec.js    |   28 +
 .../nodejs/spec/examples/Examples.spec.js       |   40 +
 .../nodejs/spec/query/ScanQuery.spec.js         |  207 +
 .../nodejs/spec/query/SqlFieldsQuery.spec.js    |  247 +
 .../nodejs/spec/query/SqlQuery.spec.js          |  247 +
 .../platforms/nodejs/spec/support/jasmine.json  |   11 +
 117 files changed, 70013 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/README.md
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/README.md 
b/modules/platforms/nodejs/README.md
new file mode 100644
index 0000000..63a6725
--- /dev/null
+++ b/modules/platforms/nodejs/README.md
@@ -0,0 +1,615 @@
+# NodeJS Client for Apache Ignite #
+
+This client allows your application to work with the [Apache Ignite 
platform](https://ignite.apache.org/) via the [Binary Client 
Protocol](https://apacheignite.readme.io/docs/binary-client-protocol).
+
+The client includes:
+- [API 
specification](https://rawgit.com/nobitlost/ignite/master/modules/platforms/nodejs/api_spec/index.html)
+- [implementation](./lib)
+- [examples](./examples)
+- [tests](./spec)
+- docs
+  - the main readme (this file)
+  - [readme for examples](./examples/README.md)
+  - [readme for tests](./spec/README.md)
+
+## Installation ##
+
+[Node.js](https://nodejs.org/en/) version 8 or higher is required. Either 
download the Node.js [pre-built binary](https://nodejs.org/en/download/) for 
the target platform, or install Node.js via [package 
manager](https://nodejs.org/en/download/package-manager).
+
+Once `node` and `npm` are installed, execute the following commands:
+
+(temporary, while the NPM module is not released on 
[npmjs](https://www.npmjs.com))
+
+1. Clone or download Ignite repository https://github.com/nobitlost/ignite.git 
to `local_ignite_path`
+2. Go to `local_ignite_path/modules/platforms/nodejs` folder
+3. Execute `npm link` command
+4. Execute `npm link apache-ignite-client` command (needed only for examples 
and tests)
+
+```bash
+cd local_ignite_path/modules/platforms/nodejs
+npm link
+npm link apache-ignite-client
+```
+
+## Supported Features ##
+
+The client supports all operations and types from the [Binary Client Protocol 
v.2.4](https://apacheignite.readme.io/v2.4/docs/binary-client-protocol) except 
the following not-applicable features:
+- OP_REGISTER_BINARY_TYPE_NAME and OP_GET_BINARY_TYPE_NAME operations are not 
supported.
+- Filter object for OP_QUERY_SCAN operation is not supported. OP_QUERY_SCAN 
operation itself is supported.
+- It is not possible to register a new Ignite Enum type. Reading and writing 
items of the existing Ignite Enum types are supported.
+
+The following additional features are supported:
+- Authentication using username/password.
+- SSL/TLS connection.
+- "Failover re-connection algorithm".
+
+## API Specification ##
+
+Full specification of the client's public API is available 
[here](https://rawgit.com/nobitlost/ignite/master/modules/platforms/nodejs/api_spec/index.html)
+
+It is auto-generated from the [jsdoc](http://usejsdoc.org/) comments in source 
files and located in the [api_spec](./api_spec) folder.
+
+Promises async/await mechanism is used by the API and the client's 
implementation.
+
+## Data Types ##
+
+The client supports two cases of mapping between Ignite types defined by the 
Binary Client Protocol and JavaScript types:
+- default mapping,
+- explicit mapping.
+
+A mapping occurs every time an application writes or reads a field to/from an 
Ignite cache via the client's API. A field here is any data in a cache - key or 
value of a cache entry or a map, element of an array or set, field of a complex 
object, etc.
+
+Using the client's API methods, an application can explicitly specify an 
Ignite type for a field. The client uses this information during the field 
read/write operations. It returns the corresponding JavaScript type in results 
of read operations. It checks the corresponding JavaScript type in inputs of 
write operations.
+
+If an application does not explicitly specify an Ignite type for a field, the 
client uses default mapping during the field read/write operations.
+
+Default mapping between Ignite and JavaScript types is described 
[here](https://rawgit.com/nobitlost/ignite/master/modules/platforms/nodejs/api_spec/ObjectType.html).
+
+### Complex Object Type Support ###
+
+The client provides two ways to operate with the Ignite Complex Object type - 
in the deserialized form and in the binary form.
+
+An application can specify an Ignite type of a field by an instance of the 
*ComplexObjectType* class which references an instance of a JavaScript Object. 
In this case, when the application reads a value of the field, the client 
deserializes the received Ignite Complex Object and returns it to the client as 
an instance of the corresponding JavaScript Object. When the application writes 
a value of the field, the client expects an instance of the corresponding 
JavaScript Object and serializes it to the Ignite Complex Object.
+
+If an application does not specify an Ignite type of a field and reads a value 
of the field, the client returns the received Ignite Complex Object as an 
instance of the *BinaryObject* class - a binary form of the Ignite Complex 
Object. The *BinaryObject* allows to manipulate with it's content - read and 
write values of the object's fields, add and remove the fields, etc. Also, an 
application can create an instance of the *BinaryObject* class from a 
JavaScript Object. An application can write the *BinaryObject* as a value of a 
field in a cache, if that field has no explicitly specified Ignite type.
+
+The client takes care of obtaining or registering information about Ignite 
Complex Object type, including schema, from/at Ignite cluster. It is done 
automatically by the client, when required for reading or writing of the Ignite 
Complex Object from/to a cache.
+
+## Usage ##
+
+The below sections exaplains the basic steps to work with Apache Ignite using 
NodeJS client.
+
+### Instantiate Ignite Client ###
+
+A usage of the client starts from the creation of an *IgniteClient* class 
instance. The constructor has one, optional, parameter - *onStateChanged* 
callback which will be called every time the client moves to a new connection 
state (see below).
+
+It is possible to create as many *IgniteClient* instances as needed. All of 
them will work fully independently.
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+
+const igniteClient = new IgniteClient(onStateChanged);
+
+function onStateChanged(state, reason) {
+    if (state === IgniteClient.STATE.CONNECTED) {
+        console.log('Client is started');
+    }
+    else if (state === IgniteClient.STATE.DISCONNECTED) {
+        console.log('Client is stopped');
+        if (reason) {
+            console.log(reason);
+        }
+    }
+}
+```
+
+### Create Ignite Client Configuration ###
+
+The next step is to define a configuration for the client's connection - 
create an *IgniteClientConfiguration* class instance.
+
+A mandatory part of the configuration, which is specified in the constructor, 
is a list of endpoints of the Ignite nodes. At least one endpoint must be 
specified. A client connects to one node only - a random endpoint from the 
provided list. Other nodes, if provided, are used by the client for the 
"failover re-connection algorithm": the client tries to re-connect to the next 
random endpoint from the list if the current connection has lost.
+
+Optional parts of the configuration can be specified using additional set 
methods. They include:
+- username and password for authentication,
+- SSL/TLS connection enabling,
+- NodeJS connection options.
+
+By default, the client establishes a non-secure connection with default 
connection options defined by NodeJS and does not use authentication.
+
+Example: default Ignite Client Configuration
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+
+const igniteClientConfiguration = new 
IgniteClientConfiguration('127.0.0.1:10800');
+```
+
+Example: Ignite Client Configuration with username/password authentication and 
additional connection options
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+
+const igniteClientConfiguration = new 
IgniteClientConfiguration('127.0.0.1:10800').
+    setUserName('ignite').
+    setPassword('ignite').
+    setConnectionOptions(false, { 'timeout' : 0 });
+```
+
+### Connect Ignite Client ###
+
+The next step is to connect the client to an Ignite node. The configuration 
for the client's connection, which includes endpoint(s) to connect to, is 
specified in the connect method.
+
+The client has three connection states - *CONNECTING*, *CONNECTED*, 
*DISCONNECTED*. A state is reported via *onStateChanged* callback, if that was 
provided in the client's constructor.
+
+Any operations with Ignite caches are possible in the *CONNECTED* state only.
+
+If the client unexpectedly lost the connection, it automatically moves to the 
*CONNECTING* state and tries to re-connect using the "failover re-connection 
algorithm". If not possible to connect to all endpoints from the provided list, 
the client moves to the *DISCONNECTED* state.
+
+At any moment, an application can call the disconnect method and forcibly 
moves the client to the *DISCONNECTED* state.
+
+When the client becomes disconnected, an application can call the connect 
method again - with the same or different configuration (eg. with different 
list of endpoints).
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+
+async function connectClient() {
+    const igniteClient = new IgniteClient(onStateChanged);
+    try {
+        const igniteClientConfiguration = new 
IgniteClientConfiguration('127.0.0.1:10800');
+        // connect to Ignite node
+        await igniteClient.connect(igniteClientConfiguration);
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+function onStateChanged(state, reason) {
+    if (state === IgniteClient.STATE.CONNECTED) {
+        console.log('Client is started');
+    }
+    else if (state === IgniteClient.STATE.DISCONNECTED) {
+        console.log('Client is stopped');
+        if (reason) {
+            console.log(reason);
+        }
+    }
+}
+
+connectClient();
+```
+
+### Obtain Cache Instance ###
+
+The next step is to obtain a Cache instance - an instance of the *CacheClient* 
class. One Cache instance gives access to one Ignite cache.
+
+The Ignite client provides several methods to manipulate with Ignite caches 
and obtain a Cache instance - get a cache by it's name, create a cache with the 
specified name and optional cache configuration, get or create a cache, 
destroys a cache, etc.
+
+It is possible to obtain as many *CacheClient* instances as needed - for the 
same or different Ignite caches - and work with all of them "in parallel".
+
+Example: get or create cache by name and destroy the cache
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+
+async function getOrCreateCacheByName() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        // get or create cache by name
+        const cache = await igniteClient.getOrCreateCache('myCache');
+
+        // perform cache key-value operations
+        // ...
+
+        // destroy cache
+        await igniteClient.destroyCache('myCache');
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+getOrCreateCacheByName();
+```
+
+Example: create cache by name and configuration
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const CacheConfiguration = IgniteClient.CacheConfiguration;
+
+async function createCacheByConfiguration() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        // create cache by name and configuration
+        const cache = await igniteClient.createCache(
+            'myCache',
+            new CacheConfiguration().setSqlSchema('PUBLIC'));
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+createCacheByConfiguration();
+```
+
+Example: get existing cache by name
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+
+async function getExistingCache() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        // get existing cache by name
+        const cache = igniteClient.getCache('myCache');
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+getExistingCache();
+```
+
+### Configure Cache Instance ###
+
+The next step is optional.
+
+It is possible to specify concrete Ignite types for the key and/or the value 
of the cache. If the key and/or value is a non-primitive type (eg. a map, a 
collection, a complex object, etc.) it is possible to specify concrete Ignite 
types for fields of that objects as well.
+
+If Ignite type is not explicitly specified for some field, the client tries to 
make automatic default mapping between JavaScript types and Ignite object types.
+
+More details about types and mappings are clarified in the [Data 
Types](#data-types) section.
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const ObjectType = IgniteClient.ObjectType;
+const MapObjectType = IgniteClient.MapObjectType;
+
+async function setCacheKeyValueTypes() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        const cache = await igniteClient.getOrCreateCache('myCache');
+        // set cache key/value types
+        cache.setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER).
+            setValueType(new MapObjectType(
+                MapObjectType.MAP_SUBTYPE.LINKED_HASH_MAP,
+                ObjectType.PRIMITIVE_TYPE.SHORT,
+                ObjectType.PRIMITIVE_TYPE.BYTE_ARRAY));
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+setCacheKeyValueTypes();
+```
+
+Now, everything is ready to manipulate with the data in the cache.
+
+### Key-Value Queries ###
+
+The *CacheClient* class provides methods to manipulate with the key and the 
value of the cache using Key-Value Queries operations - put, get, put all, get 
all, replace, clear, etc.
+
+Example: different cache Key-Value operations with primitive types
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const ObjectType = IgniteClient.ObjectType;
+const CacheEntry = IgniteClient.CacheEntry;
+
+async function performCacheKeyValueOperations() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        const cache = (await igniteClient.getOrCreateCache('myCache')).
+            setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER);
+        // put and get value
+        await cache.put(1, 'abc');
+        const value = await cache.get(1);
+
+        // put and get multiple values using putAll()/getAll() methods
+        await cache.putAll([new CacheEntry(2, 'value2'), new CacheEntry(3, 
'value3')]);
+        const values = await cache.getAll([1, 2, 3]);
+
+        // removes all entries from the cache
+        await cache.clear();
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+performCacheKeyValueOperations();
+```
+
+Example: cache put/get Complex Objects and Binary Objects
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const ObjectType = IgniteClient.ObjectType;
+const CacheEntry = IgniteClient.CacheEntry;
+const ComplexObjectType = IgniteClient.ComplexObjectType;
+
+class Person {
+    constructor(id = null, name = null, salary = null) {
+        this.id = id;
+        this.name = name;
+        this.salary = salary;
+    }
+}
+
+async function putGetComplexAndBinaryObjects() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        const cache = await igniteClient.getOrCreateCache('myPersonCache');
+        // Complex Object type for JavaScript Person class instances
+        const personComplexObjectType = new ComplexObjectType(new Person(0, 
'', 0)).
+            setFieldType('id', ObjectType.PRIMITIVE_TYPE.INTEGER); 
+        // set cache key and value types
+        cache.setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER).
+            setValueType(personComplexObjectType);
+        // put Complex Objects to the cache
+        await cache.put(1, new Person(1, 'John Doe', 1000));
+        await cache.put(2, new Person(2, 'Jane Roe', 2000));
+        // get Complex Object, returned value is an instance of Person class
+        const person = await cache.get(1);
+        console.log(person);
+
+        // new CacheClient instance of the same cache to operate with 
BinaryObjects
+        const binaryCache = igniteClient.getCache('myPersonCache').
+            setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER);
+        // get Complex Object from the cache in a binary form, returned value 
is an instance of BinaryObject class
+        let binaryPerson = await binaryCache.get(2);
+        console.log('Binary form of Person:');       
+        for (let fieldName of binaryPerson.getFieldNames()) {
+            let fieldValue = await binaryPerson.getField(fieldName);
+            console.log(fieldName + ' : ' + fieldValue);
+        }
+        // modify Binary Object and put it to the cache
+        binaryPerson.setField('id', 3, ObjectType.PRIMITIVE_TYPE.INTEGER).
+            setField('name', 'Mary Major');
+        await binaryCache.put(3, binaryPerson);
+
+        // get Binary Object from the cache and convert it to JavaScript Object
+        binaryPerson = await binaryCache.get(3);
+        console.log(await binaryPerson.toObject(personComplexObjectType));
+
+        await igniteClient.destroyCache('myPersonCache');
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+putGetComplexAndBinaryObjects();
+```
+
+### SQL, SQL Fields and Scan Queries ###
+
+The *CacheClient* class provides the query method that accepts an instance of 
a concrete query definition class and returns an instance of a concrete cursor 
class which can be used to obtain the results of the query.
+
+Every cursor class allows
+- either to iterate over the results of the query by obtaining one element of 
the results after another,
+- or to get all elements of the results in a one array at once.
+
+#### SQL Query ####
+
+First, define the query by creating and configuring an instance of the 
*SqlQuery* class.
+
+Then, pass the *SqlQuery* instance in to the query method of the Cache 
instance and obtain an instance of the *Cursor* class.
+
+Finally, use the *Cursor* instance to iterate over or get all cache entries 
returned by the query.
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const CacheConfiguration = IgniteClient.CacheConfiguration;
+const QueryEntity = IgniteClient.QueryEntity;
+const QueryField = IgniteClient.QueryField;
+const ObjectType = IgniteClient.ObjectType;
+const ComplexObjectType = IgniteClient.ComplexObjectType;
+const CacheEntry = IgniteClient.CacheEntry;
+const SqlQuery = IgniteClient.SqlQuery;
+
+async function performSqlQuery() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        // cache configuration required for sql query execution
+        const cacheConfiguration = new CacheConfiguration().
+            setQueryEntities(
+                new QueryEntity().
+                    setValueTypeName('Person').
+                    setFields([
+                        new QueryField('name', 'java.lang.String'),
+                        new QueryField('salary', 'java.lang.Double')
+                    ]));
+        const cache = (await 
igniteClient.getOrCreateCache('sqlQueryPersonCache', cacheConfiguration)).
+            setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER).
+            setValueType(new ComplexObjectType({ 'name' : '', 'salary' : 0 }, 
'Person'));
+
+        // put multiple values using putAll()
+        await cache.putAll([
+            new CacheEntry(1, { 'name' : 'John Doe', 'salary' : 1000 }),
+            new CacheEntry(2, { 'name' : 'Jane Roe', 'salary' : 2000 }),
+            new CacheEntry(2, { 'name' : 'Mary Major', 'salary' : 1500 })]);
+
+        // create and configure sql query
+        const sqlQuery = new SqlQuery('Person', 'salary > ? and salary <= ?').
+            setArgs(900, 1600);
+        // obtain sql query cursor
+        const cursor = await cache.query(sqlQuery);
+        // getAll cache entries returned by the sql query
+        for (let cacheEntry of await cursor.getAll()) {
+            console.log(cacheEntry.getValue());
+        }
+
+        await igniteClient.destroyCache('sqlQueryPersonCache');
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+performSqlQuery();
+```
+
+#### Scan Query ####
+
+First, define the query by creating and configuring an instance of the 
*ScanQuery* class.
+
+Then, pass the *ScanQuery* instance in to the query method of the Cache 
instance and obtain an instance of the *Cursor* class.
+
+Finally, use the *Cursor* instance to iterate over or get all cache entries 
returned by the query.
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const ObjectType = IgniteClient.ObjectType;
+const CacheEntry = IgniteClient.CacheEntry;
+const ScanQuery = IgniteClient.ScanQuery;
+
+async function performScanQuery() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        const cache = (await igniteClient.getOrCreateCache('myCache')).
+            setKeyType(ObjectType.PRIMITIVE_TYPE.INTEGER);
+
+        // put multiple values using putAll()
+        await cache.putAll([
+            new CacheEntry(1, 'value1'),
+            new CacheEntry(2, 'value2'),
+            new CacheEntry(3, 'value3')]);
+
+        // create and configure scan query
+        const scanQuery = new ScanQuery().
+            setPageSize(1);
+        // obtain scan query cursor
+        const cursor = await cache.query(scanQuery);
+        // getAll cache entries returned by the scan query
+        for (let cacheEntry of await cursor.getAll()) {
+            console.log(cacheEntry.getValue());
+        }
+
+        await igniteClient.destroyCache('myCache');
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+performScanQuery();
+```
+
+#### SQL Fields Query ####
+
+First, define the query by creating and configuring an instance of the 
*SqlFieldsQuery* class.
+
+Then, pass the *SqlFieldsQuery* instance in to the query method of the Cache 
instance and obtain an instance of the *SqlFieldsCursor* class.
+
+Finally, use the *SqlFieldsCursor* instance to iterate over or get all 
elements returned by the query.
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
+const CacheConfiguration = IgniteClient.CacheConfiguration;
+const ObjectType = IgniteClient.ObjectType;
+const CacheEntry = IgniteClient.CacheEntry;
+const SqlFieldsQuery = IgniteClient.SqlFieldsQuery;
+
+async function performSqlFieldsQuery() {
+    const igniteClient = new IgniteClient();
+    try {
+        await igniteClient.connect(new 
IgniteClientConfiguration('127.0.0.1:10800'));
+        const cache = await igniteClient.getOrCreateCache('myPersonCache', new 
CacheConfiguration().
+            setSqlSchema('PUBLIC'));
+
+        // create table using SqlFieldsQuery
+        (await cache.query(new SqlFieldsQuery(
+           'CREATE TABLE Person (id INTEGER PRIMARY KEY, firstName VARCHAR, 
lastName VARCHAR, salary DOUBLE)'))).getAll();
+
+        // insert data into the table
+        const insertQuery = new SqlFieldsQuery('INSERT INTO Person (id, 
firstName, lastName, salary) values (?, ?, ?, ?)').
+            setArgTypes(ObjectType.PRIMITIVE_TYPE.INTEGER);
+        (await cache.query(insertQuery.setArgs(1, 'John', 'Doe', 
1000))).getAll();
+        (await cache.query(insertQuery.setArgs(2, 'Jane', 'Roe', 
2000))).getAll();
+
+        // obtain sql fields cursor
+        const sqlFieldsCursor = await cache.query(
+            new SqlFieldsQuery("SELECT concat(firstName, ' ', lastName), 
salary from Person").
+                setPageSize(1));
+
+        // iterate over elements returned by the query
+        do {
+            console.log(await sqlFieldsCursor.getValue());
+        } while (sqlFieldsCursor.hasMore());
+
+        // drop the table
+        (await cache.query(new SqlFieldsQuery("DROP TABLE Person"))).getAll();
+    }
+    catch (err) {
+        console.log(err.message);
+    }
+    finally {
+        igniteClient.disconnect();
+    }
+}
+
+performSqlFieldsQuery();
+```
+
+### Enable Debug ###
+
+To switch on/off the client's debug output (including errors logging), call 
*setDebug()* method of the *IgniteClient* instance. Debug output is disabled by 
default.
+
+```javascript
+const IgniteClient = require('apache-ignite-client');
+
+const igniteClient = new IgniteClient();
+igniteClient.setDebug(true);
+```

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/api_spec/BinaryObject.html
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/api_spec/BinaryObject.html 
b/modules/platforms/nodejs/api_spec/BinaryObject.html
new file mode 100644
index 0000000..a387c1e
--- /dev/null
+++ b/modules/platforms/nodejs/api_spec/BinaryObject.html
@@ -0,0 +1,1847 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Class: BinaryObject</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Class: BinaryObject</h1>
+
+    
+
+
+
+
+<section>
+
+<header>
+    
+        <h2><span class="attribs"><span 
class="type-signature"></span></span>BinaryObject<span 
class="signature">(typeName)</span><span class="type-signature"></span></h2>
+        
+            <div class="class-description"><p>Class representing a complex 
Ignite object in the binary form.</p>
+<p>It corresponds to COMPOSITE_TYPE.COMPLEX_OBJECT <a 
href="ObjectType.html#.COMPOSITE_TYPE">ObjectType.COMPOSITE_TYPE</a>,
+has mandatory type Id, which corresponds to a name of the complex type,
+and includes optional fields.</p>
+<p>An instance of the BinaryObject can be obtained/created by the following 
ways:</p>
+<ul>
+<li>returned by the client when a complex object is received from Ignite cache
+and is not deserialized to another JavaScript object.</li>
+<li>created using the public constructor. Fields may be added to such an 
instance using setField() method.</li>
+<li>created from a JavaScript object using static fromObject() method.</li>
+</ul></div>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+
+    
+    <h2>Constructor</h2>
+    
+
+    
+    <h4 class="name" id="BinaryObject"><span class="type-signature"></span>new 
BinaryObject<span class="signature">(typeName)</span><span 
class="type-signature"></span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Creates an instance of the BinaryObject without any fields.</p>
+<p>Fields may be added later using setField() method.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>typeName</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>name of the complex type to 
generate the type Id.</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line61">line 61</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+        <h3 class="subsection-title">Methods</h3>
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id=".fromObject"><span class="type-signature">(async, 
static) </span>fromObject<span class="signature">(jsObject, 
complexObjectType<span class="signature-attributes">opt</span>)</span><span 
class="type-signature"> &rarr; {<a 
href="BinaryObject.html">BinaryObject</a>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Creates an instance of the BinaryObject from the specified instance of 
JavaScript Object.</p>
+<p>All fields of the JavaScript Object instance with their values are added to 
the BinaryObject.
+Fields may be added or removed later using setField() and removeField() 
methods.</p>
+<p>If complexObjectType parameter is specified, then the type Id is taken from 
it.
+Otherwise, the type Id is generated from the name of the JavaScript Object.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+        <th>Attributes</th>
+        
+
+        
+        <th>Default</th>
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>jsObject</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">object</span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                </td>
+            
+
+            <td class="description last"><p>instance of JavaScript Object
+  which adds and initializes the fields of the BinaryObject instance.</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>complexObjectType</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a 
href="ComplexObjectType.html">ComplexObjectType</a></span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+                    &lt;optional><br>
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                    null
+                
+                </td>
+            
+
+            <td class="description last"><p>instance of complex type definition
+  which specifies non-standard mapping of the fields of the BinaryObject 
instance
+  to/from the Ignite types.</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line105">line 105</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>new BinaryObject instance.</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type"><a href="BinaryObject.html">BinaryObject</a></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="getField"><span class="type-signature">(async) 
</span>getField<span class="signature">(fieldName, fieldType<span 
class="signature-attributes">opt</span>)</span><span class="type-signature"> 
&rarr; {*}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Returns a value of the specified field.</p>
+<p>Optionally, specifies a type of the field.
+If the type is not specified then the Ignite client
+will try to make automatic mapping between JavaScript types and Ignite object 
types -
+according to the mapping table defined in the description of the <a 
href="ObjectType.html">ObjectType</a> class.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+        <th>Attributes</th>
+        
+
+        
+        <th>Default</th>
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldName</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                </td>
+            
+
+            <td class="description last"><p>name of the field.</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldType</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a 
href="ObjectType.html#.PRIMITIVE_TYPE">ObjectType.PRIMITIVE_TYPE</a></span>
+|
+
+<span class="param-type"><a href="CompositeType.html">CompositeType</a></span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+                    &lt;optional><br>
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                    null
+                
+                </td>
+            
+
+            <td class="description last"><p>type of the field:</p>
+<ul>
+<li>either a type code of primitive (simple) type</li>
+<li>or an instance of class representing non-primitive (composite) type</li>
+<li>or null (or not specified) that means the type is not specified.</li>
+</ul></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line209">line 209</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>value of the field or JavaScript undefined if the field does not 
exist.</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">*</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="getFieldNames"><span 
class="type-signature"></span>getFieldNames<span 
class="signature">()</span><span class="type-signature"> &rarr; 
{Array.&lt;string>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Returns names of all fields of this BinaryObject instance.</p>
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line261">line 261</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>names of all fields.</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">Array.&lt;string></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="getTypeName"><span 
class="type-signature"></span>getTypeName<span class="signature">()</span><span 
class="type-signature"> &rarr; {string}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Returns type name of this BinaryObject instance.</p>
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line250">line 250</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>type name.</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">string</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="hasField"><span 
class="type-signature"></span>hasField<span 
class="signature">(fieldName)</span><span class="type-signature"> &rarr; 
{boolean}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Checks if the specified field exists in this BinaryObject instance.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldName</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>name of the field.</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line184">line 184</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>true if exists, false otherwise.</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">boolean</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="removeField"><span 
class="type-signature"></span>removeField<span 
class="signature">(fieldName)</span><span class="type-signature"> &rarr; {<a 
href="BinaryObject.html">BinaryObject</a>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Removes the specified field.
+Does nothing if the field does not exist.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldName</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>name of the field.</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line167">line 167</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>the same instance of BinaryObject</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type"><a href="BinaryObject.html">BinaryObject</a></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="setField"><span 
class="type-signature"></span>setField<span class="signature">(fieldName, 
fieldValue, fieldType<span class="signature-attributes">opt</span>)</span><span 
class="type-signature"> &rarr; {<a 
href="BinaryObject.html">BinaryObject</a>}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Sets the new value of the specified field.
+Adds the specified field, if it did not exist before.</p>
+<p>Optionally, specifies a type of the field.
+If the type is not specified then during operations the Ignite client
+will try to make automatic mapping between JavaScript types and Ignite object 
types -
+according to the mapping table defined in the description of the <a 
href="ObjectType.html">ObjectType</a> class.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+        <th>Attributes</th>
+        
+
+        
+        <th>Default</th>
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldName</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                </td>
+            
+
+            <td class="description last"><p>name of the field.</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldValue</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">*</span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                </td>
+            
+
+            <td class="description last"><p>new value of the field.</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>fieldType</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a 
href="ObjectType.html#.PRIMITIVE_TYPE">ObjectType.PRIMITIVE_TYPE</a></span>
+|
+
+<span class="param-type"><a href="CompositeType.html">CompositeType</a></span>
+
+
+            
+            </td>
+
+            
+                <td class="attributes">
+                
+                    &lt;optional><br>
+                
+
+                
+
+                
+                </td>
+            
+
+            
+                <td class="default">
+                
+                    null
+                
+                </td>
+            
+
+            <td class="description last"><p>type of the field:</p>
+<ul>
+<li>either a type code of primitive (simple) type</li>
+<li>or an instance of class representing non-primitive (composite) type</li>
+<li>or null (or not specified) that means the type is not specified.</li>
+</ul></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line148">line 148</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>the same instance of BinaryObject</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type"><a href="BinaryObject.html">BinaryObject</a></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="toObject"><span class="type-signature">(async) 
</span>toObject<span class="signature">(complexObjectType)</span><span 
class="type-signature"> &rarr; {object}</span></h4>
+    
+
+    
+
+
+
+<div class="description">
+    <p>Deserializes this BinaryObject instance into an instance of the 
specified complex object type.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>complexObjectType</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type"><a 
href="ComplexObjectType.html">ComplexObjectType</a></span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>instance of class representing 
complex object type.</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="BinaryObject.js.html">BinaryObject.js</a>, <a 
href="BinaryObject.js.html#line227">line 227</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+<h5>Throws:</h5>
+
+        
+
+<dl>
+    <dt>
+        <div class="param-desc">
+        <p>if error.</p>
+        </div>
+    </dt>
+    <dd></dd>
+    <dt>
+        <dl>
+            <dt>
+                Type
+            </dt>
+            <dd>
+                
+<span class="param-type"><a 
href="IgniteClientError.html">IgniteClientError</a></span>
+
+
+            </dd>
+        </dl>
+    </dt>
+    <dd></dd>
+</dl>
+
+
+    
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <ul>
+<li>instance of the JavaScript object
+which corresponds to the specified complex object type.</li>
+</ul>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">object</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+    
+
+    
+
+    
+</article>
+
+</section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a 
href="BinaryObject.html">BinaryObject</a></li><li><a 
href="CacheClient.html">CacheClient</a></li><li><a 
href="CacheConfiguration.html">CacheConfiguration</a></li><li><a 
href="CacheEntry.html">CacheEntry</a></li><li><a 
href="CacheKeyConfiguration.html">CacheKeyConfiguration</a></li><li><a 
href="CollectionObjectType.html">CollectionObjectType</a></li><li><a 
href="ComplexObjectType.html">ComplexObjectType</a></li><li><a 
href="CompositeType.html">CompositeType</a></li><li><a 
href="Cursor.html">Cursor</a></li><li><a 
href="EnumItem.html">EnumItem</a></li><li><a 
href="IgniteClient.html">IgniteClient</a></li><li><a 
href="IgniteClientConfiguration.html">IgniteClientConfiguration</a></li><li><a 
href="IgniteClientError.html">IgniteClientError</a></li><li><a 
href="IllegalStateError.html">IllegalStateError</a></li><li><a 
href="LostConnectionError.html">LostConnectionError</a></li><li><a 
href="MapObjectType.html">MapObjectType</
 a></li><li><a href="ObjectArrayType.html">ObjectArrayType</a></li><li><a 
href="ObjectType.html">ObjectType</a></li><li><a 
href="OperationError.html">OperationError</a></li><li><a 
href="Query.html">Query</a></li><li><a 
href="QueryEntity.html">QueryEntity</a></li><li><a 
href="QueryField.html">QueryField</a></li><li><a 
href="QueryIndex.html">QueryIndex</a></li><li><a 
href="ScanQuery.html">ScanQuery</a></li><li><a 
href="SqlFieldsCursor.html">SqlFieldsCursor</a></li><li><a 
href="SqlFieldsQuery.html">SqlFieldsQuery</a></li><li><a 
href="SqlQuery.html">SqlQuery</a></li><li><a 
href="Timestamp.html">Timestamp</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc";>JSDoc 
3.5.5</a> on Tue May 22 2018 12:08:48 GMT+0300 (Russia TZ 2 Standard Time)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c56d16fb/modules/platforms/nodejs/api_spec/BinaryObject.js.html
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/api_spec/BinaryObject.js.html 
b/modules/platforms/nodejs/api_spec/BinaryObject.js.html
new file mode 100644
index 0000000..4479a26
--- /dev/null
+++ b/modules/platforms/nodejs/api_spec/BinaryObject.js.html
@@ -0,0 +1,549 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: BinaryObject.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: BinaryObject.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict';
+
+const Util = require('util');
+const ObjectType = require('./ObjectType').ObjectType;
+const ComplexObjectType = require('./ObjectType').ComplexObjectType;
+const Errors = require('./Errors');
+const BinaryUtils = require('./internal/BinaryUtils');
+const BinaryType = require('./internal/BinaryType');
+const BinaryField = require('./internal/BinaryType').BinaryField;
+const BinaryTypeBuilder = require('./internal/BinaryType').BinaryTypeBuilder;
+const BinaryWriter = require('./internal/BinaryWriter');
+const ArgumentChecker = require('./internal/ArgumentChecker');
+const Logger = require('./internal/Logger');
+
+const HEADER_LENGTH = 24;
+const VERSION = 1;
+
+// user type
+const FLAG_USER_TYPE = 0x0001;
+// schema exists
+const FLAG_HAS_SCHEMA = 0x0002;
+// object contains raw data
+const FLAG_HAS_RAW_DATA = 0x0004;
+// offsets take 1 byte
+const FLAG_OFFSET_ONE_BYTE = 0x0008;
+// offsets take 2 bytes
+const FLAG_OFFSET_TWO_BYTES = 0x0010;
+// compact footer, no field IDs
+const FLAG_COMPACT_FOOTER = 0x0020;
+
+/**
+ * Class representing a complex Ignite object in the binary form.
+ *
+ * It corresponds to COMPOSITE_TYPE.COMPLEX_OBJECT {@link 
ObjectType.COMPOSITE_TYPE},
+ * has mandatory type Id, which corresponds to a name of the complex type,
+ * and includes optional fields.
+ *
+ * An instance of the BinaryObject can be obtained/created by the following 
ways:
+ *   - returned by the client when a complex object is received from Ignite 
cache
+ * and is not deserialized to another JavaScript object.
+ *   - created using the public constructor. Fields may be added to such an 
instance using setField() method.
+ *   - created from a JavaScript object using static fromObject() method.
+ */
+class BinaryObject {
+
+    /**
+     * Creates an instance of the BinaryObject without any fields.
+     *
+     * Fields may be added later using setField() method.
+     *
+     * @param {string} typeName - name of the complex type to generate the 
type Id.
+     *
+     * @return {BinaryObject} - new BinaryObject instance.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    constructor(typeName) {
+        ArgumentChecker.notEmpty(typeName, 'typeName');
+        this._buffer = null;
+        this._fields = new Map();
+        this._typeBuilder = BinaryTypeBuilder.fromTypeName(typeName);
+        this._modified = false;
+        this._schemaOffset = null;
+        this._compactFooter = false;
+    }
+
+    /**
+     * Creates an instance of the BinaryObject from the specified instance of 
JavaScript Object.
+     *
+     * All fields of the JavaScript Object instance with their values are 
added to the BinaryObject.
+     * Fields may be added or removed later using setField() and removeField() 
methods.
+     *
+     * If complexObjectType parameter is specified, then the type Id is taken 
from it.
+     * Otherwise, the type Id is generated from the name of the JavaScript 
Object.
+     *
+     * @async
+     *
+     * @param {object} jsObject - instance of JavaScript Object
+     *   which adds and initializes the fields of the BinaryObject instance.
+     * @param {ComplexObjectType} [complexObjectType] - instance of complex 
type definition
+     *   which specifies non-standard mapping of the fields of the 
BinaryObject instance
+     *   to/from the Ignite types.
+     *
+     * @return {BinaryObject} - new BinaryObject instance.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    static async fromObject(jsObject, complexObjectType = null) {
+        ArgumentChecker.notEmpty(jsObject, 'jsObject');
+        ArgumentChecker.hasType(complexObjectType, 'complexObjectType', false, 
ComplexObjectType);
+        const typeBuilder = BinaryTypeBuilder.fromObject(jsObject, 
complexObjectType);
+        const result = new BinaryObject(typeBuilder.getTypeName());
+        result._typeBuilder = typeBuilder;
+        let fieldName;
+        for (let field of result._typeBuilder.getFields()) {
+            fieldName = field.name;
+            if (jsObject &amp;&amp; jsObject[fieldName] !== undefined) {
+                result.setField(
+                    fieldName,
+                    jsObject[fieldName],
+                    complexObjectType ? 
complexObjectType._getFieldType(fieldName) : null);
+            }
+            else {
+                throw Errors.IgniteClientError.serializationError(
+                    true, Util.format('field "%s" is undefined', fieldName));
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Sets the new value of the specified field.
+     * Adds the specified field, if it did not exist before.
+     *
+     * Optionally, specifies a type of the field.
+     * If the type is not specified then during operations the Ignite client
+     * will try to make automatic mapping between JavaScript types and Ignite 
object types -
+     * according to the mapping table defined in the description of the {@link 
ObjectType} class.
+     *
+     * @param {string} fieldName - name of the field.
+     * @param {*} fieldValue - new value of the field.
+     * @param {ObjectType.PRIMITIVE_TYPE | CompositeType} [fieldType] - type 
of the field:
+     *   - either a type code of primitive (simple) type
+     *   - or an instance of class representing non-primitive (composite) type
+     *   - or null (or not specified) that means the type is not specified.
+     *
+     * @return {BinaryObject} - the same instance of BinaryObject
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    setField(fieldName, fieldValue, fieldType = null) {
+        ArgumentChecker.notEmpty(fieldName, 'fieldName');
+        this._modified = true;
+        const field = new BinaryObjectField(fieldName, fieldValue, fieldType);
+        this._fields.set(field.id, field);
+        this._typeBuilder.setField(fieldName, field.typeCode);
+        return this;
+    }
+
+    /**
+     * Removes the specified field.
+     * Does nothing if the field does not exist.
+     *
+     * @param {string} fieldName - name of the field.
+     *
+     * @return {BinaryObject} - the same instance of BinaryObject
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    removeField(fieldName) {
+        ArgumentChecker.notEmpty(fieldName, 'fieldName');
+        this._modified = true;
+        this._fields.delete(BinaryField._calculateId(fieldName));
+        this._typeBuilder.removeField(fieldName);
+        return this;
+    }
+
+    /**
+     * Checks if the specified field exists in this BinaryObject instance.
+     *
+     * @param {string} fieldName - name of the field.
+     *
+     * @return {boolean} - true if exists, false otherwise.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    hasField(fieldName) {
+        ArgumentChecker.notEmpty(fieldName, 'fieldName');
+        return this._fields.has(BinaryField._calculateId(fieldName));
+    }
+
+    /**
+     * Returns a value of the specified field.
+     *
+     * Optionally, specifies a type of the field.
+     * If the type is not specified then the Ignite client
+     * will try to make automatic mapping between JavaScript types and Ignite 
object types -
+     * according to the mapping table defined in the description of the {@link 
ObjectType} class.
+     *
+     * @async
+     *
+     * @param {string} fieldName - name of the field.
+     * @param {ObjectType.PRIMITIVE_TYPE | CompositeType} [fieldType] - type 
of the field:
+     *   - either a type code of primitive (simple) type
+     *   - or an instance of class representing non-primitive (composite) type
+     *   - or null (or not specified) that means the type is not specified.
+     *
+     * @return {*} - value of the field or JavaScript undefined if the field 
does not exist.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    async getField(fieldName, fieldType = null) {
+        ArgumentChecker.notEmpty(fieldName, 'fieldName');
+        const field = this._fields.get(BinaryField._calculateId(fieldName));
+        return field ? await field.getValue(fieldType) : undefined;
+    }
+
+    /**
+     * Deserializes this BinaryObject instance into an instance of the 
specified complex object type.
+     *
+     * @async
+     *
+     * @param {ComplexObjectType} complexObjectType - instance of class 
representing complex object type.
+     *
+     * @return {object} - instance of the JavaScript object
+     *   which corresponds to the specified complex object type.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    async toObject(complexObjectType) {
+        ArgumentChecker.notNull(complexObjectType, 'complexObjectType');
+        ArgumentChecker.hasType(complexObjectType, 'complexObjectType', false, 
ComplexObjectType);
+        const result = new (complexObjectType._objectConstructor);
+        let binaryField;
+        let fieldName;
+        for (let field of this._fields.values()) {
+            binaryField = this._typeBuilder.getField(field.id);
+            if (!binaryField) {
+                throw Errors.IgniteClientError.serializationError(
+                    false, Util.format('field with id "%s" can not be 
deserialized', field.id));
+            }
+            fieldName = binaryField.name;
+            result[fieldName] = await 
field.getValue(complexObjectType._getFieldType(fieldName));
+        }
+        return result;
+    }
+
+    /**
+     * Returns type name of this BinaryObject instance.
+     *
+     * @return {string} - type name.
+     */
+    getTypeName() {
+        return this._typeBuilder.getTypeName();
+    }
+
+    /**
+     * Returns names of all fields of this BinaryObject instance.
+     *
+     * @return {Array&lt;string>} - names of all fields.
+     *
+     * @throws {IgniteClientError} if error.
+     */
+    getFieldNames() {
+        return this._typeBuilder._schema.fieldIds.map(fieldId => {
+            const field = this._typeBuilder.getField(fieldId);
+            if (field) {
+                return field.name;
+            }
+            else {
+                throw Errors.IgniteClientError.internalError(
+                    Util.format('Field "%s" is absent in binary type fields', 
fieldId));
+            }
+        });
+    }
+
+    /** Private methods */
+
+    /**
+     * @ignore
+     */
+    static _isFlagSet(flags, flag) {
+        return (flags &amp; flag) === flag;
+    }
+
+    /**
+     * @ignore
+     */
+    static async _fromBuffer(buffer) {
+        const result = new BinaryObject(new ComplexObjectType({})._typeName);
+        result._buffer = buffer;
+        result._startPos = buffer.position;
+        await result._read();
+        return result;
+    }
+
+    /**
+     * @ignore
+     */
+    async _write(buffer) {
+        if (this._buffer &amp;&amp; !this._modified) {
+            buffer.writeBuffer(this._buffer.buffer, this._startPos, 
this._startPos + this._length);
+        }
+        else {
+            await this._typeBuilder.finalize();
+            this._startPos = buffer.position;
+            buffer.position = this._startPos + HEADER_LENGTH;
+            // write fields
+            for (let field of this._fields.values()) {
+                await field._writeValue(buffer, 
this._typeBuilder.getField(field.id).typeCode);
+            }
+            this._schemaOffset = buffer.position - this._startPos;
+            // write schema
+            for (let field of this._fields.values()) {
+                field._writeOffset(buffer, this._startPos);
+            }
+            this._length = buffer.position - this._startPos;
+            this._buffer = buffer;
+            // write header
+            this._writeHeader();
+            this._buffer.position = this._startPos + this._length;
+            this._modified = false;
+        }
+
+        if (Logger.debug) {
+            Logger.logDebug('BinaryObject._write [' + 
[...this._buffer.getSlice(this._startPos, this._startPos + this._length)] + 
']');
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    _writeHeader() {
+        this._buffer.position = this._startPos;
+        // type code
+        this._buffer.writeByte(BinaryUtils.TYPE_CODE.COMPLEX_OBJECT);
+        // version
+        this._buffer.writeByte(VERSION);
+        // flags
+        this._buffer.writeShort(FLAG_USER_TYPE | FLAG_HAS_SCHEMA | 
FLAG_COMPACT_FOOTER);
+        // type id
+        this._buffer.writeInteger(this._typeBuilder.getTypeId());
+        // hash code
+        this._buffer.writeInteger(BinaryUtils.contentHashCode(
+            this._buffer, this._startPos + HEADER_LENGTH, this._schemaOffset - 
1));
+        // length
+        this._buffer.writeInteger(this._length);
+        // schema id
+        this._buffer.writeInteger(this._typeBuilder.getSchemaId());
+        // schema offset
+        this._buffer.writeInteger(this._schemaOffset);
+    }
+
+    /**
+     * @ignore
+     */
+    async _read() {
+        await this._readHeader();
+        this._buffer.position = this._startPos + this._schemaOffset;
+        const fieldOffsets = new Array();
+        const fieldIds = this._typeBuilder._schema.fieldIds;
+        let index = 0;
+        let fieldId;
+        while (this._buffer.position &lt; this._startPos + this._length) {
+            if (!this._compactFooter) {
+                fieldId = this._buffer.readInteger();
+                this._typeBuilder._schema.addField(fieldId);
+            }
+            else {
+                if (index >= fieldIds.length) {
+                    throw Errors.IgniteClientError.serializationError(
+                        false, 'wrong number of fields in schema');
+                }
+                fieldId = fieldIds[index];
+                index++;
+            }
+            fieldOffsets.push([fieldId, 
this._buffer.readNumber(this._offsetType)]);
+        }
+        fieldOffsets.sort((val1, val2) => val1[1] - val2[1]);
+        let offset;
+        let nextOffset;
+        let field;
+        for (let i = 0; i &lt; fieldOffsets.length; i++) {
+            fieldId = fieldOffsets[i][0];
+            offset = fieldOffsets[i][1];
+            nextOffset = i + 1 &lt; fieldOffsets.length ? fieldOffsets[i + 
1][1] : this._schemaOffset;
+            field = BinaryObjectField._fromBuffer(
+                this._buffer, this._startPos + offset, nextOffset - offset, 
fieldId);
+            this._fields.set(field.id, field);
+        }
+        this._buffer.position = this._startPos + this._length;
+    }
+
+    /**
+     * @ignore
+     */
+    async _readHeader() {
+        // type code
+        this._buffer.readByte();
+        // version
+        const version = this._buffer.readByte();
+        if (version !== VERSION) {
+            throw Errors.IgniteClientError.internalError();
+        }
+        // flags
+        const flags = this._buffer.readShort();
+        // type id
+        const typeId = this._buffer.readInteger();
+        // hash code
+        this._buffer.readInteger();
+        // length
+        this._length = this._buffer.readInteger();
+        // schema id
+        const schemaId = this._buffer.readInteger();
+        // schema offset
+        this._schemaOffset = this._buffer.readInteger();
+        const hasSchema = BinaryObject._isFlagSet(flags, FLAG_HAS_SCHEMA);
+        this._compactFooter = BinaryObject._isFlagSet(flags, 
FLAG_COMPACT_FOOTER);
+        this._offsetType = BinaryObject._isFlagSet(flags, 
FLAG_OFFSET_ONE_BYTE) ?
+            BinaryUtils.TYPE_CODE.BYTE :
+            BinaryObject._isFlagSet(flags, FLAG_OFFSET_TWO_BYTES) ?
+                BinaryUtils.TYPE_CODE.SHORT :
+                BinaryUtils.TYPE_CODE.INTEGER;
+
+        if (BinaryObject._isFlagSet(FLAG_HAS_RAW_DATA)) {
+            throw Errors.IgniteClientError.serializationError(
+                false, 'complex objects with raw data are not supported');
+        }
+        if (this._compactFooter &amp;&amp; !hasSchema) {
+            throw Errors.IgniteClientError.serializationError(
+                false, 'schema is absent for object with compact footer');
+        }
+        this._typeBuilder = await BinaryTypeBuilder.fromTypeId(typeId, 
schemaId, hasSchema);
+    }
+}
+
+/**
+ * @ignore
+ */
+class BinaryObjectField {
+    constructor(name, value = undefined, type = null) {
+        this._name = name;
+        this._id = BinaryField._calculateId(name);
+        this._value = value;
+        this._type = type;
+        if (!type &amp;&amp; value !== undefined &amp;&amp; value !== null) {
+            this._type = BinaryUtils.calcObjectType(value);
+        }
+        this._typeCode = null;
+        if (this._type) {
+            this._typeCode = BinaryUtils.getTypeCode(this._type);
+        }
+    }
+
+    get id() {
+        return this._id;
+    }
+
+    get typeCode() {
+        return this._typeCode;
+    }
+
+    async getValue(type = null) {
+        if (this._value === undefined || this._buffer &amp;&amp; this._type 
!== type) {
+            this._buffer.position = this._offset;
+            const BinaryReader = require('./internal/BinaryReader');
+            this._value = await BinaryReader.readObject(this._buffer, type);
+            this._type = type;
+        }
+        return this._value;
+    }
+
+    static _fromBuffer(buffer, offset, length, id) {
+        const result = new BinaryObjectField(null);
+        result._id = id;
+        result._buffer = buffer;
+        result._offset = offset;
+        result._length = length;
+        return result;
+    }
+
+    async _writeValue(buffer, expectedTypeCode) {
+        const offset = buffer.position;
+        if (this._buffer) {
+            buffer.writeBuffer(this._buffer.buffer, this._offset, this._offset 
+ this._length);
+        }
+        else {
+            BinaryUtils.checkCompatibility(this._value, expectedTypeCode);
+            await BinaryWriter.writeObject(buffer, this._value, this._type);
+        }
+        this._buffer = buffer;
+        this._length = buffer.position - offset;
+        this._offset = offset;
+    }
+
+    _writeOffset(buffer, headerStartPos) {
+        buffer.writeInteger(this._offset - headerStartPos);
+    }
+}
+
+module.exports = BinaryObject;
+</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a 
href="BinaryObject.html">BinaryObject</a></li><li><a 
href="CacheClient.html">CacheClient</a></li><li><a 
href="CacheConfiguration.html">CacheConfiguration</a></li><li><a 
href="CacheEntry.html">CacheEntry</a></li><li><a 
href="CacheKeyConfiguration.html">CacheKeyConfiguration</a></li><li><a 
href="CollectionObjectType.html">CollectionObjectType</a></li><li><a 
href="ComplexObjectType.html">ComplexObjectType</a></li><li><a 
href="CompositeType.html">CompositeType</a></li><li><a 
href="Cursor.html">Cursor</a></li><li><a 
href="EnumItem.html">EnumItem</a></li><li><a 
href="IgniteClient.html">IgniteClient</a></li><li><a 
href="IgniteClientConfiguration.html">IgniteClientConfiguration</a></li><li><a 
href="IgniteClientError.html">IgniteClientError</a></li><li><a 
href="IllegalStateError.html">IllegalStateError</a></li><li><a 
href="LostConnectionError.html">LostConnectionError</a></li><li><a 
href="MapObjectType.html">MapObjectType</
 a></li><li><a href="ObjectArrayType.html">ObjectArrayType</a></li><li><a 
href="ObjectType.html">ObjectType</a></li><li><a 
href="OperationError.html">OperationError</a></li><li><a 
href="Query.html">Query</a></li><li><a 
href="QueryEntity.html">QueryEntity</a></li><li><a 
href="QueryField.html">QueryField</a></li><li><a 
href="QueryIndex.html">QueryIndex</a></li><li><a 
href="ScanQuery.html">ScanQuery</a></li><li><a 
href="SqlFieldsCursor.html">SqlFieldsCursor</a></li><li><a 
href="SqlFieldsQuery.html">SqlFieldsQuery</a></li><li><a 
href="SqlQuery.html">SqlQuery</a></li><li><a 
href="Timestamp.html">Timestamp</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc";>JSDoc 
3.5.5</a> on Tue May 22 2018 12:08:48 GMT+0300 (Russia TZ 2 Standard Time)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>

Reply via email to