summaryrefslogtreecommitdiffstats
path: root/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions
diff options
context:
space:
mode:
Diffstat (limited to 'jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions')
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Concat.java76
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Function.java191
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetAttribute.java538
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetInput.java108
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetOperationOutput.java227
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetProperty.java639
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Token.java111
7 files changed, 1890 insertions, 0 deletions
diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Concat.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Concat.java
new file mode 100644
index 0000000..af69f86
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Concat.java
@@ -0,0 +1,76 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+
+import org.openecomp.sdc.toscaparser.TopologyTemplate;
+import org.openecomp.sdc.toscaparser.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/functions/Function.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Function.java
new file mode 100644
index 0000000..3a95090
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Function.java
@@ -0,0 +1,191 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+
+import org.openecomp.sdc.toscaparser.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/functions/GetAttribute.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetAttribute.java
new file mode 100644
index 0000000..3a6db8a
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetAttribute.java
@@ -0,0 +1,538 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+import org.openecomp.sdc.toscaparser.Capability;
+import org.openecomp.sdc.toscaparser.EntityTemplate;
+import org.openecomp.sdc.toscaparser.NodeTemplate;
+import org.openecomp.sdc.toscaparser.RelationshipTemplate;
+import org.openecomp.sdc.toscaparser.TopologyTemplate;
+import org.openecomp.sdc.toscaparser.common.ExceptionCollector;
+import org.openecomp.sdc.toscaparser.elements.AttributeDef;
+import org.openecomp.sdc.toscaparser.elements.CapabilityTypeDef;
+import org.openecomp.sdc.toscaparser.elements.DataType;
+import org.openecomp.sdc.toscaparser.elements.EntityType;
+import org.openecomp.sdc.toscaparser.elements.NodeType;
+import org.openecomp.sdc.toscaparser.elements.PropertyDef;
+import org.openecomp.sdc.toscaparser.elements.RelationshipType;
+import org.openecomp.sdc.toscaparser.elements.StatefulEntityType;
+import org.openecomp.sdc.toscaparser.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/functions/GetInput.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetInput.java
new file mode 100644
index 0000000..91eea5d
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetInput.java
@@ -0,0 +1,108 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+import org.openecomp.sdc.toscaparser.DataEntity;
+import org.openecomp.sdc.toscaparser.TopologyTemplate;
+import org.openecomp.sdc.toscaparser.common.ExceptionCollector;
+import org.openecomp.sdc.toscaparser.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/functions/GetOperationOutput.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetOperationOutput.java
new file mode 100644
index 0000000..2d736b2
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetOperationOutput.java
@@ -0,0 +1,227 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+
+import org.openecomp.sdc.toscaparser.EntityTemplate;
+import org.openecomp.sdc.toscaparser.NodeTemplate;
+import org.openecomp.sdc.toscaparser.RelationshipTemplate;
+import org.openecomp.sdc.toscaparser.TopologyTemplate;
+import org.openecomp.sdc.toscaparser.common.ExceptionCollector;
+import org.openecomp.sdc.toscaparser.elements.InterfacesDef;
+import org.openecomp.sdc.toscaparser.elements.RelationshipType;
+import org.openecomp.sdc.toscaparser.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/functions/GetProperty.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetProperty.java
new file mode 100644
index 0000000..87600d8
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetProperty.java
@@ -0,0 +1,639 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+import org.openecomp.sdc.toscaparser.Capability;
+import org.openecomp.sdc.toscaparser.NodeTemplate;
+import org.openecomp.sdc.toscaparser.Property;
+import org.openecomp.sdc.toscaparser.TopologyTemplate;
+import org.openecomp.sdc.toscaparser.RelationshipTemplate;
+import org.openecomp.sdc.toscaparser.common.ExceptionCollector;
+import org.openecomp.sdc.toscaparser.elements.CapabilityTypeDef;
+import org.openecomp.sdc.toscaparser.elements.EntityType;
+import org.openecomp.sdc.toscaparser.elements.NodeType;
+import org.openecomp.sdc.toscaparser.elements.PropertyDef;
+import org.openecomp.sdc.toscaparser.elements.RelationshipType;
+import org.openecomp.sdc.toscaparser.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/functions/Token.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Token.java
new file mode 100644
index 0000000..2bfadd0
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/Token.java
@@ -0,0 +1,111 @@
+package org.openecomp.sdc.toscaparser.functions;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+import org.openecomp.sdc.toscaparser.NodeTemplate;
+import org.openecomp.sdc.toscaparser.TopologyTemplate;
+import org.openecomp.sdc.toscaparser.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