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