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.portspectype import PortSpec
20 from toscaparser.elements.scalarunit import ScalarUnit_Frequency
21 from toscaparser.elements.scalarunit import ScalarUnit_Size
22 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,
32 self.custom_def = custom_def
33 self.datatype = DataType(datatypename, custom_def)
34 self.schema = self.datatype.get_all_properties()
35 self.value = value_dict
36 self.property_name = prop_name
39 '''Validate the value by the definition of the datatype.'''
41 # A datatype can not have both 'type' and 'properties' definitions.
42 # If the datatype has 'type' definition
43 if self.datatype.value_type:
44 self.value = DataEntity.validate_datatype(self.datatype.value_type,
48 schema = Schema(self.property_name, self.datatype.defs)
49 for constraint in schema.constraints:
50 constraint.validate(self.value)
51 # If the datatype has 'properties' definition
53 if not isinstance(self.value, dict):
54 ExceptionCollector.appendException(
55 TypeMismatchError(what=self.value,
56 type=self.datatype.type))
61 allowed_props = self.schema.keys()
62 for name, prop_def in self.schema.items():
64 required_props.append(name)
66 default_props[name] = prop_def.default
69 for value_key in list(self.value.keys()):
70 if value_key not in allowed_props:
71 ExceptionCollector.appendException(
72 UnknownFieldError(what=(_('Data value of type "%s"')
73 % self.datatype.type),
77 for def_key, def_value in list(default_props.items()):
78 if def_key not in list(self.value.keys()):
79 self.value[def_key] = def_value
83 for req_key in required_props:
84 if req_key not in list(self.value.keys()):
85 missingprop.append(req_key)
87 ExceptionCollector.appendException(
88 MissingRequiredFieldError(
89 what=(_('Data value of type "%s"')
90 % self.datatype.type), required=missingprop))
93 for name, value in list(self.value.items()):
94 schema_name = self._find_schema(name)
97 prop_schema = Schema(name, schema_name)
98 # check if field value meets type defined
99 DataEntity.validate_datatype(prop_schema.type, value,
100 prop_schema.entry_schema,
102 # check if field value meets constraints defined
103 if prop_schema.constraints:
104 for constraint in prop_schema.constraints:
105 if isinstance(value, list):
107 constraint.validate(val)
109 constraint.validate(value)
113 def _find_schema(self, name):
114 if self.schema and name in self.schema.keys():
115 return self.schema[name].schema
118 def validate_datatype(type, value, entry_schema=None, custom_def=None,
120 '''Validate value with given type.
122 If type is list or map, validate its entry by entry_schema(if defined)
123 If type is a user-defined complex datatype, custom_def is required.
125 from toscaparser.functions import is_function
126 if is_function(value):
128 if type == Schema.STRING:
129 return validateutils.validate_string(value)
130 elif type == Schema.INTEGER:
131 return validateutils.validate_integer(value)
132 elif type == Schema.FLOAT:
133 return validateutils.validate_float(value)
134 elif type == Schema.NUMBER:
135 return validateutils.validate_numeric(value)
136 elif type == Schema.BOOLEAN:
137 return validateutils.validate_boolean(value)
138 elif type == Schema.RANGE:
139 return validateutils.validate_range(value)
140 elif type == Schema.TIMESTAMP:
141 validateutils.validate_timestamp(value)
143 elif type == Schema.LIST:
144 validateutils.validate_list(value)
146 DataEntity.validate_entry(value, entry_schema, custom_def)
148 elif type == Schema.SCALAR_UNIT_SIZE:
149 return ScalarUnit_Size(value).validate_scalar_unit()
150 elif type == Schema.SCALAR_UNIT_FREQUENCY:
151 return ScalarUnit_Frequency(value).validate_scalar_unit()
152 elif type == Schema.SCALAR_UNIT_TIME:
153 return ScalarUnit_Time(value).validate_scalar_unit()
154 elif type == Schema.VERSION:
155 return validateutils.TOSCAVersionProperty(value).get_version()
156 elif type == Schema.MAP:
157 validateutils.validate_map(value)
159 DataEntity.validate_entry(value, entry_schema, custom_def)
161 elif type == Schema.PORTSPEC:
162 # TODO(TBD) bug 1567063, validate source & target as PortDef type
163 # as complex types not just as integers
164 PortSpec.validate_additional_req(value, prop_name, custom_def)
166 data = DataEntity(type, value, custom_def)
167 return data.validate()
170 def validate_entry(value, entry_schema, custom_def=None):
171 '''Validate entries for map and list.'''
172 schema = Schema(None, entry_schema)
174 if isinstance(value, dict):
175 valuelist = list(value.values())
177 DataEntity.validate_datatype(schema.type, v, schema.entry_schema,
179 if schema.constraints:
180 for constraint in schema.constraints:
181 constraint.validate(v)