1f942a93528b9e14bdbeb201adc9e1469f78eae7
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / tosca / ToscaType.java
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 package org.openecomp.sdc.be.model.tosca;
21
22 import com.fasterxml.jackson.core.type.TypeReference;
23 import com.fasterxml.jackson.databind.ObjectMapper;
24 import java.io.IOException;
25 import java.text.ParseException;
26 import java.text.SimpleDateFormat;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 import java.util.stream.Collectors;
34 import lombok.AllArgsConstructor;
35 import lombok.Getter;
36 import org.openecomp.sdc.be.model.tosca.constraints.ConstraintUtil;
37 import org.openecomp.sdc.be.model.tosca.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException;
38 import org.openecomp.sdc.be.model.tosca.validators.TimestampValidator;
39
40 /**
41  * The primitive type that TOSCA YAML supports.
42  *
43  * @author mkv
44  */
45 @AllArgsConstructor
46 public enum ToscaType {
47     // @formatter:off
48         STRING("string"),
49         INTEGER("integer"),
50         FLOAT("float"),
51         BOOLEAN("boolean"),
52         TIMESTAMP("timestamp"),
53         VERSION("version"),
54         LIST("list"),
55         MAP("map"),
56     RANGE("range"),
57         SCALAR_UNIT("scalar-unit"),
58         SCALAR_UNIT_SIZE("scalar-unit.size"),
59         SCALAR_UNIT_TIME("scalar-unit.time"),
60         SCALAR_UNIT_BITRATE("scalar-unit.bitrate"),
61         SCALAR_UNIT_FREQUENCY("scalar-unit.frequency");
62     // @formatter:on
63     @Getter
64     private final String type;
65
66     // @formatter:off
67     private static final List<String> SCALAR_UNIT_BITRATE_VALID_UNITS = Arrays.asList("TiBps", "TBps", "GiBps", "GBps", "MiBps", "MBps", "KiBps", "KBps", "Bps", "Tibps", "Tbps", "Gibps", "Gbps", "Mibps", "Mbps", "Kibps", "Kbps", "bps");
68     private static final String SCALAR_UNIT_BITRATE_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_BITRATE_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$";
69     private static final List<String> SCALAR_UNIT_TIME_VALID_UNITS = Arrays.asList("d", "h", "m", "s", "ms", "us", "ns");
70     private static final String SCALAR_UNIT_TIME_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_TIME_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$";
71     private static final List<String> SCALAR_UNIT_SIZE_VALID_UNITS = Arrays.asList("TiB", "TB", "GiB", "GB", "MiB", "MB", "KiB", "kB", "B");
72     private static final String SCALAR_UNIT_SIZE_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_SIZE_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$";
73     private static final List<String> SCALAR_UNIT_FREQUENCY_VALID_UNITS = Arrays.asList("GHz", "MHz", "kHz", "Hz");
74     private static final String SCALAR_UNIT_FREQUENCY_PATTERN = "(^[0-9]+\\.?[0-9]*) ?(" + SCALAR_UNIT_FREQUENCY_VALID_UNITS.stream().collect(Collectors.joining("|")) + ")$";
75     // @formatter:on
76     private static final double B_IN_TiB = Math.pow(1024, 4);
77     private static final double B_IN_GiB = Math.pow(1024, 3);
78     private static final double B_IN_MiB = Math.pow(1024, 2);
79     private static final double B_IN_KiB = Math.pow(1024, 1);
80     private static final double B_IN_TB = Math.pow(1000, 4);
81     private static final double B_IN_GB = Math.pow(1000, 3);
82     private static final double B_IN_MB = Math.pow(1000, 2);
83     private static final double B_IN_KB = Math.pow(1000, 1);
84
85     public static ToscaType getToscaType(String typeName) {
86         if (typeName == null) {
87             return null;
88         }
89         for (ToscaType type : ToscaType.values()) {
90             if (type.getType().equals(typeName)) {
91                 return type;
92             }
93         }
94         return null;
95     }
96
97     public static boolean isPrimitiveType(String dataTypeName) {
98         if (!ToscaPropertyType.MAP.getType().equals(dataTypeName) && !ToscaPropertyType.LIST.getType().equals(dataTypeName)) {
99             return isValidType(dataTypeName) != null;
100         }
101         return false;
102     }
103
104     public static ToscaType isValidType(String typeName) {
105         if (typeName == null) {
106             return null;
107         }
108         for (ToscaType type : ToscaType.values()) {
109             if (type.getType().equals(typeName)) {
110                 return type;
111             }
112         }
113         return null;
114     }
115
116     public static boolean isCollectionType(String type) {
117         return ToscaPropertyType.MAP.getType().equals(type) || ToscaPropertyType.LIST.getType().equals(type);
118     }
119
120     public boolean isValueTypeValid(Object value) {
121         switch (this) {
122             case BOOLEAN:
123                 return value.equals(true) || value.equals(false);
124             case FLOAT:
125                 return value instanceof Float;
126             case INTEGER:
127             case RANGE:
128                 return value instanceof Integer;
129             case STRING:
130             case SCALAR_UNIT_SIZE:
131             case SCALAR_UNIT_TIME:
132             case SCALAR_UNIT_BITRATE:
133             case SCALAR_UNIT_FREQUENCY:
134             case TIMESTAMP:
135             case VERSION:
136                 return value instanceof String;
137             case LIST:
138             case MAP:
139                 return true;
140             case SCALAR_UNIT:
141             default:
142                 return false;
143         }
144     }
145
146     public boolean isValidValue(String value) {
147         switch (this) {
148             case BOOLEAN:
149                 return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false");
150             case FLOAT:
151                 return isFloat(value);
152             case INTEGER:
153                 return isInteger(value);
154             case SCALAR_UNIT_SIZE:
155                 return isScalarUnitSize(value);
156             case SCALAR_UNIT_TIME:
157                 return isScalarUnitTime(value);
158             case SCALAR_UNIT_BITRATE:
159                 return isScalarUnitBitrate(value);
160             case SCALAR_UNIT_FREQUENCY:
161                 return isScalarUnitFrequency(value);
162             case STRING:
163                 return true;
164             case TIMESTAMP:
165                 return TimestampValidator.getInstance().isValid(value, null);
166             case VERSION:
167                 return VersionUtil.isValid(value);
168             case LIST:
169                 return isList(value);
170             case MAP:
171                 return isMap(value);
172             case SCALAR_UNIT:
173             default:
174                 return false;
175         }
176     }
177
178     private boolean isList(String value) {
179         ObjectMapper objectMapper = new ObjectMapper();
180         try {
181             objectMapper.readValue(value, new TypeReference<List<Object>>() {
182             });
183         } catch (IOException e) {
184             return false;
185         }
186         return true;
187     }
188
189     private boolean isMap(String value) {
190         ObjectMapper objectMapper = new ObjectMapper();
191         try {
192             objectMapper.readValue(value, new TypeReference<Map<String, Object>>() {
193             });
194         } catch (IOException e) {
195             return false;
196         }
197         return true;
198     }
199
200     private boolean isFloat(String value) {
201         try {
202             Float.valueOf(value);
203         } catch (NumberFormatException e) {
204             return false;
205         }
206         return true;
207     }
208
209     private boolean isInteger(String value) {
210         try {
211             Long.valueOf(value);
212         } catch (NumberFormatException e) {
213             return false;
214         }
215         return true;
216     }
217
218     public boolean isScalarUnit() {
219         switch (this) {
220             case SCALAR_UNIT_TIME:
221             case SCALAR_UNIT_SIZE:
222             case SCALAR_UNIT_BITRATE:
223             case SCALAR_UNIT_FREQUENCY:
224                 return true;
225             default:
226                 return false;
227         }
228     }
229
230     public Object convert(String value) {
231         switch (this) {
232             case STRING:
233                 return value;
234             case SCALAR_UNIT_TIME:
235                 return convertScalarUnitTime(value);
236             case SCALAR_UNIT_BITRATE:
237                 return convertScalarUnitBitrate(value);
238             case SCALAR_UNIT_SIZE:
239                 return convertScalarUnitSize(value);
240             case SCALAR_UNIT_FREQUENCY:
241                 return convertScalarUnitFrequency(value);
242             case BOOLEAN:
243                 return Boolean.valueOf(value);
244             case FLOAT:
245                 return Float.valueOf(value);
246             case RANGE:
247             case INTEGER:
248                 return Long.valueOf(value);
249             case TIMESTAMP:
250                 try {
251                     return new SimpleDateFormat("MMM dd, yyyy hh:mm:ss a", Locale.US).parse(value);
252                 } catch (ParseException e) {
253                     throw new IllegalArgumentException("Value must be a valid timestamp", e);
254                 }
255             case VERSION:
256                 return VersionUtil.parseVersion(value);
257             case LIST:
258                 try {
259                     return ConstraintUtil.parseToCollection(value, new TypeReference<List<Object>>() {
260                     });
261                 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
262                     throw new IllegalArgumentException("Value must be a valid List", e);
263                 }
264             case MAP:
265                 try {
266                     return ConstraintUtil.parseToCollection(value, new TypeReference<Map<String, Object>>() {
267                     });
268                 } catch (ConstraintValueDoNotMatchPropertyTypeException e) {
269                     throw new IllegalArgumentException("Value must be a valid Map", e);
270                 }
271             case SCALAR_UNIT:
272             default:
273                 return null;
274         }
275     }
276
277     private Long convertScalarUnitSize(final String value) {
278         if (isScalarUnitSize(value)) {
279             final Matcher matcher = Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim());
280             if (matcher.find()) {
281                 switch (matcher.group(2)) {
282                     case "TiB":
283                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TiB);
284                     case "TB":
285                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TB);
286                     case "GiB":
287                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GiB);
288                     case "GB":
289                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GB);
290                     case "MiB":
291                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MiB);
292                     case "MB":
293                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MB);
294                     case "KiB":
295                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KiB);
296                     case "kB":
297                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KB);
298                     case "B":
299                         return (long) (Double.parseDouble(matcher.group(1)));
300                     default:
301                         throw new IllegalArgumentException("Value must be a valid scalar-unit.size");
302                 }
303             } else {
304                 throw new IllegalArgumentException("Value must be a valid 'scalar-unit.size': " + SCALAR_UNIT_SIZE_VALID_UNITS);
305             }
306         } else {
307             throw new IllegalArgumentException("Value must be a valid 'scalar-unit.size': " + SCALAR_UNIT_SIZE_VALID_UNITS);
308         }
309     }
310
311     private Long convertScalarUnitTime(final String value) {
312         if (isScalarUnitTime(value)) {
313             final Matcher matcher = Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim());
314             if (matcher.find()) {
315                 switch (matcher.group(2)) {
316                     case "d":
317                         return (long) (Double.parseDouble(matcher.group(1)) * 24 * 60 * 60 * 1_000_000_000L);   //  24hours * 60minutes * 60seconds
318                     case "h":
319                         return (long) (Double.parseDouble(matcher.group(1)) * 60 * 60 * 1_000_000_000L);        //  60minutes * 60seconds
320                     case "m":
321                         return (long) (Double.parseDouble(matcher.group(1)) * 60 * 1_000_000_000L);             //  60seconds
322                     case "s":
323                         return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000_000L);
324                     case "ms":
325                         return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000L);
326                     case "us":
327                         return (long) (Double.parseDouble(matcher.group(1)) * 1_000L);
328                     case "ns":
329                         return (long) (Double.parseDouble(matcher.group(1)));
330                     default:
331                         throw new IllegalArgumentException("Value must be a valid scalar-unit.time");
332                 }
333             } else {
334                 throw new IllegalArgumentException("Value must be a valid 'scalar-unit.time':" + SCALAR_UNIT_TIME_VALID_UNITS);
335             }
336         } else {
337             throw new IllegalArgumentException("Value must be a valid 'scalar-unit.time':" + SCALAR_UNIT_TIME_VALID_UNITS);
338         }
339     }
340
341     private Long convertScalarUnitFrequency(final String value) {
342         if (isScalarUnitFrequency(value)) {
343             final Matcher matcher = Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim());
344             if (matcher.find()) {
345                 switch (matcher.group(2)) {
346                     case "GHz":
347                         return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000_000L);
348                     case "MHz":
349                         return (long) (Double.parseDouble(matcher.group(1)) * 1_000_000L);
350                     case "kHz":
351                         return (long) (Double.parseDouble(matcher.group(1)) * 1_000L);
352                     case "Hz":
353                         return (long) (Double.parseDouble(matcher.group(1)));
354                     default:
355                         throw new IllegalArgumentException("Value must be a valid scalar-unit.frequency");
356                 }
357             } else {
358                 throw new IllegalArgumentException("Value must be a valid 'scalar-unit.frequency':" + SCALAR_UNIT_FREQUENCY_VALID_UNITS);
359             }
360         } else {
361             throw new IllegalArgumentException("Value must be a valid 'scalar-unit.frequency':" + SCALAR_UNIT_FREQUENCY_VALID_UNITS);
362         }
363     }
364
365     private Long convertScalarUnitBitrate(final String value) {
366         if (isScalarUnitBitrate(value)) {
367             final Matcher matcher = Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim());
368             if (matcher.find()) {
369                 switch (matcher.group(2)) {
370                     case "TiBps":
371                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_TiB);
372                     case "TBps":
373                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_TB);
374                     case "GiBps":
375                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_GiB);
376                     case "GBps":
377                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_GB);
378                     case "MiBps":
379                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_MiB);
380                     case "MBps":
381                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_MB);
382                     case "KiBps":
383                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_KiB);
384                     case "KBps":
385                         return (long) (Double.parseDouble(matcher.group(1)) * 8 * B_IN_KB);
386                     case "Bps":
387                         return (long) (Double.parseDouble(matcher.group(1)) * 8);
388                     case "Tibps":
389                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TiB);
390                     case "Tbps":
391                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_TB);
392                     case "Gibps":
393                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GiB);
394                     case "Gbps":
395                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_GB);
396                     case "Mibps":
397                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MiB);
398                     case "Mbps":
399                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_MB);
400                     case "Kibps":
401                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KiB);
402                     case "Kbps":
403                         return (long) (Double.parseDouble(matcher.group(1)) * B_IN_KB);
404                     case "bps":
405                         return (long) (Double.parseDouble(matcher.group(1)));
406                     default:
407                         throw new IllegalArgumentException("Value must be a valid scalar-unit.bitrate");
408                 }
409             } else {
410                 throw new IllegalArgumentException("Value must be a valid 'scalar-unit.bitrate':" + SCALAR_UNIT_BITRATE_VALID_UNITS);
411             }
412         } else {
413             throw new IllegalArgumentException("Value must be a valid 'scalar-unit.bitrate':" + SCALAR_UNIT_BITRATE_VALID_UNITS);
414         }
415     }
416
417     private boolean isScalarUnitBitrate(final String value) {
418         final Matcher matcher = Pattern.compile(SCALAR_UNIT_BITRATE_PATTERN).matcher(value.trim());
419         return matcher.find() && SCALAR_UNIT_BITRATE_VALID_UNITS.contains(matcher.group(2));
420     }
421
422     private boolean isScalarUnitSize(final String value) {
423         final Matcher matcher = Pattern.compile(SCALAR_UNIT_SIZE_PATTERN).matcher(value.trim());
424         return matcher.find() && SCALAR_UNIT_SIZE_VALID_UNITS.contains(matcher.group(2));
425     }
426
427     private boolean isScalarUnitTime(final String value) {
428         final Matcher matcher = Pattern.compile(SCALAR_UNIT_TIME_PATTERN).matcher(value.trim());
429         return matcher.find() && SCALAR_UNIT_TIME_VALID_UNITS.contains(matcher.group(2));
430     }
431
432     private boolean isScalarUnitFrequency(final String value) {
433         final Matcher matcher = Pattern.compile(SCALAR_UNIT_FREQUENCY_PATTERN).matcher(value.trim());
434         return matcher.find() && SCALAR_UNIT_FREQUENCY_VALID_UNITS.contains(matcher.group(2));
435     }
436
437     public String getValidValues() {
438         switch (this) {
439             case SCALAR_UNIT_TIME:
440                 return String.valueOf(SCALAR_UNIT_TIME_VALID_UNITS);
441             case SCALAR_UNIT_SIZE:
442                 return String.valueOf(SCALAR_UNIT_SIZE_VALID_UNITS);
443             case SCALAR_UNIT_BITRATE:
444                 return String.valueOf(SCALAR_UNIT_BITRATE_VALID_UNITS);
445             case SCALAR_UNIT_FREQUENCY:
446                 return String.valueOf(SCALAR_UNIT_FREQUENCY_VALID_UNITS);
447             default:
448                 return "";
449         }
450     }
451 }