1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
13 from toscaparser.common.exception import ExceptionCollector
14 from toscaparser.common.exception import MissingRequiredFieldError
15 from toscaparser.common.exception import TypeMismatchError
16 from toscaparser.common.exception import UnknownFieldError
17 from toscaparser.elements.constraints import Schema
18 from toscaparser.elements.datatype import DataType
19 from toscaparser.elements.scalarunit import ScalarUnit_Frequency
20 from toscaparser.elements.scalarunit import ScalarUnit_Size
21 from toscaparser.elements.scalarunit import ScalarUnit_Time
23 from toscaparser.utils.gettextutils import _
24 from toscaparser.utils import validateutils
27 class DataEntity(object):
28 '''A complex data value entity.'''
30 def __init__(self, datatypename, value_dict, custom_def=None):
31 self.custom_def = custom_def
32 self.datatype = DataType(datatypename, custom_def)
33 self.schema = self.datatype.get_all_properties()
34 self.value = value_dict
37 '''Validate the value by the definition of the datatype.'''
39 # A datatype can not have both 'type' and 'properties' definitions.
40 # If the datatype has 'type' definition
41 if self.datatype.value_type:
42 self.value = DataEntity.validate_datatype(self.datatype.value_type,
46 schema = Schema(None, self.datatype.defs)
47 for constraint in schema.constraints:
48 constraint.validate(self.value)
49 # If the datatype has 'properties' definition
51 if not isinstance(self.value, dict):
52 ExceptionCollector.appendException(
53 TypeMismatchError(what=self.value,
54 type=self.datatype.type))
59 allowed_props = self.schema.keys()
60 for name, prop_def in self.schema.items():
62 required_props.append(name)
64 default_props[name] = prop_def.default
67 for value_key in list(self.value.keys()):
68 if value_key not in allowed_props:
69 ExceptionCollector.appendException(
70 UnknownFieldError(what=(_('Data value of type "%s"')
71 % self.datatype.type),
75 for def_key, def_value in list(default_props.items()):
76 if def_key not in list(self.value.keys()):
77 self.value[def_key] = def_value
81 for req_key in required_props:
82 if req_key not in list(self.value.keys()):
83 missingprop.append(req_key)
85 ExceptionCollector.appendException(
86 MissingRequiredFieldError(
87 what=(_('Data value of type "%s"')
88 % self.datatype.type), required=missingprop))
91 for name, value in list(self.value.items()):
92 prop_schema = Schema(name, self._find_schema(name))
93 # check if field value meets type defined
94 DataEntity.validate_datatype(prop_schema.type, value,
95 prop_schema.entry_schema,
97 # check if field value meets constraints defined
98 if prop_schema.constraints:
99 for constraint in prop_schema.constraints:
100 if isinstance(value, list):
102 constraint.validate(val)
104 constraint.validate(value)
108 def _find_schema(self, name):
109 if self.schema and name in self.schema.keys():
110 return self.schema[name].schema
113 def validate_datatype(type, value, entry_schema=None, custom_def=None):
114 '''Validate value with given type.
116 If type is list or map, validate its entry by entry_schema(if defined)
117 If type is a user-defined complex datatype, custom_def is required.
119 if type == Schema.STRING:
120 return validateutils.validate_string(value)
121 elif type == Schema.INTEGER:
122 return validateutils.validate_integer(value)
123 elif type == Schema.FLOAT:
124 return validateutils.validate_float(value)
125 elif type == Schema.NUMBER:
126 return validateutils.validate_number(value)
127 elif type == Schema.BOOLEAN:
128 return validateutils.validate_boolean(value)
129 elif type == Schema.RANGE:
130 return validateutils.validate_range(value)
131 elif type == Schema.TIMESTAMP:
132 validateutils.validate_timestamp(value)
134 elif type == Schema.LIST:
135 validateutils.validate_list(value)
137 DataEntity.validate_entry(value, entry_schema, custom_def)
139 elif type == Schema.SCALAR_UNIT_SIZE:
140 return ScalarUnit_Size(value).validate_scalar_unit()
141 elif type == Schema.SCALAR_UNIT_FREQUENCY:
142 return ScalarUnit_Frequency(value).validate_scalar_unit()
143 elif type == Schema.SCALAR_UNIT_TIME:
144 return ScalarUnit_Time(value).validate_scalar_unit()
145 elif type == Schema.VERSION:
146 return validateutils.TOSCAVersionProperty(value).get_version()
147 elif type == Schema.MAP:
148 validateutils.validate_map(value)
150 DataEntity.validate_entry(value, entry_schema, custom_def)
153 data = DataEntity(type, value, custom_def)
154 return data.validate()
157 def validate_entry(value, entry_schema, custom_def=None):
158 '''Validate entries for map and list.'''
159 schema = Schema(None, entry_schema)
161 if isinstance(value, dict):
162 valuelist = list(value.values())
164 DataEntity.validate_datatype(schema.type, v, schema.entry_schema,
166 if schema.constraints:
167 for constraint in schema.constraints:
168 constraint.validate(v)