http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/23d6ba76/apache-ariatosca-0.1.1/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/modeling/service_template.py 
b/apache-ariatosca-0.1.1/aria/modeling/service_template.py
deleted file mode 100644
index 57fd672..0000000
--- a/apache-ariatosca-0.1.1/aria/modeling/service_template.py
+++ /dev/null
@@ -1,2411 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-ARIA modeling service template module
-"""
-
-# pylint: disable=too-many-lines, no-self-argument, no-member, abstract-method
-
-from __future__ import absolute_import  # so we can import standard 'types'
-
-from datetime import datetime
-
-from sqlalchemy import (
-    Column,
-    Text,
-    Integer,
-    Boolean,
-    DateTime,
-    PickleType
-)
-from sqlalchemy.ext.declarative import declared_attr
-
-from ..parser import validation
-from ..parser.consumption import ConsumptionContext
-from ..parser.reading import deepcopy_with_locators
-from ..utils import (collections, formatting, console)
-from ..utils.versions import VersionString
-from .mixins import TemplateModelMixin
-from . import (
-    relationship,
-    utils,
-    types as modeling_types
-)
-
-
-class ServiceTemplateBase(TemplateModelMixin):
-    """
-    Template for creating :class:`Service` instances.
-
-    Usually created by various DSL parsers, such as ARIA's TOSCA extension. 
However, it can also be
-    created programmatically.
-    """
-
-    __tablename__ = 'service_template'
-
-    __private_fields__ = ('substitution_template_fk',
-                          'node_type_fk',
-                          'group_type_fk',
-                          'policy_type_fk',
-                          'relationship_type_fk',
-                          'capability_type_fk',
-                          'interface_type_fk',
-                          'artifact_type_fk')
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    main_file_name = Column(Text, doc="""
-    Filename of CSAR or YAML file from which this service template was parsed.
-    
-    :type: :obj:`basestring`
-    """)
-
-    created_at = Column(DateTime, nullable=False, index=True, doc="""
-    Creation timestamp.
-
-    :type: :class:`~datetime.datetime`
-    """)
-
-    updated_at = Column(DateTime, doc="""
-    Update timestamp.
-
-    :type: :class:`~datetime.datetime`
-    """)
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    @declared_attr
-    def substitution_template(cls):
-        """
-        Exposes an entire service as a single node.
-
-        :type: :class:`SubstitutionTemplate`
-        """
-        return relationship.one_to_one(
-            cls, 'substitution_template', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def node_types(cls):
-        """
-        Base for the node type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='node_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def group_types(cls):
-        """
-        Base for the group type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='group_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def policy_types(cls):
-        """
-        Base for the policy type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='policy_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def relationship_types(cls):
-        """
-        Base for the relationship type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='relationship_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def capability_types(cls):
-        """
-        Base for the capability type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='capability_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def interface_types(cls):
-        """
-        Base for the interface type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='interface_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def artifact_types(cls):
-        """
-        Base for the artifact type hierarchy,
-
-        :type: :class:`Type`
-        """
-        return relationship.one_to_one(
-            cls, 'type', fk='artifact_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def services(cls):
-        """
-        Instantiated services.
-
-        :type: [:class:`Service`]
-        """
-        return relationship.one_to_many(cls, 'service', dict_key='name')
-
-    @declared_attr
-    def node_templates(cls):
-        """
-        Templates for creating nodes.
-
-        :type: {:obj:`basestring`, :class:`NodeTemplate`}
-        """
-        return relationship.one_to_many(cls, 'node_template', dict_key='name')
-
-    @declared_attr
-    def group_templates(cls):
-        """
-        Templates for creating groups.
-
-        :type: {:obj:`basestring`, :class:`GroupTemplate`}
-        """
-        return relationship.one_to_many(cls, 'group_template', dict_key='name')
-
-    @declared_attr
-    def policy_templates(cls):
-        """
-        Templates for creating policies.
-
-        :type: {:obj:`basestring`, :class:`PolicyTemplate`}
-        """
-        return relationship.one_to_many(cls, 'policy_template', 
dict_key='name')
-
-    @declared_attr
-    def workflow_templates(cls):
-        """
-        Templates for creating workflows.
-
-        :type: {:obj:`basestring`, :class:`OperationTemplate`}
-        """
-        return relationship.one_to_many(cls, 'operation_template', 
dict_key='name')
-
-    @declared_attr
-    def outputs(cls):
-        """
-        Declarations for output parameters are filled in after service 
installation.
-
-        :type: {:obj:`basestring`: :class:`Output`}
-        """
-        return relationship.one_to_many(cls, 'output', dict_key='name')
-
-    @declared_attr
-    def inputs(cls):
-        """
-        Declarations for externally provided parameters.
-
-        :type: {:obj:`basestring`: :class:`Input`}
-        """
-        return relationship.one_to_many(cls, 'input', dict_key='name')
-
-    @declared_attr
-    def plugin_specifications(cls):
-        """
-        Required plugins for instantiated services.
-
-        :type: {:obj:`basestring`: :class:`PluginSpecification`}
-        """
-        return relationship.one_to_many(cls, 'plugin_specification', 
dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    # endregion
-
-    # region many_to_many relationships
-
-    @declared_attr
-    def meta_data(cls):
-        """
-        Associated metadata.
-
-        :type: {:obj:`basestring`: :class:`Metadata`}
-        """
-        # Warning! We cannot use the attr name "metadata" because it's used by 
SQLAlchemy!
-        return relationship.many_to_many(cls, 'metadata', dict_key='name')
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def substitution_template_fk(cls):
-        """For ServiceTemplate one-to-one to SubstitutionTemplate"""
-        return relationship.foreign_key('substitution_template', nullable=True)
-
-    @declared_attr
-    def node_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def group_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def policy_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def relationship_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def capability_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def interface_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def artifact_type_fk(cls):
-        """For ServiceTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    # endregion
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('description', self.description),
-            ('metadata', formatting.as_raw_dict(self.meta_data)),
-            ('node_templates', formatting.as_raw_list(self.node_templates)),
-            ('group_templates', formatting.as_raw_list(self.group_templates)),
-            ('policy_templates', 
formatting.as_raw_list(self.policy_templates)),
-            ('substitution_template', 
formatting.as_raw(self.substitution_template)),
-            ('inputs', formatting.as_raw_dict(self.inputs)),
-            ('outputs', formatting.as_raw_dict(self.outputs)),
-            ('workflow_templates', 
formatting.as_raw_list(self.workflow_templates))))
-
-    @property
-    def types_as_raw(self):
-        return collections.OrderedDict((
-            ('node_types', formatting.as_raw(self.node_types)),
-            ('group_types', formatting.as_raw(self.group_types)),
-            ('policy_types', formatting.as_raw(self.policy_types)),
-            ('relationship_types', formatting.as_raw(self.relationship_types)),
-            ('capability_types', formatting.as_raw(self.capability_types)),
-            ('interface_types', formatting.as_raw(self.interface_types)),
-            ('artifact_types', formatting.as_raw(self.artifact_types))))
-
-    def instantiate(self, container, model_storage, inputs=None):  # pylint: 
disable=arguments-differ
-        from . import models
-        context = ConsumptionContext.get_thread_local()
-        now = datetime.now()
-        service = models.Service(created_at=now,
-                                 updated_at=now,
-                                 
description=deepcopy_with_locators(self.description),
-                                 service_template=self)
-        context.modeling.instance = service
-
-        service.inputs = utils.merge_parameter_values(inputs, self.inputs, 
model_cls=models.Input)
-        # TODO: now that we have inputs, we should scan properties and inputs 
and evaluate functions
-
-        for plugin_specification in self.plugin_specifications.itervalues():
-            if plugin_specification.enabled:
-                if plugin_specification.resolve(model_storage):
-                    plugin = plugin_specification.plugin
-                    service.plugins[plugin.name] = plugin
-                else:
-                    context = ConsumptionContext.get_thread_local()
-                    context.validation.report('specified plugin not found: 
{0}'.format(
-                        plugin_specification.name), 
level=validation.Issue.EXTERNAL)
-
-        utils.instantiate_dict(self, service.meta_data, self.meta_data)
-
-        for node_template in self.node_templates.itervalues():
-            for _ in range(node_template.default_instances):
-                node = node_template.instantiate(container)
-                service.nodes[node.name] = node
-
-        utils.instantiate_dict(self, service.groups, self.group_templates)
-        utils.instantiate_dict(self, service.policies, self.policy_templates)
-        utils.instantiate_dict(self, service.workflows, 
self.workflow_templates)
-
-        if self.substitution_template is not None:
-            service.substitution = 
self.substitution_template.instantiate(container)
-
-        utils.instantiate_dict(self, service.outputs, self.outputs)
-
-        return service
-
-    def validate(self):
-        utils.validate_dict_values(self.meta_data)
-        utils.validate_dict_values(self.node_templates)
-        utils.validate_dict_values(self.group_templates)
-        utils.validate_dict_values(self.policy_templates)
-        if self.substitution_template is not None:
-            self.substitution_template.validate()
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.outputs)
-        utils.validate_dict_values(self.workflow_templates)
-        if self.node_types is not None:
-            self.node_types.validate()
-        if self.group_types is not None:
-            self.group_types.validate()
-        if self.policy_types is not None:
-            self.policy_types.validate()
-        if self.relationship_types is not None:
-            self.relationship_types.validate()
-        if self.capability_types is not None:
-            self.capability_types.validate()
-        if self.interface_types is not None:
-            self.interface_types.validate()
-        if self.artifact_types is not None:
-            self.artifact_types.validate()
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.meta_data, report_issues)
-        utils.coerce_dict_values(self.node_templates, report_issues)
-        utils.coerce_dict_values(self.group_templates, report_issues)
-        utils.coerce_dict_values(self.policy_templates, report_issues)
-        if self.substitution_template is not None:
-            self.substitution_template.coerce_values(report_issues)
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.outputs, report_issues)
-        utils.coerce_dict_values(self.workflow_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.description is not None:
-            console.puts(context.style.meta(self.description))
-        utils.dump_dict_values(self.meta_data, 'Metadata')
-        for node_template in self.node_templates.itervalues():
-            node_template.dump()
-        for group_template in self.group_templates.itervalues():
-            group_template.dump()
-        for policy_template in self.policy_templates.itervalues():
-            policy_template.dump()
-        if self.substitution_template is not None:
-            self.substitution_template.dump()
-        utils.dump_dict_values(self.inputs, 'Inputs')
-        utils.dump_dict_values(self.outputs, 'Outputs')
-        utils.dump_dict_values(self.workflow_templates, 'Workflow templates')
-
-    def dump_types(self):
-        if self.node_types.children:
-            console.puts('Node types:')
-            self.node_types.dump()
-        if self.group_types.children:
-            console.puts('Group types:')
-            self.group_types.dump()
-        if self.capability_types.children:
-            console.puts('Capability types:')
-            self.capability_types.dump()
-        if self.relationship_types.children:
-            console.puts('Relationship types:')
-            self.relationship_types.dump()
-        if self.policy_types.children:
-            console.puts('Policy types:')
-            self.policy_types.dump()
-        if self.artifact_types.children:
-            console.puts('Artifact types:')
-            self.artifact_types.dump()
-        if self.interface_types.children:
-            console.puts('Interface types:')
-            self.interface_types.dump()
-
-
-class NodeTemplateBase(TemplateModelMixin):
-    """
-    Template for creating zero or more :class:`Node` instances, which are 
typed vertices in the
-    service topology.
-    """
-
-    __tablename__ = 'node_template'
-
-    __private_fields__ = ('type_fk',
-                          'service_template_fk')
-
-    # region association proxies
-
-    @declared_attr
-    def service_template_name(cls):
-        return relationship.association_proxy('service_template', 'name')
-
-    @declared_attr
-    def type_name(cls):
-        return relationship.association_proxy('type', 'name')
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def nodes(cls):
-        """
-        Instantiated nodes.
-
-        :type: [:class:`Node`]
-        """
-        return relationship.one_to_many(cls, 'node')
-
-    @declared_attr
-    def interface_templates(cls):
-        """
-        Associated interface templates.
-
-        :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
-        """
-        return relationship.one_to_many(cls, 'interface_template', 
dict_key='name')
-
-    @declared_attr
-    def artifact_templates(cls):
-        """
-        Associated artifacts.
-
-        :type: {:obj:`basestring`: :class:`ArtifactTemplate`}
-        """
-        return relationship.one_to_many(cls, 'artifact_template', 
dict_key='name')
-
-    @declared_attr
-    def capability_templates(cls):
-        """
-        Associated exposed capability templates.
-
-        :type: {:obj:`basestring`: :class:`CapabilityTemplate`}
-        """
-        return relationship.one_to_many(cls, 'capability_template', 
dict_key='name')
-
-    @declared_attr
-    def requirement_templates(cls):
-        """
-        Associated potential relationships with other nodes.
-
-        :type: [:class:`RequirementTemplate`]
-        """
-        return relationship.one_to_many(cls, 'requirement_template', 
other_fk='node_template_fk')
-
-    @declared_attr
-    def properties(cls):
-        """
-        Declarations for associated immutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Property`}
-        """
-        return relationship.one_to_many(cls, 'property', dict_key='name')
-
-    @declared_attr
-    def attributes(cls):
-        """
-        Declarations for associated mutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Attribute`}
-        """
-        return relationship.one_to_many(cls, 'attribute', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def type(cls):
-        """
-        Node type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def service_template(cls):
-        """
-        Containing service template.
-
-        :type: :class:`ServiceTemplate`
-        """
-        return relationship.many_to_one(cls, 'service_template')
-
-    # endregion
-
-    # region foreign_keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For NodeTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to NodeTemplate"""
-        return relationship.foreign_key('service_template')
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    default_instances = Column(Integer, default=1, doc="""
-    Default number nodes that will appear in the service.
-
-    :type: :obj:`int`
-    """)
-
-    min_instances = Column(Integer, default=0, doc="""
-    Minimum number nodes that will appear in the service.
-
-    :type: :obj:`int`
-    """)
-
-    max_instances = Column(Integer, default=None, doc="""
-    Maximum number nodes that will appear in the service.
-
-    :type: :obj:`int`
-    """)
-
-    target_node_template_constraints = Column(PickleType, doc="""
-    Constraints for filtering relationship targets.
-
-    :type: [:class:`NodeTemplateConstraint`]
-    """)
-
-    def is_target_node_template_valid(self, target_node_template):
-        if self.target_node_template_constraints:
-            for node_template_constraint in 
self.target_node_template_constraints:
-                if not node_template_constraint.matches(self, 
target_node_template):
-                    return False
-        return True
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('type_name', self.type.name),
-            ('default_instances', self.default_instances),
-            ('min_instances', self.min_instances),
-            ('max_instances', self.max_instances),
-            ('properties', formatting.as_raw_dict(self.properties)),
-            ('attributes', formatting.as_raw_dict(self.properties)),
-            ('interface_templates', 
formatting.as_raw_list(self.interface_templates)),
-            ('artifact_templates', 
formatting.as_raw_list(self.artifact_templates)),
-            ('capability_templates', 
formatting.as_raw_list(self.capability_templates)),
-            ('requirement_templates', 
formatting.as_raw_list(self.requirement_templates))))
-
-    def instantiate(self, container):
-        from . import models
-        if self.nodes:
-            highest_name_suffix = max(int(n.name.rsplit('_', 1)[-1]) for n in 
self.nodes)
-            suffix = highest_name_suffix + 1
-        else:
-            suffix = 1
-        name = '{name}_{index}'.format(name=self.name, index=suffix)
-        node = models.Node(name=name,
-                           type=self.type,
-                           
description=deepcopy_with_locators(self.description),
-                           state=models.Node.INITIAL,
-                           node_template=self)
-        utils.instantiate_dict(node, node.properties, self.properties)
-        utils.instantiate_dict(node, node.attributes, self.attributes)
-        utils.instantiate_dict(node, node.interfaces, self.interface_templates)
-        utils.instantiate_dict(node, node.artifacts, self.artifact_templates)
-        utils.instantiate_dict(node, node.capabilities, 
self.capability_templates)
-
-        # Default attributes
-        if 'tosca_name' in node.attributes:
-            node.attributes['tosca_name'].value = self.name
-        if 'tosca_id' in node.attributes:
-            node.attributes['tosca_id'].value = name
-
-        return node
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.attributes)
-        utils.validate_dict_values(self.interface_templates)
-        utils.validate_dict_values(self.artifact_templates)
-        utils.validate_dict_values(self.capability_templates)
-        utils.validate_list_values(self.requirement_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.attributes, report_issues)
-        utils.coerce_dict_values(self.interface_templates, report_issues)
-        utils.coerce_dict_values(self.artifact_templates, report_issues)
-        utils.coerce_dict_values(self.capability_templates, report_issues)
-        utils.coerce_list_values(self.requirement_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Node template: 
{0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: 
{0}'.format(context.style.type(self.type.name)))
-            console.puts('Instances: {0:d} ({1:d}{2})'.format(
-                self.default_instances,
-                self.min_instances,
-                ' to {0:d}'.format(self.max_instances)
-                if self.max_instances is not None
-                else ' or more'))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_dict_values(self.attributes, 'Attributes')
-            utils.dump_interfaces(self.interface_templates)
-            utils.dump_dict_values(self.artifact_templates, 'Artifact 
templates')
-            utils.dump_dict_values(self.capability_templates, 'Capability 
templates')
-            utils.dump_list_values(self.requirement_templates, 'Requirement 
templates')
-
-
-class GroupTemplateBase(TemplateModelMixin):
-    """
-    Template for creating a :class:`Group` instance, which is a typed logical 
container for zero or
-    more :class:`Node` instances.
-    """
-
-    __tablename__ = 'group_template'
-
-    __private_fields__ = ('type_fk',
-                          'service_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def groups(cls):
-        """
-        Instantiated groups.
-
-        :type: [:class:`Group`]
-        """
-        return relationship.one_to_many(cls, 'group')
-
-    @declared_attr
-    def interface_templates(cls):
-        """
-        Associated interface templates.
-
-        :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
-        """
-        return relationship.one_to_many(cls, 'interface_template', 
dict_key='name')
-
-    @declared_attr
-    def properties(cls):
-        """
-        Declarations for associated immutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Property`}
-        """
-        return relationship.one_to_many(cls, 'property', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def service_template(cls):
-        """
-        Containing service template.
-
-        :type: :class:`ServiceTemplate`
-        """
-        return relationship.many_to_one(cls, 'service_template')
-
-    @declared_attr
-    def type(cls):
-        """
-        Group type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region many_to_many relationships
-
-    @declared_attr
-    def node_templates(cls):
-        """
-        Nodes instantiated by these templates will be members of the group.
-
-        :type: [:class:`NodeTemplate`]
-        """
-        return relationship.many_to_many(cls, 'node_template')
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For GroupTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to GroupTemplate"""
-        return relationship.foreign_key('service_template')
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('type_name', self.type.name),
-            ('properties', formatting.as_raw_dict(self.properties)),
-            ('interface_templates', 
formatting.as_raw_list(self.interface_templates))))
-
-    def instantiate(self, container):
-        from . import models
-        group = models.Group(name=self.name,
-                             type=self.type,
-                             
description=deepcopy_with_locators(self.description),
-                             group_template=self)
-        utils.instantiate_dict(self, group.properties, self.properties)
-        utils.instantiate_dict(self, group.interfaces, 
self.interface_templates)
-        if self.node_templates:
-            for node_template in self.node_templates:
-                group.nodes += node_template.nodes
-        return group
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.interface_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.interface_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Group template: 
{0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: 
{0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interface_templates)
-            if self.node_templates:
-                console.puts('Member node templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in 
self.node_templates))))
-
-
-class PolicyTemplateBase(TemplateModelMixin):
-    """
-    Template for creating a :class:`Policy` instance, which is a typed set of 
orchestration hints
-    applied to zero or more :class:`Node` or :class:`Group` instances.
-    """
-
-    __tablename__ = 'policy_template'
-
-    __private_fields__ = ('type_fk',
-                          'service_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def policies(cls):
-        """
-        Instantiated policies.
-
-        :type: [:class:`Policy`]
-        """
-        return relationship.one_to_many(cls, 'policy')
-
-    @declared_attr
-    def properties(cls):
-        """
-        Declarations for associated immutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Property`}
-        """
-        return relationship.one_to_many(cls, 'property', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def service_template(cls):
-        """
-        Containing service template.
-
-        :type: :class:`ServiceTemplate`
-        """
-        return relationship.many_to_one(cls, 'service_template')
-
-    @declared_attr
-    def type(cls):
-        """
-        Policy type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region many_to_many relationships
-
-    @declared_attr
-    def node_templates(cls):
-        """
-        Policy will be enacted on all nodes instantiated by these templates.
-
-        :type: {:obj:`basestring`: :class:`NodeTemplate`}
-        """
-        return relationship.many_to_many(cls, 'node_template')
-
-    @declared_attr
-    def group_templates(cls):
-        """
-        Policy will be enacted on all nodes in all groups instantiated by 
these templates.
-
-        :type: {:obj:`basestring`: :class:`GroupTemplate`}
-        """
-        return relationship.many_to_many(cls, 'group_template')
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For PolicyTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to PolicyTemplate"""
-        return relationship.foreign_key('service_template')
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('type_name', self.type.name),
-            ('properties', formatting.as_raw_dict(self.properties))))
-
-    def instantiate(self, container):
-        from . import models
-        policy = models.Policy(name=self.name,
-                               type=self.type,
-                               
description=deepcopy_with_locators(self.description),
-                               policy_template=self)
-        utils.instantiate_dict(self, policy.properties, self.properties)
-        if self.node_templates:
-            for node_template in self.node_templates:
-                policy.nodes += node_template.nodes
-        if self.group_templates:
-            for group_template in self.group_templates:
-                policy.groups += group_template.groups
-        return policy
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Policy template: 
{0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: 
{0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            if self.node_templates:
-                console.puts('Target node templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in 
self.node_templates))))
-            if self.group_templates:
-                console.puts('Target group templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in 
self.group_templates))))
-
-
-class SubstitutionTemplateBase(TemplateModelMixin):
-    """
-    Template for creating a :class:`Substitution` instance, which exposes an 
entire instantiated
-    service as a single node.
-    """
-
-    __tablename__ = 'substitution_template'
-
-    __private_fields__ = ('node_type_fk',)
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def substitutions(cls):
-        """
-        Instantiated substitutions.
-
-        :type: [:class:`Substitution`]
-        """
-        return relationship.one_to_many(cls, 'substitution')
-
-    @declared_attr
-    def mappings(cls):
-        """
-        Map requirement and capabilities to exposed node.
-
-        :type: {:obj:`basestring`: :class:`SubstitutionTemplateMapping`}
-        """
-        return relationship.one_to_many(cls, 'substitution_template_mapping', 
dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def node_type(cls):
-        """
-        Exposed node type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def node_type_fk(cls):
-        """For SubstitutionTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    # endregion
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('node_type_name', self.node_type.name),
-            ('mappings', formatting.as_raw_dict(self.mappings))))
-
-    def instantiate(self, container):
-        from . import models
-        substitution = models.Substitution(node_type=self.node_type,
-                                           substitution_template=self)
-        utils.instantiate_dict(container, substitution.mappings, self.mappings)
-        return substitution
-
-    def validate(self):
-        utils.validate_dict_values(self.mappings)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.mappings, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Substitution template:')
-        with context.style.indent:
-            console.puts('Node type: 
{0}'.format(context.style.type(self.node_type.name)))
-            utils.dump_dict_values(self.mappings, 'Mappings')
-
-
-class SubstitutionTemplateMappingBase(TemplateModelMixin):
-    """
-    Used by :class:`SubstitutionTemplate` to map a capability template or a 
requirement template to
-    the exposed node.
-
-    The :attr:`name` field should match the capability or requirement name on 
the exposed node's
-    type.
-
-    Only one of :attr:`capability_template` and :attr:`requirement_template` 
can be set.
-    """
-
-    __tablename__ = 'substitution_template_mapping'
-
-    __private_fields__ = ('substitution_template_fk',
-                          'capability_template_fk',
-                          'requirement_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    @declared_attr
-    def capability_template(cls):
-        """
-        Capability template to expose (can be ``None``).
-
-        :type: :class:`CapabilityTemplate`
-        """
-        return relationship.one_to_one(
-            cls, 'capability_template', 
back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def requirement_template(cls):
-        """
-        Requirement template to expose (can be ``None``).
-
-        :type: :class:`RequirementTemplate`
-        """
-        return relationship.one_to_one(
-            cls, 'requirement_template', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region one_to_many relationships
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def substitution_template(cls):
-        """
-        Containing substitution template.
-
-        :type: :class:`SubstitutionTemplate`
-        """
-        return relationship.many_to_one(cls, 'substitution_template', 
back_populates='mappings')
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def substitution_template_fk(cls):
-        """For SubstitutionTemplate one-to-many to 
SubstitutionTemplateMapping"""
-        return relationship.foreign_key('substitution_template')
-
-    @declared_attr
-    def capability_template_fk(cls):
-        """For SubstitutionTemplate one-to-one to CapabilityTemplate"""
-        return relationship.foreign_key('capability_template', nullable=True)
-
-    @declared_attr
-    def requirement_template_fk(cls):
-        """For SubstitutionTemplate one-to-one to RequirementTemplate"""
-        return relationship.foreign_key('requirement_template', nullable=True)
-
-    # endregion
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),))
-
-    def coerce_values(self, report_issues):
-        pass
-
-    def instantiate(self, container):
-        from . import models
-        context = ConsumptionContext.get_thread_local()
-        if self.capability_template is not None:
-            node_template = self.capability_template.node_template
-        else:
-            node_template = self.requirement_template.node_template
-        nodes = node_template.nodes
-        if len(nodes) == 0:
-            context.validation.report(
-                'mapping "{0}" refers to node template "{1}" but there are no '
-                'node instances'.format(self.mapped_name, 
self.node_template.name),
-                level=validation.Issue.BETWEEN_INSTANCES)
-            return None
-        # The TOSCA spec does not provide a way to choose the node,
-        # so we will just pick the first one
-        node = nodes[0]
-        capability = None
-        if self.capability_template:
-            for a_capability in node.capabilities.itervalues():
-                if a_capability.capability_template.name == 
self.capability_template.name:
-                    capability = a_capability
-        return models.SubstitutionMapping(name=self.name,
-                                          capability=capability,
-                                          
requirement_template=self.requirement_template,
-                                          node=node)
-
-
-    def validate(self):
-        context = ConsumptionContext.get_thread_local()
-        if (self.capability_template is None) and (self.requirement_template 
is None):
-            context.validation.report('mapping "{0}" refers to neither 
capability nor a requirement'
-                                      ' in node template: {1}'.format(
-                                          self.name,
-                                          
formatting.safe_repr(self.node_template.name)),
-                                      level=validation.Issue.BETWEEN_TYPES)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.capability_template is not None:
-            node_template = self.capability_template.node_template
-        else:
-            node_template = self.requirement_template.node_template
-        console.puts('{0} -> {1}.{2}'.format(
-            context.style.node(self.name),
-            context.style.node(node_template.name),
-            context.style.node(self.capability_template.name
-                               if self.capability_template
-                               else self.requirement_template.name)))
-
-
-class RequirementTemplateBase(TemplateModelMixin):
-    """
-    Template for creating :class:`Relationship` instances, which are 
optionally-typed edges in the
-    service topology, connecting a :class:`Node` to a :class:`Capability` of 
another node.
-
-    Note that there is no equivalent "Requirement" instance model. Instead, 
during instantiation a
-    requirement template is matched with a capability and a 
:class:`Relationship` is instantiated.
-
-    A requirement template *must* target a :class:`CapabilityType` or a 
capability name. It can
-    optionally target a specific :class:`NodeType` or :class:`NodeTemplate`.
-
-    Requirement templates may optionally contain a 
:class:`RelationshipTemplate`. If they do not,
-    a :class:`Relationship` will be instantiated with default values.
-    """
-
-    __tablename__ = 'requirement_template'
-
-    __private_fields__ = ('target_capability_type_fk',
-                          'target_node_template_fk',
-                          'target_node_type_fk',
-                          'relationship_template_fk',
-                          'node_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    @declared_attr
-    def target_capability_type(cls):
-        """
-        Target capability type.
-
-        :type: :class:`CapabilityType`
-        """
-        return relationship.one_to_one(cls,
-                                       'type',
-                                       fk='target_capability_type_fk',
-                                       back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def target_node_template(cls):
-        """
-        Target node template (can be ``None``).
-
-        :type: :class:`NodeTemplate`
-        """
-        return relationship.one_to_one(cls,
-                                       'node_template',
-                                       fk='target_node_template_fk',
-                                       back_populates=relationship.NO_BACK_POP)
-
-    @declared_attr
-    def relationship_template(cls):
-        """
-        Associated relationship template (can be ``None``).
-
-        :type: :class:`RelationshipTemplate`
-        """
-        return relationship.one_to_one(cls, 'relationship_template')
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def relationships(cls):
-        """
-        Instantiated relationships.
-
-        :type: [:class:`Relationship`]
-        """
-        return relationship.one_to_many(cls, 'relationship')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def node_template(cls):
-        """
-        Containing node template.
-
-        :type: :class:`NodeTemplate`
-        """
-        return relationship.many_to_one(cls, 'node_template', 
fk='node_template_fk')
-
-    @declared_attr
-    def target_node_type(cls):
-        """
-        Target node type (can be ``None``).
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(
-            cls, 'type', fk='target_node_type_fk', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def target_node_type_fk(cls):
-        """For RequirementTemplate many-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def target_node_template_fk(cls):
-        """For RequirementTemplate one-to-one to NodeTemplate"""
-        return relationship.foreign_key('node_template', nullable=True)
-
-    @declared_attr
-    def target_capability_type_fk(cls):
-        """For RequirementTemplate one-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to RequirementTemplate"""
-        return relationship.foreign_key('node_template')
-
-    @declared_attr
-    def relationship_template_fk(cls):
-        """For RequirementTemplate one-to-one to RelationshipTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
-
-    # endregion
-
-    target_capability_name = Column(Text, doc="""
-    Target capability name in node template or node type (can be ``None``).
-
-    :type: :obj:`basestring`
-    """)
-
-    target_node_template_constraints = Column(PickleType, doc="""
-    Constraints for filtering relationship targets.
-
-    :type: [:class:`NodeTemplateConstraint`]
-    """)
-
-    def find_target(self, source_node_template):
-        context = ConsumptionContext.get_thread_local()
-
-        # We might already have a specific node template, so we'll just verify 
it
-        if self.target_node_template is not None:
-            if not 
source_node_template.is_target_node_template_valid(self.target_node_template):
-                context.validation.report('requirement "{0}" of node template 
"{1}" is for node '
-                                          'template "{2}" but it does not 
match constraints'.format(
-                                              self.name,
-                                              self.target_node_template.name,
-                                              source_node_template.name),
-                                          level=validation.Issue.BETWEEN_TYPES)
-            if (self.target_capability_type is not None) \
-                or (self.target_capability_name is not None):
-                target_node_capability = 
self.find_target_capability(source_node_template,
-                                                                     
self.target_node_template)
-                if target_node_capability is None:
-                    return None, None
-            else:
-                target_node_capability = None
-
-            return self.target_node_template, target_node_capability
-
-        # Find first node that matches the type
-        elif self.target_node_type is not None:
-            for target_node_template in \
-                    
self.node_template.service_template.node_templates.values():
-                if 
self.target_node_type.get_descendant(target_node_template.type.name) is None:
-                    continue
-
-                if not 
source_node_template.is_target_node_template_valid(target_node_template):
-                    continue
-
-                target_node_capability = 
self.find_target_capability(source_node_template,
-                                                                     
target_node_template)
-                if target_node_capability is None:
-                    continue
-
-                return target_node_template, target_node_capability
-
-        return None, None
-
-    def find_target_capability(self, source_node_template, 
target_node_template):
-        for capability_template in 
target_node_template.capability_templates.itervalues():
-            if capability_template.satisfies_requirement(source_node_template,
-                                                         self,
-                                                         target_node_template):
-                return capability_template
-        return None
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('target_node_type_name', self.target_node_type.name
-             if self.target_node_type is not None else None),
-            ('target_node_template_name', self.target_node_template.name
-             if self.target_node_template is not None else None),
-            ('target_capability_type_name', self.target_capability_type.name
-             if self.target_capability_type is not None else None),
-            ('target_capability_name', self.target_capability_name),
-            ('relationship_template', 
formatting.as_raw(self.relationship_template))))
-
-    def validate(self):
-        if self.relationship_template:
-            self.relationship_template.validate()
-
-    def coerce_values(self, report_issues):
-        if self.relationship_template is not None:
-            self.relationship_template.coerce_values(report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts(context.style.node(self.name))
-        else:
-            console.puts('Requirement:')
-        with context.style.indent:
-            if self.target_node_type is not None:
-                console.puts('Target node type: {0}'.format(
-                    context.style.type(self.target_node_type.name)))
-            elif self.target_node_template is not None:
-                console.puts('Target node template: {0}'.format(
-                    context.style.node(self.target_node_template.name)))
-            if self.target_capability_type is not None:
-                console.puts('Target capability type: {0}'.format(
-                    context.style.type(self.target_capability_type.name)))
-            elif self.target_capability_name is not None:
-                console.puts('Target capability name: {0}'.format(
-                    context.style.node(self.target_capability_name)))
-            if self.target_node_template_constraints:
-                console.puts('Target node template constraints:')
-                with context.style.indent:
-                    for constraint in self.target_node_template_constraints:
-                        console.puts(context.style.literal(constraint))
-            if self.relationship_template:
-                console.puts('Relationship:')
-                with context.style.indent:
-                    self.relationship_template.dump()
-
-
-class RelationshipTemplateBase(TemplateModelMixin):
-    """
-    Optional addition to a :class:`RequirementTemplate`.
-
-    Note that a relationship template here is not exactly equivalent to a 
relationship template
-    entity in TOSCA. For example, a TOSCA requirement specifying a 
relationship type rather than a
-    relationship template would still be represented here as a relationship 
template.
-    """
-
-    __tablename__ = 'relationship_template'
-
-    __private_fields__ = ('type_fk',)
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def relationships(cls):
-        """
-        Instantiated relationships.
-
-        :type: [:class:`Relationship`]
-        """
-        return relationship.one_to_many(cls, 'relationship')
-
-    @declared_attr
-    def interface_templates(cls):
-        """
-        Associated interface templates.
-
-        :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
-        """
-        return relationship.one_to_many(cls, 'interface_template', 
dict_key='name')
-
-    @declared_attr
-    def properties(cls):
-        """
-        Declarations for associated immutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Property`}
-        """
-        return relationship.one_to_many(cls, 'property', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def type(cls):
-        """
-        Relationship type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For RelationshipTemplate many-to-one to Type"""
-        return relationship.foreign_key('type', nullable=True)
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('type_name', self.type.name if self.type is not None else None),
-            ('name', self.name),
-            ('description', self.description),
-            ('properties', formatting.as_raw_dict(self.properties)),
-            ('interface_templates', 
formatting.as_raw_list(self.interface_templates))))
-
-    def instantiate(self, container):
-        from . import models
-        relationship_model = models.Relationship(name=self.name,
-                                                 type=self.type,
-                                                 relationship_template=self)
-        utils.instantiate_dict(container, relationship_model.properties, 
self.properties)
-        utils.instantiate_dict(container, relationship_model.interfaces, 
self.interface_templates)
-        return relationship_model
-
-    def validate(self):
-        # TODO: either type or name must be set
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.interface_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.interface_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type is not None:
-            console.puts('Relationship type: 
{0}'.format(context.style.type(self.type.name)))
-        else:
-            console.puts('Relationship template: {0}'.format(
-                context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interface_templates, 'Interface 
templates')
-
-
-class CapabilityTemplateBase(TemplateModelMixin):
-    """
-    Template for creating :class:`Capability` instances, typed attachments 
which serve two purposes:
-    to provide extra properties and attributes to :class:`Node` instances, and 
to expose targets for
-    :class:`Relationship` instances from other nodes.
-    """
-
-    __tablename__ = 'capability_template'
-
-    __private_fields__ = ('type_fk',
-                          'node_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def capabilities(cls):
-        """
-        Instantiated capabilities.
-
-        :type: [:class:`Capability`]
-        """
-        return relationship.one_to_many(cls, 'capability')
-
-    @declared_attr
-    def properties(cls):
-        """
-        Declarations for associated immutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Property`}
-        """
-        return relationship.one_to_many(cls, 'property', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def node_template(cls):
-        """
-        Containing node template.
-
-        :type: :class:`NodeTemplate`
-        """
-        return relationship.many_to_one(cls, 'node_template')
-
-    @declared_attr
-    def type(cls):
-        """
-        Capability type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region many_to_many relationships
-
-    @declared_attr
-    def valid_source_node_types(cls):
-        """
-        Reject requirements that are not from these node types.
-
-        :type: [:class:`Type`]
-        """
-        return relationship.many_to_many(cls, 'type', prefix='valid_sources')
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For CapabilityTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to CapabilityTemplate"""
-        return relationship.foreign_key('node_template')
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    min_occurrences = Column(Integer, default=None, doc="""
-    Minimum number of requirement matches required.
-
-    :type: :obj:`int`
-    """)
-
-    max_occurrences = Column(Integer, default=None, doc="""
-    Maximum number of requirement matches allowed.
-
-    :type: :obj:`int`
-    """)
-
-    def satisfies_requirement(self,
-                              source_node_template,
-                              requirement,
-                              target_node_template):
-        # Do we match the required capability type?
-        if requirement.target_capability_type and \
-            requirement.target_capability_type.get_descendant(self.type.name) 
is None:
-            return False
-
-        # Are we in valid_source_node_types?
-        if self.valid_source_node_types:
-            for valid_source_node_type in self.valid_source_node_types:
-                if 
valid_source_node_type.get_descendant(source_node_template.type.name) is None:
-                    return False
-
-        # Apply requirement constraints
-        if requirement.target_node_template_constraints:
-            for node_template_constraint in 
requirement.target_node_template_constraints:
-                if not node_template_constraint.matches(source_node_template, 
target_node_template):
-                    return False
-
-        return True
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('type_name', self.type.name),
-            ('min_occurrences', self.min_occurrences),
-            ('max_occurrences', self.max_occurrences),
-            ('valid_source_node_types', [v.name for v in 
self.valid_source_node_types]),
-            ('properties', formatting.as_raw_dict(self.properties))))
-
-    def instantiate(self, container):
-        from . import models
-        capability = models.Capability(name=self.name,
-                                       type=self.type,
-                                       min_occurrences=self.min_occurrences,
-                                       max_occurrences=self.max_occurrences,
-                                       occurrences=0,
-                                       capability_template=self)
-        utils.instantiate_dict(container, capability.properties, 
self.properties)
-        return capability
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: 
{0}'.format(context.style.type(self.type.name)))
-            console.puts(
-                'Occurrences: {0:d}{1}'.format(
-                    self.min_occurrences or 0,
-                    ' to {0:d}'.format(self.max_occurrences)
-                    if self.max_occurrences is not None
-                    else ' or more'))
-            if self.valid_source_node_types:
-                console.puts('Valid source node types: {0}'.format(
-                    ', '.join((str(context.style.type(v.name))
-                               for v in self.valid_source_node_types))))
-            utils.dump_dict_values(self.properties, 'Properties')
-
-
-class InterfaceTemplateBase(TemplateModelMixin):
-    """
-    Template for creating :class:`Interface` instances, which are typed 
bundles of
-    :class:`Operation` instances.
-
-    Can be associated with a :class:`NodeTemplate`, a :class:`GroupTemplate`, 
or a
-    :class:`RelationshipTemplate`.
-    """
-
-    __tablename__ = 'interface_template'
-
-    __private_fields__ = ('type_fk',
-                          'node_template_fk',
-                          'group_template_fk',
-                          'relationship_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def inputs(cls):
-        """
-        Declarations for externally provided parameters that can be used by 
all operations of the
-        interface.
-
-        :type: {:obj:`basestring`: :class:`Input`}
-        """
-        return relationship.one_to_many(cls, 'input', dict_key='name')
-
-    @declared_attr
-    def interfaces(cls):
-        """
-        Instantiated interfaces.
-
-        :type: [:class:`Interface`]
-        """
-        return relationship.one_to_many(cls, 'interface')
-
-    @declared_attr
-    def operation_templates(cls):
-        """
-        Associated operation templates.
-
-        :type: {:obj:`basestring`: :class:`OperationTemplate`}
-        """
-        return relationship.one_to_many(cls, 'operation_template', 
dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def node_template(cls):
-        """
-        Containing node template (can be ``None``).
-
-        :type: :class:`NodeTemplate`
-        """
-        return relationship.many_to_one(cls, 'node_template')
-
-    @declared_attr
-    def group_template(cls):
-        """
-        Containing group template (can be ``None``).
-
-        :type: :class:`GroupTemplate`
-        """
-        return relationship.many_to_one(cls, 'group_template')
-
-    @declared_attr
-    def relationship_template(cls):
-        """
-        Containing relationship template (can be ``None``).
-
-        :type: :class:`RelationshipTemplate`
-        """
-        return relationship.many_to_one(cls, 'relationship_template')
-
-    @declared_attr
-    def type(cls):
-        """
-        Interface type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For InterfaceTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to InterfaceTemplate"""
-        return relationship.foreign_key('node_template', nullable=True)
-
-    @declared_attr
-    def group_template_fk(cls):
-        """For GroupTemplate one-to-many to InterfaceTemplate"""
-        return relationship.foreign_key('group_template', nullable=True)
-
-    @declared_attr
-    def relationship_template_fk(cls):
-        """For RelationshipTemplate one-to-many to InterfaceTemplate"""
-        return relationship.foreign_key('relationship_template', nullable=True)
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('type_name', self.type.name),
-            ('inputs', formatting.as_raw_dict(self.inputs)),  # pylint: 
disable=no-member
-            # TODO fix self.properties reference
-            ('operation_templates', 
formatting.as_raw_list(self.operation_templates))))
-
-    def instantiate(self, container):
-        from . import models
-        interface = models.Interface(name=self.name,
-                                     type=self.type,
-                                     
description=deepcopy_with_locators(self.description),
-                                     interface_template=self)
-        utils.instantiate_dict(container, interface.inputs, self.inputs)
-        utils.instantiate_dict(container, interface.operations, 
self.operation_templates)
-        return interface
-
-    def validate(self):
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.operation_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.operation_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Interface type: 
{0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            utils.dump_dict_values(self.operation_templates, 'Operation 
templates')
-
-
-class OperationTemplateBase(TemplateModelMixin):
-    """
-    Template for creating :class:`Operation` instances, which are entry points 
to Python functions
-    called as part of a workflow execution.
-    """
-
-    __tablename__ = 'operation_template'
-
-    __private_fields__ = ('service_template_fk',
-                          'interface_template_fk',
-                          'plugin_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    @declared_attr
-    def plugin_specification(cls):
-        """
-        Associated plugin specification.
-
-        :type: :class:`PluginSpecification`
-        """
-        return relationship.one_to_one(
-            cls, 'plugin_specification', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def operations(cls):
-        """
-        Instantiated operations.
-
-        :type: [:class:`Operation`]
-        """
-        return relationship.one_to_many(cls, 'operation')
-
-    @declared_attr
-    def inputs(cls):
-        """
-        Declarations for parameters provided to the :attr:`implementation`.
-
-        :type: {:obj:`basestring`: :class:`Input`}
-        """
-        return relationship.one_to_many(cls, 'input', dict_key='name')
-
-    @declared_attr
-    def configurations(cls):
-        """
-        Configuration parameters for the operation instance Python 
:attr:`function`.
-
-        :type: {:obj:`basestring`: :class:`Configuration`}
-        """
-        return relationship.one_to_many(cls, 'configuration', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def service_template(cls):
-        """
-        Containing service template (can be ``None``). For workflow operation 
templates.
-
-        :type: :class:`ServiceTemplate`
-        """
-        return relationship.many_to_one(cls, 'service_template',
-                                        back_populates='workflow_templates')
-
-    @declared_attr
-    def interface_template(cls):
-        """
-        Containing interface template (can be ``None``).
-
-        :type: :class:`InterfaceTemplate`
-        """
-        return relationship.many_to_one(cls, 'interface_template')
-
-    # endregion
-
-    # region many_to_many relationships
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to OperationTemplate"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    @declared_attr
-    def interface_template_fk(cls):
-        """For InterfaceTemplate one-to-many to OperationTemplate"""
-        return relationship.foreign_key('interface_template', nullable=True)
-
-    @declared_attr
-    def plugin_specification_fk(cls):
-        """For OperationTemplate one-to-one to PluginSpecification"""
-        return relationship.foreign_key('plugin_specification', nullable=True)
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    relationship_edge = Column(Boolean, doc="""
-    When ``True`` specifies that the operation is on the relationship's target 
edge; ``False`` is
-    the source edge (only used by operations on relationships)
-
-    :type: :obj:`bool`
-    """)
-
-    implementation = Column(Text, doc="""
-    Implementation (usually the name of an artifact).
-
-    :type: :obj:`basestring`
-    """)
-
-    dependencies = Column(modeling_types.StrictList(item_cls=basestring), 
doc="""
-    Dependencies (usually names of artifacts).
-
-    :type: [:obj:`basestring`]
-    """)
-
-    function = Column(Text, doc="""
-    Full path to Python function.
-
-    :type: :obj:`basestring`
-    """)
-
-    executor = Column(Text, doc="""
-    Name of executor.
-
-    :type: :obj:`basestring`
-    """)
-
-    max_attempts = Column(Integer, doc="""
-    Maximum number of attempts allowed in case of task failure.
-
-    :type: :obj:`int`
-    """)
-
-    retry_interval = Column(Integer, doc="""
-    Interval between task retry attemps (in seconds).
-
-    :type: :obj:`float`
-    """)
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('implementation', self.implementation),
-            ('dependencies', self.dependencies),
-            ('inputs', formatting.as_raw_dict(self.inputs))))
-
-    def instantiate(self, container):
-        from . import models
-
-        plugin = self.plugin_specification.plugin \
-            if (self.plugin_specification is not None) and 
self.plugin_specification.enabled \
-            else None
-
-        operation = models.Operation(name=self.name,
-                                     
description=deepcopy_with_locators(self.description),
-                                     relationship_edge=self.relationship_edge,
-                                     implementation=self.implementation,
-                                     dependencies=self.dependencies,
-                                     executor=self.executor,
-                                     plugin=plugin,
-                                     function=self.function,
-                                     max_attempts=self.max_attempts,
-                                     retry_interval=self.retry_interval,
-                                     operation_template=self)
-
-        utils.instantiate_dict(container, operation.inputs, self.inputs)
-        utils.instantiate_dict(container, operation.configurations, 
self.configurations)
-
-        return operation
-
-    def validate(self):
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.configurations)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.configurations, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            if self.implementation is not None:
-                console.puts('Implementation: {0}'.format(
-                    context.style.literal(self.implementation)))
-            if self.dependencies:
-                console.puts('Dependencies: {0}'.format(
-                    ', '.join((str(context.style.literal(v)) for v in 
self.dependencies))))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            if self.executor is not None:
-                console.puts('Executor: 
{0}'.format(context.style.literal(self.executor)))
-            if self.max_attempts is not None:
-                console.puts('Max attempts: 
{0}'.format(context.style.literal(self.max_attempts)))
-            if self.retry_interval is not None:
-                console.puts('Retry interval: {0}'.format(
-                    context.style.literal(self.retry_interval)))
-            if self.plugin_specification is not None:
-                console.puts('Plugin specification: {0}'.format(
-                    context.style.literal(self.plugin_specification.name)))
-            utils.dump_dict_values(self.configurations, 'Configuration')
-            if self.function is not None:
-                console.puts('Function: 
{0}'.format(context.style.literal(self.function)))
-
-
-class ArtifactTemplateBase(TemplateModelMixin):
-    """
-    Template for creating an :class:`Artifact` instance, which is a typed 
file, either provided in a
-    CSAR or downloaded from a repository.
-    """
-
-    __tablename__ = 'artifact_template'
-
-    __private_fields__ = ('type_fk',
-                          'node_template_fk')
-
-    # region association proxies
-
-    # endregion
-
-    # region one_to_one relationships
-
-    # endregion
-
-    # region one_to_many relationships
-
-    @declared_attr
-    def artifacts(cls):
-        """
-        Instantiated artifacts.
-
-        :type: [:class:`Artifact`]
-        """
-        return relationship.one_to_many(cls, 'artifact')
-
-    @declared_attr
-    def properties(cls):
-        """
-        Declarations for associated immutable parameters.
-
-        :type: {:obj:`basestring`: :class:`Property`}
-        """
-        return relationship.one_to_many(cls, 'property', dict_key='name')
-
-    # endregion
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def node_template(cls):
-        """
-        Containing node template.
-
-        :type: :class:`NodeTemplate`
-        """
-        return relationship.many_to_one(cls, 'node_template')
-
-    @declared_attr
-    def type(cls):
-        """
-        Artifact type.
-
-        :type: :class:`Type`
-        """
-        return relationship.many_to_one(cls, 'type', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def type_fk(cls):
-        """For ArtifactTemplate many-to-one to Type"""
-        return relationship.foreign_key('type')
-
-    @declared_attr
-    def node_template_fk(cls):
-        """For NodeTemplate one-to-many to ArtifactTemplate"""
-        return relationship.foreign_key('node_template')
-
-    # endregion
-
-    description = Column(Text, doc="""
-    Human-readable description.
-
-    :type: :obj:`basestring`
-    """)
-
-    source_path = Column(Text, doc="""
-    Source path (in CSAR or repository).
-
-    :type: :obj:`basestring`
-    """)
-
-    target_path = Column(Text, doc="""
-    Path at which to install at destination.
-
-    :type: :obj:`basestring`
-    """)
-
-    repository_url = Column(Text, doc="""
-    Repository URL.
-
-    :type: :obj:`basestring`
-    """)
-
-    repository_credential = Column(modeling_types.StrictDict(basestring, 
basestring), doc="""
-    Credentials for accessing the repository.
-
-    :type: {:obj:`basestring`, :obj:`basestring`}
-    """)
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('description', self.description),
-            ('type_name', self.type.name),
-            ('source_path', self.source_path),
-            ('target_path', self.target_path),
-            ('repository_url', self.repository_url),
-            ('repository_credential', 
formatting.as_agnostic(self.repository_credential)),
-            ('properties', formatting.as_raw_dict(self.properties))))
-
-    def instantiate(self, container):
-        from . import models
-        artifact = models.Artifact(name=self.name,
-                                   type=self.type,
-                                   
description=deepcopy_with_locators(self.description),
-                                   source_path=self.source_path,
-                                   target_path=self.target_path,
-                                   repository_url=self.repository_url,
-                                   
repository_credential=self.repository_credential,
-                                   artifact_template=self)
-        utils.instantiate_dict(container, artifact.properties, self.properties)
-        return artifact
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Artifact type: 
{0}'.format(context.style.type(self.type.name)))
-            console.puts('Source path: 
{0}'.format(context.style.literal(self.source_path)))
-            if self.target_path is not None:
-                console.puts('Target path: 
{0}'.format(context.style.literal(self.target_path)))
-            if self.repository_url is not None:
-                console.puts('Repository URL: {0}'.format(
-                    context.style.literal(self.repository_url)))
-            if self.repository_credential:
-                console.puts('Repository credential: {0}'.format(
-                    context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(self.properties, 'Properties')
-
-
-class PluginSpecificationBase(TemplateModelMixin):
-    """
-    Requirement for a :class:`Plugin`.
-
-    The actual plugin to be selected depends on those currently installed in 
ARIA.
-    """
-
-    __tablename__ = 'plugin_specification'
-
-    __private_fields__ = ('service_template_fk',
-                          'plugin_fk')
-
-    version = Column(Text, doc="""
-    Minimum plugin version.
-
-    :type: :obj:`basestring`
-    """)
-
-    enabled = Column(Boolean, nullable=False, default=True, doc="""
-    Whether the plugin is enabled.
-
-    :type: :obj:`bool`
-    """)
-
-    # region many_to_one relationships
-
-    @declared_attr
-    def service_template(cls):
-        """
-        Containing service template.
-
-        :type: :class:`ServiceTemplate`
-        """
-        return relationship.many_to_one(cls, 'service_template')
-
-    @declared_attr
-    def plugin(cls): # pylint: disable=method-hidden
-        """
-        Matched plugin.
-
-        :type: :class:`Plugin`
-        """
-        return relationship.many_to_one(cls, 'plugin', 
back_populates=relationship.NO_BACK_POP)
-
-    # endregion
-
-    # region foreign keys
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to PluginSpecification"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    @declared_attr
-    def plugin_fk(cls):
-        """For PluginSpecification many-to-one to Plugin"""
-        return relationship.foreign_key('plugin', nullable=True)
-
-    # endregion
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('version', self.version),
-            ('enabled', self.enabled)))
-
-    def coerce_values(self, report_issues):
-        pass
-
-    def resolve(self, model_storage):
-        # TODO: we are planning a separate "instantiation" module where this 
will be called or
-        # moved to.
-        plugins = model_storage.plugin.list()
-        matching_plugins = []
-        if plugins:
-            for plugin in plugins:
-                if (plugin.name == self.name) and \
-                    ((self.version is None) or \
-                     (VersionString(plugin.package_version) >= self.version)):
-                    matching_plugins.append(plugin)
-        self.plugin = None
-        if matching_plugins:
-            # Return highest version of plugin
-            key = lambda plugin: VersionString(plugin.package_version).key
-            self.plugin = sorted(matching_plugins, key=key)[-1]
-        return self.plugin is not None

Reply via email to