[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / catalog-ui / app / scripts / utils / dictionary / dictionary.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 /**
21
22  This code was copy from collections.ts lib
23  https://github.com/basarat/typescript-collections
24 **/
25
26 module Sdc.Utils{
27   'use strict';
28
29   // Used internally by dictionary
30   interface IDictionaryPair<K, V>{
31       key: K;
32       value: V;
33   }
34
35   export class Dictionary<K, V>{
36
37       /**
38        * Object holding the key-value pairs.
39        * @type {Object}
40        * @private
41        */
42       private table: { [key: string]: IDictionaryPair<K, V> };
43       //: [key: K] will not work since indices can only by strings in javascript and typescript enforces this.
44
45       /**
46        * Number of elements in the list.
47        * @type {number}
48        * @private
49        */
50       private nElements: number;
51
52       /**
53        * Function used to convert keys to strings.
54        * @type {function(Object):string}
55        * @private
56        */
57       private toStr: (key: K) => string;
58
59
60       /**
61        * Creates an empty dictionary.
62        * @class <p>Dictionaries map keys to values; each key can map to at most one value.
63        * This implementation accepts any kind of objects as keys.</p>
64        *
65        * <p>If the keys are custom objects a function which converts keys to unique
66        * strings must be provided. Example:</p>
67        * <pre>
68        * function petToString(pet) {
69        *  return pet.name;
70        * }
71        * </pre>
72        * @constructor
73        * @param {function(Object):string=} toStrFunction optional function used
74        * to convert keys to strings. If the keys aren"t strings or if toString()
75        * is not appropriate, a custom function which receives a key and returns a
76        * unique string must be provided.
77        */
78       constructor(toStrFunction?: (key: K) => string) {
79           this.table = {};
80           this.nElements = 0;
81           this.toStr = toStrFunction || this.defaultToString;
82       }
83
84
85       /**
86        copy from angular.js  isUndefined
87        */
88       private isUndefined = (value: any):boolean => {
89         return typeof value === 'undefined';
90       }
91
92       defaultToString = (item: any): string => {
93         return item.toString();
94       }
95
96       /**
97        * Returns the value to which this dictionary maps the specified key.
98        * Returns undefined if this dictionary contains no mapping for this key.
99        * @param {Object} key key whose associated value is to be returned.
100        * @return {*} the value to which this dictionary maps the specified key or
101        * undefined if the map contains no mapping for this key.
102        */
103       getValue = (key: K): V => {
104           let pair: IDictionaryPair<K, V> = this.table[this.toStr(key)];
105           if (this.isUndefined(pair)) {
106               return undefined;
107           }
108           return pair.value;
109       }
110
111
112       /**
113        * Associates the specified value with the specified key in this dictionary.
114        * If the dictionary previously contained a mapping for this key, the old
115        * value is replaced by the specified value.
116        * @param {Object} key key with which the specified value is to be
117        * associated.
118        * @param {Object} value value to be associated with the specified key.
119        * @return {*} previous value associated with the specified key, or undefined if
120        * there was no mapping for the key or if the key/value are undefined.
121        */
122       setValue = (key: K, value: V): V => {
123
124           if (this.isUndefined(key) || this.isUndefined(value)) {
125               return undefined;
126           }
127
128           let ret: V;
129           let k = this.toStr(key);
130           let previousElement: IDictionaryPair<K, V> = this.table[k];
131           if (this.isUndefined(previousElement)) {
132               this.nElements++;
133               ret = undefined;
134           } else {
135               ret = previousElement.value;
136           }
137           this.table[k] = {
138               key: key,
139               value: value
140           };
141           return ret;
142       }
143
144       /**
145        * Removes the mapping for this key from this dictionary if it is present.
146        * @param {Object} key key whose mapping is to be removed from the
147        * dictionary.
148        * @return {*} previous value associated with specified key, or undefined if
149        * there was no mapping for key.
150        */
151       remove = (key: K): V => {
152           let k = this.toStr(key);
153           let previousElement: IDictionaryPair<K, V> = this.table[k];
154           if (!this.isUndefined(previousElement)) {
155               delete this.table[k];
156               this.nElements--;
157               return previousElement.value;
158           }
159           return undefined;
160       }
161
162       /**
163        * Returns an array containing all of the keys in this dictionary.
164        * @return {Array} an array containing all of the keys in this dictionary.
165        */
166       keys = (): K[] => {
167           let array: K[] = [];
168           for (let name in this.table) {
169               if (this.table.hasOwnProperty(name)) {
170                   let pair: IDictionaryPair<K, V> = this.table[name];
171                   array.push(pair.key);
172               }
173           }
174           return array;
175       }
176
177       /**
178        * Returns an array containing all of the values in this dictionary.
179        * @return {Array} an array containing all of the values in this dictionary.
180        */
181       values = (): V[] => {
182           let array: V[] = [];
183           for (let name in this.table) {
184               if (this.table.hasOwnProperty(name)) {
185                   let pair: IDictionaryPair<K, V> = this.table[name];
186                   array.push(pair.value);
187               }
188           }
189           return array;
190       }
191
192       /**
193       * Executes the provided function once for each key-value pair
194       * present in this dictionary.
195       * @param {function(Object,Object):*} callback function to execute, it is
196       * invoked with two arguments: key and value. To break the iteration you can
197       * optionally return false.
198       */
199       forEach = (callback: (key: K, value: V) => any): void => {
200           for (let name in this.table) {
201               if (this.table.hasOwnProperty(name)) {
202                   let pair: IDictionaryPair<K, V> = this.table[name];
203                   let ret = callback(pair.key, pair.value);
204                   if (ret === false) {
205                       return;
206                   }
207               }
208           }
209       }
210
211       /**
212        * Returns true if this dictionary contains a mapping for the specified key.
213        * @param {Object} key key whose presence in this dictionary is to be
214        * tested.
215        * @return {boolean} true if this dictionary contains a mapping for the
216        * specified key.
217        */
218       containsKey = (key: K): boolean => {
219           return !this.isUndefined(this.getValue(key));
220       }
221
222       /**
223       * Removes all mappings from this dictionary.
224       * @this {Dictionary}
225       */
226       clear = () => {
227
228           this.table = {};
229           this.nElements = 0;
230       }
231
232       /**
233        * Returns the number of keys in this dictionary.
234        * @return {number} the number of key-value mappings in this dictionary.
235        */
236       size = (): number => {
237           return this.nElements;
238       }
239
240       /**
241        * Returns true if this dictionary contains no mappings.
242        * @return {boolean} true if this dictionary contains no mappings.
243        */
244       isEmpty = (): boolean => {
245           return this.nElements <= 0;
246       }
247
248       toString = (): string => {
249           let toret = "{";
250           this.forEach((k, v) => {
251               toret = toret + "\n\t" + k.toString() + " : " + v.toString();
252           });
253           return toret + "\n}";
254       }
255   } // End of dictionary
256
257 }