blob: 0726afc18ced553a591c30c755afee59302b212b [file] [log] [blame]
Sean Condon83fc39f2018-04-19 18:56:13 +01001/*
2 * Copyright 2014-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import { Injectable } from '@angular/core';
17import { ActivatedRoute, Router} from '@angular/router';
18import { LogService } from '../../log.service';
19
20// Angular>=2 workaround for missing definition
21declare const InstallTrigger: any;
22
23
24// TODO Move all this trie stuff to its own class
25// Angular>=2 Tightened up on types to avoid compiler errors
26interface TrieC {
Sean Condon49e15be2018-05-16 16:58:29 +010027 p: any;
28 s: string[];
Sean Condon83fc39f2018-04-19 18:56:13 +010029}
30// trie operation
31function _trieOp(op: string, trie, word: string, data) {
Sean Condon49e15be2018-05-16 16:58:29 +010032 const p = trie;
33 const w: string = word.toUpperCase();
34 const s: Array<string> = w.split('');
35 let c: TrieC = { p: p, s: s };
36 let t = [];
37 let x = 0;
38 const f1 = op === '+' ? add : probe;
39 const f2 = op === '+' ? insert : remove;
Sean Condon83fc39f2018-04-19 18:56:13 +010040
Sean Condon49e15be2018-05-16 16:58:29 +010041 function add(cAdded): TrieC {
42 const q = cAdded.s.shift();
43 let np = cAdded.p[q];
Sean Condon83fc39f2018-04-19 18:56:13 +010044
45 if (!np) {
Sean Condon49e15be2018-05-16 16:58:29 +010046 cAdded.p[q] = {};
47 np = cAdded.p[q];
Sean Condon83fc39f2018-04-19 18:56:13 +010048 x = 1;
49 }
Sean Condon49e15be2018-05-16 16:58:29 +010050 return { p: np, s: cAdded.s };
Sean Condon83fc39f2018-04-19 18:56:13 +010051 }
52
Sean Condon49e15be2018-05-16 16:58:29 +010053 function probe(cProbed): TrieC {
54 const q = cProbed.s.shift();
55 const k: number = Object.keys(cProbed.p).length;
56 const np = cProbed.p[q];
Sean Condon83fc39f2018-04-19 18:56:13 +010057
Sean Condon49e15be2018-05-16 16:58:29 +010058 t.push({ q: q, k: k, p: cProbed.p });
Sean Condon83fc39f2018-04-19 18:56:13 +010059 if (!np) {
60 t = [];
61 return { p: [], s: [] };
62 }
Sean Condon49e15be2018-05-16 16:58:29 +010063 return { p: np, s: cProbed.s };
Sean Condon83fc39f2018-04-19 18:56:13 +010064 }
65
66 function insert() {
67 c.p._data = data;
68 return x ? 'added' : 'updated';
69 }
70
71 function remove() {
72 if (t.length) {
73 t = t.reverse();
74 while (t.length) {
Sean Condon49e15be2018-05-16 16:58:29 +010075 const d = t.shift();
Sean Condon83fc39f2018-04-19 18:56:13 +010076 delete d.p[d.q];
77 if (d.k > 1) {
78 t = [];
79 }
80 }
81 return 'removed';
82 }
83 return 'absent';
84 }
85
86 while (c.s.length) {
87 c = f1(c);
88 }
89 return f2();
90}
91
92// add word to trie (word will be converted to uppercase)
93// data associated with the word
94// returns 'added' or 'updated'
95function addToTrie(trie, word, data) {
96 return _trieOp('+', trie, word, data);
97}
98
99// remove word from trie (word will be converted to uppercase)
100// returns 'removed' or 'absent'
101// Angular>=2 added in quotes for data. error TS2554: Expected 4 arguments, but got 3.
102function removeFromTrie(trie, word) {
103 return _trieOp('-', trie, word, '');
104}
105
106// lookup word (converted to uppercase) in trie
107// returns:
108// undefined if the word is not in the trie
109// -1 for a partial match (word is a prefix to an existing word)
110// data for the word for an exact match
111function trieLookup(trie, word) {
Sean Condon49e15be2018-05-16 16:58:29 +0100112 const s = word.toUpperCase().split('');
113 let p = trie;
114 let n;
Sean Condon83fc39f2018-04-19 18:56:13 +0100115
116 while (s.length) {
117 n = s.shift();
118 p = p[n];
119 if (!p) {
120 return undefined;
121 }
122 }
123 if (p._data) {
124 return p._data;
125 }
126 return -1;
127}
128
129
130/**
131 * ONOS GUI -- Util -- General Purpose Functions
132 */
133@Injectable()
134export class FnService {
135 // internal state
136 debugFlags = new Map<string, boolean>([
137// [ "LoadingService", true ]
138 ]);
139
140 constructor(
141 private route: ActivatedRoute,
142 private log: LogService
143 ) {
144 this.route.queryParams.subscribe(params => {
Sean Condon49e15be2018-05-16 16:58:29 +0100145 const debugparam: string = params['debug'];
146 log.debug('Param:', debugparam);
Sean Condon83fc39f2018-04-19 18:56:13 +0100147 this.parseDebugFlags(debugparam);
148 });
Sean Condon49e15be2018-05-16 16:58:29 +0100149 log.debug('FnService constructed');
Sean Condon83fc39f2018-04-19 18:56:13 +0100150 }
151
152 isF(f) {
153 return typeof f === 'function' ? f : null;
154 }
155
156 isA(a) {
157 // NOTE: Array.isArray() is part of EMCAScript 5.1
158 return Array.isArray(a) ? a : null;
159 }
160
161 isS(s) {
162 return typeof s === 'string' ? s : null;
163 }
164
165 isO(o) {
166 return (o && typeof o === 'object' && o.constructor === Object) ? o : null;
167 }
168
169// contains: contains,
170// areFunctions: areFunctions,
171// areFunctionsNonStrict: areFunctionsNonStrict,
172// windowSize: windowSize,
173
174 /**
175 * Returns true if current browser determined to be a mobile device
176 */
177 isMobile() {
Sean Condon49e15be2018-05-16 16:58:29 +0100178 const ua = window.navigator.userAgent;
179 const patt = /iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/;
Sean Condon83fc39f2018-04-19 18:56:13 +0100180 return patt.test(ua);
181 }
182
183 /**
184 * Returns true if the current browser determined to be Chrome
185 */
186 isChrome() {
Sean Condon49e15be2018-05-16 16:58:29 +0100187 const isChromium = (window as any).chrome;
188 const vendorName = window.navigator.vendor;
Sean Condon83fc39f2018-04-19 18:56:13 +0100189
Sean Condon49e15be2018-05-16 16:58:29 +0100190 const isOpera = window.navigator.userAgent.indexOf('OPR') > -1;
Sean Condon83fc39f2018-04-19 18:56:13 +0100191 return (isChromium !== null &&
192 isChromium !== undefined &&
193 vendorName === 'Google Inc.' &&
Sean Condon49e15be2018-05-16 16:58:29 +0100194 isOpera === false);
195 }
196
197 isChromeHeadless() {
198 const vendorName = window.navigator.vendor;
199 const headlessChrome = window.navigator.userAgent.indexOf('HeadlessChrome') > -1;
200
201 return (vendorName === 'Google Inc.' && headlessChrome === true);
Sean Condon83fc39f2018-04-19 18:56:13 +0100202 }
203
204 /**
205 * Returns true if the current browser determined to be Safari
206 */
207 isSafari() {
208 return (window.navigator.userAgent.indexOf('Safari') !== -1 &&
209 window.navigator.userAgent.indexOf('Chrome') === -1);
210 }
211
212 /**
213 * Returns true if the current browser determined to be Firefox
214 */
215 isFirefox() {
216 return typeof InstallTrigger !== 'undefined';
217 }
218
219 /**
220 * Return the given string with the first character capitalized.
221 */
222 cap(s) {
223 return s ? s[0].toUpperCase() + s.slice(1).toLowerCase() : s;
224 }
225
226 /**
227 * output debug message to console, if debug tag set...
228 * e.g. fs.debug('mytag', arg1, arg2, ...)
229 */
230 debug(tag, ...args) {
231 if (this.debugFlags.get(tag)) {
232 this.log.debug(tag, args.join());
233 }
234 }
235
236 parseDebugFlags(dbgstr: string): void {
Sean Condon49e15be2018-05-16 16:58:29 +0100237 const bits = dbgstr ? dbgstr.split(',') : [];
238 bits.forEach((key) => {
Sean Condon83fc39f2018-04-19 18:56:13 +0100239 this.debugFlags.set(key, true);
240 });
241 this.log.debug('Debug flags:', dbgstr);
242 }
243
244 /**
245 * Return true if the given debug flag was specified in the query params
246 */
247 debugOn(tag: string): boolean {
248 return this.debugFlags.get(tag);
249 }
250
251}