diff options
Diffstat (limited to 'jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions')
7 files changed, 1890 insertions, 0 deletions
diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Concat.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Concat.java new file mode 100644 index 0000000..9f29dd2 --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Concat.java @@ -0,0 +1,76 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; + +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; +import org.openecomp.sdc.toscaparser.api.common.ExceptionCollector; + +public class Concat extends Function { + // Validate the function and provide an instance of the function + + // Concatenation of values are supposed to be produced at runtime and + // therefore its the responsibility of the TOSCA engine to implement the + // evaluation of Concat functions. + + // Arguments: + + // * List of strings that needs to be concatenated + + // Example: + + // [ 'http://', + // get_attribute: [ server, public_address ], + // ':' , + // get_attribute: [ server, port ] ] + + + public Concat(TopologyTemplate ttpl,Object context,String name,ArrayList<Object> args) { + super(ttpl,context,name,args); + } + + @Override + public Object result() { + return this; + } + + @Override + void validate() { + if(args.size() < 1) { + ExceptionCollector.appendException( + "ValueError: Invalid arguments for function \"concat\". " + + "Expected at least one argument"); + } + } + +} + +/*python + +class Concat(Function): +"""Validate the function and provide an instance of the function + +Concatenation of values are supposed to be produced at runtime and +therefore its the responsibility of the TOSCA engine to implement the +evaluation of Concat functions. + +Arguments: + +* List of strings that needs to be concatenated + +Example: + + [ 'http://', + get_attribute: [ server, public_address ], + ':' , + get_attribute: [ server, port ] ] +""" + +def validate(self): + if len(self.args) < 1: + ExceptionCollector.appendException( + ValueError(_('Invalid arguments for function "{0}". Expected ' + 'at least one arguments.').format(CONCAT))) + +def result(self): + return self +*/
\ No newline at end of file diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Function.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Function.java new file mode 100644 index 0000000..102fbc0 --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Function.java @@ -0,0 +1,191 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; + +public abstract class Function { + + protected static final String GET_PROPERTY = "get_property"; + protected static final String GET_ATTRIBUTE = "get_attribute"; + protected static final String GET_INPUT = "get_input"; + protected static final String GET_OPERATION_OUTPUT = "get_operation_output"; + protected static final String CONCAT = "concat"; + protected static final String TOKEN = "token"; + + protected static final String SELF = "SELF"; + protected static final String HOST = "HOST"; + protected static final String TARGET = "TARGET"; + protected static final String SOURCE = "SOURCE"; + + protected static final String HOSTED_ON = "tosca.relationships.HostedOn"; + + protected static HashMap<String,String> functionMappings = _getFunctionMappings(); + + private static HashMap<String,String> _getFunctionMappings() { + HashMap<String,String> map = new HashMap<>(); + map.put(GET_PROPERTY,"GetProperty"); + map.put(GET_INPUT, "GetInput"); + map.put(GET_ATTRIBUTE, "GetAttribute"); + map.put(GET_OPERATION_OUTPUT, "GetOperationOutput"); + map.put(CONCAT, "Concat"); + map.put(TOKEN, "Token"); + return map; + } + + protected TopologyTemplate toscaTpl; + protected Object context; + protected String name; + protected ArrayList<Object> args; + + + public Function(TopologyTemplate _toscaTpl,Object _context,String _name,ArrayList<Object> _args) { + toscaTpl = _toscaTpl; + context = _context; + name = _name; + args = _args; + validate(); + + } + + abstract Object result(); + + abstract void validate(); + + @SuppressWarnings("unchecked") + public static boolean isFunction(Object funcObj) { + // Returns True if the provided function is a Tosca intrinsic function. + // + //Examples: + // + //* "{ get_property: { SELF, port } }" + //* "{ get_input: db_name }" + //* Function instance + + //:param function: Function as string or a Function instance. + //:return: True if function is a Tosca intrinsic function, otherwise False. + // + + if(funcObj instanceof LinkedHashMap) { + LinkedHashMap<String,Object> function = (LinkedHashMap<String,Object>)funcObj; + if(function.size() == 1) { + String funcName = (new ArrayList<String>(function.keySet())).get(0); + return functionMappings.keySet().contains(funcName); + } + } + return (funcObj instanceof Function); + } + + @SuppressWarnings("unchecked") + public static Object getFunction(TopologyTemplate ttpl,Object context,Object rawFunctionObj) { + // Gets a Function instance representing the provided template function. + + // If the format provided raw_function format is not relevant for template + // functions or if the function name doesn't exist in function mapping the + // method returns the provided raw_function. + // + // :param tosca_tpl: The tosca template. + // :param node_template: The node template the function is specified for. + // :param raw_function: The raw function as dict. + // :return: Template function as Function instance or the raw_function if + // parsing was unsuccessful. + + if(isFunction(rawFunctionObj)) { + if(rawFunctionObj instanceof LinkedHashMap) { + LinkedHashMap<String,Object> rawFunction = (LinkedHashMap<String,Object>)rawFunctionObj; + String funcName = (new ArrayList<String>(rawFunction.keySet())).get(0); + if(functionMappings.keySet().contains(funcName)) { + String funcType = functionMappings.get(funcName); + Object oargs = (new ArrayList<Object>(rawFunction.values())).get(0); + ArrayList<Object> funcArgs; + if(oargs instanceof ArrayList) { + funcArgs = (ArrayList<Object>)oargs; + } + else { + funcArgs = new ArrayList<>(); + funcArgs.add(oargs); + } + + if(funcType.equals("GetInput")) { + return new GetInput(ttpl,context,funcName,funcArgs); + } + else if(funcType.equals("GetAttribute")) { + return new GetAttribute(ttpl,context,funcName,funcArgs); + } + else if(funcType.equals("GetProperty")) { + return new GetProperty(ttpl,context,funcName,funcArgs); + } + else if(funcType.equals("GetOperationOutput")) { + return new GetOperationOutput(ttpl,context,funcName,funcArgs); + } + else if(funcType.equals("Concat")) { + return new Concat(ttpl,context,funcName,funcArgs); + } + else if(funcType.equals("Token")) { + return new Token(ttpl,context,funcName,funcArgs); + } + } + } + } + return rawFunctionObj; + } +} + +/*python + +from toscaparser.common.exception import ExceptionCollector +from toscaparser.common.exception import UnknownInputError +from toscaparser.dataentity import DataEntity +from toscaparser.elements.constraints import Schema +from toscaparser.elements.datatype import DataType +from toscaparser.elements.entity_type import EntityType +from toscaparser.elements.relationshiptype import RelationshipType +from toscaparser.elements.statefulentitytype import StatefulEntityType +from toscaparser.utils.gettextutils import _ + + +GET_PROPERTY = 'get_property' +GET_ATTRIBUTE = 'get_attribute' +GET_INPUT = 'get_input' +GET_OPERATION_OUTPUT = 'get_operation_output' +CONCAT = 'concat' +TOKEN = 'token' + +SELF = 'SELF' +HOST = 'HOST' +TARGET = 'TARGET' +SOURCE = 'SOURCE' + +HOSTED_ON = 'tosca.relationships.HostedOn' + + +@six.add_metaclass(abc.ABCMeta) +class Function(object): + """An abstract type for representing a Tosca template function.""" + + def __init__(self, tosca_tpl, context, name, args): + self.tosca_tpl = tosca_tpl + self.context = context + self.name = name + self.args = args + self.validate() + + @abc.abstractmethod + def result(self): + """Invokes the function and returns its result + + Some methods invocation may only be relevant on runtime (for example, + getting runtime properties) and therefore its the responsibility of + the orchestrator/translator to take care of such functions invocation. + + :return: Function invocation result. + """ + return {self.name: self.args} + + @abc.abstractmethod + def validate(self): + """Validates function arguments.""" + pass +*/ diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetAttribute.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetAttribute.java new file mode 100644 index 0000000..5536dc5 --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetAttribute.java @@ -0,0 +1,538 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import org.openecomp.sdc.toscaparser.api.Capability; +import org.openecomp.sdc.toscaparser.api.EntityTemplate; +import org.openecomp.sdc.toscaparser.api.NodeTemplate; +import org.openecomp.sdc.toscaparser.api.RelationshipTemplate; +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; +import org.openecomp.sdc.toscaparser.api.common.ExceptionCollector; +import org.openecomp.sdc.toscaparser.api.elements.AttributeDef; +import org.openecomp.sdc.toscaparser.api.elements.CapabilityTypeDef; +import org.openecomp.sdc.toscaparser.api.elements.DataType; +import org.openecomp.sdc.toscaparser.api.elements.EntityType; +import org.openecomp.sdc.toscaparser.api.elements.NodeType; +import org.openecomp.sdc.toscaparser.api.elements.PropertyDef; +import org.openecomp.sdc.toscaparser.api.elements.RelationshipType; +import org.openecomp.sdc.toscaparser.api.elements.StatefulEntityType; +import org.openecomp.sdc.toscaparser.api.elements.constraints.Schema; + +public class GetAttribute extends Function { + // Get an attribute value of an entity defined in the service template + + // Node template attributes values are set in runtime and therefore its the + // responsibility of the Tosca engine to implement the evaluation of + // get_attribute functions. + + // Arguments: + + // * Node template name | HOST. + // * Attribute name. + + // If the HOST keyword is passed as the node template name argument the + // function will search each node template along the HostedOn relationship + // chain until a node which contains the attribute is found. + + // Examples: + + // * { get_attribute: [ server, private_address ] } + // * { get_attribute: [ HOST, private_address ] } + // * { get_attribute: [ HOST, private_address, 0 ] } + // * { get_attribute: [ HOST, private_address, 0, some_prop] } + + public GetAttribute(TopologyTemplate ttpl,Object context,String name,ArrayList<Object> args) { + super(ttpl,context,name,args); + } + + @Override + void validate() { + if(args.size() < 2) { + ExceptionCollector.appendException( + "ValueError: Illegal arguments for function \"get_attribute\". Expected arguments: \"node-template-name\", \"req-or-cap\" (optional), \"property name.\""); + return; + } + else if(args.size() == 2) { + _findNodeTemplateContainingAttribute(); + } + else { + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + if(nodeTpl == null) { + return; + } + int index = 2; + AttributeDef attr = nodeTpl.getTypeDefinition().getAttributeDefValue((String)args.get(1)); + if(attr != null) { + // found + } + else { + index = 3; + // then check the req or caps + attr = _findReqOrCapAttribute((String)args.get(1),(String)args.get(2)); + if(attr == null) { + return; + } + } + + String valueType = (String)attr.getSchema().get("type"); + if(args.size() > index) { + for(Object elem: args.subList(index,args.size())) { + if(valueType.equals("list")) { + if(!(elem instanceof Integer)) { + ExceptionCollector.appendException(String.format( + "ValueError: Illegal arguments for function \"get_attribute\" \"%s\". Expected positive integer argument", + elem.toString())); + } + Object ob = attr.getSchema().get("entry_schema"); + valueType = (String) + ((LinkedHashMap<String,Object>)ob).get("type"); + } + else if(valueType.equals("map")) { + Object ob = attr.getSchema().get("entry_schema"); + valueType = (String) + ((LinkedHashMap<String,Object>)ob).get("type"); + } + else { + boolean bFound = false; + for(String p: Schema.PROPERTY_TYPES) { + if(p.equals(valueType)) { + bFound = true; + break; + } + } + if(bFound) { + ExceptionCollector.appendException(String.format( + "ValueError: 'Illegal arguments for function \"get_attribute\". Unexpected attribute/index value \"%d\"", + elem)); + return; + } + else { // It is a complex type + DataType dataType = new DataType(valueType,null); + LinkedHashMap<String,PropertyDef> props = + dataType.getAllProperties(); + PropertyDef prop = props.get((String)elem); + if(prop != null) { + valueType = (String)prop.getSchema().get("type"); + } + else { + ExceptionCollector.appendException(String.format( + "KeyError: Illegal arguments for function \"get_attribute\". Attribute name \"%s\" not found in \"%\"", + elem,valueType)); + } + } + } + } + } + } + } + + @Override + public Object result() { + return this; + } + + private NodeTemplate getReferencedNodeTemplate() { + // Gets the NodeTemplate instance the get_attribute function refers to + + // If HOST keyword was used as the node template argument, the node + // template which contains the attribute along the HostedOn relationship + // chain will be returned. + + return _findNodeTemplateContainingAttribute(); + + } + + // Attributes can be explicitly created as part of the type definition + // or a property name can be implicitly used as an attribute name + private NodeTemplate _findNodeTemplateContainingAttribute() { + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + if(nodeTpl != null && + !_attributeExistsInType(nodeTpl.getTypeDefinition()) && + !nodeTpl.getProperties().keySet().contains(getAttributeName())) { + ExceptionCollector.appendException(String.format( + "KeyError: Attribute \"%s\" was not found in node template \"%s\"", + getAttributeName(),nodeTpl.getName())); + } + return nodeTpl; + } + + private boolean _attributeExistsInType(StatefulEntityType typeDefinition) { + LinkedHashMap<String,AttributeDef> attrsDef = typeDefinition.getAttributesDef(); + return attrsDef.get(getAttributeName()) != null; + } + + private NodeTemplate _findHostContainingAttribute(String nodeTemplateName) { + NodeTemplate nodeTemplate = _findNodeTemplate(nodeTemplateName); + if(nodeTemplate != null) { + LinkedHashMap<String,Object> hostedOnRel = + (LinkedHashMap<String,Object>)EntityType.TOSCA_DEF.get(HOSTED_ON); + for(Object ro: nodeTemplate.getRequirements()) { + if(ro != null && ro instanceof LinkedHashMap) { + LinkedHashMap<String,Object> r = (LinkedHashMap<String,Object>)ro; + for(String requirement: r.keySet()) { + String targetName = (String)r.get(requirement); + NodeTemplate targetNode = _findNodeTemplate(targetName); + NodeType targetType = (NodeType)targetNode.getTypeDefinition(); + for(CapabilityTypeDef capability: targetType.getCapabilitiesObjects()) { +// if(((ArrayList<String>)hostedOnRel.get("valid_target_types")).contains(capability.getType())) { + if(capability.inheritsFrom((ArrayList<String>)hostedOnRel.get("valid_target_types"))) { + if(_attributeExistsInType(targetType)) { + return targetNode; + } + return _findHostContainingAttribute(targetName); + } + } + } + } + } + } + return null; + } + + + private NodeTemplate _findNodeTemplate(String nodeTemplateName) { + if(nodeTemplateName.equals(HOST)) { + // Currently this is the only way to tell whether the function + // is used within the outputs section of the TOSCA template. + if(context instanceof ArrayList) { + ExceptionCollector.appendException( + "ValueError: \"get_attribute: [ HOST, ... ]\" is not allowed in \"outputs\" section of the TOSCA template"); + return null; + } + NodeTemplate nodeTpl = _findHostContainingAttribute(SELF); + if(nodeTpl == null) { + ExceptionCollector.appendException(String.format( + "ValueError: \"get_attribute: [ HOST, ... ]\" was used in " + + "node template \"%s\" but \"%s\" was not found in " + + "the relationship chain",((NodeTemplate)context).getName(),HOSTED_ON)); + return null; + } + return nodeTpl; + } + if(nodeTemplateName.equals(TARGET)) { + if(!(((EntityTemplate)context).getTypeDefinition() instanceof RelationshipType)) { + ExceptionCollector.appendException( + "KeyError: \"TARGET\" keyword can only be used in context " + + " to \"Relationships\" target node"); + return null; + } + return ((RelationshipTemplate)context).getTarget(); + } + if(nodeTemplateName.equals(SOURCE)) { + if(!(((EntityTemplate)context).getTypeDefinition() instanceof RelationshipType)) { + ExceptionCollector.appendException( + "KeyError: \"SOURCE\" keyword can only be used in context " + + " to \"Relationships\" source node"); + return null; + } + return ((RelationshipTemplate)context).getTarget(); + } + String name; + if(nodeTemplateName.equals(SELF) && !(context instanceof ArrayList)) { + name = ((NodeTemplate)context).getName(); + } + else { + name = nodeTemplateName; + } + for(NodeTemplate nt: toscaTpl.getNodeTemplates()) { + if(nt.getName().equals(name)) { + return nt; + } + } + ExceptionCollector.appendException(String.format( + "KeyError: Node template \"%s\" was not found",nodeTemplateName)); + return null; + } + + public AttributeDef _findReqOrCapAttribute(String reqOrCap,String attrName) { + + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + // Find attribute in node template's requirements + for(Object ro: nodeTpl.getRequirements()) { + if(ro != null && ro instanceof LinkedHashMap) { + LinkedHashMap<String,Object> r = (LinkedHashMap<String,Object>)ro; + for(String req: r.keySet()) { + String nodeName = (String)r.get(req); + if(req.equals(reqOrCap)) { + NodeTemplate nodeTemplate = _findNodeTemplate(nodeName); + return _getCapabilityAttribute(nodeTemplate,req,attrName); + } + } + } + } + // If requirement was not found, look in node template's capabilities + return _getCapabilityAttribute(nodeTpl,reqOrCap,attrName); + } + + private AttributeDef _getCapabilityAttribute(NodeTemplate nodeTemplate, + String capabilityName, + String attrName) { + // Gets a node template capability attribute + LinkedHashMap<String,Capability> caps = nodeTemplate.getCapabilities(); + if(caps != null && caps.keySet().contains(capabilityName)) { + Capability cap = caps.get(capabilityName); + AttributeDef attribute = null; + LinkedHashMap<String,AttributeDef> attrs = + cap.getDefinition().getAttributesDef(); + if(attrs != null && attrs.keySet().contains(attrName)) { + attribute = attrs.get(attrName); + } + if(attribute == null) { + ExceptionCollector.appendException(String.format( + "KeyError: Attribute \"%s\" was not found in capability \"%s\" of node template \"%s\" referenced from node template \"%s\"", + attrName,capabilityName,nodeTemplate.getName(),((NodeTemplate)context).getName())); + } + return attribute; + } + String msg = String.format( + "Requirement/Capability \"%s\" referenced from node template \"%s\" was not found in node template \"%s\"", + capabilityName,((NodeTemplate)context).getName(),nodeTemplate.getName()); + ExceptionCollector.appendException("KeyError: " + msg); + return null; + } + + String getNodeTemplateName() { + return (String)args.get(0); + } + + String getAttributeName() { + return (String)args.get(1); + } + +} + +/*python + +class GetAttribute(Function): +"""Get an attribute value of an entity defined in the service template + +Node template attributes values are set in runtime and therefore its the +responsibility of the Tosca engine to implement the evaluation of +get_attribute functions. + +Arguments: + +* Node template name | HOST. +* Attribute name. + +If the HOST keyword is passed as the node template name argument the +function will search each node template along the HostedOn relationship +chain until a node which contains the attribute is found. + +Examples: + +* { get_attribute: [ server, private_address ] } +* { get_attribute: [ HOST, private_address ] } +* { get_attribute: [ HOST, private_address, 0 ] } +* { get_attribute: [ HOST, private_address, 0, some_prop] } +""" + +def validate(self): + if len(self.args) < 2: + ExceptionCollector.appendException( + ValueError(_('Illegal arguments for function "{0}". Expected ' + 'arguments: "node-template-name", "req-or-cap"' + '(optional), "property name"' + ).format(GET_ATTRIBUTE))) + return + elif len(self.args) == 2: + self._find_node_template_containing_attribute() + else: + node_tpl = self._find_node_template(self.args[0]) + if node_tpl is None: + return + index = 2 + attrs = node_tpl.type_definition.get_attributes_def() + found = [attrs[self.args[1]]] if self.args[1] in attrs else [] + if found: + attr = found[0] + else: + index = 3 + # then check the req or caps + attr = self._find_req_or_cap_attribute(self.args[1], + self.args[2]) + + value_type = attr.schema['type'] + if len(self.args) > index: + for elem in self.args[index:]: + if value_type == "list": + if not isinstance(elem, int): + ExceptionCollector.appendException( + ValueError(_('Illegal arguments for function' + ' "{0}". "{1}" Expected positive' + ' integer argument' + ).format(GET_ATTRIBUTE, elem))) + value_type = attr.schema['entry_schema']['type'] + elif value_type == "map": + value_type = attr.schema['entry_schema']['type'] + elif value_type in Schema.PROPERTY_TYPES: + ExceptionCollector.appendException( + ValueError(_('Illegal arguments for function' + ' "{0}". Unexpected attribute/' + 'index value "{1}"' + ).format(GET_ATTRIBUTE, elem))) + return + else: # It is a complex type + data_type = DataType(value_type) + props = data_type.get_all_properties() + found = [props[elem]] if elem in props else [] + if found: + prop = found[0] + value_type = prop.schema['type'] + else: + ExceptionCollector.appendException( + KeyError(_('Illegal arguments for function' + ' "{0}". Attribute name "{1}" not' + ' found in "{2}"' + ).format(GET_ATTRIBUTE, + elem, + value_type))) + +def result(self): + return self + +def get_referenced_node_template(self): + """Gets the NodeTemplate instance the get_attribute function refers to. + + If HOST keyword was used as the node template argument, the node + template which contains the attribute along the HostedOn relationship + chain will be returned. + """ + return self._find_node_template_containing_attribute() + +# Attributes can be explicitly created as part of the type definition +# or a property name can be implicitly used as an attribute name +def _find_node_template_containing_attribute(self): + node_tpl = self._find_node_template(self.args[0]) + if node_tpl and \ + not self._attribute_exists_in_type(node_tpl.type_definition) \ + and self.attribute_name not in node_tpl.get_properties(): + ExceptionCollector.appendException( + KeyError(_('Attribute "%(att)s" was not found in node ' + 'template "%(ntpl)s".') % + {'att': self.attribute_name, + 'ntpl': node_tpl.name})) + return node_tpl + +def _attribute_exists_in_type(self, type_definition): + attrs_def = type_definition.get_attributes_def() + found = [attrs_def[self.attribute_name]] \ + if self.attribute_name in attrs_def else [] + return len(found) == 1 + +def _find_host_containing_attribute(self, node_template_name=SELF): + node_template = self._find_node_template(node_template_name) + if node_template: + hosted_on_rel = EntityType.TOSCA_DEF[HOSTED_ON] + for r in node_template.requirements: + for requirement, target_name in r.items(): + target_node = self._find_node_template(target_name) + target_type = target_node.type_definition + for capability in target_type.get_capabilities_objects(): + if capability.type in \ + hosted_on_rel['valid_target_types']: + if self._attribute_exists_in_type(target_type): + return target_node + return self._find_host_containing_attribute( + target_name) + +def _find_node_template(self, node_template_name): + if node_template_name == HOST: + # Currently this is the only way to tell whether the function + # is used within the outputs section of the TOSCA template. + if isinstance(self.context, list): + ExceptionCollector.appendException( + ValueError(_( + '"get_attribute: [ HOST, ... ]" is not allowed in ' + '"outputs" section of the TOSCA template.'))) + return + node_tpl = self._find_host_containing_attribute() + if not node_tpl: + ExceptionCollector.appendException( + ValueError(_( + '"get_attribute: [ HOST, ... ]" was used in node ' + 'template "{0}" but "{1}" was not found in ' + 'the relationship chain.').format(self.context.name, + HOSTED_ON))) + return + return node_tpl + if node_template_name == TARGET: + if not isinstance(self.context.type_definition, RelationshipType): + ExceptionCollector.appendException( + KeyError(_('"TARGET" keyword can only be used in context' + ' to "Relationships" target node'))) + return + return self.context.target + if node_template_name == SOURCE: + if not isinstance(self.context.type_definition, RelationshipType): + ExceptionCollector.appendException( + KeyError(_('"SOURCE" keyword can only be used in context' + ' to "Relationships" source node'))) + return + return self.context.source + name = self.context.name \ + if node_template_name == SELF and \ + not isinstance(self.context, list) \ + else node_template_name + for node_template in self.tosca_tpl.nodetemplates: + if node_template.name == name: + return node_template + ExceptionCollector.appendException( + KeyError(_( + 'Node template "{0}" was not found.' + ).format(node_template_name))) + +def _find_req_or_cap_attribute(self, req_or_cap, attr_name): + node_tpl = self._find_node_template(self.args[0]) + # Find attribute in node template's requirements + for r in node_tpl.requirements: + for req, node_name in r.items(): + if req == req_or_cap: + node_template = self._find_node_template(node_name) + return self._get_capability_attribute( + node_template, + req, + attr_name) + # If requirement was not found, look in node template's capabilities + return self._get_capability_attribute(node_tpl, + req_or_cap, + attr_name) + +def _get_capability_attribute(self, + node_template, + capability_name, + attr_name): + """Gets a node template capability attribute.""" + caps = node_template.get_capabilities() + if caps and capability_name in caps.keys(): + cap = caps[capability_name] + attribute = None + attrs = cap.definition.get_attributes_def() + if attrs and attr_name in attrs.keys(): + attribute = attrs[attr_name] + if not attribute: + ExceptionCollector.appendException( + KeyError(_('Attribute "%(attr)s" was not found in ' + 'capability "%(cap)s" of node template ' + '"%(ntpl1)s" referenced from node template ' + '"%(ntpl2)s".') % {'attr': attr_name, + 'cap': capability_name, + 'ntpl1': node_template.name, + 'ntpl2': self.context.name})) + return attribute + msg = _('Requirement/Capability "{0}" referenced from node template ' + '"{1}" was not found in node template "{2}".').format( + capability_name, + self.context.name, + node_template.name) + ExceptionCollector.appendException(KeyError(msg)) + +@property +def node_template_name(self): + return self.args[0] + +@property +def attribute_name(self): + return self.args[1] +*/
\ No newline at end of file diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetInput.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetInput.java new file mode 100644 index 0000000..7970207 --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetInput.java @@ -0,0 +1,108 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import org.openecomp.sdc.toscaparser.api.DataEntity; +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; +import org.openecomp.sdc.toscaparser.api.common.ExceptionCollector; +import org.openecomp.sdc.toscaparser.api.parameters.Input; + +public class GetInput extends Function { + + public GetInput(TopologyTemplate toscaTpl,Object context,String name,ArrayList<Object> _args) { + super(toscaTpl,context,name,_args); + + } + + @Override + void validate() { + if(args.size() != 1) { + ExceptionCollector.appendException(String.format( + "ValueError: Expected one argument for function \"get_input\" but received \"%s\"", + args.toString())); + } + boolean bFound = false; + for(Input inp: toscaTpl.getInputs()) { + if(inp.getName().equals(args.get(0))) { + bFound = true; + break; + } + } + if(!bFound) { + ExceptionCollector.appendException(String.format( + "UnknownInputError: Unknown input \"%s\"",args.get(0))); + } + } + + public Object result() { + if(toscaTpl.getParsedParams() != null && + toscaTpl.getParsedParams().get(getInputName()) != null) { + LinkedHashMap<String,Object> ttinp = (LinkedHashMap<String,Object>)toscaTpl.getTpl().get("inputs"); + LinkedHashMap<String,Object> ttinpinp = (LinkedHashMap<String,Object>)ttinp.get(getInputName()); + String type = (String)ttinpinp.get("type"); + + return DataEntity.validateDatatype( + type, toscaTpl.getParsedParams().get(getInputName()),null,null,null); + } + + Input inputDef = null; + for(Input inpDef: toscaTpl.getInputs()) { + if(getInputName().equals(inpDef.getName())) { + inputDef = inpDef; + break; + } + } + if(inputDef != null) { + return inputDef.getDefault(); + } + return null; + } + + public String getInputName() { + return (String)args.get(0); + } + +} + +/*python + +class GetInput(Function): +"""Get a property value declared within the input of the service template. + +Arguments: + +* Input name. + +Example: + +* get_input: port +""" + +def validate(self): + if len(self.args) != 1: + ExceptionCollector.appendException( + ValueError(_( + 'Expected one argument for function "get_input" but ' + 'received "%s".') % self.args)) + inputs = [input.name for input in self.tosca_tpl.inputs] + if self.args[0] not in inputs: + ExceptionCollector.appendException( + UnknownInputError(input_name=self.args[0])) + +def result(self): + if self.tosca_tpl.parsed_params and \ + self.input_name in self.tosca_tpl.parsed_params: + return DataEntity.validate_datatype( + self.tosca_tpl.tpl['inputs'][self.input_name]['type'], + self.tosca_tpl.parsed_params[self.input_name]) + + input = [input_def for input_def in self.tosca_tpl.inputs + if self.input_name == input_def.name][0] + return input.default + +@property +def input_name(self): + return self.args[0] + +*/
\ No newline at end of file diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetOperationOutput.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetOperationOutput.java new file mode 100644 index 0000000..f2231a1 --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetOperationOutput.java @@ -0,0 +1,227 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; + +import org.openecomp.sdc.toscaparser.api.EntityTemplate; +import org.openecomp.sdc.toscaparser.api.NodeTemplate; +import org.openecomp.sdc.toscaparser.api.RelationshipTemplate; +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; +import org.openecomp.sdc.toscaparser.api.common.ExceptionCollector; +import org.openecomp.sdc.toscaparser.api.elements.InterfacesDef; +import org.openecomp.sdc.toscaparser.api.elements.RelationshipType; +import org.openecomp.sdc.toscaparser.api.elements.StatefulEntityType; + +public class GetOperationOutput extends Function { + + public GetOperationOutput(TopologyTemplate ttpl,Object context,String name,ArrayList<Object> args) { + super(ttpl,context,name,args); + } + + @Override + public void validate() { + if(args.size() == 4) { + _findNodeTemplate((String)args.get(0)); + String interfaceName = _findInterfaceName((String)args.get(1)); + _findOperationName(interfaceName,(String)args.get(2)); + } + else { + ExceptionCollector.appendException( + "ValueError: Illegal arguments for function \"get_operation_output\". " + + "Expected arguments: \"template_name\",\"interface_name\"," + + "\"operation_name\",\"output_variable_name\""); + } + } + + private String _findInterfaceName(String _interfaceName) { + boolean bFound = false; + for(String sect: InterfacesDef.SECTIONS) { + if(sect.equals(_interfaceName)) { + bFound = true; + break; + } + } + if(bFound) { + return _interfaceName; + } + else { + ExceptionCollector.appendException(String.format( + "ValueError: invalid interface name \"%s\" in \"get_operation_output\"", + _interfaceName)); + return null; + } + } + + private String _findOperationName(String interfaceName,String operationName) { + + if(interfaceName.equals("Configure") || + interfaceName.equals("tosca.interfaces.node.relationship.Configure")) { + boolean bFound = false; + for(String sect: StatefulEntityType.interfacesRelationshipConfigureOperations) { + if(sect.equals(operationName)) { + bFound = true; + break; + } + } + if(bFound) { + return operationName; + } + else { + ExceptionCollector.appendException(String.format( + "ValueError: Invalid operation of Configure interface \"%s\" in \"get_operation_output\"", + operationName)); + return null; + } + } + if(interfaceName.equals("Standard") || + interfaceName.equals("tosca.interfaces.node.lifecycle.Standard")) { + boolean bFound = false; + for(String sect: StatefulEntityType.interfacesNodeLifecycleOperations) { + if(sect.equals(operationName)) { + bFound = true; + break; + } + } + if(bFound) { + return operationName; + } + else { + ExceptionCollector.appendException(String.format( + "ValueError: Invalid operation of Configure interface \"%s\" in \"get_operation_output\"", + operationName)); + return null; + } + } + else { + ExceptionCollector.appendException(String.format( + "ValueError: Invalid interface name \"%s\" in \"get_operation_output\"", + interfaceName)); + return null; + } + } + + private NodeTemplate _findNodeTemplate(String nodeTemplateName) { + if(nodeTemplateName.equals(TARGET)) { + if(!(((EntityTemplate)context).getTypeDefinition() instanceof RelationshipType)) { + ExceptionCollector.appendException( + "KeyError: \"TARGET\" keyword can only be used in context " + + " to \"Relationships\" target node"); + return null; + } + return ((RelationshipTemplate)context).getTarget(); + } + if(nodeTemplateName.equals(SOURCE)) { + if(!(((EntityTemplate)context).getTypeDefinition() instanceof RelationshipType)) { + ExceptionCollector.appendException( + "KeyError: \"SOURCE\" keyword can only be used in context " + + " to \"Relationships\" source node"); + return null; + } + return ((RelationshipTemplate)context).getTarget(); + } + String name; + if(nodeTemplateName.equals(SELF) && !(context instanceof ArrayList)) { + name = ((NodeTemplate)context).getName(); + } + else { + name = nodeTemplateName; + } + for(NodeTemplate nt: toscaTpl.getNodeTemplates()) { + if(nodeTemplateName.equals(name)) { + return nt; + } + } + ExceptionCollector.appendException(String.format( + "KeyError: Node template \"%s\" was not found",nodeTemplateName)); + return null; + } + + @Override + public Object result() { + return this; + } + +} + +/*python + +class GetOperationOutput(Function): +def validate(self): + if len(self.args) == 4: + self._find_node_template(self.args[0]) + interface_name = self._find_interface_name(self.args[1]) + self._find_operation_name(interface_name, self.args[2]) + else: + ExceptionCollector.appendException( + ValueError(_('Illegal arguments for function "{0}". Expected ' + 'arguments: "template_name","interface_name",' + '"operation_name","output_variable_name"' + ).format(GET_OPERATION_OUTPUT))) + return + +def _find_interface_name(self, interface_name): + if interface_name in toscaparser.elements.interfaces.SECTIONS: + return interface_name + else: + ExceptionCollector.appendException( + ValueError(_('Enter a valid interface name' + ).format(GET_OPERATION_OUTPUT))) + return + +def _find_operation_name(self, interface_name, operation_name): + if(interface_name == 'Configure' or + interface_name == 'tosca.interfaces.node.relationship.Configure'): + if(operation_name in + StatefulEntityType. + interfaces_relationship_configure_operations): + return operation_name + else: + ExceptionCollector.appendException( + ValueError(_('Enter an operation of Configure interface' + ).format(GET_OPERATION_OUTPUT))) + return + elif(interface_name == 'Standard' or + interface_name == 'tosca.interfaces.node.lifecycle.Standard'): + if(operation_name in + StatefulEntityType.interfaces_node_lifecycle_operations): + return operation_name + else: + ExceptionCollector.appendException( + ValueError(_('Enter an operation of Standard interface' + ).format(GET_OPERATION_OUTPUT))) + return + else: + ExceptionCollector.appendException( + ValueError(_('Enter a valid operation name' + ).format(GET_OPERATION_OUTPUT))) + return + +def _find_node_template(self, node_template_name): + if node_template_name == TARGET: + if not isinstance(self.context.type_definition, RelationshipType): + ExceptionCollector.appendException( + KeyError(_('"TARGET" keyword can only be used in context' + ' to "Relationships" target node'))) + return + return self.context.target + if node_template_name == SOURCE: + if not isinstance(self.context.type_definition, RelationshipType): + ExceptionCollector.appendException( + KeyError(_('"SOURCE" keyword can only be used in context' + ' to "Relationships" source node'))) + return + return self.context.source + name = self.context.name \ + if node_template_name == SELF and \ + not isinstance(self.context, list) \ + else node_template_name + for node_template in self.tosca_tpl.nodetemplates: + if node_template.name == name: + return node_template + ExceptionCollector.appendException( + KeyError(_( + 'Node template "{0}" was not found.' + ).format(node_template_name))) + +def result(self): + return self +*/
\ No newline at end of file diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetProperty.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetProperty.java new file mode 100644 index 0000000..e55250c --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/GetProperty.java @@ -0,0 +1,639 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import org.openecomp.sdc.toscaparser.api.Capability; +import org.openecomp.sdc.toscaparser.api.NodeTemplate; +import org.openecomp.sdc.toscaparser.api.Property; +import org.openecomp.sdc.toscaparser.api.RelationshipTemplate; +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; +import org.openecomp.sdc.toscaparser.api.common.ExceptionCollector; +import org.openecomp.sdc.toscaparser.api.elements.CapabilityTypeDef; +import org.openecomp.sdc.toscaparser.api.elements.EntityType; +import org.openecomp.sdc.toscaparser.api.elements.NodeType; +import org.openecomp.sdc.toscaparser.api.elements.PropertyDef; +import org.openecomp.sdc.toscaparser.api.elements.RelationshipType; +import org.openecomp.sdc.toscaparser.api.elements.StatefulEntityType; + +public class GetProperty extends Function { + // Get a property value of an entity defined in the same service template + + // Arguments: + + // * Node template name | SELF | HOST | SOURCE | TARGET. + // * Requirement or capability name (optional). + // * Property name. + + // If requirement or capability name is specified, the behavior is as follows: + // The req or cap name is first looked up in the specified node template's + // requirements. + // If found, it would search for a matching capability + // of an other node template and get its property as specified in function + // arguments. + // Otherwise, the req or cap name would be looked up in the specified + // node template's capabilities and if found, it would return the property of + // the capability as specified in function arguments. + + // Examples: + + // * { get_property: [ mysql_server, port ] } + // * { get_property: [ SELF, db_port ] } + // * { get_property: [ SELF, database_endpoint, port ] } + // * { get_property: [ SELF, database_endpoint, port, 1 ] } + + + public GetProperty(TopologyTemplate ttpl,Object context,String name,ArrayList<Object> args) { + super(ttpl,context,name,args); + } + + @Override + void validate() { + if(args.size() < 2) { + ExceptionCollector.appendException( + "ValueError: Illegal arguments for function \"get_property\". Expected arguments: \"node-template-name\", \"req-or-cap\" (optional), \"property name.\""); + return; + } + if(args.size() == 2) { + Property foundProp = _findProperty((String)args.get(1)); + if(foundProp == null) { + return; + } + Object prop = foundProp.getValue(); + if(prop instanceof Function) { + Function.getFunction(toscaTpl,context, prop); + } + } + else if(args.size() >= 3) { + // do not use _find_property to avoid raise KeyError + // if the prop is not found + // First check if there is property with this name + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + LinkedHashMap<String,Property> props; + if(nodeTpl != null) { + props = nodeTpl.getProperties(); + } + else { + props = new LinkedHashMap<>(); + } + int index = 2; + Object propertyValue; + if(props.get(args.get(1)) != null) { + propertyValue = ((Property)props.get(args.get(1))).getValue(); + } + else { + index = 3; + // then check the req or caps + propertyValue = _findReqOrCapProperty((String)args.get(1),(String)args.get(2)); + } + + if(args.size() > index) { + for(Object elem: args.subList(index,args.size()-1)) { + if(propertyValue instanceof ArrayList) { + int intElem = (int)elem; + propertyValue = _getIndexValue(propertyValue,intElem); + } + else { + propertyValue = _getAttributeValue(propertyValue,(String)elem); + } + } + } + } + } + + @SuppressWarnings("unchecked") + private Object _findReqOrCapProperty(String reqOrCap,String propertyName) { + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + if(nodeTpl == null) { + return null; + } + // look for property in node template's requirements + for(Object r: nodeTpl.getRequirements()) { + if(r instanceof LinkedHashMap) { + LinkedHashMap<String,Object> rlist = (LinkedHashMap<String,Object>)r; + for(String req: rlist.keySet()) { + String nodeName = (String)rlist.get(req); + if(req.equals(reqOrCap)) { + NodeTemplate nodeTemplate = _findNodeTemplate(nodeName); + return _getCapabilityProperty(nodeTemplate,req,propertyName,true); + } + } + } + } + // If requirement was not found, look in node template's capabilities + return _getCapabilityProperty(nodeTpl,reqOrCap,propertyName,true); + } + + private Object _getCapabilityProperty(NodeTemplate nodeTemplate, + String capabilityName, + String propertyName, + boolean throwErrors) { + + // Gets a node template capability property + Object property = null; + LinkedHashMap<String,Capability> caps = nodeTemplate.getCapabilities(); + if(caps != null && caps.get(capabilityName) != null) { + Capability cap = caps.get(capabilityName); + LinkedHashMap<String,Property> props = cap.getProperties(); + if(props != null && props.get(propertyName) != null) { + property = ((Property)props.get(propertyName)).getValue(); + } + if(property == null && throwErrors) { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" was not found in capability \"%s\" of node template \"%s\" referenced from node template \"%s\"", + propertyName,capabilityName,nodeTemplate.getName(),((NodeTemplate)context).getName())); + } + return property; + } + if(throwErrors) { + ExceptionCollector.appendException(String.format( + "KeyError: Requirement/Capability \"%s\" referenced from node template \"%s\" was not found in node template \"%s\"", + capabilityName,((NodeTemplate)context).getName(),nodeTemplate.getName())); + } + + return null; + } + + private Property _findProperty(String propertyName) { + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + if(nodeTpl == null) { + return null; + } + LinkedHashMap<String,Property> props = nodeTpl.getProperties(); + Property found = props.get(propertyName); + if(found == null) { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" was not found in node template \"%s\"", + propertyName,nodeTpl.getName())); + } + return found; + } + + private NodeTemplate _findNodeTemplate(String nodeTemplateName) { + if(nodeTemplateName.equals(SELF)) { + return (NodeTemplate)context; + } + // enable the HOST value in the function + if(nodeTemplateName.equals(HOST)) { + NodeTemplate node = _findHostContainingProperty(null); + if(node == null) { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" was not found in capability \"%s\" of node template \"%s\" referenced from node template \"%s\"", + (String)args.get(2),(String)args.get(1),((NodeTemplate)context).getName())); + return null; + } + return node; + } + if(nodeTemplateName.equals(TARGET)) { + if(!(((RelationshipTemplate)context).getTypeDefinition() instanceof RelationshipType)) { + ExceptionCollector.appendException( + "KeyError: \"TARGET\" keyword can only be used in context to \"Relationships\" target node"); + return null; + } + return ((RelationshipTemplate)context).getTarget(); + } + if(nodeTemplateName.equals(SOURCE)) { + if(!(((RelationshipTemplate)context).getTypeDefinition() instanceof RelationshipType)) { + ExceptionCollector.appendException( + "KeyError: \"SOURCE\" keyword can only be used in context to \"Relationships\" target node"); + return null; + } + return ((RelationshipTemplate)context).getSource(); + } + if(toscaTpl.getNodeTemplates() == null) { + return null; + } + for(NodeTemplate nodeTemplate: toscaTpl.getNodeTemplates()) { + if(nodeTemplate.getName().equals(nodeTemplateName)) { + return nodeTemplate; + } + } + ExceptionCollector.appendException(String.format( + "KeyError: Node template \"%s\" was not found. Referenced from Node Template \"%s\"", + nodeTemplateName,((NodeTemplate)context).getName())); + + return null; + } + + @SuppressWarnings("rawtypes") + private Object _getIndexValue(Object value,int index) { + if(value instanceof ArrayList) { + if(index < ((ArrayList)value).size()) { + return ((ArrayList)value).get(index); + } + else { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" found in capability \"%s\" referenced from node template \"%s\" must have an element with index %d", + args.get(2),args.get(1),((NodeTemplate)context).getName(),index)); + + } + } + else { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" found in capability \"%s\" referenced from node template \"%s\" must be a list", + args.get(2),args.get(1),((NodeTemplate)context).getName())); + } + return null; + } + + @SuppressWarnings("unchecked") + private Object _getAttributeValue(Object value,String attribute) { + if(value instanceof LinkedHashMap) { + Object ov = ((LinkedHashMap<String,Object>)value).get(attribute); + if(ov != null) { + return ov; + } + else { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" found in capability \"%s\" referenced from node template \"%s\" must have an attribute named \"%s\"", + args.get(2),args.get(1),((NodeTemplate)context).getName(),attribute)); + } + } + else { + ExceptionCollector.appendException(String.format( + "KeyError: Property \"%s\" found in capability \"%s\" referenced from node template \"%s\" must be a dict", + args.get(2),args.get(1),((NodeTemplate)context).getName())); + } + return null; + } + + // Add this functions similar to get_attribute case + private NodeTemplate _findHostContainingProperty(String nodeTemplateName) { + if(nodeTemplateName == null) { + nodeTemplateName = SELF; + } + NodeTemplate nodeTemplate = _findNodeTemplate(nodeTemplateName); + LinkedHashMap<String,Object> hostedOnRel = (LinkedHashMap<String,Object>) + EntityType.TOSCA_DEF.get(HOSTED_ON); + for(Object r: nodeTemplate.getRequirements()) { + if(r instanceof LinkedHashMap) { + LinkedHashMap<String,Object> rlist = (LinkedHashMap<String,Object>)r; + for(String requirement: rlist.keySet()) { + String targetName = (String)rlist.get(requirement); + NodeTemplate targetNode = _findNodeTemplate(targetName); + NodeType targetType = (NodeType)targetNode.getTypeDefinition(); + for(CapabilityTypeDef capDef: targetType.getCapabilitiesObjects()) { + if(capDef.inheritsFrom((ArrayList<String>)hostedOnRel.get("valid_target_types"))) { + if(_propertyExistsInType(targetType)) { + return targetNode; + } + // If requirement was not found, look in node + // template's capabilities + if(args.size() > 2 && + _getCapabilityProperty(targetNode,(String)args.get(1),(String)args.get(2),false) != null) { + return targetNode; + } + + return _findHostContainingProperty(targetName); + } + } + } + } + } + return null; + } + + private boolean _propertyExistsInType(StatefulEntityType typeDefinition) { + LinkedHashMap<String,PropertyDef> propsDef = typeDefinition.getPropertiesDef(); + return propsDef.keySet().contains((String)args.get(1)); + } + + @Override + public Object result() { + Object propertyValue; + if(args.size() >= 3) { + // First check if there is property with this name + NodeTemplate nodeTpl = _findNodeTemplate((String)args.get(0)); + LinkedHashMap<String,Property> props; + if(nodeTpl != null) { + props = nodeTpl.getProperties(); + } + else { + props = new LinkedHashMap<>(); + } + int index = 2; + if(props.get(args.get(1)) != null) { + propertyValue = ((Property)props.get(args.get(1))).getValue(); + } + else { + index = 3; + // then check the req or caps + propertyValue = _findReqOrCapProperty((String)args.get(1),(String)args.get(2)); + } + + if(args.size() > index) { + for(Object elem: args.subList(index,args.size()-1)) { + if(propertyValue instanceof ArrayList) { + int intElem = (int)elem; + propertyValue = _getIndexValue(propertyValue,intElem); + } + else { + propertyValue = _getAttributeValue(propertyValue,(String)elem); + } + } + } + } + else { + propertyValue = _findProperty((String)args.get(1)).getValue(); + } + if(propertyValue instanceof Function) { + return ((Function)propertyValue).result(); + } + return Function.getFunction(toscaTpl,context,propertyValue); + } + + public String getNodeTemplateName() { + return (String)args.get(0); + } + + public String getPropertyName() { + if(args.size() > 2) { + return (String)args.get(2); + } + return (String)args.get(1); + } + + public String getReqorCap() { + if(args.size() > 2) { + return (String)args.get(1); + } + return null; + } + +} + +/*python + +class GetProperty(Function): +"""Get a property value of an entity defined in the same service template. + +Arguments: + +* Node template name | SELF | HOST | SOURCE | TARGET. +* Requirement or capability name (optional). +* Property name. + +If requirement or capability name is specified, the behavior is as follows: +The req or cap name is first looked up in the specified node template's +requirements. +If found, it would search for a matching capability +of an other node template and get its property as specified in function +arguments. +Otherwise, the req or cap name would be looked up in the specified +node template's capabilities and if found, it would return the property of +the capability as specified in function arguments. + +Examples: + +* { get_property: [ mysql_server, port ] } +* { get_property: [ SELF, db_port ] } +* { get_property: [ SELF, database_endpoint, port ] } +* { get_property: [ SELF, database_endpoint, port, 1 ] } +""" + +def validate(self): + if len(self.args) < 2: + ExceptionCollector.appendException( + ValueError(_( + 'Expected arguments: "node-template-name", "req-or-cap" ' + '(optional), "property name".'))) + return + if len(self.args) == 2: + found_prop = self._find_property(self.args[1]) + if not found_prop: + return + prop = found_prop.value + if not isinstance(prop, Function): + get_function(self.tosca_tpl, self.context, prop) + elif len(self.args) >= 3: + # do not use _find_property to avoid raise KeyError + # if the prop is not found + # First check if there is property with this name + node_tpl = self._find_node_template(self.args[0]) + props = node_tpl.get_properties() if node_tpl else [] + index = 2 + found = [props[self.args[1]]] if self.args[1] in props else [] + if found: + property_value = found[0].value + else: + index = 3 + # then check the req or caps + property_value = self._find_req_or_cap_property(self.args[1], + self.args[2]) + if len(self.args) > index: + for elem in self.args[index:]: + if isinstance(property_value, list): + int_elem = int(elem) + property_value = self._get_index_value(property_value, + int_elem) + else: + property_value = self._get_attribute_value( + property_value, + elem) + +def _find_req_or_cap_property(self, req_or_cap, property_name): + node_tpl = self._find_node_template(self.args[0]) + # Find property in node template's requirements + for r in node_tpl.requirements: + for req, node_name in r.items(): + if req == req_or_cap: + node_template = self._find_node_template(node_name) + return self._get_capability_property( + node_template, + req, + property_name) + # If requirement was not found, look in node template's capabilities + return self._get_capability_property(node_tpl, + req_or_cap, + property_name) + +def _get_capability_property(self, + node_template, + capability_name, + property_name): + """Gets a node template capability property.""" + caps = node_template.get_capabilities() + if caps and capability_name in caps.keys(): + cap = caps[capability_name] + property = None + props = cap.get_properties() + if props and property_name in props.keys(): + property = props[property_name].value + if not property: + ExceptionCollector.appendException( + KeyError(_('Property "%(prop)s" was not found in ' + 'capability "%(cap)s" of node template ' + '"%(ntpl1)s" referenced from node template ' + '"%(ntpl2)s".') % {'prop': property_name, + 'cap': capability_name, + 'ntpl1': node_template.name, + 'ntpl2': self.context.name})) + return property + msg = _('Requirement/Capability "{0}" referenced from node template ' + '"{1}" was not found in node template "{2}".').format( + capability_name, + self.context.name, + node_template.name) + ExceptionCollector.appendException(KeyError(msg)) + +def _find_property(self, property_name): + node_tpl = self._find_node_template(self.args[0]) + if not node_tpl: + return + props = node_tpl.get_properties() + found = [props[property_name]] if property_name in props else [] + if len(found) == 0: + ExceptionCollector.appendException( + KeyError(_('Property "%(prop)s" was not found in node ' + 'template "%(ntpl)s".') % + {'prop': property_name, + 'ntpl': node_tpl.name})) + return None + return found[0] + +def _find_node_template(self, node_template_name): + if node_template_name == SELF: + return self.context + # enable the HOST value in the function + if node_template_name == HOST: + return self._find_host_containing_property() + if node_template_name == TARGET: + if not isinstance(self.context.type_definition, RelationshipType): + ExceptionCollector.appendException( + KeyError(_('"TARGET" keyword can only be used in context' + ' to "Relationships" target node'))) + return + return self.context.target + if node_template_name == SOURCE: + if not isinstance(self.context.type_definition, RelationshipType): + ExceptionCollector.appendException( + KeyError(_('"SOURCE" keyword can only be used in context' + ' to "Relationships" source node'))) + return + return self.context.source + if not hasattr(self.tosca_tpl, 'nodetemplates'): + return + for node_template in self.tosca_tpl.nodetemplates: + if node_template.name == node_template_name: + return node_template + ExceptionCollector.appendException( + KeyError(_( + 'Node template "{0}" was not found.' + ).format(node_template_name))) + +def _get_index_value(self, value, index): + if isinstance(value, list): + if index < len(value): + return value[index] + else: + ExceptionCollector.appendException( + KeyError(_( + "Property '{0}' found in capability '{1}'" + " referenced from node template {2}" + " must have an element with index {3}."). + format(self.args[2], + self.args[1], + self.context.name, + index))) + else: + ExceptionCollector.appendException( + KeyError(_( + "Property '{0}' found in capability '{1}'" + " referenced from node template {2}" + " must be a list.").format(self.args[2], + self.args[1], + self.context.name))) + +def _get_attribute_value(self, value, attibute): + if isinstance(value, dict): + if attibute in value: + return value[attibute] + else: + ExceptionCollector.appendException( + KeyError(_( + "Property '{0}' found in capability '{1}'" + " referenced from node template {2}" + " must have an attribute named {3}."). + format(self.args[2], + self.args[1], + self.context.name, + attibute))) + else: + ExceptionCollector.appendException( + KeyError(_( + "Property '{0}' found in capability '{1}'" + " referenced from node template {2}" + " must be a dict.").format(self.args[2], + self.args[1], + self.context.name))) + +# Add this functions similar to get_attribute case +def _find_host_containing_property(self, node_template_name=SELF): + node_template = self._find_node_template(node_template_name) + hosted_on_rel = EntityType.TOSCA_DEF[HOSTED_ON] + for r in node_template.requirements: + for requirement, target_name in r.items(): + target_node = self._find_node_template(target_name) + target_type = target_node.type_definition + for capability in target_type.get_capabilities_objects(): + if capability.type in hosted_on_rel['valid_target_types']: + if self._property_exists_in_type(target_type): + return target_node + return self._find_host_containing_property( + target_name) + return None + +def _property_exists_in_type(self, type_definition): + props_def = type_definition.get_properties_def() + found = [props_def[self.args[1]]] \ + if self.args[1] in props_def else [] + return len(found) == 1 + +def result(self): + if len(self.args) >= 3: + # First check if there is property with this name + node_tpl = self._find_node_template(self.args[0]) + props = node_tpl.get_properties() if node_tpl else [] + index = 2 + found = [props[self.args[1]]] if self.args[1] in props else [] + if found: + property_value = found[0].value + else: + index = 3 + # then check the req or caps + property_value = self._find_req_or_cap_property(self.args[1], + self.args[2]) + if len(self.args) > index: + for elem in self.args[index:]: + if isinstance(property_value, list): + int_elem = int(elem) + property_value = self._get_index_value(property_value, + int_elem) + else: + property_value = self._get_attribute_value( + property_value, + elem) + else: + property_value = self._find_property(self.args[1]).value + if isinstance(property_value, Function): + return property_value.result() + return get_function(self.tosca_tpl, + self.context, + property_value) + +@property +def node_template_name(self): + return self.args[0] + +@property +def property_name(self): + if len(self.args) > 2: + return self.args[2] + return self.args[1] + +@property +def req_or_cap(self): + if len(self.args) > 2: + return self.args[1] + return None +*/ diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Token.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Token.java new file mode 100644 index 0000000..e282d8a --- /dev/null +++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/api/functions/Token.java @@ -0,0 +1,111 @@ +package org.openecomp.sdc.toscaparser.api.functions; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import org.openecomp.sdc.toscaparser.api.NodeTemplate; +import org.openecomp.sdc.toscaparser.api.TopologyTemplate; +import org.openecomp.sdc.toscaparser.api.common.ExceptionCollector; + +public class Token extends Function { + // Validate the function and provide an instance of the function + + //The token function is used within a TOSCA service template on a string to + //parse out (tokenize) substrings separated by one or more token characters + //within a larger string. + + //Arguments: + + //* The composite string that contains one or more substrings separated by + // token characters. + //* The string that contains one or more token characters that separate + // substrings within the composite string. + //* The integer indicates the index of the substring to return from the + // composite string. Note that the first substring is denoted by using + // the '0' (zero) integer value. + + //Example: + + // [ get_attribute: [ my_server, data_endpoint, ip_address ], ':', 1 ] + + + public Token(TopologyTemplate ttpl,Object context,String name,ArrayList<Object> args) { + super(ttpl,context,name,args); + } + + @Override + public Object result() { + return this; + } + + @Override + void validate() { + if(args.size() < 3) { + ExceptionCollector.appendException( + "ValueError: Invalid arguments for function \"token\". " + + "Expected at least three arguments"); + } + else { + if(!(args.get(1) instanceof String) || + ((String)args.get(1)).length() != 1) { + ExceptionCollector.appendException( + "ValueError: Invalid arguments for function \"token\". " + + "Expected single char value as second argument"); + } + if(!(args.get(2) instanceof Integer)) { + ExceptionCollector.appendException( + "ValueError: Invalid arguments for function \"token\"" + + "Expected integer value as third argument"); + } + } + } + +} + +/*python + +class Token(Function): +"""Validate the function and provide an instance of the function + +The token function is used within a TOSCA service template on a string to +parse out (tokenize) substrings separated by one or more token characters +within a larger string. + + +Arguments: + +* The composite string that contains one or more substrings separated by + token characters. +* The string that contains one or more token characters that separate + substrings within the composite string. +* The integer indicates the index of the substring to return from the + composite string. Note that the first substring is denoted by using + the '0' (zero) integer value. + +Example: + + [ get_attribute: [ my_server, data_endpoint, ip_address ], ':', 1 ] + +""" + +def validate(self): + if len(self.args) < 3: + ExceptionCollector.appendException( + ValueError(_('Invalid arguments for function "{0}". Expected ' + 'at least three arguments.').format(TOKEN))) + else: + if not isinstance(self.args[1], str) or len(self.args[1]) != 1: + ExceptionCollector.appendException( + ValueError(_('Invalid arguments for function "{0}". ' + 'Expected single char value as second ' + 'argument.').format(TOKEN))) + + if not isinstance(self.args[2], int): + ExceptionCollector.appendException( + ValueError(_('Invalid arguments for function "{0}". ' + 'Expected integer value as third ' + 'argument.').format(TOKEN))) + +def result(self): + return self +*/
\ No newline at end of file |