| /* | |
| * 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'; | |
| import * as Util from "util"; | |
| import ArgumentChecker from "./internal/ArgumentChecker"; | |
| import { IgniteClientError } from "./Errors"; | |
| import { PRIMITIVE_TYPE, COMPOSITE_TYPE } from "./internal/Constants"; | |
| import BinaryUtils from "./internal/BinaryUtils"; | |
| /** | |
| * Base class representing a type of Ignite object. | |
| * | |
| * The class has no public constructor. Only subclasses may be instantiated. | |
| * | |
| * There are two groups of Ignite object types: | |
| * | |
| * - Primitive (simple) types. To fully describe such a type it is enough to specify | |
| * Ignite type code {@link ObjectType.PRIMITIVE_TYPE} only. | |
| * | |
| * - Non-primitive (composite) types. To fully describe such a type | |
| * Ignite type code {@link ObjectType.COMPOSITE_TYPE} with additional information should be specified. | |
| * Eg. a kind of map or a kind of collection. | |
| * | |
| * This class helps the Ignite client to make a mapping between JavaScript types | |
| * and types used by Ignite. | |
| * | |
| * In many methods the Ignite client does not require to directly specify a type of Ignite object. | |
| * In this case the Ignite client tries to make automatic mapping between JavaScript types | |
| * and Ignite object types according to the following mapping tables: | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * | |
| * DEFAULT MAPPING FROM JavaScript type TO Ignite type code. | |
| * | |
| * This mapping is used when an application does not explicitly specify an Ignite type | |
| * for a field and is writing data to that field. | |
| * | |
| * <pre> | |
| * | JavaScript type | Ignite type code | | |
| * | ------------------------- | ----------------------| | |
| * | number | DOUBLE | | |
| * | boolean | BOOLEAN | | |
| * | string | STRING | | |
| * | Date | DATE | | |
| * | Timestamp* | TIMESTAMP | | |
| * | EnumItem* | ENUM | | |
| * | Decimal** | DECIMAL | | |
| * | BinaryObject* | COMPLEX_OBJECT | | |
| * | Array of number | DOUBLE_ARRAY | | |
| * | Array of boolean | BOOLEAN_ARRAY | | |
| * | Array of string | STRING_ARRAY | | |
| * | Array of Date | DATE_ARRAY | | |
| * | Array of Timestamp* | TIMESTAMP_ARRAY | | |
| * | Array of EnumItem* | ENUM_ARRAY | | |
| * | Array of Decimal** | DECIMAL_ARRAY | | |
| * | Array of BinaryObject* | OBJECT_ARRAY | | |
| * | Array of any other Object | OBJECT_ARRAY | | |
| * | Set | COLLECTION (HASH_SET) | | |
| * | Map | MAP (HASH_MAP) | | |
| * | any other Object | COMPLEX_OBJECT | | |
| * </pre> | |
| * | |
| * Type of an array content is determined by the type of the first element of the array. | |
| * Empty array has no default mapping. | |
| * | |
| * All other JavaScript types have no default mapping. | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * | |
| * DEFAULT MAPPING FROM Ignite type code TO JavaScript type. | |
| * | |
| * This mapping is used when an application does not explicitly specify an Ignite type | |
| * for a field and is reading data from that field. | |
| * | |
| * <pre> | |
| * | Ignite type code | JavaScript type | | |
| * | ---------------------------- | --------------------------------------| | |
| * | BYTE | number | | |
| * | SHORT | number | | |
| * | INTEGER | number | | |
| * | LONG | number | | |
| * | FLOAT | number | | |
| * | DOUBLE | number | | |
| * | DECIMAL | Decimal** | | |
| * | BOOLEAN | boolean | | |
| * | STRING | string | | |
| * | CHAR | string (one character) | | |
| * | UUID | Array of number (16 numbers) | | |
| * | DATE | Date | | |
| * | TIME | Date | | |
| * | TIMESTAMP | Timestamp* | | |
| * | ENUM | EnumItem* | | |
| * | COMPLEX_OBJECT | BinaryObject* | | |
| * | BYTE_ARRAY | Array of number | | |
| * | SHORT_ARRAY | Array of number | | |
| * | INTEGER_ARRAY | Array of number | | |
| * | LONG_ARRAY | Array of number | | |
| * | FLOAT_ARRAY | Array of number | | |
| * | DOUBLE_ARRAY | Array of number | | |
| * | DECIMAL_ARRAY | Array of Decimal** | | |
| * | BOOLEAN_ARRAY | Array of boolean | | |
| * | STRING_ARRAY | Array of string | | |
| * | CHAR_ARRAY | Array of string (one character) | | |
| * | UUID_ARRAY | Array of Array of number (16 numbers) | | |
| * | DATE_ARRAY | Array of Date | | |
| * | TIME_ARRAY | Array of Date | | |
| * | TIMESTAMP_ARRAY | Array of Timestamp* | | |
| * | ENUM_ARRAY | Array of EnumItem* | | |
| * | OBJECT_ARRAY | Array | | |
| * | COLLECTION (USER_COL) | Array | | |
| * | COLLECTION (ARR_LIST) | Array | | |
| * | COLLECTION (LINKED_LIST) | Array | | |
| * | COLLECTION (SINGLETON_LIST) | Array | | |
| * | COLLECTION (HASH_SET) | Set | | |
| * | COLLECTION (LINKED_HASH_SET) | Set | | |
| * | COLLECTION (USER_SET) | Set | | |
| * | MAP (HASH_MAP) | Map | | |
| * | MAP (LINKED_HASH_MAP) | Map | | |
| * | NULL | null | | |
| * </pre> | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * | |
| * RETURNED JavaScript types WHEN READING DATA OF THE SPECIFIED Ignite type code. | |
| * | |
| * When an application explicitly specifies an Ignite type for a field | |
| * and is reading data from that field - the following JavaScript types | |
| * are returned for every concrete Ignite type code - | |
| * | |
| * SEE THE PREVIOUS TABLE with the following additional comments: | |
| * | |
| * - for COMPLEX_OBJECT the Ignite Client returns a JavaScript Object | |
| * which is defined by the specified {@link ComplexObjectType}. | |
| * | |
| * - the returned Map for MAP is defined by the specified {@link MapObjectType}. | |
| * | |
| * - the returned Set or Array for COLLECTION is defined by the specified {@link CollectionObjectType}. | |
| * | |
| * - the returned Array for OBJECT_ARRAY is defined by the specified {@link ObjectArrayType}. | |
| * | |
| * - NULL cannot be specified as a type of a field but JavaScript null may be returned | |
| * as a value of a field. | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * | |
| * ALLOWED JavaScript types WHEN WRITING DATA OF THE SPECIFIED Ignite type code. | |
| * | |
| * When an application explicitly specifies an Ignite type for a field | |
| * and is writing data to that field - the following JavaScript types | |
| * are allowed for every concrete Ignite type code - | |
| * | |
| * SEE THE PREVIOUS TABLE with the following additional comments: | |
| * | |
| * - for COMPLEX_OBJECT the Ignite Client allows a JavaScript Object | |
| * which is defined by the specified {@link ComplexObjectType}. | |
| * | |
| * - the allowed Map for MAP is defined by the specified {@link MapObjectType}. | |
| * | |
| * - the allowed Set or Array for COLLECTION is defined by the specified {@link CollectionObjectType}. | |
| * | |
| * - the allowed Array for OBJECT_ARRAY is defined by the specified {@link ObjectArrayType}. | |
| * | |
| * - NULL cannot be specified as a type of a field but JavaScript null is allowed | |
| * as value of a field (but not as a key/value in a cache) or as a value of Array/Set/Map element | |
| * for all Ignite types, except BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, CHAR, BOOLEAN. | |
| * | |
| * - for all *_ARRAY Ignite types an empty JavaScript Array is allowed. | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * | |
| * COMMENTS TO ALL TABLES | |
| * | |
| * JavaScript type - is a JavaScript primitive or a JavaScript Object | |
| * ({@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures}) | |
| * | |
| * (*) Timestamp, EnumItem and BinaryObject - are JavaScript Objects introduced by the Ignite client. | |
| * | |
| * (**) Decimal - is an external JavaScript Object exported into the Ignite client | |
| * ({@link https://github.com/MikeMcl/decimal.js}) | |
| * | |
| * Ignite type code - is the type code of an Ignite primitive type ({@link ObjectType.PRIMITIVE_TYPE}) | |
| * or an Ignite composite type ({@link ObjectType.COMPOSITE_TYPE}). | |
| * | |
| * ---------------------------------------------------------------------------- | |
| * | |
| * @hideconstructor | |
| */ | |
| export class ObjectType { | |
| private _typeCode: number; | |
| static get PRIMITIVE_TYPE(): typeof PRIMITIVE_TYPE { | |
| return PRIMITIVE_TYPE; | |
| } | |
| static get COMPOSITE_TYPE(): typeof COMPOSITE_TYPE { | |
| return COMPOSITE_TYPE; | |
| } | |
| constructor(typeCode: number) { | |
| this._typeCode = typeCode; | |
| } | |
| get typeCode() { | |
| return this._typeCode; | |
| } | |
| } | |
| /** | |
| * Base class representing a non-primitive (composite) type of Ignite object. | |
| * | |
| * The class has no public constructor. Only subclasses may be instantiated. | |
| * | |
| * @hideconstructor | |
| * @extends ObjectType | |
| */ | |
| export class CompositeType extends ObjectType { | |
| } | |
| /** | |
| * Supported kinds of map. | |
| * @typedef MapObjectType.MAP_SUBTYPE | |
| * @enum | |
| * @readonly | |
| * @property HASH_MAP 1 | |
| * @property LINKED_HASH_MAP 2 | |
| */ | |
| export enum MAP_SUBTYPE { | |
| HASH_MAP = 1, | |
| LINKED_HASH_MAP = 2 | |
| } | |
| /** | |
| * Class representing a map type of Ignite object. | |
| * | |
| * It is described by COMPOSITE_TYPE.MAP {@link ObjectType.COMPOSITE_TYPE} | |
| * and one of {@link MapObjectType.MAP_SUBTYPE}. | |
| * | |
| * @extends CompositeType | |
| */ | |
| export class MapObjectType extends CompositeType { | |
| private _subType: MAP_SUBTYPE; | |
| private _keyType: PRIMITIVE_TYPE | CompositeType; | |
| private _valueType: PRIMITIVE_TYPE | CompositeType; | |
| static get MAP_SUBTYPE() { | |
| return MAP_SUBTYPE; | |
| } | |
| /** | |
| * Public constructor. | |
| * | |
| * Optionally specifies a kind of map and types of keys and values in the map. | |
| * | |
| * If a kind of map is not specified, MAP_SUBTYPE.HASH_MAP is assumed. | |
| * | |
| * If key and/or value 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 {MAP_SUBTYPE} [mapSubType=MAP_SUBTYPE.HASH_MAP] - map subtype, one of the | |
| * {@link MAP_SUBTYPE} constants. | |
| * @param {PRIMITIVE_TYPE | CompositeType} [keyType=null] - type of the keys in the map: | |
| * - 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 | |
| * @param {PRIMITIVE_TYPE | CompositeType} [valueType=null] - type of the values in the map: | |
| * - 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 {MapObjectType} - new MapObjectType instance | |
| * | |
| * @throws {IgniteClientError} if error. | |
| */ | |
| constructor(mapSubType: MAP_SUBTYPE = MapObjectType.MAP_SUBTYPE.HASH_MAP, keyType: PRIMITIVE_TYPE | CompositeType = null, valueType: PRIMITIVE_TYPE | CompositeType = null) { | |
| super(COMPOSITE_TYPE.MAP); | |
| ArgumentChecker.hasValueFrom(mapSubType, 'mapSubType', false, MapObjectType.MAP_SUBTYPE); | |
| this._subType = mapSubType; | |
| BinaryUtils.checkObjectType(keyType, 'keyType'); | |
| BinaryUtils.checkObjectType(valueType, 'valueType'); | |
| this._keyType = keyType; | |
| this._valueType = valueType; | |
| } | |
| } | |
| /** | |
| * Supported kinds of collections. | |
| * @typedef CollectionObjectType.COLLECTION_SUBTYPE | |
| * @enum | |
| * @readonly | |
| * @property USER_SET -1 | |
| * @property USER_COL 0 | |
| * @property ARRAY_LIST 1 | |
| * @property LINKED_LIST 2 | |
| * @property HASH_SET 3 | |
| * @property LINKED_HASH_SET 4 | |
| * @property SINGLETON_LIST 5 | |
| */ | |
| export enum COLLECTION_SUBTYPE { | |
| USER_SET = -1, | |
| USER_COL = 0, | |
| ARRAY_LIST = 1, | |
| LINKED_LIST = 2, | |
| HASH_SET = 3, | |
| LINKED_HASH_SET = 4, | |
| SINGLETON_LIST = 5 | |
| } | |
| /** | |
| * Class representing a collection type of Ignite object. | |
| * | |
| * It is described by COMPOSITE_TYPE.COLLECTION {@link ObjectType.COMPOSITE_TYPE} | |
| * and one of {@link CollectionObjectType.COLLECTION_SUBTYPE}. | |
| * | |
| * @extends CompositeType | |
| */ | |
| export class CollectionObjectType extends CompositeType { | |
| private _subType: COLLECTION_SUBTYPE; | |
| private _elementType: PRIMITIVE_TYPE | CompositeType; | |
| static get COLLECTION_SUBTYPE() { | |
| return COLLECTION_SUBTYPE; | |
| } | |
| /** | |
| * Public constructor. | |
| * | |
| * Specifies a kind of collection | |
| * and optionally specifies a type of elements in the collection. | |
| * | |
| * If the type of elements 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 {COLLECTION_SUBTYPE} collectionSubType - collection subtype, one of the | |
| * {@link COLLECTION_SUBTYPE} constants. | |
| * @param {PRIMITIVE_TYPE | CompositeType} [elementType=null] - type of elements in the collection: | |
| * - 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 {CollectionObjectType} - new CollectionObjectType instance | |
| * | |
| * @throws {IgniteClientError} if error. | |
| */ | |
| constructor(collectionSubType: COLLECTION_SUBTYPE, elementType: PRIMITIVE_TYPE | CompositeType = null) { | |
| super(COMPOSITE_TYPE.COLLECTION); | |
| ArgumentChecker.hasValueFrom( | |
| collectionSubType, 'collectionSubType', false, CollectionObjectType.COLLECTION_SUBTYPE); | |
| this._subType = collectionSubType; | |
| BinaryUtils.checkObjectType(elementType, 'elementType'); | |
| this._elementType = elementType; | |
| } | |
| /** Private methods */ | |
| /** | |
| * @ignore | |
| */ | |
| static _isSet(subType) { | |
| return subType === CollectionObjectType.COLLECTION_SUBTYPE.USER_SET || | |
| subType === CollectionObjectType.COLLECTION_SUBTYPE.HASH_SET || | |
| subType === CollectionObjectType.COLLECTION_SUBTYPE.LINKED_HASH_SET; | |
| } | |
| /** | |
| * @ignore | |
| */ | |
| _isSet() { | |
| return CollectionObjectType._isSet(this._subType); | |
| } | |
| } | |
| /** | |
| * Class representing an array type of Ignite objects. | |
| * | |
| * It is described by COMPOSITE_TYPE.OBJECT_ARRAY {@link ObjectType.COMPOSITE_TYPE}. | |
| * | |
| * @extends CompositeType | |
| */ | |
| export class ObjectArrayType extends CompositeType { | |
| _elementType: PRIMITIVE_TYPE | CompositeType; | |
| /** | |
| * Public constructor. | |
| * | |
| * Optionally specifies a type of elements in the array. | |
| * | |
| * If the type of elements 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 {PRIMITIVE_TYPE | CompositeType} [elementType=null] - type of the array element: | |
| * - 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 {ObjectArrayType} - new ObjectArrayType instance | |
| * | |
| * @throws {IgniteClientError} if error. | |
| */ | |
| constructor(elementType: PRIMITIVE_TYPE | CompositeType = null) { | |
| super(COMPOSITE_TYPE.OBJECT_ARRAY); | |
| BinaryUtils.checkObjectType(elementType, 'elementType'); | |
| this._elementType = elementType; | |
| } | |
| } | |
| /** | |
| * Class representing a complex type of Ignite object. | |
| * | |
| * It is described by COMPOSITE_TYPE.COMPLEX_OBJECT {@link ObjectType.COMPOSITE_TYPE}, | |
| * by a name of the complex type and by a JavaScript Object which is mapped to/from the Ignite complex type. | |
| * | |
| * @extends CompositeType | |
| */ | |
| export class ComplexObjectType extends CompositeType { | |
| private _template: object; | |
| private _objectConstructor: Function; | |
| private _typeName: string; | |
| private _fields: Map<string, any>; | |
| /** | |
| * Public constructor. | |
| * | |
| * Specifies a JavaScript Object type which will be mapped to/from the complex type. | |
| * This specification is done using an instance of the JavaScript Object. | |
| * | |
| * If an object of the complex type is going to be received (deserialized), | |
| * the JavaScript Object must have a constructor without parameters or with optional parameters only. | |
| * | |
| * The JavaScript Object defines a set of fields of the complex type. | |
| * | |
| * By default, the fields have no types specified. It means 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. | |
| * | |
| * A type of any field may be specified later by setFieldType() method. | |
| * | |
| * By default, the name of the complex type is the name of the JavaScript Object. | |
| * The name may be explicitely specified using optional typeName parameter in the constructor. | |
| * | |
| * @param {object} jsObject - instance of JavaScript Object which will be mapped to/from this complex type. | |
| * @param {string} [typeName] - name of the complex type. | |
| * | |
| * @return {ComplexObjectType} - new ComplexObjectType instance | |
| * | |
| * @throws {IgniteClientError} if error. | |
| */ | |
| constructor(jsObject, typeName = null) { | |
| super(COMPOSITE_TYPE.COMPLEX_OBJECT); | |
| ArgumentChecker.notEmpty(jsObject, 'jsObject'); | |
| this._template = jsObject; | |
| this._objectConstructor = jsObject && jsObject.constructor ? | |
| jsObject.constructor : Object; | |
| if (!typeName) { | |
| typeName = this._objectConstructor.name; | |
| } | |
| this._typeName = typeName; | |
| this._fields = new Map<string, any>(); | |
| for (let fieldName of BinaryUtils.getJsObjectFieldNames(this._template)) { | |
| this._fields.set(fieldName, null); | |
| } | |
| } | |
| /** | |
| * Specifies a type of the field in the complex type. | |
| * | |
| * 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 {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 (means the type is not specified). | |
| * | |
| * @return {ComplexObjectType} - the same instance of the ComplexObjectType. | |
| * | |
| * @throws {IgniteClientError} if error. | |
| */ | |
| setFieldType(fieldName, fieldType) { | |
| if (!this._fields.has(fieldName)) { | |
| throw IgniteClientError.illegalArgumentError( | |
| Util.format('Field "%s" is absent in the complex object type', fieldName)); | |
| } | |
| BinaryUtils.checkObjectType(fieldType, 'fieldType'); | |
| this._fields.set(fieldName, fieldType); | |
| return this; | |
| } | |
| /** Private methods */ | |
| /** | |
| * @ignore | |
| */ | |
| _getFieldType(fieldName) { | |
| return this._fields.get(fieldName); | |
| } | |
| get typeName() { | |
| return this._typeName; | |
| } | |
| } |