summaryrefslogtreecommitdiffstats
path: root/app/toscalib/templates/value.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/toscalib/templates/value.py')
-rw-r--r--app/toscalib/templates/value.py266
1 files changed, 266 insertions, 0 deletions
diff --git a/app/toscalib/templates/value.py b/app/toscalib/templates/value.py
new file mode 100644
index 0000000..fee0ceb
--- /dev/null
+++ b/app/toscalib/templates/value.py
@@ -0,0 +1,266 @@
+from toscalib.types.data import TYP_LIST, TYP_MAP, TYP_STR, DataType
+from toscalib.templates.property_item import PropertyItem
+import copy, logging
+
+FUNCTIONS = (GET_INPUT, GET_PROPERTY, GET_ATTRIBUTE, GET_OPERATION, GET_NODES, GET_ARTIFACT, CONCAT) = \
+ ('get_input', 'get_property', 'get_attribute', 'get_operation_output', 'get_nodes_of_type', 'get_artifact', 'concat')
+
+VALUE_STATE = (VALID_VALUE, FUNCTION, NULL) = \
+ (1, 2, 3)
+
+def _is_function(value):
+ if type(value) is not dict:
+ return None
+ if len(value.keys()) != 1:
+ return None
+ key = list(value.keys())[0]
+ if key not in FUNCTIONS:
+ return None
+
+ if key == GET_INPUT:
+ out_value = FunctionValue(key)
+ out_value.target_property = value[key]
+ return out_value
+ elif key == CONCAT:
+ out_value = FunctionValue(key)
+ value_list = value[key]
+ if type(value_list) is not list:
+ return None
+ out_value.extra_data = []
+ for value_item in value_list:
+ out_value.extra_data.append(Value(DataType(TYP_STR), value_item))
+ return out_value
+ else:
+ out_value = FunctionValue(key)
+ value_list = value[key]
+ if type(value_list) is not list:
+ return None
+ out_value.extra_data = value_list
+
+ return out_value
+
+
+class FunctionValue(object):
+ def __init__(self, func_type):
+ self.type = func_type
+ self.target_property = None
+ self.extra_data = []
+ self.value_from_node = None
+ self.value_from_item = None
+ self.result = None
+
+ def _update_prefix(self, prefix):
+ if self.type == GET_INPUT:
+ self.target_property = prefix + self.target_property
+ elif (self.type == GET_PROPERTY or self.type == GET_ATTRIBUTE):
+ if self.extra_data is not None and len(self.extra_data) > 1 and self.extra_data[0] != 'SELF':
+ if self.extra_data[0] == 'NO_PREFIX':
+ self.extra_data[0] = prefix[:len(prefix)-1]
+ else:
+ self.extra_data[0] = prefix + self.extra_data[0]
+ elif self.type == CONCAT:
+ for item in self.extra_data:
+ if item.function is not None:
+ item._update_prefix(prefix)
+
+ def _update_function_reference(self, temp, self_node = None, self_item = None):
+ if self.type == GET_INPUT:
+# if temp.inputs.has_key(self.target_property):
+ if self.target_property in temp.inputs:
+ self.value_from_item = temp.inputs[self.target_property]
+ return
+# elif temp.aux_inputs.has_key(self.target_property):
+ elif self.target_property in temp.aux_inputs:
+ self.value_from_item = temp.aux_inputs[self.target_property]
+ return
+ else:
+ logging.debug( 'get_input function points to a non-existent input, autofill'+ self.target_property)
+ def_item = copy.deepcopy(self_item.definition)
+ def_item.name = self.target_property
+ temp.inputs[self.target_property] = PropertyItem(def_item)
+ self.value_from_item = temp.inputs[self.target_property]
+ return
+ elif self.type == GET_PROPERTY:
+ if self.extra_data is None or len(self.extra_data) < 2:
+ logging.warning('Error, get_property has not enough parameters '+ self.extra_data)
+ return
+# if self.extra_data[0] != 'SELF' and temp.node_dict.has_key(self.extra_data[0]) is False:
+ if self.extra_data[0] != 'SELF' and self.extra_data[0] not in temp.node_dict:
+ logging.warning( 'Error, get_property from unrecognized node '+ self.extra_data[0])
+ return
+
+ if self.extra_data[0] == 'SELF':
+ node_item = self_node
+ else:
+ node_item = temp.node_dict[self.extra_data[0]]
+ self.value_from_node = node_item
+
+ if len(self.extra_data) == 2:
+ self.value_from_item = node_item._get_property_item(self.extra_data[1])
+ return
+ elif len(self.extra_data) == 3:
+ self.value_from_item = node_item._get_capability_property(self.extra_data[1], self.extra_data[2])
+ if self.value_from_item is not None:
+ return
+ req_item = node_item._get_requirement_item_first(self.extra_data[1])
+ if req_item is None:
+ return
+ new_node_item = req_item.value
+ if new_node_item is None:
+ self.value_from_node = None
+ return
+ self.value_from_node = new_node_item
+# if req_item.cap_match.properties.has_key(self.extra_data[2]):
+ if self.extra_data[2] in req_item.cap_match.properties:
+ self.value_from_item = req_item.cap_match.properties[self.extra_data[2]]
+ else:
+ self.value_from_item = new_node_item._get_property_item(self.extra_data[2])
+
+ else:
+ logging.warning( 'Too many parameters for get_property function '+ self.extra_data)
+ elif self.type == GET_ATTRIBUTE:
+ if self.extra_data is None or len(self.extra_data) < 2:
+ logging.error( 'Error, get_attribute has not enough parameters '+ self.extra_data)
+ return
+# if self.extra_data[0] != 'SELF' and temp.node_dict.has_key(self.extra_data[0]) is False:
+ if self.extra_data[0] != 'SELF' and self.extra_data[0] not in temp.node_dict:
+ logging.error( 'Error, get_attribute from unrecognized node '+ self.extra_data[0])
+ return
+
+ if self.extra_data[0] == 'SELF':
+ node_item = self_node
+ else:
+ node_item = temp.node_dict[self.extra_data[0]]
+
+ self.value_from_node = node_item
+
+ if len(self.extra_data) > 3:
+ logging.warning( 'Too many parameters for get_attribute function '+ self.extra_data)
+ return
+ if self.extra_data[1] == 'id':
+ self.value_from_item = node_item.id
+ else:
+ self.value_from_item = node_item._get_attribute_item(self.extra_data[1])
+
+ if self.value_from_item is not None:
+ return
+ req_item = node_item._get_requirement_item_first(self.extra_data[1])
+ if req_item is None:
+ return
+ new_node_item = req_item.value
+ if new_node_item is None:
+ self.value_from_node = None
+ return
+ self.value_from_node = new_node_item
+ self.value_from_item = new_node_item._get_attribute_item(self.extra_data[2])
+ return
+
+ elif self.type == CONCAT:
+ for item in self.extra_data:
+ if item.function is not None:
+ item._update_function_reference(temp, self_node)
+ else:
+ logging.warning( 'Function '+ self.type+ ' is not supported')
+ return
+
+ def _calculate_function_result(self, tags= '' ):
+ if 'func' in tags:
+ return self._get_function_representation(tags), FUNCTION
+
+ if self.type == CONCAT:
+ function_ret = VALID_VALUE
+ function_str = ""
+ for item in self.extra_data:
+ item_str, item_value = item._get_value(tags)
+ if item_value is FUNCTION:
+ function_ret = FUNCTION
+ break
+ elif item_str is not None:
+ function_str = function_str + item_str
+ if function_ret == FUNCTION:
+ return self._get_function_representation(tags), FUNCTION
+ else:
+ return function_str, function_ret
+
+ if 'w_default' in tags and self.type == GET_INPUT and self.value_from_item is not None and hasattr(self.value_from_item.definition, 'default') is True and self.value_from_item.definition.default is not None:
+ return self.value_from_item.definition.default, VALID_VALUE
+
+ if self.value_from_item is None or self.value_from_item.value is None or self.value_from_item.value.function == self:
+ return self._get_function_representation(tags), FUNCTION
+ else:
+ return self.value_from_item.value._get_value(tags)
+
+ def _get_value(self, tags = ''):
+ return self._calculate_function_result(tags)
+
+ def _get_function_representation(self, tags=''):
+ if self.type == GET_INPUT:
+ out_str = {}
+ out_str[self.type]= self.target_property
+ elif self.type == GET_PROPERTY:
+ out_str = {}
+ if self.value_from_node is None or 'rawfunc' in tags:
+ out_val = copy.deepcopy(self.extra_data)
+ else:
+ out_val = []
+ out_val.append(self.value_from_node.name)
+ out_val.append(self.extra_data[len(self.extra_data)-1])
+
+ out_str[self.type] = out_val
+ elif self.type == GET_ATTRIBUTE:
+ out_str = {}
+ if self.value_from_node is None or 'rawfunc' in tags:
+ out_val = copy.deepcopy(self.extra_data)
+ else:
+ out_val = []
+ out_val.append(self.value_from_node.name)
+ out_val.append(self.extra_data[len(self.extra_data)-1])
+ if self.extra_data[1] == 'id' and 'heat' in tags:
+ out_str['get_id'] = out_val[0]
+ else:
+ out_str[self.type] = out_val
+ elif self.type == CONCAT:
+ out_str = {}
+ out_list = []
+ for item in self.extra_data:
+ item_str, item_value = item._get_value(tags)
+ out_list.append(item_str)
+ out_str[self.type] = out_list
+ else:
+ out_str = {}
+ out_str[self.type]= copy.deepcopy(self.extra_data)
+ return out_str
+
+ def _get_function_result(self):
+ return self.result
+
+class Value(object):
+ def __init__(self, prop_type, value):
+ self.type = prop_type.name
+ self.type_obj = copy.deepcopy(prop_type)
+ self.raw_value = value
+ self.value = None
+ self.function = _is_function(value)
+
+ if self.function is None:
+ self.value = self.type_obj._format_value(value)
+
+ def _update_function_reference(self, temp, self_node = None, self_item = None):
+ if self.value is not None:
+ self.type_obj._update_function_reference(temp, self.value, self_node, self_item)
+ if self.function is not None:
+ self.function._update_function_reference(temp, self_node, self_item)
+
+ def _update_prefix(self, prefix):
+ if self.value is not None:
+ self.type_obj._update_prefix(prefix, self.value)
+ if self.function is not None:
+ self.function._update_prefix(prefix)
+
+ def _get_value(self, tags = ''):
+ if self.function is not None:
+ return self.function._get_value(tags)
+ if self.value is not None:
+ return self.type_obj._get_value(self.value, tags)
+
+ \ No newline at end of file