Create wt-odlux directory
[ccsdk/features.git] / sdnr / wt-odlux / odlux / apps / configurationApp / src / utilities / verifyer.ts
1 /**
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt odlux
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18
19 import { YangRange, Operator, ViewElementNumber, ViewElementString, isViewElementNumber, isViewElementString } from '../models/uiModels';
20
21 export type validated = { isValid: boolean; error?: string };
22
23 export type validatedRange = { isValid: boolean; error?: string };
24
25 const rangeErrorStartNumber = 'The entered number must be';
26 const rangeErrorInnerMinTextNumber = 'greater or equals than';
27 const rangeErrorInnerMaxTextNumber = 'less or equals than';
28 const rangeErrorEndTextNumber = '.';
29
30 const rangeErrorStartString = 'The entered text must have';
31 const rangeErrorInnerMinTextString = 'no more than';
32 const rangeErrorInnerMaxTextString = 'less than';
33 const rangeErrorEndTextString = ' characters.';
34
35 let errorMessageStart = '';
36 let errorMessageMiddleMinPart = '';
37 let errorMessageMiddleMaxPart = '';
38 let errorMessageEnd = '';
39
40 const isYangRange = (val: YangRange | Operator<YangRange>): val is YangRange => (val as YangRange).min !== undefined;
41   
42 const isYangOperator = (val: YangRange | Operator<YangRange>): val is Operator<YangRange> => (val as Operator<YangRange>).operation !== undefined;
43
44 const isRegExp = (val: RegExp | Operator<RegExp>): val is RegExp => (val as RegExp).source !== undefined;
45
46 const isRegExpOperator = (val: RegExp | Operator<RegExp>): val is Operator<RegExp> => (val as Operator<RegExp>).operation !== undefined;
47
48 const getRangeErrorMessagesRecursively = (value: Operator<YangRange>, data: number): string[] => {
49   let currentIteration: string[] = [];
50   
51   // iterate over all elements
52   for (let i = 0; i < value.arguments.length; i++) {
53     const element = value.arguments[i];
54   
55     let min = undefined;
56     let max = undefined;
57   
58     let isNumberCorrect = false;
59   
60     if (isYangRange(element)) {
61   
62       //check found min values
63       if (!isNaN(element.min)) {
64         if (data < element.min) {
65           min = element.min;
66         } else {
67           isNumberCorrect = true;
68         }
69       }
70   
71       // check found max values
72       if (!isNaN(element.max)) {
73         if (data > element.max) {
74           max = element.max;
75         } else {
76           isNumberCorrect = true;
77         }
78       }
79   
80       // construct error messages
81       if (min != undefined) {
82         currentIteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMinPart} ${min}`);
83       } else if (max != undefined) {
84         currentIteration.push(`${value.operation.toLocaleLowerCase()} ${errorMessageMiddleMaxPart} ${max}`);
85   
86       }
87   
88     } else if (isYangOperator(element)) {
89   
90       //get error_message from expression
91       const result = getRangeErrorMessagesRecursively(element, data);
92       if (result.length === 0) {
93         isNumberCorrect = true;
94       }
95       currentIteration = currentIteration.concat(result);
96     }
97   
98     // if its an OR operation, the number has been checked and min/max are empty (thus not violated)
99     // delete everything found (because at least one found is correct, therefore all are correct) and break from loop
100     if (min === undefined && max === undefined && isNumberCorrect && value.operation === 'OR') {
101   
102       currentIteration.splice(0, currentIteration.length);
103       break;
104     }
105   }
106   
107   return currentIteration;
108 };
109
110 const createStartMessage = (element: string) => {
111   //remove leading or or and from text
112   if (element.startsWith('and')) {
113     element = element.replace('and', '');
114   } else if (element.startsWith('or')) {
115     element = element.replace('or', '');
116   }
117   return `${errorMessageStart} ${element}`;
118 };
119   
120 const getRangeErrorMessages = (value: Operator<YangRange>, data: number): string => {
121
122   const currentIteration = getRangeErrorMessagesRecursively(value, data);
123   
124   // build complete error message from found parts
125   let errorMessage = '';
126   if (currentIteration.length > 1) {
127   
128     currentIteration.forEach((element, index) => {
129       if (index === 0) {
130         errorMessage = createStartMessage(element);
131       } else if (index === currentIteration.length - 1) {
132         errorMessage += ` ${element}${errorMessageEnd}`;
133       } else {
134         errorMessage += `, ${element}`;
135       }
136     });
137   } else if (currentIteration.length == 1) {
138     errorMessage = `${createStartMessage(currentIteration[0])}${errorMessageEnd}`;
139   }
140   
141   return errorMessage;
142 };
143
144 export const checkRange = (element: ViewElementNumber | ViewElementString, data: number): string => {
145   const number = data;
146
147   let expression = undefined;
148
149   if (isViewElementString(element)) {
150     expression = element.length;
151
152     errorMessageStart = rangeErrorStartString;
153     errorMessageMiddleMaxPart = rangeErrorInnerMaxTextString;
154     errorMessageMiddleMinPart = rangeErrorInnerMinTextString;
155     errorMessageEnd = rangeErrorEndTextString;
156
157   } else if (isViewElementNumber(element)) {
158     expression = element.range;
159
160     errorMessageStart = rangeErrorStartNumber;
161     errorMessageMiddleMaxPart = rangeErrorInnerMaxTextNumber;
162     errorMessageMiddleMinPart = rangeErrorInnerMinTextNumber;
163     errorMessageEnd = rangeErrorEndTextNumber;
164   }
165
166   if (expression) {
167     if (isYangOperator(expression)) {
168
169       const errorMessage = getRangeErrorMessages(expression, data);
170       return errorMessage;
171
172     } else
173     if (isYangRange(expression)) {
174
175       if (!isNaN(expression.min)) {
176         if (number < expression.min) {
177           return `${errorMessageStart} ${errorMessageMiddleMinPart} ${expression.min}${errorMessageEnd}`;
178         }
179       }
180
181       if (!isNaN(expression.max)) {
182         if (number > expression.max) {
183           return `${errorMessageStart} ${errorMessageMiddleMaxPart} ${expression.max}${errorMessageEnd}`;
184         }
185       }
186     }
187   }
188
189   return '';
190 };
191
192 const getRegexRecursively = (value: Operator<RegExp>, data: string): boolean[] => {
193   let currentItteration: boolean[] = [];
194   for (let i = 0; i < value.arguments.length; i++) {
195     const element = value.arguments[i];
196     if (isRegExp(element)) {
197       // if regex is found, add it to list
198       currentItteration.push(element.test(data));
199     } else if (isRegExpOperator(element)) {
200       //if RegexExpression is found, try to get regex from it
201       currentItteration = currentItteration.concat(getRegexRecursively(element, data));
202     }
203   }
204   
205   if (value.operation === 'OR') {
206     // if one is true, all are true, all found items can be discarded
207     let result = currentItteration.find(element => element);
208     if (result) {
209       return [];
210     }
211   }
212   return currentItteration;
213 };
214   
215 const isPatternValid = (value: Operator<RegExp>, data: string): boolean => {
216   // get all regex
217   const result = getRegexRecursively(value, data);
218   
219   if (value.operation === 'AND') {
220     // if AND operation is executed...
221     // no element can be false
222     const check = result.find(element => element !== true);
223     if (check)
224       return false;
225     else
226       return true;
227   } else {
228     // if OR operation is executed...
229     // ... just one element must be true
230     const check = result.find(element => element === true);
231     if (check)
232       return true;
233     else
234       return false;
235   
236   }
237 };
238
239 export const checkPattern = (expression: RegExp | Operator<RegExp> | undefined, data: string): validated => {
240
241   if (expression) {
242     if (isRegExp(expression)) {
243       const isValid = expression.test(data);
244       if (!isValid)
245         return { isValid: isValid, error: 'The input is in a wrong format.' };
246
247     } else if (isRegExpOperator(expression)) {
248       const result = isPatternValid(expression, data);
249
250       if (!result) {
251         return { isValid: false, error: 'The input is in a wrong format.' };
252       }
253     }
254   }
255
256   return { isValid: true };
257 };
258
259
260
261