blob: 3e1ad426cf002ab019399787ff0a03e7f0217e02 [file] [log] [blame]
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
elif self.value_from_item is None: #This might not be the best solution, needs to pay attention to
# logging.debug( 'get_input function points to a non-existent input, set it to NONE')
# self_item.value = None
#this code is causing problems when properties in different nodes are calling the same get_input but actually mean different input values
logging.warning( 'get_input function points to a non-existent input, autofill '+ self.target_property)
def_item = copy.deepcopy(self_item.definition)
def_item.name = self_node.name + '_' + self.target_property
self.target_property = self_node.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)