UNPKG

pip-services3-commons-node

Version:
701 lines (640 loc) 24.5 kB
/** @module data */ /** @hidden */ let _ = require('lodash'); import { TypeCode } from '../convert/TypeCode'; import { TypeConverter } from '../convert/TypeConverter'; import { StringConverter } from '../convert/StringConverter'; import { BooleanConverter } from '../convert/BooleanConverter'; import { IntegerConverter } from '../convert/IntegerConverter'; import { LongConverter } from '../convert/LongConverter'; import { FloatConverter } from '../convert/FloatConverter'; import { DoubleConverter } from '../convert/DoubleConverter'; import { DateTimeConverter } from '../convert/DateTimeConverter'; import { MapConverter } from '../convert/MapConverter'; import { ICloneable } from './ICloneable'; import { AnyValue } from './AnyValue'; import { AnyValueArray } from './AnyValueArray'; /** * Cross-language implementation of dynamic object map (dictionary) what can hold values of any type. * The stored values can be converted to different types using variety of accessor methods. * * ### Example ### * * let value1 = new AnyValueMap({ key1: 1, key2: "123.456", key3: "2018-01-01" }); * * value1.getAsBoolean("key1"); // Result: true * value1.getAsInteger("key2"); // Result: 123 * value1.getAsFloat("key2"); // Result: 123.456 * value1.getAsDateTime("key3"); // Result: new Date(2018,0,1) * * @see [[StringConverter]] * @see [[TypeConverter]] * @see [[BooleanConverter]] * @see [[IntegerConverter]] * @see [[LongConverter]] * @see [[DoubleConverter]] * @see [[FloatConverter]] * @see [[DateTimeConverter]] * @see [[ICloneable]] */ export class AnyValueMap implements ICloneable { /** * Creates a new instance of the map and assigns its value. * * @param value (optional) values to initialize this map. */ public constructor(values: any = null) { this.append(values); } /** * Gets a map element specified by its key. * * @param key a key of the element to get. * @returns the value of the map element. */ public get(key: string): any { return this[key] || null; } /** * Gets keys of all elements stored in this map. * * @returns a list with all map keys. */ public getKeys(): string[] { let keys: string[] = []; for (let key in this) { if (this.hasOwnProperty(key)) { keys.push(key); } } return keys; } /** * Puts a new value into map element specified by its key. * * @param key a key of the element to put. * @param value a new value for map element. */ public put(key: string, value: any): any { this[key] = value; } /** * Removes a map element specified by its key * * @param key a key of the element to remove. */ public remove(key: string): void { delete this[key]; } /** * Appends new elements to this map. * * @param map a map with elements to be added. */ public append(map: any): void { if (map == null) return; for (let key in map) { let value = map[key]; if (map.hasOwnProperty(key)) this[key] = value; } } /** * Clears this map by removing all its elements. */ public clear(): any { for (let key in this) { let value = this[key]; if (this.hasOwnProperty(key)) delete this[key]; } } /** * Gets a number of elements stored in this map. * * @returns the number of elements in this map. */ public length(): number { let count: number = 0; for (let key in this) { if (this.hasOwnProperty(key) && !_.isFunction(this[key])) { count ++; } } return count; } /** * Gets the value stored in map element without any conversions. * When element key is not defined it returns the entire map value. * * @param key (optional) a key of the element to get * @returns the element value or value of the map when index is not defined. */ public getAsObject(key: string = undefined): any { if (key === undefined) { let result: any = {}; for (let key in this) { let value = this[key]; if (this.hasOwnProperty(key)) result[key] = value; } return result; } else { return this.get(key); } } /** * Sets a new value to map element specified by its index. * When the index is not defined, it resets the entire map value. * This method has double purpose because method overrides are not supported in JavaScript. * * @param key (optional) a key of the element to set * @param value a new element or map value. * * @see [[MapConverter.toMap]] */ public setAsObject(key: any, value: any = undefined): void { if (value === undefined) { value = key this.clear(); let values = MapConverter.toMap(value); this.append(values); } else { this.put(key, value); } } /** * Converts map element into a string or returns null if conversion is not possible. * * @param key a key of element to get. * @returns string value of the element or null if conversion is not supported. * * @see [[StringConverter.toNullableString]] */ public getAsNullableString(key: string): string { let value = this.get(key); return StringConverter.toNullableString(value); } /** * Converts map element into a string or returns "" if conversion is not possible. * * @param key a key of element to get. * @returns string value of the element or "" if conversion is not supported. * * @see [[getAsStringWithDefault]] */ public getAsString(key: string): string { return this.getAsStringWithDefault(key, null); } /** * Converts map element into a string or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns string value of the element or default value if conversion is not supported. * * @see [[StringConverter.toStringWithDefault]] */ public getAsStringWithDefault(key: string, defaultValue: string): string { let value = this.get(key); return StringConverter.toStringWithDefault(value, defaultValue); } /** * Converts map element into a boolean or returns null if conversion is not possible. * * @param key a key of element to get. * @returns boolean value of the element or null if conversion is not supported. * * @see [[BooleanConverter.toNullableBoolean]] */ public getAsNullableBoolean(key: string): boolean { let value = this.get(key); return BooleanConverter.toNullableBoolean(value); } /** * Converts map element into a boolean or returns false if conversion is not possible. * * @param key a key of element to get. * @returns boolean value of the element or false if conversion is not supported. * * @see [[getAsBooleanWithDefault]] */ public getAsBoolean(key: string): boolean { return this.getAsBooleanWithDefault(key, false); } /** * Converts map element into a boolean or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns boolean value of the element or default value if conversion is not supported. * * @see [[BooleanConverter.toBooleanWithDefault]] */ public getAsBooleanWithDefault(key: string, defaultValue: boolean): boolean { let value = this.get(key); return BooleanConverter.toBooleanWithDefault(value, defaultValue); } /** * Converts map element into an integer or returns null if conversion is not possible. * * @param key a key of element to get. * @returns integer value of the element or null if conversion is not supported. * * @see [[IntegerConverter.toNullableInteger]] */ public getAsNullableInteger(key: string): number { let value = this.get(key); return IntegerConverter.toNullableInteger(value); } /** * Converts map element into an integer or returns 0 if conversion is not possible. * * @param key a key of element to get. * @returns integer value of the element or 0 if conversion is not supported. * * @see [[getAsIntegerWithDefault]] */ public getAsInteger(key: string): number { return this.getAsIntegerWithDefault(key, 0); } /** * Converts map element into an integer or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns integer value of the element or default value if conversion is not supported. * * @see [[IntegerConverter.toIntegerWithDefault]] */ public getAsIntegerWithDefault(key: string, defaultValue: number): number { let value = this.get(key); return IntegerConverter.toIntegerWithDefault(value, defaultValue); } /** * Converts map element into a long or returns null if conversion is not possible. * * @param key a key of element to get. * @returns long value of the element or null if conversion is not supported. * * @see [[LongConverter.toNullableLong]] */ public getAsNullableLong(key: string): number { let value = this.get(key); return LongConverter.toNullableLong(value); } /** * Converts map element into a long or returns 0 if conversion is not possible. * * @param key a key of element to get. * @returns long value of the element or 0 if conversion is not supported. * * @see [[getAsLongWithDefault]] */ public getAsLong(key: string): number { return this.getAsLongWithDefault(key, 0); } /** * Converts map element into a long or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns long value of the element or default value if conversion is not supported. * * @see [[LongConverter.toLongWithDefault]] */ public getAsLongWithDefault(key: string, defaultValue: number): number { let value = this.get(key); return LongConverter.toLongWithDefault(value, defaultValue); } /** * Converts map element into a float or returns null if conversion is not possible. * * @param key a key of element to get. * @returns float value of the element or null if conversion is not supported. * * @see [[FloatConverter.toNullableFloat]] */ public getAsNullableFloat(key: string): number { let value = this.get(key); return FloatConverter.toNullableFloat(value); } /** * Converts map element into a float or returns 0 if conversion is not possible. * * @param key a key of element to get. * @returns float value of the element or 0 if conversion is not supported. * * @see [[getAsFloatWithDefault]] */ public getAsFloat(key: string): number { return this.getAsFloatWithDefault(key, 0); } /** * Converts map element into a flot or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns flot value of the element or default value if conversion is not supported. * * @see [[FloatConverter.toFloatWithDefault]] */ public getAsFloatWithDefault(key: string, defaultValue: number): number { let value = this.get(key); return FloatConverter.toFloatWithDefault(value, defaultValue); } /** * Converts map element into a double or returns null if conversion is not possible. * * @param key a key of element to get. * @returns double value of the element or null if conversion is not supported. * * @see [[DoubleConverter.toNullableDouble]] */ public getAsNullableDouble(key: string): number { let value = this.get(key); return DoubleConverter.toNullableDouble(value); } /** * Converts map element into a double or returns 0 if conversion is not possible. * * @param key a key of element to get. * @returns double value of the element or 0 if conversion is not supported. * * @see [[getAsDoubleWithDefault]] */ public getAsDouble(key: string): number { return this.getAsDoubleWithDefault(key, 0); } /** * Converts map element into a double or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns double value of the element or default value if conversion is not supported. * * @see [[DoubleConverter.toDoubleWithDefault]] */ public getAsDoubleWithDefault(key: string, defaultValue: number): number { let value = this.get(key); return DoubleConverter.toDoubleWithDefault(value, defaultValue); } /** * Converts map element into a Date or returns null if conversion is not possible. * * @param key a key of element to get. * @returns Date value of the element or null if conversion is not supported. * * @see [[DateTimeConverter.toNullableDateTime]] */ public getAsNullableDateTime(key: string): Date { let value = this.get(key); return DateTimeConverter.toNullableDateTime(value); } /** * Converts map element into a Date or returns the current date if conversion is not possible. * * @param key a key of element to get. * @returns Date value of the element or the current date if conversion is not supported. * * @see [[getAsDateTimeWithDefault]] */ public getAsDateTime(key: string): Date { return this.getAsDateTimeWithDefault(key, null); } /** * Converts map element into a Date or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns Date value of the element or default value if conversion is not supported. * * @see [[DateTimeConverter.toDateTimeWithDefault]] */ public getAsDateTimeWithDefault(key: string, defaultValue: Date): Date { let value = this.get(key); return DateTimeConverter.toDateTimeWithDefault(value, defaultValue); } /** * Converts map element into a value defined by specied typecode. * If conversion is not possible it returns null. * * @param type the TypeCode that defined the type of the result * @param key a key of element to get. * @returns element value defined by the typecode or null if conversion is not supported. * * @see [[TypeConverter.toNullableType]] */ public getAsNullableType<T>(type: TypeCode, key: string): T { let value = this.get(key); return TypeConverter.toNullableType<T>(type, value); } /** * Converts map element into a value defined by specied typecode. * If conversion is not possible it returns default value for the specified type. * * @param type the TypeCode that defined the type of the result * @param key a key of element to get. * @returns element value defined by the typecode or default if conversion is not supported. * * @see [[getAsTypeWithDefault]] */ public getAsType<T>(type: TypeCode, key: string): T { return this.getAsTypeWithDefault<T>(type, key, null); } /** * Converts map element into a value defined by specied typecode. * If conversion is not possible it returns default value. * * @param type the TypeCode that defined the type of the result * @param key a key of element to get. * @param defaultValue the default value * @returns element value defined by the typecode or default value if conversion is not supported. * * @see [[TypeConverter.toTypeWithDefault]] */ public getAsTypeWithDefault<T>(type: TypeCode, key: string, defaultValue: T): T { let value = this.get(key); return TypeConverter.toTypeWithDefault(type, value, defaultValue); } /** * Converts map element into an AnyValue or returns an empty AnyValue if conversion is not possible. * * @param key a key of element to get. * @returns AnyValue value of the element or empty AnyValue if conversion is not supported. * * @see [[AnyValue]] * @see [[AnyValue.constructor]] */ public getAsValue(key: string): AnyValue { let value = this.get(key); return new AnyValue(value); } /** * Converts map element into an AnyValueArray or returns null if conversion is not possible. * * @param key a key of element to get. * @returns AnyValueArray value of the element or null if conversion is not supported. * * @see [[AnyValueArray]] * @see [[AnyValueArray.fromValue]] */ public getAsNullableArray(key: string): AnyValueArray { let value = this.get(key); return value != null ? AnyValueArray.fromValue(value) : null; } /** * Converts map element into an AnyValueArray or returns empty AnyValueArray if conversion is not possible. * * @param key a key of element to get. * @returns AnyValueArray value of the element or empty AnyValueArray if conversion is not supported. * * @see [[AnyValueArray]] * @see [[AnyValueArray.fromValue]] */ public getAsArray(key: string): AnyValueArray { let value = this.get(key); return AnyValueArray.fromValue(value); } /** * Converts map element into an AnyValueArray or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns AnyValueArray value of the element or default value if conversion is not supported. * * @see [[AnyValueArray]] * @see [[getAsNullableArray]] */ public getAsArrayWithDefault(key: string, defaultValue: AnyValueArray): AnyValueArray { let result = this.getAsNullableArray(key); return result != null ? result : defaultValue; } /** * Converts map element into an AnyValueMap or returns null if conversion is not possible. * * @param key a key of element to get. * @returns AnyValueMap value of the element or null if conversion is not supported. * * @see [[fromValue]] */ public getAsNullableMap(key: string): AnyValueMap { let value = this.get(key); return value != null ? AnyValueMap.fromValue(value) : null; } /** * Converts map element into an AnyValueMap or returns empty AnyValueMap if conversion is not possible. * * @param key a key of element to get. * @returns AnyValueMap value of the element or empty AnyValueMap if conversion is not supported. * * @see [[fromValue]] */ public getAsMap(key: string): AnyValueMap { let value = this.get(key); return AnyValueMap.fromValue(value); } /** * Converts map element into an AnyValueMap or returns default value if conversion is not possible. * * @param key a key of element to get. * @param defaultValue the default value * @returns AnyValueMap value of the element or default value if conversion is not supported. * * @see [[getAsNullableMap]] */ public getAsMapWithDefault(key: string, defaultValue: AnyValueMap): AnyValueMap { let result = this.getAsNullableMap(key); return result != null ? result: defaultValue; } /** * Gets a string representation of the object. * The result is a semicolon-separated list of key-value pairs as * "key1=value1;key2=value2;key=value3" * * @returns a string representation of the object. */ public toString(): string { let builder = ''; // Todo: User encoder for (let key in this) { if (this.hasOwnProperty(key)) { let value = this[key]; if (builder.length > 0) builder += ';'; if (value != null) builder += key + '=' + value; else builder += key; } } return builder; } /** * Creates a binary clone of this object. * * @returns a clone of this object. */ public clone(): any { return new AnyValueMap(this); } /** * Converts specified value into AnyValueMap. * * @param value value to be converted * @returns a newly created AnyValueMap. * * @see [[setAsObject]] */ public static fromValue(value: any): AnyValueMap { let result = new AnyValueMap(); result.setAsObject(value); return result; } /** * Creates a new AnyValueMap from a list of key-value pairs called tuples. * * @param tuples a list of values where odd elements are keys and the following even elements are values * @returns a newly created AnyValueArray. * * @see [[fromTuplesArray]] */ public static fromTuples(...tuples: any[]): AnyValueMap { return AnyValueMap.fromTuplesArray(tuples); } /** * Creates a new AnyValueMap from a list of key-value pairs called tuples. * The method is similar to [[fromTuples]] but tuples are passed as array instead of parameters. * * @param tuples a list of values where odd elements are keys and the following even elements are values * @returns a newly created AnyValueArray. */ public static fromTuplesArray(tuples: any[]): AnyValueMap { let result = new AnyValueMap(); if (tuples == null || tuples.length == 0) return result; for (let index = 0; index < tuples.length; index += 2) { if (index + 1 >= tuples.length) break; let name = StringConverter.toString(tuples[index]); let value = tuples[index + 1]; result.setAsObject(name, value); } return result; } /** * Creates a new AnyValueMap by merging two or more maps. * Maps defined later in the list override values from previously defined maps. * * @param maps an array of maps to be merged * @returns a newly created AnyValueMap. */ public static fromMaps(...maps: any[]): AnyValueMap { let result = new AnyValueMap(); if (maps != null && maps.length > 0) { for (let index = 0; index < maps.length; index++) result.append(maps[index]); } return result; } }