aboutsummaryrefslogtreecommitdiffstats
path: root/jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetAttribute.java
diff options
context:
space:
mode:
Diffstat (limited to 'jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetAttribute.java')
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/functions/GetAttribute.java538
1 files changed, 538 insertions, 0 deletions
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