Update tosca lib to version 0.5
[parser.git] / tosca2heat / tosca-parser / toscaparser / entity_template.py
@@ -15,10 +15,13 @@ from toscaparser.common.exception import ExceptionCollector
 from toscaparser.common.exception import MissingRequiredFieldError
 from toscaparser.common.exception import UnknownFieldError
 from toscaparser.common.exception import ValidationError
+from toscaparser.elements.grouptype import GroupType
 from toscaparser.elements.interfaces import InterfacesDef
 from toscaparser.elements.nodetype import NodeType
+from toscaparser.elements.policytype import PolicyType
 from toscaparser.elements.relationshiptype import RelationshipType
 from toscaparser.properties import Property
+from toscaparser.utils.gettextutils import _
 
 
 class EntityTemplate(object):
@@ -30,9 +33,9 @@ class EntityTemplate(object):
                ('derived_from', 'properties', 'requirements', 'interfaces',
                 'capabilities', 'type', 'description', 'directives',
                 'attributes', 'artifacts', 'node_filter', 'copy')
-    REQUIREMENTS_SECTION = (NODE, CAPABILITY, RELATIONSHIP, OCCURRENCES) = \
+    REQUIREMENTS_SECTION = (NODE, CAPABILITY, RELATIONSHIP, OCCURRENCES, NODE_FILTER) = \
                            ('node', 'capability', 'relationship',
-                            'occurrences')
+                            'occurrences', 'node_filter')
     # Special key names
     SPECIAL_SECTIONS = (METADATA) = ('metadata')
 
@@ -56,6 +59,19 @@ class EntityTemplate(object):
                 type = self.entity_tpl['type']
             self.type_definition = RelationshipType(type,
                                                     None, custom_def)
+        if entity_name == 'policy_type':
+            type = self.entity_tpl.get('type')
+            if not type:
+                msg = (_('Policy definition of "%(pname)s" must have'
+                       ' a "type" ''attribute.') % dict(pname=name))
+                ExceptionCollector.appendException(
+                    ValidationError(msg))
+
+            self.type_definition = PolicyType(type, custom_def)
+        if entity_name == 'group_type':
+            type = self.entity_tpl.get('type')
+            self.type_definition = GroupType(type, custom_def) \
+                if type is not None else None
         self._properties = None
         self._interfaces = None
         self._requirements = None
@@ -126,13 +142,24 @@ class EntityTemplate(object):
     def _create_capabilities(self):
         capability = []
         caps = self.type_definition.get_value(self.CAPABILITIES,
-                                              self.entity_tpl)
+                                              self.entity_tpl, True)
         if caps:
             for name, props in caps.items():
                 capabilities = self.type_definition.get_capabilities()
                 if name in capabilities.keys():
                     c = capabilities[name]
-                    cap = Capability(name, props['properties'], c)
+                    properties = {}
+                    # first use the definition default value
+                    if c.properties:
+                        for property_name in c.properties.keys():
+                            prop_def = c.properties[property_name]
+                            if 'default' in prop_def:
+                                properties[property_name] = prop_def['default']
+                    # then update (if available) with the node properties
+                    if 'properties' in props and props['properties']:
+                        properties.update(props['properties'])
+
+                    cap = Capability(name, properties, c)
                     capability.append(cap)
         return capability
 
@@ -182,27 +209,31 @@ class EntityTemplate(object):
         required_props = []
         for p in entitytype.get_properties_def_objects():
             allowed_props.append(p.name)
-            if p.required:
+            # If property is 'required' and has no 'default' value then record
+            if p.required and p.default is None:
                 required_props.append(p.name)
+        # validate all required properties have values
         if properties:
+            req_props_no_value_or_default = []
             self._common_validate_field(properties, allowed_props,
                                         'properties')
             # make sure it's not missing any property required by a tosca type
-            missingprop = []
             for r in required_props:
                 if r not in properties.keys():
-                    missingprop.append(r)
-            if missingprop:
+                    req_props_no_value_or_default.append(r)
+            # Required properties found without value or a default value
+            if req_props_no_value_or_default:
                 ExceptionCollector.appendException(
                     MissingRequiredFieldError(
                         what='"properties" of template "%s"' % self.name,
-                        required=missingprop))
+                        required=req_props_no_value_or_default))
         else:
+            # Required properties in schema, but not in template
             if required_props:
                 ExceptionCollector.appendException(
                     MissingRequiredFieldError(
                         what='"properties" of template "%s"' % self.name,
-                        required=missingprop))
+                        required=required_props))
 
     def _validate_field(self, template):
         if not isinstance(template, dict):
@@ -252,16 +283,19 @@ class EntityTemplate(object):
         type_interfaces = None
         if isinstance(self.type_definition, RelationshipType):
             if isinstance(self.entity_tpl, dict):
-                for rel_def, value in self.entity_tpl.items():
-                    if rel_def != 'type':
-                        rel_def = self.entity_tpl.get(rel_def)
-                        rel = None
-                        if isinstance(rel_def, dict):
-                            rel = rel_def.get('relationship')
-                        if rel:
-                            if self.INTERFACES in rel:
-                                type_interfaces = rel[self.INTERFACES]
-                                break
+                if self.INTERFACES in self.entity_tpl:
+                    type_interfaces = self.entity_tpl[self.INTERFACES]
+                else:
+                    for rel_def, value in self.entity_tpl.items():
+                        if rel_def != 'type':
+                            rel_def = self.entity_tpl.get(rel_def)
+                            rel = None
+                            if isinstance(rel_def, dict):
+                                rel = rel_def.get('relationship')
+                            if rel:
+                                if self.INTERFACES in rel:
+                                    type_interfaces = rel[self.INTERFACES]
+                                    break
         else:
             type_interfaces = self.type_definition.get_value(self.INTERFACES,
                                                              self.entity_tpl)