Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-180-convert-parameter-to-one-to-many 515c5886c -> 42f924f58


Clean up the code


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/42f924f5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/42f924f5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/42f924f5

Branch: refs/heads/ARIA-180-convert-parameter-to-one-to-many
Commit: 42f924f586cffca7463499c92f36500904de9a0c
Parents: 515c588
Author: Avia Efrat <a...@gigaspaces.com>
Authored: Thu May 25 19:40:35 2017 +0300
Committer: Avia Efrat <a...@gigaspaces.com>
Committed: Thu May 25 19:40:35 2017 +0300

----------------------------------------------------------------------
 aria/modeling/models.py                         |    5 -
 aria/modeling/relationship.py                   |    2 -
 aria/modeling/service_common.py                 | 1209 +++---------------
 .../simple_v1_0/modeling/__init__.py            |    2 +-
 tests/mock/models.py                            |   13 +-
 tests/storage/test_model_storage.py             |    6 +-
 6 files changed, 224 insertions(+), 1013 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/42f924f5/aria/modeling/models.py
----------------------------------------------------------------------
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index 9b7e776..bfa0ece 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -72,7 +72,6 @@ __all__ = (
     'ServiceModification',
 
     # Common service models
-    'Parameter',
     'Input',
     'Output',
     'Property',
@@ -210,9 +209,6 @@ class ServiceModification(aria_declarative_base, 
service_changes.ServiceModifica
 
 # region common service models
 
-class Parameter(aria_declarative_base, service_common.ParameterBase):
-    pass
-
 
 class Input(aria_declarative_base, service_common.InputBase):
     pass
@@ -296,7 +292,6 @@ models_to_register = [
     ServiceModification,
 
     # Common service models
-    Parameter,
     Input,
     Output,
     Property,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/42f924f5/aria/modeling/relationship.py
----------------------------------------------------------------------
diff --git a/aria/modeling/relationship.py b/aria/modeling/relationship.py
index 8644d42..40be5b2 100644
--- a/aria/modeling/relationship.py
+++ b/aria/modeling/relationship.py
@@ -289,8 +289,6 @@ def many_to_many(model_class,
         secondary_table_name = '{0}_{1}'.format(prefix, secondary_table_name)
         if other_property is None:
             other_property = '{0}_{1}'.format(prefix, 
formatting.pluralize(this_table))
-    elif other_property is None:
-        other_property = '{0}_{1}'.format(other_table, 
formatting.pluralize(this_table))
 
     secondary_table = _get_secondary_table(
         model_class.metadata,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/42f924f5/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 0542e00..227d4ea 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -32,7 +32,7 @@ from . import (
 )
 
 
-class ParameterBase(TemplateModelMixin, caching.HasCachedMethods):
+class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
     """
     Represents a typed value. The value can contain nested intrinsic functions.
 
@@ -81,9 +81,10 @@ class ParameterBase(TemplateModelMixin, 
caching.HasCachedMethods):
         for the_relationship in self.__mapper__.relationships:
             v = getattr(self, the_relationship.key)
             if v:
-                return v[0] # because we are many-to-many, the back reference 
will be a list
+                return v
 
-        raise ValueError('orphaned parameter: does not have an owner: 
{0}'.format(self.name))
+        raise ValueError('orphaned {class_name}: does not have an owner: 
{name}'.format(
+            class_name=type(self).__name__, name=self.name))
 
     @property
     @caching.cachedmethod
@@ -118,7 +119,7 @@ class ParameterBase(TemplateModelMixin, 
caching.HasCachedMethods):
         elif isinstance(container, models.Capability) or isinstance(container, 
models.Artifact):
             container = container.node
         elif isinstance(container, models.CapabilityTemplate) \
-            or isinstance(container, models.ArtifactTemplate):
+                or isinstance(container, models.ArtifactTemplate):
             container = container.node_template
         elif isinstance(container, models.Task):
             container = container.actor
@@ -174,11 +175,10 @@ class ParameterBase(TemplateModelMixin, 
caching.HasCachedMethods):
             ('description', self.description)))
 
     def instantiate(self, container):
-        from . import models
-        return models.Parameter(name=self.name, # pylint: 
disable=unexpected-keyword-arg
-                                type_name=self.type_name,
-                                _value=self._value,
-                                description=self.description)
+        return self.__class__(name=self.name,  # pylint: 
disable=unexpected-keyword-arg
+                              type_name=self.type_name,
+                              _value=self._value,
+                              description=self.description)
 
     def coerce_values(self, report_issues):
         value = self._value
@@ -217,162 +217,81 @@ class ParameterBase(TemplateModelMixin, 
caching.HasCachedMethods):
         :type description: basestring
         """
 
-        from . import models
         type_name = canonical_type_name(value)
         if type_name is None:
             type_name = full_type_name(value)
-        return models.Parameter(name=name, # pylint: 
disable=unexpected-keyword-arg
-                                type_name=type_name,
-                                value=value,
-                                description=description)
-
-
-# TODO dry this code. currently it is almost a copy of ParameterBase
-class OutputBase(TemplateModelMixin, caching.HasCachedMethods):
-    """
-    Represents a typed value. The value can contain nested intrinsic functions.
+        return cls(name=name,  # pylint: disable=unexpected-keyword-arg
+                   type_name=type_name,
+                   value=value,
+                   description=description)
 
-    This model can be used as the ``container_holder`` argument for 
:func:`functions.evaluate`.
 
-    :ivar name: Name
-    :vartype name: basestring
-    :ivar type_name: Type name
-    :vartype type_name: basestring
-    :ivar value: Value
-    :ivar description: Description
-    :vartype description: basestring
-    """
+class OutputBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods):
 
     __tablename__ = 'output'
 
-    name = Column(Text)
-    type_name = Column(Text)
-    description = Column(Text)
-    _value = Column(PickleType)
-
-    @property
-    def value(self):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self)
-            if evaluation is not None:
-                value = evaluation.value
-        return value
+    # region foreign keys
 
-    @value.setter
-    def value(self, value):
-        self._value = value
+    @declared_attr
+    def service_template_fk(cls):
+        return relationship.foreign_key('service_template', nullable=True)
 
-    @property
-    @caching.cachedmethod
-    def owner(self):
-        """
-        The sole owner of this parameter, which is another model that relates 
to it.
+    @declared_attr
+    def service_fk(cls):
+        return relationship.foreign_key('service', nullable=True)
 
-        *All* parameters should have an owner model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
+    # endregion
 
-        # Find first non-null relationship
-        for the_relationship in self.__mapper__.relationships:
-            v = getattr(self, the_relationship.key)
-            if v:
-                return v[0] # because we are many-to-many, the back reference 
will be a list
+    # region many_to_one relationships
 
-        raise ValueError('orphaned output: does not have an owner: 
{0}'.format(self.name))
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
 
+    @declared_attr
+    def service(cls):
+        return relationship.many_to_one(cls, 'service')
 
-    @property
-    @caching.cachedmethod
-    def container(self): # pylint: 
disable=too-many-return-statements,too-many-branches
-        """
-        The logical container for this parameter, which would be another 
model: service, node,
-        group, or policy (or their templates).
+    # endregion
 
-        The logical container is equivalent to the ``SELF`` keyword used by 
intrinsic functions in
-        TOSCA.
 
-        *All* parameters should have a container model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
+class InputBase(ParameterMixin, TemplateModelMixin, caching.HasCachedMethods):
 
-        from . import models
+    __tablename__ = 'input'
 
-        container = self.owner
+    # region foreign keys
 
-        # Extract interface from operation
-        if isinstance(container, models.Operation):
-            container = container.interface
-        elif isinstance(container, models.OperationTemplate):
-            container = container.interface_template
+    @declared_attr
+    def service_template_fk(cls):
+        return relationship.foreign_key('service_template', nullable=True)
 
-        # Extract from other models
-        if isinstance(container, models.Interface):
-            container = container.node or container.group or 
container.relationship
-        elif isinstance(container, models.InterfaceTemplate):
-            container = container.node_template or container.group_template \
-                or container.relationship_template
-        elif isinstance(container, models.Capability) or isinstance(container, 
models.Artifact):
-            container = container.node
-        elif isinstance(container, models.CapabilityTemplate) \
-            or isinstance(container, models.ArtifactTemplate):
-            container = container.node_template
-        elif isinstance(container, models.Task):
-            container = container.actor
+    @declared_attr
+    def service_fk(cls):
+        return relationship.foreign_key('service', nullable=True)
 
-        # Extract node from relationship
-        if isinstance(container, models.Relationship):
-            container = container.source_node
-        elif isinstance(container, models.RelationshipTemplate):
-            container = container.requirement_template.node_template
+    @declared_attr
+    def interface_fk(cls):
+        return relationship.foreign_key('interface', nullable=True)
 
-        if container is not None:
-            return container
+    @declared_attr
+    def operation_fk(cls):
+        return relationship.foreign_key('operation', nullable=True)
 
-        raise ValueError('orphaned output: does not have a container: 
{0}'.format(self.name))
-
-    # @property
-    # @caching.cachedmethod
-    # def service(self):
-    #     """
-    #     The :class:`Service` containing this parameter, or None if not 
contained in a service.
-    #     """
-    #
-    #     from . import models
-    #     container = self.container
-    #     if isinstance(container, models.Service):
-    #         return container
-    #     elif hasattr(container, 'service'):
-    #         return container.service
-    #     return None
-
-    # @property
-    # @caching.cachedmethod
-    # def service_template(self):
-    #     """
-    #     The :class:`ServiceTemplate` containing this parameter, or None if 
not contained in a
-    #     service template.
-    #     """
-    #
-    #     from . import models
-    #     container = self.container
-    #     if isinstance(container, models.ServiceTemplate):
-    #         return container
-    #     elif hasattr(container, 'service_template'):
-    #         return container.service_template
-    #     return None
+    @declared_attr
+    def interface_template_fk(cls):
+        return relationship.foreign_key('interface_template', nullable=True)
 
-    # region foreign keys
+    @declared_attr
+    def operation_template_fk(cls):
+        return relationship.foreign_key('operation_template', nullable=True)
 
     @declared_attr
-    def service_template_fk(cls):
-        """For Output many-to-one to ServiceTemplate"""
-        return relationship.foreign_key('service_template', nullable=True)
+    def execution_fk(cls):
+        return relationship.foreign_key('execution', nullable=True)
 
     @declared_attr
-    def service_fk(cls):
-        """For Output many-to-one to Service"""
-        return relationship.foreign_key('service', nullable=True)
+    def task_fk(cls):
+        return relationship.foreign_key('task', nullable=True)
 
     # endregion
 
@@ -386,550 +305,85 @@ class OutputBase(TemplateModelMixin, 
caching.HasCachedMethods):
     def service(cls):
         return relationship.many_to_one(cls, 'service')
 
-    # endregion
+    @declared_attr
+    def interface(cls):
+        return relationship.many_to_one(cls, 'interface')
 
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('type_name', self.type_name),
-            ('value', self.value),
-            ('description', self.description)))
+    @declared_attr
+    def operation(cls):
+        return relationship.many_to_one(cls, 'operation')
 
-    def instantiate(self, container):
-        from . import models
-        return models.Output(name=self.name,  # pylint: 
disable=unexpected-keyword-arg
-                             type_name=self.type_name,
-                             _value=self._value,
-                             description=self.description)
+    @declared_attr
+    def interface_template(cls):
+        return relationship.many_to_one(cls, 'interface_template')
 
-    def coerce_values(self, report_issues):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self, report_issues)
-            if (evaluation is not None) and evaluation.final:
-                # A final evaluation can safely replace the existing value
-                self._value = evaluation.value
+    @declared_attr
+    def operation_template(cls):
+        return relationship.many_to_one(cls, 'operation_template')
 
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type_name is not None:
-            console.puts('{0}: {1} ({2})'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value)),
-                context.style.type(self.type_name)))
-        else:
-            console.puts('{0}: {1}'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value))))
-        if self.description:
-            console.puts(context.style.meta(self.description))
+    @declared_attr
+    def execution(cls):
+        return relationship.many_to_one(cls, 'execution')
 
-    def unwrap(self):
-        return self.name, self.value
+    @declared_attr
+    def task(cls):
+        return relationship.many_to_one(cls, 'task')
 
-    @classmethod
-    def wrap(cls, name, value, description=None):
-        """
-        Wraps an arbitrary value as a parameter. The type will be guessed via 
introspection.
+    # endregion
 
-        :param name: Output name
-        :type name: basestring
-        :param value: Output value
-        :param description: Description (optional)
-        :type description: basestring
-        """
 
-        from . import models
-        type_name = canonical_type_name(value)
-        if type_name is None:
-            type_name = full_type_name(value)
-        return models.Output(name=name, # pylint: 
disable=unexpected-keyword-arg
-                             type_name=type_name,
-                             value=value,
-                             description=description)
+class PropertyBase(ParameterMixin, TemplateModelMixin, 
caching.HasCachedMethods):
 
+    __tablename__ = 'property'
 
-class TypeBase(InstanceModelMixin):
-    """
-    Represents a type and its children.
-    """
+    # region foreign keys
 
-    __tablename__ = 'type'
+    @declared_attr
+    def node_template_fk(cls):
+        return relationship.foreign_key('node_template', nullable=True)
 
-    __private_fields__ = ['parent_type_fk']
+    @declared_attr
+    def group_template_fk(cls):
+        return relationship.foreign_key('group_template', nullable=True)
 
-    variant = Column(Text, nullable=False)
-    description = Column(Text)
-    _role = Column(Text, name='role')
+    @declared_attr
+    def policy_template_fk(cls):
+        return relationship.foreign_key('policy_template', nullable=True)
 
     @declared_attr
-    def parent(cls):
-        return relationship.one_to_one_self(cls, 'parent_type_fk')
+    def relationship_template_fk(cls):
+        return relationship.foreign_key('relationship_template', nullable=True)
 
     @declared_attr
-    def children(cls):
-        return relationship.one_to_many_self(cls, 'parent_type_fk')
+    def capability_template_fk(cls):
+        return relationship.foreign_key('capability_template', nullable=True)
 
-    # region foreign keys
+    @declared_attr
+    def artifact_template_fk(cls):
+        return relationship.foreign_key('artifact_template', nullable=True)
 
     @declared_attr
-    def parent_type_fk(cls):
-        """For Type one-to-many to Type"""
-        return relationship.foreign_key('type', nullable=True)
+    def node_fk(cls):
+        return relationship.foreign_key('node', nullable=True)
 
-    # endregion
+    @declared_attr
+    def group_fk(cls):
+        return relationship.foreign_key('group', nullable=True)
 
-    @property
-    def role(self):
-        def get_role(the_type):
-            if the_type is None:
-                return None
-            elif the_type._role is None:
-                return get_role(the_type.parent)
-            return the_type._role
+    @declared_attr
+    def policy_fk(cls):
+        return relationship.foreign_key('policy', nullable=True)
 
-        return get_role(self)
+    @declared_attr
+    def relationship_fk(cls):
+        return relationship.foreign_key('relationship', nullable=True)
 
-    @role.setter
-    def role(self, value):
-        self._role = value
-
-    def is_descendant(self, base_name, name):
-        base = self.get_descendant(base_name)
-        if base is not None:
-            if base.get_descendant(name) is not None:
-                return True
-        return False
-
-    def get_descendant(self, name):
-        if self.name == name:
-            return self
-        for child in self.children:
-            found = child.get_descendant(name)
-            if found is not None:
-                return found
-        return None
-
-    def iter_descendants(self):
-        for child in self.children:
-            yield child
-            for descendant in child.iter_descendants():
-                yield descendant
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('role', self.role)))
-
-    @property
-    def as_raw_all(self):
-        types = []
-        self._append_raw_children(types)
-        return types
-
-    def coerce_values(self, report_issues):
-        pass
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts(context.style.type(self.name))
-        with context.style.indent:
-            for child in self.children:
-                child.dump()
-
-    def _append_raw_children(self, types):
-        for child in self.children:
-            raw_child = formatting.as_raw(child)
-            raw_child['parent'] = self.name
-            types.append(raw_child)
-            child._append_raw_children(types)
-
-    @property
-    def hierarchy(self):
-        """
-        Return the type hierarchy.
-        :return:
-        """
-        return [self] + (self.parent.hierarchy if self.parent else [])
-
-
-# TODO dry this code. currently it is almost a copy of ParameterBase
-class InputBase(TemplateModelMixin, caching.HasCachedMethods):
-    """
-    Represents a typed value. The value can contain nested intrinsic functions.
-
-    This model can be used as the ``container_holder`` argument for 
:func:`functions.evaluate`.
-
-    :ivar name: Name
-    :vartype name: basestring
-    :ivar type_name: Type name
-    :vartype type_name: basestring
-    :ivar value: Value
-    :ivar description: Description
-    :vartype description: basestring
-    """
-
-    __tablename__ = 'input'
-
-    name = Column(Text)
-    type_name = Column(Text)
-    description = Column(Text)
-    _value = Column(PickleType)
-
-    @property
-    def value(self):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self)
-            if evaluation is not None:
-                value = evaluation.value
-        return value
-
-    @value.setter
-    def value(self, value):
-        self._value = value
-
-    # region foreign keys
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For Input many-to-one to ServiceTemplate"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    @declared_attr
-    def service_fk(cls):
-        """For Input many-to-one to Service"""
-        return relationship.foreign_key('service', nullable=True)
-
-    @declared_attr
-    def interface_fk(cls):
-        """For Input many-to-one to Interface"""
-        return relationship.foreign_key('interface', nullable=True)
-
-    @declared_attr
-    def operation_fk(cls):
-        """For Input many-to-one to Operation"""
-        return relationship.foreign_key('operation', nullable=True)
-
-    @declared_attr
-    def interface_template_fk(cls):
-        """For Input many-to-one to InterfaceTemplate"""
-        return relationship.foreign_key('interface_template', nullable=True)
-
-    @declared_attr
-    def operation_template_fk(cls):
-        """For Input many-to-one to OperationTemplate"""
-        return relationship.foreign_key('operation_template', nullable=True)
-
-    @declared_attr
-    def execution_fk(cls):
-        """For Input many-to-one to Execution"""
-        return relationship.foreign_key('execution', nullable=True)
-
-    @declared_attr
-    def task_fk(cls):
-        """For Input many-to-one to Task"""
-        return relationship.foreign_key('task', nullable=True)
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def service_template(cls):
-        return relationship.many_to_one(cls, 'service_template')
-
-    @declared_attr
-    def service(cls):
-        return relationship.many_to_one(cls, 'service')
-
-    @declared_attr
-    def interface(cls):
-        return relationship.many_to_one(cls, 'interface')
-
-    @declared_attr
-    def operation(cls):
-        return relationship.many_to_one(cls, 'operation')
-
-    @declared_attr
-    def interface_template(cls):
-        return relationship.many_to_one(cls, 'interface_template')
-
-    @declared_attr
-    def operation_template(cls):
-        return relationship.many_to_one(cls, 'operation_template')
-
-    @declared_attr
-    def execution(cls):
-        return relationship.many_to_one(cls, 'execution')
-
-    @declared_attr
-    def task(cls):
-        return relationship.many_to_one(cls, 'task')
-
-    # endregion
-
-    @property
-    @caching.cachedmethod
-    def owner(self):
-        """
-        The sole owner of this parameter, which is another model that relates 
to it.
-
-        *All* parameters should have an owner model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
-
-        # Find first non-null relationship
-        for the_relationship in self.__mapper__.relationships:
-            v = getattr(self, the_relationship.key)
-            if v:
-                return v # because we are many-to-many, the back reference 
will be a list
-
-        raise ValueError('orphaned input: does not have an owner: 
{0}'.format(self.name))
-
-
-    @property
-    @caching.cachedmethod
-    def container(self): # pylint: 
disable=too-many-return-statements,too-many-branches
-        """
-        The logical container for this parameter, which would be another 
model: service, node,
-        group, or policy (or their templates).
-
-        The logical container is equivalent to the ``SELF`` keyword used by 
intrinsic functions in
-        TOSCA.
-
-        *All* parameters should have a container model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
-
-        from . import models
-
-        container = self.owner
-
-        # Extract interface from operation
-        if isinstance(container, models.Operation):
-            container = container.interface
-        elif isinstance(container, models.OperationTemplate):
-            container = container.interface_template
-
-        # Extract from other models
-        if isinstance(container, models.Interface):
-            container = container.node or container.group or 
container.relationship
-        elif isinstance(container, models.InterfaceTemplate):
-            container = container.node_template or container.group_template \
-                        or container.relationship_template
-        elif isinstance(container, models.Capability) or isinstance(container, 
models.Artifact):
-            container = container.node
-        elif isinstance(container, models.CapabilityTemplate) \
-                or isinstance(container, models.ArtifactTemplate):
-            container = container.node_template
-        elif isinstance(container, models.Task):
-            container = container.actor
-
-        # Extract node from relationship
-        if isinstance(container, models.Relationship):
-            container = container.source_node
-        elif isinstance(container, models.RelationshipTemplate):
-            container = container.requirement_template.node_template
-
-        if container is not None:
-            return container
-
-        raise ValueError('orphaned input: does not have a container: 
{0}'.format(self.name))
-
-    # @property
-    # @caching.cachedmethod
-    # def service(self):
-    #     """
-    #     The :class:`Service` containing this parameter, or None if not 
contained in a service.
-    #     """
-    #
-    #     from . import models
-    #     container = self.container
-    #     if isinstance(container, models.Service):
-    #         return container
-    #     elif hasattr(container, 'service'):
-    #         return container.service
-    #     return None
-    #
-    # @property
-    # @caching.cachedmethod
-    # def service_template(self):
-    #     """
-    #     The :class:`ServiceTemplate` containing this parameter, or None if 
not contained in a
-    #     service template.
-    #     """
-    #
-    #     from . import models
-    #     container = self.container
-    #     if isinstance(container, models.ServiceTemplate):
-    #         return container
-    #     elif hasattr(container, 'service_template'):
-    #         return container.service_template
-    #     return None
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('type_name', self.type_name),
-            ('value', self.value),
-            ('description', self.description)))
-
-    def instantiate(self, container):
-        from . import models
-        return models.Input(name=self.name,  # pylint: 
disable=unexpected-keyword-arg
-                            type_name=self.type_name,
-                            _value=self._value,
-                            description=self.description)
-
-    def coerce_values(self, report_issues):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self, report_issues)
-            if (evaluation is not None) and evaluation.final:
-                # A final evaluation can safely replace the existing value
-                self._value = evaluation.value
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type_name is not None:
-            console.puts('{0}: {1} ({2})'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value)),
-                context.style.type(self.type_name)))
-        else:
-            console.puts('{0}: {1}'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value))))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-
-    def unwrap(self):
-        return self.name, self.value
-
-    @classmethod
-    def wrap(cls, name, value, description=None):
-        """
-        Wraps an arbitrary value as a parameter. The type will be guessed via 
introspection.
-
-        :param name: Input name
-        :type name: basestring
-        :param value: Input value
-        :param description: Description (optional)
-        :type description: basestring
-        """
-
-        from . import models
-        type_name = canonical_type_name(value)
-        if type_name is None:
-            type_name = full_type_name(value)
-        return models.Input(name=name, # pylint: disable=unexpected-keyword-arg
-                            type_name=type_name,
-                            value=value,
-                            description=description)
-
-
-# TODO dry this code. currently it is almost a copy of ParameterBase
-class PropertyBase(TemplateModelMixin, caching.HasCachedMethods):
-    """
-    Represents a typed value. The value can contain nested intrinsic functions.
-
-    This model can be used as the ``container_holder`` argument for 
:func:`functions.evaluate`.
-
-    :ivar name: Name
-    :vartype name: basestring
-    :ivar type_name: Type name
-    :vartype type_name: basestring
-    :ivar value: Value
-    :ivar description: Description
-    :vartype description: basestring
-    """
-
-    __tablename__ = 'property'
-
-    name = Column(Text)
-    type_name = Column(Text)
-    description = Column(Text)
-    _value = Column(PickleType)
-
-    @property
-    def value(self):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self)
-            if evaluation is not None:
-                value = evaluation.value
-        return value
-
-    @value.setter
-    def value(self, value):
-        self._value = value
-
-    # region foreign keys
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For Property many-to-one to NodeTemplate"""
-        return relationship.foreign_key('node_template', nullable=True)
-
-    @declared_attr
-    def group_template_fk(cls):
-        """For Property many-to-one to GroupTemplate"""
-        return relationship.foreign_key('group_template', nullable=True)
-
-    @declared_attr
-    def policy_template_fk(cls):
-        """For Property many-to-one to PolicyTemplate"""
-        return relationship.foreign_key('policy_template', nullable=True)
-
-    @declared_attr
-    def relationship_template_fk(cls):
-        """For Property many-to-one to RelationshipTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
-
-    @declared_attr
-    def capability_template_fk(cls):
-        """For Property many-to-one to CapabilityTemplate"""
-        return relationship.foreign_key('capability_template', nullable=True)
-
-    @declared_attr
-    def artifact_template_fk(cls):
-        """For Property many-to-one to ArtifactTemplate"""
-        return relationship.foreign_key('artifact_template', nullable=True)
-
-    @declared_attr
-    def node_fk(cls):
-        """For Property many-to-one to Node"""
-        return relationship.foreign_key('node', nullable=True)
-
-    @declared_attr
-    def group_fk(cls):
-        """For Property many-to-one to Group"""
-        return relationship.foreign_key('group', nullable=True)
-
-    @declared_attr
-    def policy_fk(cls):
-        """For Property many-to-one to Policy"""
-        return relationship.foreign_key('policy', nullable=True)
-
-    @declared_attr
-    def relationship_fk(cls):
-        """For Property many-to-one to Relationship"""
-        return relationship.foreign_key('relationship', nullable=True)
-
-    @declared_attr
-    def capability_fk(cls):
-        """For Property many-to-one to Capability"""
-        return relationship.foreign_key('capability', nullable=True)
+    @declared_attr
+    def capability_fk(cls):
+        return relationship.foreign_key('capability', nullable=True)
 
     @declared_attr
     def artifact_fk(cls):
-        """For Property many-to-one to Artifact"""
         return relationship.foreign_key('artifact', nullable=True)
     # endregion
 
@@ -949,237 +403,46 @@ class PropertyBase(TemplateModelMixin, 
caching.HasCachedMethods):
 
     @declared_attr
     def relationship_template(cls):
-        return relationship.many_to_one(cls, 'relationship_template')
-
-    @declared_attr
-    def capability_template(cls):
-        return relationship.many_to_one(cls, 'capability_template')
-
-    @declared_attr
-    def artifact_template(cls):
-        return relationship.many_to_one(cls, 'artifact_template')
-
-    @declared_attr
-    def node(cls):
-        return relationship.many_to_one(cls, 'node')
-
-    @declared_attr
-    def group(cls):
-        return relationship.many_to_one(cls, 'group')
-
-    @declared_attr
-    def policy(cls):
-        return relationship.many_to_one(cls, 'policy')
-
-    @declared_attr
-    def relationship(cls):
-        return relationship.many_to_one(cls, 'relationship')
-
-    @declared_attr
-    def capability(cls):
-        return relationship.many_to_one(cls, 'capability')
-
-    @declared_attr
-    def artifact(cls):
-        return relationship.many_to_one(cls, 'artifact')
-
-    # endregion
-
-    @property
-    @caching.cachedmethod
-    def owner(self):
-        """
-        The sole owner of this parameter, which is another model that relates 
to it.
-
-        *All* parameters should have an owner model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
-
-        # Find first non-null relationship
-        for the_relationship in self.__mapper__.relationships:
-            v = getattr(self, the_relationship.key)
-            if v:
-                return v
-
-        raise ValueError('orphaned property: does not have an owner: 
{0}'.format(self.name))
-
-
-    @property
-    @caching.cachedmethod
-    def container(self):  # pylint: 
disable=too-many-return-statements,too-many-branches
-        """
-        The logical container for this parameter, which would be another 
model: service, node,
-        group, or policy (or their templates).
-
-        The logical container is equivalent to the ``SELF`` keyword used by 
intrinsic functions in
-        TOSCA.
-
-        *All* parameters should have a container model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
-
-        from . import models
-
-        container = self.owner
-
-        # Extract interface from operation
-        if isinstance(container, models.Operation):
-            container = container.interface
-        elif isinstance(container, models.OperationTemplate):
-            container = container.interface_template
-
-        # Extract from other models
-        if isinstance(container, models.Interface):
-            container = container.node or container.group or 
container.relationship
-        elif isinstance(container, models.InterfaceTemplate):
-            container = container.node_template or container.group_template \
-                        or container.relationship_template
-        elif isinstance(container, models.Capability) or isinstance(container, 
models.Artifact):
-            container = container.node
-        elif isinstance(container, models.CapabilityTemplate) \
-                or isinstance(container, models.ArtifactTemplate):
-            container = container.node_template
-        elif isinstance(container, models.Task):
-            container = container.actor
-
-        # Extract node from relationship
-        if isinstance(container, models.Relationship):
-            container = container.source_node
-        elif isinstance(container, models.RelationshipTemplate):
-            container = container.requirement_template.node_template
-
-        if container is not None:
-            return container
-
-        raise ValueError('orphaned property: does not have a container: 
{0}'.format(self.name))
-
-    @property
-    @caching.cachedmethod
-    def service(self):
-        """
-        The :class:`Service` containing this parameter, or None if not 
contained in a service.
-        """
-
-        from . import models
-        container = self.container
-        if isinstance(container, models.Service):
-            return container
-        elif hasattr(container, 'service'):
-            return container.service
-        return None
-
-    @property
-    @caching.cachedmethod
-    def service_template(self):
-        """
-        The :class:`ServiceTemplate` containing this parameter, or None if not 
contained in a
-        service template.
-        """
-
-        from . import models
-        container = self.container
-        if isinstance(container, models.ServiceTemplate):
-            return container
-        elif hasattr(container, 'service_template'):
-            return container.service_template
-        return None
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('type_name', self.type_name),
-            ('value', self.value),
-            ('description', self.description)))
-
-    def instantiate(self, container):
-        from . import models
-        return models.Property(name=self.name,  # pylint: 
disable=unexpected-keyword-arg
-                               type_name=self.type_name,
-                               _value=self._value,
-                               description=self.description)
-
-    def coerce_values(self, report_issues):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self, report_issues)
-            if (evaluation is not None) and evaluation.final:
-                # A final evaluation can safely replace the existing value
-                self._value = evaluation.value
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type_name is not None:
-            console.puts('{0}: {1} ({2})'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value)),
-                context.style.type(self.type_name)))
-        else:
-            console.puts('{0}: {1}'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value))))
-        if self.description:
-            console.puts(context.style.meta(self.description))
+        return relationship.many_to_one(cls, 'relationship_template')
 
-    def unwrap(self):
-        return self.name, self.value
+    @declared_attr
+    def capability_template(cls):
+        return relationship.many_to_one(cls, 'capability_template')
 
-    @classmethod
-    def wrap(cls, name, value, description=None):
-        """
-        Wraps an arbitrary value as a parameter. The type will be guessed via 
introspection.
+    @declared_attr
+    def artifact_template(cls):
+        return relationship.many_to_one(cls, 'artifact_template')
 
-        :param name: Input name
-        :type name: basestring
-        :param value: Input value
-        :param description: Description (optional)
-        :type description: basestring
-        """
+    @declared_attr
+    def node(cls):
+        return relationship.many_to_one(cls, 'node')
 
-        from . import models
-        type_name = canonical_type_name(value)
-        if type_name is None:
-            type_name = full_type_name(value)
-        return models.Property(name=name, # pylint: 
disable=unexpected-keyword-arg
-                               type_name=type_name,
-                               value=value,
-                               description=description)
+    @declared_attr
+    def group(cls):
+        return relationship.many_to_one(cls, 'group')
 
+    @declared_attr
+    def policy(cls):
+        return relationship.many_to_one(cls, 'policy')
 
-class AttributeBase(TemplateModelMixin, caching.HasCachedMethods):
-    """
-    Represents a typed value. The value can contain nested intrinsic functions.
+    @declared_attr
+    def relationship(cls):
+        return relationship.many_to_one(cls, 'relationship')
 
-    This model can be used as the ``container_holder`` argument for 
:func:`functions.evaluate`.
+    @declared_attr
+    def capability(cls):
+        return relationship.many_to_one(cls, 'capability')
 
-    :ivar name: Name
-    :vartype name: basestring
-    :ivar type_name: Type name
-    :vartype type_name: basestring
-    :ivar value: Value
-    :ivar description: Description
-    :vartype description: basestring
-    """
+    @declared_attr
+    def artifact(cls):
+        return relationship.many_to_one(cls, 'artifact')
 
-    __tablename__ = 'attribute'
+    # endregion
 
-    name = Column(Text)
-    type_name = Column(Text)
-    description = Column(Text)
-    _value = Column(PickleType)
 
-    @property
-    def value(self):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self)
-            if evaluation is not None:
-                value = evaluation.value
-        return value
+class AttributeBase(ParameterMixin, TemplateModelMixin, 
caching.HasCachedMethods):
 
-    @value.setter
-    def value(self, value):
-        self._value = value
+    __tablename__ = 'attribute'
 
     # region foreign keys
 
@@ -1207,164 +470,112 @@ class AttributeBase(TemplateModelMixin, 
caching.HasCachedMethods):
 
     # endregion
 
-    @property
-    @caching.cachedmethod
-    def owner(self):
-        """
-        The sole owner of this attribute, which is another model that relates 
to it.
-
-        *All* parameters should have an owner model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
 
-        # Find first non-null relationship
-        for the_relationship in self.__mapper__.relationships:
-            v = getattr(self, the_relationship.key)
-            if v:
-                return v # because we are many-to-many, the back reference 
will be a list
+class TypeBase(InstanceModelMixin):
+    """
+    Represents a type and its children.
+    """
 
-        raise ValueError('orphaned attribute: does not have an owner: 
{0}'.format(self.name))
+    __tablename__ = 'type'
 
-    @property
-    @caching.cachedmethod
-    def container(self): # pylint: 
disable=too-many-return-statements,too-many-branches
-        """
-        The logical container for this attribute, which would be another 
model: service, node,
-        group, or policy (or their templates).
+    __private_fields__ = ['parent_type_fk']
 
-        The logical container is equivalent to the ``SELF`` keyword used by 
intrinsic functions in
-        TOSCA.
+    variant = Column(Text, nullable=False)
+    description = Column(Text)
+    _role = Column(Text, name='role')
 
-        *All* parameters should have a container model. In case this property 
method fails to find
-        it, it will raise a ValueError, which should signify an abnormal, 
orphaned parameter.
-        """
+    @declared_attr
+    def parent(cls):
+        return relationship.one_to_one_self(cls, 'parent_type_fk')
 
-        from . import models
+    @declared_attr
+    def children(cls):
+        return relationship.one_to_many_self(cls, 'parent_type_fk')
 
-        container = self.owner
+    # region foreign keys
 
-        # Extract interface from operation
-        if isinstance(container, models.Operation):
-            container = container.interface
-        elif isinstance(container, models.OperationTemplate):
-            container = container.interface_template
+    @declared_attr
+    def parent_type_fk(cls):
+        """For Type one-to-many to Type"""
+        return relationship.foreign_key('type', nullable=True)
 
-        # Extract from other models
-        if isinstance(container, models.Interface):
-            container = container.node or container.group or 
container.relationship
-        elif isinstance(container, models.InterfaceTemplate):
-            container = container.node_template or container.group_template \
-                        or container.relationship_template
-        elif isinstance(container, models.Capability) or isinstance(container, 
models.Artifact):
-            container = container.node
-        elif isinstance(container, models.CapabilityTemplate) \
-                or isinstance(container, models.ArtifactTemplate):
-            container = container.node_template
-        elif isinstance(container, models.Task):
-            container = container.actor
+    # endregion
 
-        # Extract node from relationship
-        if isinstance(container, models.Relationship):
-            container = container.source_node
-        elif isinstance(container, models.RelationshipTemplate):
-            container = container.requirement_template.node_template
+    @property
+    def role(self):
+        def get_role(the_type):
+            if the_type is None:
+                return None
+            elif the_type._role is None:
+                return get_role(the_type.parent)
+            return the_type._role
 
-        if container is not None:
-            return container
+        return get_role(self)
 
-        raise ValueError('orphaned attribute: does not have a container: 
{0}'.format(self.name))
+    @role.setter
+    def role(self, value):
+        self._role = value
 
-    @property
-    @caching.cachedmethod
-    def service(self):
-        """
-        The :class:`Service` containing this parameter, or None if not 
contained in a service.
-        """
+    def is_descendant(self, base_name, name):
+        base = self.get_descendant(base_name)
+        if base is not None:
+            if base.get_descendant(name) is not None:
+                return True
+        return False
 
-        from . import models
-        container = self.container
-        if isinstance(container, models.Service):
-            return container
-        elif hasattr(container, 'service'):
-            return container.service
+    def get_descendant(self, name):
+        if self.name == name:
+            return self
+        for child in self.children:
+            found = child.get_descendant(name)
+            if found is not None:
+                return found
         return None
 
-    @property
-    @caching.cachedmethod
-    def service_template(self):
-        """
-        The :class:`ServiceTemplate` containing this parameter, or None if not 
contained in a
-        service template.
-        """
-
-        from . import models
-        container = self.container
-        if isinstance(container, models.ServiceTemplate):
-            return container
-        elif hasattr(container, 'service_template'):
-            return container.service_template
-        return None
+    def iter_descendants(self):
+        for child in self.children:
+            yield child
+            for descendant in child.iter_descendants():
+                yield descendant
 
     @property
     def as_raw(self):
         return collections.OrderedDict((
             ('name', self.name),
-            ('type_name', self.type_name),
-            ('value', self.value),
-            ('description', self.description)))
+            ('description', self.description),
+            ('role', self.role)))
 
-    def instantiate(self, container):
-        from . import models
-        return models.Attribute(name=self.name, # pylint: 
disable=unexpected-keyword-arg
-                                type_name=self.type_name,
-                                _value=self._value,
-                                description=self.description)
+    @property
+    def as_raw_all(self):
+        types = []
+        self._append_raw_children(types)
+        return types
 
     def coerce_values(self, report_issues):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self, report_issues)
-            if (evaluation is not None) and evaluation.final:
-                # A final evaluation can safely replace the existing value
-                self._value = evaluation.value
+        pass
 
     def dump(self):
         context = ConsumptionContext.get_thread_local()
-        if self.type_name is not None:
-            console.puts('{0}: {1} ({2})'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value)),
-                context.style.type(self.type_name)))
-        else:
-            console.puts('{0}: {1}'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value))))
-        if self.description:
-            console.puts(context.style.meta(self.description))
+        if self.name:
+            console.puts(context.style.type(self.name))
+        with context.style.indent:
+            for child in self.children:
+                child.dump()
 
-    def unwrap(self):
-        return self.name, self.value
+    def _append_raw_children(self, types):
+        for child in self.children:
+            raw_child = formatting.as_raw(child)
+            raw_child['parent'] = self.name
+            types.append(raw_child)
+            child._append_raw_children(types)
 
-    @classmethod
-    def wrap(cls, name, value, description=None):
+    @property
+    def hierarchy(self):
         """
-        Wraps an arbitrary value as a parameter. The type will be guessed via 
introspection.
-
-        :param name: Parameter name
-        :type name: basestring
-        :param value: Parameter value
-        :param description: Description (optional)
-        :type description: basestring
+        Return the type hierarchy.
+        :return:
         """
-
-        from . import models
-        type_name = canonical_type_name(value)
-        if type_name is None:
-            type_name = full_type_name(value)
-        return models.Attribute(name=name, # pylint: 
disable=unexpected-keyword-arg
-                                type_name=type_name,
-                                value=value,
-                                description=description)
+        return [self] + (self.parent.hierarchy if self.parent else [])
 
 
 class MetadataBase(TemplateModelMixin):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/42f924f5/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py 
b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index d89fc90..ba6eb16 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -32,7 +32,7 @@ from aria.modeling.models import (Type, ServiceTemplate, 
NodeTemplate,
                                   RequirementTemplate, RelationshipTemplate, 
CapabilityTemplate,
                                   GroupTemplate, PolicyTemplate, 
SubstitutionTemplate,
                                   SubstitutionTemplateMapping, 
InterfaceTemplate, OperationTemplate,
-                                  ArtifactTemplate, Metadata, Parameter, 
Input, Output, Property,
+                                  ArtifactTemplate, Metadata, Input, Output, 
Property,
                                   Attribute, PluginSpecification)
 
 from .constraints import (Equal, GreaterThan, GreaterOrEqual, LessThan, 
LessOrEqual, InRange,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/42f924f5/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 1935051..745ef71 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -94,7 +94,7 @@ def create_service_with_dependencies(include_execution=False,
         service.executions = [execution]
         execution.id = '1'
     if include_input:
-        input = create_parameter(name='input1', value='value1', 
model_class=models.Input)
+        input = create_input(name='input1', value='value1')
         service.inputs = {'input1': input}
     if include_node:
         node_template = create_node_template(service_template=service_template)
@@ -110,8 +110,7 @@ def 
create_node_template_with_dependencies(include_node=False, include_property=
         service = create_service(service_template=service_template)
         create_node(dependency_node_template=node_template, service=service)
     if include_property:
-        node_template.properties = {'prop1': create_parameter(name='prop1', 
value='value1',
-                                                              
model_class=models.Property)}
+        node_template.properties = {'prop1': create_property(name='prop1', 
value='value1')}
     return node_template
 
 
@@ -282,13 +281,17 @@ def create_plugin_specification(name='test_plugin', 
version='0.1'):
     )
 
 
-def create_parameter(name, value, model_class=models.Parameter):
+def _create_parameter(name, value, model_class):
     p = model_class()
     return p.wrap(name, value)
 
 
+def create_property(name, value):
+    return _create_parameter(name, value, model_class=models.Property)
+
+
 def create_input(name, value):
-    return create_parameter(name, value, model_class=models.Input)
+    return _create_parameter(name, value, model_class=models.Input)
 
 
 def _dictify(item):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/42f924f5/tests/storage/test_model_storage.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_model_storage.py 
b/tests/storage/test_model_storage.py
index 4dabfaf..518d624 100644
--- a/tests/storage/test_model_storage.py
+++ b/tests/storage/test_model_storage.py
@@ -107,7 +107,11 @@ def test_application_storage_factory():
     assert storage.plugin
     assert storage.task
 
-    assert storage.parameter
+    assert storage.input
+    assert storage.output
+    assert storage.property
+    assert storage.attribute
+
     assert storage.type
     assert storage.metadata
 

Reply via email to