You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by em...@apache.org on 2017/03/12 21:49:13 UTC

[1/2] incubator-ariatosca git commit: Remove dependency on context, modeling exceptions, some refactoring

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-105-integrate-modeling dd5bfa930 -> 16a945383


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/parser/consumption/modeling.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/modeling.py b/aria/parser/consumption/modeling.py
index f4e71a5..4847ba7 100644
--- a/aria/parser/consumption/modeling.py
+++ b/aria/parser/consumption/modeling.py
@@ -17,49 +17,52 @@ from ...utils.formatting import json_dumps, yaml_dumps
 from .consumer import Consumer, ConsumerChain
 
 
-class Derive(Consumer):
+class DeriveServiceTemplate(Consumer):
     """
-    Derives the service model.
+    Derives the service template from the presenter.
     """
 
     def consume(self):
         if self.context.presentation.presenter is None:
-            self.context.validation.report('Derive consumer: missing presenter')
+            self.context.validation.report('DeriveServiceTemplate consumer: missing presenter')
             return
 
         if not hasattr(self.context.presentation.presenter, '_get_model'):
-            self.context.validation.report('Derive consumer: presenter does not support '
-                                           '"_get_model"')
+            self.context.validation.report('DeriveServiceTemplate consumer: presenter does not'
+                                           ' support "_get_model"')
             return
 
         self.context.modeling.template = \
             self.context.presentation.presenter._get_model(self.context)
 
 
-class CoerceModelValues(Consumer):
+class CoerceServiceTemplateValues(Consumer):
     """
-    Coerces values in the service model.
+    Coerces values in the service template.
     """
 
     def consume(self):
-        self.context.modeling.template.coerce_values(self.context, None, True)
+        self.context.modeling.template.coerce_values(None, True)
 
 
-class ValidateModel(Consumer):
+class ValidateServiceTemplate(Consumer):
     """
-    Validates the service model.
+    Validates the service template.
     """
 
     def consume(self):
-        self.context.modeling.template.validate(self.context)
+        self.context.modeling.template.validate()
 
-class Model(ConsumerChain):
+
+class ServiceTemplate(ConsumerChain):
     """
-    Generates the service model by deriving it from the presentation.
+    Generates the service template from the presenter.
     """
 
     def __init__(self, context):
-        super(Model, self).__init__(context, (Derive, CoerceModelValues, ValidateModel))
+        super(ServiceTemplate, self).__init__(context, (DeriveServiceTemplate,
+                                                        CoerceServiceTemplateValues,
+                                                        ValidateServiceTemplate))
 
     def dump(self):
         if self.context.has_arg_switch('yaml'):
@@ -71,7 +74,8 @@ class Model(ConsumerChain):
             raw = self.context.modeling.template_as_raw
             self.context.write(json_dumps(raw, indent=indent))
         else:
-            self.context.modeling.template.dump(self.context)
+            self.context.modeling.template.dump()
+
 
 class Types(Consumer):
     """
@@ -88,35 +92,40 @@ class Types(Consumer):
             raw = self.context.modeling.types_as_raw
             self.context.write(json_dumps(raw, indent=indent))
         else:
-            self.context.modeling.dump_types(self.context)
+            self.context.modeling.template.dump_types()
 
-class Instantiate(Consumer):
+
+class InstantiateServiceInstance(Consumer):
     """
-    Instantiates the service model.
+    Instantiates the service template into a service instance.
     """
 
     def consume(self):
         if self.context.modeling.template is None:
-            self.context.validation.report('Instantiate consumer: missing service model')
+            self.context.validation.report('InstantiateServiceInstance consumer: missing service '
+                                           'model')
             return
 
-        self.context.modeling.template.instantiate(self.context, None)
+        self.context.modeling.template.instantiate(None)
+
 
-class CoerceInstanceValues(Consumer):
+class CoerceServiceInstanceValues(Consumer):
     """
     Coerces values in the service instance.
     """
 
     def consume(self):
-        self.context.modeling.instance.coerce_values(self.context, None, True)
+        self.context.modeling.instance.coerce_values(None, True)
 
-class ValidateInstance(Consumer):
+
+class ValidateServiceInstance(Consumer):
     """
     Validates the service instance.
     """
 
     def consume(self):
-        self.context.modeling.instance.validate(self.context)
+        self.context.modeling.instance.validate()
+
 
 class SatisfyRequirements(Consumer):
     """
@@ -124,7 +133,8 @@ class SatisfyRequirements(Consumer):
     """
 
     def consume(self):
-        self.context.modeling.instance.satisfy_requirements(self.context)
+        self.context.modeling.instance.satisfy_requirements()
+
 
 class ValidateCapabilities(Consumer):
     """
@@ -132,22 +142,27 @@ class ValidateCapabilities(Consumer):
     """
 
     def consume(self):
-        self.context.modeling.instance.validate_capabilities(self.context)
+        self.context.modeling.instance.validate_capabilities()
+
 
-class Instance(ConsumerChain):
+class ServiceInstance(ConsumerChain):
     """
-    Generates the service instance by instantiating the service model.
+    Generates the service instance by instantiating the service template.
     """
 
     def __init__(self, context):
-        super(Instance, self).__init__(context, (Instantiate, CoerceInstanceValues,
-                                                 ValidateInstance, CoerceInstanceValues,
-                                                 SatisfyRequirements, CoerceInstanceValues,
-                                                 ValidateCapabilities, CoerceInstanceValues))
+        super(ServiceInstance, self).__init__(context, (InstantiateServiceInstance,
+                                                        CoerceServiceInstanceValues,
+                                                        ValidateServiceInstance,
+                                                        CoerceServiceInstanceValues,
+                                                        SatisfyRequirements,
+                                                        CoerceServiceInstanceValues,
+                                                        ValidateCapabilities,
+                                                        CoerceServiceInstanceValues))
 
     def dump(self):
         if self.context.has_arg_switch('graph'):
-            self.context.modeling.instance.dump_graph(self.context)
+            self.context.modeling.instance.dump_graph()
         elif self.context.has_arg_switch('yaml'):
             indent = self.context.get_arg_value_int('indent', 2)
             raw = self.context.modeling.instance_as_raw
@@ -157,4 +172,4 @@ class Instance(ConsumerChain):
             raw = self.context.modeling.instance_as_raw
             self.context.write(json_dumps(raw, indent=indent))
         else:
-            self.context.modeling.instance.dump(self.context)
+            self.context.modeling.instance.dump()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/parser/reading/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/__init__.py b/aria/parser/reading/__init__.py
index 32aa5b5..b5c0709 100644
--- a/aria/parser/reading/__init__.py
+++ b/aria/parser/reading/__init__.py
@@ -13,7 +13,7 @@
 from .raw import RawReader
 from .reader import Reader
 from .yaml import YamlReader
-from .locator import Locator
+from .locator import (Locator, deepcopy_with_locators, copy_locators)
 from .json import JsonReader
 from .jinja import JinjaReader
 from .context import ReadingContext
@@ -34,6 +34,8 @@ __all__ = (
     'ReadingContext',
     'RawReader',
     'Locator',
+    'deepcopy_with_locators',
+    'copy_locators',
     'YamlReader',
     'JsonReader',
     'JinjaReader')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/parser/reading/locator.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/locator.py b/aria/parser/reading/locator.py
index a1cfa9c..4142ee7 100644
--- a/aria/parser/reading/locator.py
+++ b/aria/parser/reading/locator.py
@@ -10,12 +10,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from copy import deepcopy
+
+
 from ...utils.console import puts, Colored, indent
 
+
 # We are inheriting the primitive types in order to add the ability to set
 # an attribute (_locator) on them.
 
-
 class LocatableString(unicode):
     pass
 
@@ -117,3 +120,35 @@ class Locator(object):
     def __str__(self):
         # Should be in same format as Issue.locator_as_str
         return '"%s":%d:%d' % (self.location, self.line, self.column)
+
+
+def deepcopy_with_locators(value):
+    """
+    Like :code:`deepcopy`, but also copies over locators.
+    """
+
+    res = deepcopy(value)
+    copy_locators(res, value)
+    return res
+
+
+def copy_locators(target, source):
+    """
+    Copies over :code:`_locator` for all elements, recursively.
+
+    Assumes that target and source have exactly the same list/dict structure.
+    """
+
+    locator = getattr(source, '_locator', None)
+    if locator is not None:
+        try:
+            setattr(target, '_locator', locator)
+        except AttributeError:
+            pass
+
+    if isinstance(target, list) and isinstance(source, list):
+        for i, _ in enumerate(target):
+            copy_locators(target[i], source[i])
+    elif isinstance(target, dict) and isinstance(source, dict):
+        for k, v in target.items():
+            copy_locators(v, source[k])

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/tests/end2end/test_tosca_simple_v1_0.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_tosca_simple_v1_0.py b/tests/end2end/test_tosca_simple_v1_0.py
index f2a41ce..4658fc3 100644
--- a/tests/end2end/test_tosca_simple_v1_0.py
+++ b/tests/end2end/test_tosca_simple_v1_0.py
@@ -71,7 +71,7 @@ def test_use_case_network_4():
 
 
 def test_use_case_webserver_dbms_1():
-    consume_use_case('webserver-dbms-1', 'model')
+    consume_use_case('webserver-dbms-1', 'template')
 
 
 def test_use_case_webserver_dbms_2():
@@ -83,7 +83,7 @@ def test_use_case_multi_tier_1():
 
 
 def test_use_case_container_1():
-    consume_use_case('container-1', 'model')
+    consume_use_case('container-1', 'template')
 
 
 # NodeCellar
@@ -101,7 +101,7 @@ def test_node_cellar_presentation():
 
 
 def test_node_cellar_model():
-    consume_node_cellar('model')
+    consume_node_cellar('template')
 
 
 def test_node_cellar_types():

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/tests/parser/utils.py
----------------------------------------------------------------------
diff --git a/tests/parser/utils.py b/tests/parser/utils.py
index 994aac6..8460de8 100644
--- a/tests/parser/utils.py
+++ b/tests/parser/utils.py
@@ -21,10 +21,10 @@ from aria.parser.consumption import (
     ConsumerChain,
     Read,
     Validate,
-    Model,
+    ServiceTemplate,
     Types,
     Inputs,
-    Instance
+    ServiceInstance
 )
 from aria.utils.imports import import_fullname
 
@@ -66,14 +66,14 @@ def create_consumer(context, consumer_class_name):
         dumper = None
     elif consumer_class_name == 'presentation':
         dumper = consumer.consumers[0]
-    elif consumer_class_name == 'model':
-        consumer.append(Model)
+    elif consumer_class_name == 'template':
+        consumer.append(ServiceTemplate)
     elif consumer_class_name == 'types':
-        consumer.append(Model, Types)
+        consumer.append(ServiceTemplate, Types)
     elif consumer_class_name == 'instance':
-        consumer.append(Model, Inputs, Instance)
+        consumer.append(ServiceTemplate, Inputs, ServiceInstance)
     else:
-        consumer.append(Model, Inputs, Instance)
+        consumer.append(ServiceTemplate, Inputs, ServiceInstance)
         consumer.append(import_fullname(consumer_class_name))
 
     if dumper is None:


[2/2] incubator-ariatosca git commit: Remove dependency on context, modeling exceptions, some refactoring

Posted by em...@apache.org.
Remove dependency on context, modeling exceptions, some refactoring


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

Branch: refs/heads/ARIA-105-integrate-modeling
Commit: 16a945383eb5cc6f8d4c97a3c6369e3bf235b1e8
Parents: dd5bfa9
Author: Tal Liron <ta...@gmail.com>
Authored: Sun Mar 12 16:48:58 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Sun Mar 12 16:48:58 2017 -0500

----------------------------------------------------------------------
 aria/cli/args_parser.py                 |   2 +-
 aria/cli/commands.py                    |  17 +-
 aria/cli/dry.py                         |  13 +
 aria/modeling/exceptions.py             |  14 +-
 aria/modeling/mixins.py                 |   8 +-
 aria/modeling/service_common.py         |  26 +-
 aria/modeling/service_instance.py       | 304 ++++++++++++----------
 aria/modeling/service_template.py       | 373 ++++++++++++++-------------
 aria/modeling/utils.py                  |  84 ++----
 aria/parser/consumption/__init__.py     |   6 +-
 aria/parser/consumption/modeling.py     |  83 +++---
 aria/parser/reading/__init__.py         |   4 +-
 aria/parser/reading/locator.py          |  37 ++-
 tests/end2end/test_tosca_simple_v1_0.py |   6 +-
 tests/parser/utils.py                   |  14 +-
 15 files changed, 538 insertions(+), 453 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/cli/args_parser.py
----------------------------------------------------------------------
diff --git a/aria/cli/args_parser.py b/aria/cli/args_parser.py
index 1d18145..81ee513 100644
--- a/aria/cli/args_parser.py
+++ b/aria/cli/args_parser.py
@@ -91,7 +91,7 @@ def add_parse_parser(parse):
         'consumer',
         nargs='?',
         default='validate',
-        help='"validate" (default), "presentation", "model", "types", "instance", or consumer '
+        help='"validate" (default), "presentation", "template", "types", "instance", or consumer '
              'class name (full class path or short name)')
     parse.add_argument(
         '--loader-source',

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/cli/commands.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands.py b/aria/cli/commands.py
index a9079c5..f9d3053 100644
--- a/aria/cli/commands.py
+++ b/aria/cli/commands.py
@@ -36,10 +36,10 @@ from ..parser.consumption import (
     ConsumerChain,
     Read,
     Validate,
-    Model,
+    ServiceTemplate,
     Types,
     Inputs,
-    Instance
+    ServiceInstance
 )
 from ..parser.loading import LiteralLocation, UriLocation
 from ..utils.application import StorageManager
@@ -157,14 +157,14 @@ class ParseCommand(BaseCommand):
             dumper = None
         elif consumer_class_name == 'presentation':
             dumper = consumer.consumers[0]
-        elif consumer_class_name == 'model':
-            consumer.append(Model)
+        elif consumer_class_name == 'template':
+            consumer.append(ServiceTemplate)
         elif consumer_class_name == 'types':
-            consumer.append(Model, Types)
+            consumer.append(ServiceTemplate, Types)
         elif consumer_class_name == 'instance':
-            consumer.append(Model, Inputs, Instance)
+            consumer.append(ServiceTemplate, Inputs, ServiceInstance)
         else:
-            consumer.append(Model, Inputs, Instance)
+            consumer.append(ServiceTemplate, Inputs, ServiceInstance)
             consumer.append(import_fullname(consumer_class_name))
 
         if dumper is None:
@@ -220,7 +220,8 @@ class WorkflowCommand(BaseCommand):
         # Parse
         context = ConsumptionContext()
         context.presentation.location = UriLocation(uri)
-        consumer = ConsumerChain(context, (Read, Validate, Model, Inputs, Instance))
+        consumer = ConsumerChain(context, (Read, Validate, ServiceTemplate, Inputs,
+                                           ServiceInstance))
         consumer.consume()
 
         if context.validation.dump_issues():

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/cli/dry.py
----------------------------------------------------------------------
diff --git a/aria/cli/dry.py b/aria/cli/dry.py
index 98b7217..114ab7a 100644
--- a/aria/cli/dry.py
+++ b/aria/cli/dry.py
@@ -26,6 +26,11 @@ _TERMINAL_LOCK = RLock()
 
 
 def convert_to_dry(service):
+    """
+    Converts all operations on the service (on workflows, node interfaces, and relationship
+    interfaces) to run dryly.
+    """
+
     for workflow in service.workflows:
         convert_operation_to_dry(workflow)
 
@@ -40,6 +45,10 @@ def convert_to_dry(service):
 
 
 def convert_operation_to_dry(oper):
+    """
+    Converts a single :class:`Operation` to run dryly.
+    """
+
     plugin = oper.plugin_specification.name \
         if oper.plugin_specification is not None else None
     if oper.inputs is None:
@@ -56,6 +65,10 @@ def convert_operation_to_dry(oper):
 
 @operation
 def dry_operation(ctx, _plugin, _implementation, **kwargs):
+    """
+    The dry operation simply prints out information about the operation to the console.
+    """
+
     with _TERMINAL_LOCK:
         print ctx.name
         if hasattr(ctx, 'relationship'):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/modeling/exceptions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/exceptions.py b/aria/modeling/exceptions.py
index df29a21..6931c78 100644
--- a/aria/modeling/exceptions.py
+++ b/aria/modeling/exceptions.py
@@ -16,7 +16,19 @@
 from ..exceptions import AriaException
 
 
-class CannotEvaluateFunctionException(AriaException):
+class ModelingException(AriaException):
+    """
+    ARIA modeling exception.
+    """
+
+
+class ValueFormatException(ModelingException):
+    """
+    ARIA modeling exception: the value is in the wrong format.
+    """
+
+
+class CannotEvaluateFunctionException(ModelingException):
     """
     ARIA modeling exception: cannot evaluate the function at this time.
     """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index 04497b5..b9e5079 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -384,13 +384,13 @@ class InstanceModelMixin(ModelMixin):
     def as_raw(self):
         raise NotImplementedError
 
-    def validate(self, context):
+    def validate(self):
         pass
 
-    def coerce_values(self, context, container, report_issues):
+    def coerce_values(self, container, report_issues):
         pass
 
-    def dump(self, context):
+    def dump(self):
         pass
 
 
@@ -401,5 +401,5 @@ class TemplateModelMixin(InstanceModelMixin):
     All model models can be instantiated into :class:`ServiceInstance` models.
     """
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         raise NotImplementedError

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index b3535a6..e6b3c8d 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -25,11 +25,12 @@ from sqlalchemy import (
 )
 from sqlalchemy.ext.declarative import declared_attr
 
-from ..storage import exceptions
+from ..parser.consumption import ConsumptionContext
 from ..utils import collections, formatting, console
 from .mixins import InstanceModelMixin, TemplateModelMixin
 from .types import List
 from . import utils
+from . import exceptions
 
 
 class ParameterBase(TemplateModelMixin):
@@ -68,8 +69,8 @@ class ParameterBase(TemplateModelMixin):
         try:
             return pickle.loads(self._value)
         except BaseException:
-            raise exceptions.StorageError('bad format for parameter of type "{0}": {1}'.format(
-                self.type_name, self._value))
+            raise exceptions.ValueFormatException('bad format for parameter of type "{0}": {1}'
+                                                  .format(self.type_name, self._value))
 
     @value.setter
     def value(self, value):
@@ -83,19 +84,20 @@ class ParameterBase(TemplateModelMixin):
                                                .format(self.type_name, value))
                 self._value = pickle.dumps(str(value))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         return models.Parameter(name=self.name,
                                 type_name=self.type_name,
                                 _value=self._value,
                                 description=self.description)
 
-    def coerce_values(self, context, container, report_issues):
+    def coerce_values(self, container, report_issues):
         if self.value is not None:
-            self.value = utils.coerce_value(context, container, self.value,
+            self.value = utils.coerce_value(container, self.value,
                                             report_issues)
 
-    def dump(self, context):
+    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),
@@ -189,12 +191,13 @@ class TypeBase(InstanceModelMixin):
         self._append_raw_children(types)
         return types
 
-    def dump(self, context):
+    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(context)
+                child.dump()
 
     def _append_raw_children(self, types):
         for child in self.children:
@@ -224,12 +227,13 @@ class MetadataBase(TemplateModelMixin):
             ('name', self.name),
             ('value', self.value)))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         return models.Metadata(name=self.name,
                                value=self.value)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('{0}: {1}'.format(
             context.style.property(self.name),
             context.style.literal(self.value)))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index ba18f73..613b371 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -26,6 +26,7 @@ from sqlalchemy.ext.declarative import declared_attr
 
 from .mixins import InstanceModelMixin
 from ..parser import validation
+from ..parser.consumption import ConsumptionContext
 from ..utils import collections, formatting, console
 
 from . import (
@@ -157,17 +158,17 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
 
     # endregion
 
-    def satisfy_requirements(self, context):
+    def satisfy_requirements(self):
         satisfied = True
         for node in self.nodes:
-            if not node.satisfy_requirements(context):
+            if not node.satisfy_requirements():
                 satisfied = False
         return satisfied
 
-    def validate_capabilities(self, context):
+    def validate_capabilities(self):
         satisfied = True
         for node in self.nodes:
-            if not node.validate_capabilities(context):
+            if not node.validate_capabilities():
                 satisfied = False
         return satisfied
 
@@ -192,21 +193,21 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
         return collections.FrozenList((group.name
                                        for group in self.find_groups(group_template_name)))
 
-    def is_node_a_target(self, context, target_node):
+    def is_node_a_target(self, target_node):
         for node in self.nodes:
-            if self._is_node_a_target(context, node, target_node):
+            if self._is_node_a_target(node, target_node):
                 return True
         return False
 
-    def _is_node_a_target(self, context, source_node, target_node):
-        if source_node.relationships:
-            for relationship in source_node.relationships:
-                if relationship.target_node_id == target_node.name:
+    def _is_node_a_target(self, source_node, target_node):
+        if source_node.outbound_relationships:
+            for relationship in source_node.outbound_relationships:
+                if relationship.target_node.name == target_node.name:
                     return True
                 else:
-                    node = context.modeling.instance.nodes.get(relationship.target_node_id)
+                    node = relationship.target_node
                     if node is not None:
-                        if self._is_node_a_target(context, node, target_node):
+                        if self._is_node_a_target(node, target_node):
                             return True
         return False
 
@@ -223,67 +224,74 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
             ('outputs', formatting.as_raw_dict(self.outputs)),
             ('workflows', formatting.as_raw_list(self.workflows))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.meta_data)
-        utils.validate_list_values(context, self.nodes)
-        utils.validate_list_values(context, self.groups)
-        utils.validate_list_values(context, self.policies)
+    def validate(self):
+        utils.validate_dict_values(self.meta_data)
+        utils.validate_list_values(self.nodes)
+        utils.validate_list_values(self.groups)
+        utils.validate_list_values(self.policies)
         if self.substitution is not None:
-            self.substitution.validate(context)
-        utils.validate_dict_values(context, self.inputs)
-        utils.validate_dict_values(context, self.outputs)
-        utils.validate_dict_values(context, self.workflows)
-
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.meta_data, report_issues)
-        utils.coerce_list_values(context, container, self.nodes, report_issues)
-        utils.coerce_list_values(context, container, self.groups, report_issues)
-        utils.coerce_list_values(context, container, self.policies, report_issues)
+            self.substitution.validate()
+        utils.validate_dict_values(self.inputs)
+        utils.validate_dict_values(self.outputs)
+        utils.validate_dict_values(self.workflows)
+
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.meta_data, report_issues)
+        utils.coerce_list_values(container, self.nodes, report_issues)
+        utils.coerce_list_values(container, self.groups, report_issues)
+        utils.coerce_list_values(container, self.policies, report_issues)
         if self.substitution is not None:
-            self.substitution.coerce_values(context, container, report_issues)
-        utils.coerce_dict_values(context, container, self.inputs, report_issues)
-        utils.coerce_dict_values(context, container, self.outputs, report_issues)
-        utils.coerce_dict_values(context, container, self.workflows, report_issues)
+            self.substitution.coerce_values(container, report_issues)
+        utils.coerce_dict_values(container, self.inputs, report_issues)
+        utils.coerce_dict_values(container, self.outputs, report_issues)
+        utils.coerce_dict_values(container, self.workflows, report_issues)
 
-    def dump(self, context):
+    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(context, self.meta_data, 'Metadata')
+        utils.dump_dict_values(self.meta_data, 'Metadata')
         for node in self.nodes:
-            node.dump(context)
+            node.dump()
         for group in self.groups:
-            group.dump(context)
+            group.dump()
         for policy in self.policies:
-            policy.dump(context)
+            policy.dump()
         if self.substitution is not None:
-            self.substitution.dump(context)
-        utils.dump_dict_values(context, self.inputs, 'Inputs')
-        utils.dump_dict_values(context, self.outputs, 'Outputs')
-        utils.dump_dict_values(context, self.workflows, 'Workflows')
+            self.substitution.dump()
+        utils.dump_dict_values(self.inputs, 'Inputs')
+        utils.dump_dict_values(self.outputs, 'Outputs')
+        utils.dump_dict_values(self.workflows, 'Workflows')
 
-    def dump_graph(self, context):
-        for node in self.nodes.itervalues():
-            if not self.is_node_a_target(context, node):
-                self._dump_graph_node(context, node)
+    def dump_graph(self):
+        for node in self.nodes:
+            if not self.is_node_a_target(node):
+                self._dump_graph_node(node)
 
-    def _dump_graph_node(self, context, node):
+    def _dump_graph_node(self, node):
+        context = ConsumptionContext.get_thread_local()
         console.puts(context.style.node(node.name))
-        if node.relationships:
+        if node.outbound_relationships:
             with context.style.indent:
-                for relationship in node.relationships:
-                    relationship_name = (context.style.node(relationship.template_name)
-                                         if relationship.template_name is not None
-                                         else context.style.type(relationship.type_name))
-                    capability_name = (context.style.node(relationship.target_capability_name)
-                                       if relationship.target_capability_name is not None
-                                       else None)
+                for relationship in node.outbound_relationships:
+                    if relationship.relationship_template is not None:
+                        relationship_name = context.style.node(
+                            relationship.relationship_template.name)
+                    elif relationship.type is not None:
+                        relationship_name = context.style.type(relationship.type.name)
+                    else:
+                        relationship_name = '?'
+                    if relationship.target_capability is not None:
+                        capability_name = context.style.node(relationship.target_capability.name)
+                    else:
+                        capability_name = None
                     if capability_name is not None:
                         console.puts('-> {0} {1}'.format(relationship_name, capability_name))
                     else:
                         console.puts('-> {0}'.format(relationship_name))
-                    target_node = self.nodes.get(relationship.target_node_id)
+                    target_node = relationship.target_node
                     with console.indent(3):
-                        self._dump_graph_node(context, target_node)
+                        self._dump_graph_node(target_node)
 
 
 class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
@@ -443,28 +451,29 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
 
     # endregion
 
-    def satisfy_requirements(self, context):
+    def satisfy_requirements(self):
         node_template = self.node_template
         satisfied = True
         for requirement_template in node_template.requirement_templates:
             # Find target template
             target_node_template, target_node_capability = \
-                requirement_template.find_target(context, node_template)
+                requirement_template.find_target(node_template)
             if target_node_template is not None:
-                satisfied = self._satisfy_capability(context,
-                                                     target_node_capability,
+                satisfied = self._satisfy_capability(target_node_capability,
                                                      target_node_template,
                                                      requirement_template)
             else:
+                context = ConsumptionContext.get_thread_local()
                 context.validation.report('requirement "{0}" of node "{1}" has no target node '
                                           'template'.format(requirement_template.name, self.name),
                                           level=validation.Issue.BETWEEN_INSTANCES)
                 satisfied = False
         return satisfied
 
-    def _satisfy_capability(self, context, target_node_capability, target_node_template,
+    def _satisfy_capability(self, target_node_capability, target_node_template,
                             requirement_template):
         from . import models
+        context = ConsumptionContext.get_thread_local()
         # Find target nodes
         target_nodes = context.modeling.instance.find_nodes(target_node_template.name)
         if target_nodes:
@@ -485,7 +494,7 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
             if target_node is not None:
                 if requirement_template.relationship_template is not None:
                     relationship = \
-                        requirement_template.relationship_template.instantiate(context, self)
+                        requirement_template.relationship_template.instantiate(self)
                 else:
                     relationship = models.Relationship(target_capability=target_capability)
                 relationship.name = requirement_template.name
@@ -511,7 +520,8 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
                                       level=validation.Issue.BETWEEN_INSTANCES)
             return False
 
-    def validate_capabilities(self, context):
+    def validate_capabilities(self):
+        context = ConsumptionContext.get_thread_local()
         satisfied = False
         for capability in self.capabilities.itervalues():
             if not capability.has_enough_relationships:
@@ -536,7 +546,8 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
             ('capabilities', formatting.as_raw_list(self.capabilities)),
             ('relationships', formatting.as_raw_list(self.outbound_relationships))))
 
-    def validate(self, context):
+    def validate(self):
+        context = ConsumptionContext.get_thread_local()
         if len(self.name) > context.modeling.id_max_length:
             context.validation.report('"{0}" has an ID longer than the limit of {1:d} characters: '
                                       '{2:d}'.format(
@@ -547,29 +558,30 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
 
         # TODO: validate that node template is of type?
 
-        utils.validate_dict_values(context, self.properties)
-        utils.validate_dict_values(context, self.interfaces)
-        utils.validate_dict_values(context, self.artifacts)
-        utils.validate_dict_values(context, self.capabilities)
-        utils.validate_list_values(context, self.outbound_relationships)
-
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.properties, report_issues)
-        utils.coerce_dict_values(context, self, self.interfaces, report_issues)
-        utils.coerce_dict_values(context, self, self.artifacts, report_issues)
-        utils.coerce_dict_values(context, self, self.capabilities, report_issues)
-        utils.coerce_list_values(context, self, self.outbound_relationships, report_issues)
-
-    def dump(self, context):
+        utils.validate_dict_values(self.properties)
+        utils.validate_dict_values(self.interfaces)
+        utils.validate_dict_values(self.artifacts)
+        utils.validate_dict_values(self.capabilities)
+        utils.validate_list_values(self.outbound_relationships)
+
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(self, self.properties, report_issues)
+        utils.coerce_dict_values(self, self.interfaces, report_issues)
+        utils.coerce_dict_values(self, self.artifacts, report_issues)
+        utils.coerce_dict_values(self, self.capabilities, report_issues)
+        utils.coerce_list_values(self, self.outbound_relationships, report_issues)
+
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('Node: {0}'.format(context.style.node(self.name)))
         with context.style.indent:
             console.puts('Type: {0}'.format(context.style.type(self.type.name)))
             console.puts('Template: {0}'.format(context.style.node(self.node_template.name)))
-            utils.dump_dict_values(context, self.properties, 'Properties')
-            utils.dump_interfaces(context, self.interfaces)
-            utils.dump_dict_values(context, self.artifacts, 'Artifacts')
-            utils.dump_dict_values(context, self.capabilities, 'Capabilities')
-            utils.dump_list_values(context, self.outbound_relationships, 'Relationships')
+            utils.dump_dict_values(self.properties, 'Properties')
+            utils.dump_interfaces(self.interfaces)
+            utils.dump_dict_values(self.artifacts, 'Artifacts')
+            utils.dump_dict_values(self.capabilities, 'Capabilities')
+            utils.dump_list_values(self.outbound_relationships, 'Relationships')
 
 
 class GroupBase(InstanceModelMixin):
@@ -652,20 +664,21 @@ class GroupBase(InstanceModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interfaces', formatting.as_raw_list(self.interfaces))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
-        utils.validate_dict_values(context, self.interfaces)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
+        utils.validate_dict_values(self.interfaces)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.properties, report_issues)
-        utils.coerce_dict_values(context, container, self.interfaces, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.properties, report_issues)
+        utils.coerce_dict_values(container, self.interfaces, report_issues)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('Group: {0}'.format(context.style.node(self.name)))
         with context.style.indent:
             console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(context, self.properties, 'Properties')
-            utils.dump_interfaces(context, self.interfaces)
+            utils.dump_dict_values(self.properties, 'Properties')
+            utils.dump_interfaces(self.interfaces)
             if self.nodes:
                 console.puts('Member nodes:')
                 with context.style.indent:
@@ -751,17 +764,18 @@ class PolicyBase(InstanceModelMixin):
             ('type_name', self.type_name),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.properties, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.properties, report_issues)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('Policy: {0}'.format(context.style.node(self.name)))
         with context.style.indent:
             console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(context, self.properties, 'Properties')
+            utils.dump_dict_values(self.properties, 'Properties')
             if self.nodes:
                 console.puts('Target nodes:')
                 with context.style.indent:
@@ -828,17 +842,18 @@ class SubstitutionBase(InstanceModelMixin):
             ('node_type_name', self.node_type_name),
             ('mappings', formatting.as_raw_dict(self.mappings))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.mappings)
+    def validate(self):
+        utils.validate_dict_values(self.mappings)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.mappings, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.mappings, report_issues)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('Substitution:')
         with context.style.indent:
             console.puts('Node type: {0}'.format(context.style.type(self.node_type.name)))
-            utils.dump_dict_values(context, self.mappings, 'Mappings')
+            utils.dump_dict_values(self.mappings, 'Mappings')
 
 
 class SubstitutionMappingBase(InstanceModelMixin):
@@ -910,7 +925,8 @@ class SubstitutionMappingBase(InstanceModelMixin):
         return collections.OrderedDict((
             ('name', self.name)))
 
-    def validate(self, context):
+    def validate(self):
+        context = ConsumptionContext.get_thread_local()
         if (self.capability is None) and (self.requirement_template is None):
             context.validation.report('mapping "{0}" refers to neither capability nor a requirement'
                                       ' in node: {1}'.format(
@@ -918,7 +934,8 @@ class SubstitutionMappingBase(InstanceModelMixin):
                                           formatting.safe_repr(self.node.name)),
                                       level=validation.Issue.BETWEEN_TYPES)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('{0} -> {1}.{2}'.format(
             context.style.node(self.name),
             context.style.node(self.node.name),
@@ -1046,15 +1063,16 @@ class RelationshipBase(InstanceModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interfaces', formatting.as_raw_list(self.interfaces))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
-        utils.validate_dict_values(context, self.interfaces)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
+        utils.validate_dict_values(self.interfaces)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.properties, report_issues)
-        utils.coerce_dict_values(context, container, self.interfaces, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.properties, report_issues)
+        utils.coerce_dict_values(container, self.interfaces, report_issues)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         if self.name:
             console.puts('{0} ->'.format(context.style.node(self.name)))
         else:
@@ -1069,8 +1087,8 @@ class RelationshipBase(InstanceModelMixin):
             if (self.relationship_template is not None) and self.relationship_template.name:
                 console.puts('Relationship template: {0}'.format(
                     context.style.node(self.relationship_template.name)))
-            utils.dump_dict_values(context, self.properties, 'Properties')
-            utils.dump_interfaces(context, self.interfaces, 'Interfaces')
+            utils.dump_dict_values(self.properties, 'Properties')
+            utils.dump_interfaces(self.interfaces, 'Interfaces')
 
 
 class CapabilityBase(InstanceModelMixin):
@@ -1164,13 +1182,14 @@ class CapabilityBase(InstanceModelMixin):
             ('type_name', self.type_name),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.properties, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.properties, report_issues)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts(context.style.node(self.name))
         with context.style.indent:
             console.puts('Type: {0}'.format(context.style.type(self.type.name)))
@@ -1180,7 +1199,7 @@ class CapabilityBase(InstanceModelMixin):
                 ' to {0:d}'.format(self.max_occurrences)
                 if self.max_occurrences is not None
                 else ' or more'))
-            utils.dump_dict_values(context, self.properties, 'Properties')
+            utils.dump_dict_values(self.properties, 'Properties')
 
 
 class InterfaceBase(InstanceModelMixin):
@@ -1275,22 +1294,23 @@ class InterfaceBase(InstanceModelMixin):
             ('inputs', formatting.as_raw_dict(self.inputs)),
             ('operations', formatting.as_raw_list(self.operations))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.inputs)
-        utils.validate_dict_values(context, self.operations)
+    def validate(self):
+        utils.validate_dict_values(self.inputs)
+        utils.validate_dict_values(self.operations)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.inputs, report_issues)
-        utils.coerce_dict_values(context, container, self.operations, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.inputs, report_issues)
+        utils.coerce_dict_values(container, self.operations, report_issues)
 
-    def dump(self, context):
+    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(context, self.inputs, 'Inputs')
-            utils.dump_dict_values(context, self.operations, 'Operations')
+            utils.dump_dict_values(self.inputs, 'Inputs')
+            utils.dump_dict_values(self.operations, 'Operations')
 
 
 class OperationBase(InstanceModelMixin):
@@ -1391,14 +1411,15 @@ class OperationBase(InstanceModelMixin):
             ('retry_interval', self.retry_interval),
             ('inputs', formatting.as_raw_dict(self.inputs))))
 
-    def validate(self, context):
+    def validate(self):
         # TODO must be associated with interface or service
-        utils.validate_dict_values(context, self.inputs)
+        utils.validate_dict_values(self.inputs)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.inputs, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.inputs, report_issues)
 
-    def dump(self, context):
+    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))
@@ -1417,7 +1438,7 @@ class OperationBase(InstanceModelMixin):
             if self.retry_interval is not None:
                 console.puts('Retry interval: {0}'.format(
                     context.style.literal(self.retry_interval)))
-            utils.dump_dict_values(context, self.inputs, 'Inputs')
+            utils.dump_dict_values(self.inputs, 'Inputs')
 
 
 class ArtifactBase(InstanceModelMixin):
@@ -1505,13 +1526,14 @@ class ArtifactBase(InstanceModelMixin):
             ('repository_credential', formatting.as_agnostic(self.repository_credential)),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.properties, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.properties, report_issues)
 
-    def dump(self, context):
+    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))
@@ -1526,4 +1548,4 @@ class ArtifactBase(InstanceModelMixin):
             if self.repository_credential:
                 console.puts('Repository credential: {0}'.format(
                     context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(context, self.properties, 'Properties')
+            utils.dump_dict_values(self.properties, 'Properties')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index c9a02eb..09da8e1 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -29,6 +29,8 @@ from sqlalchemy import (
 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 .mixins import TemplateModelMixin
 from . import (
@@ -267,33 +269,34 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
             ('interface_types', formatting.as_raw(self.interface_types)),
             ('artifact_types', formatting.as_raw(self.artifact_types))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
+        context = ConsumptionContext.get_thread_local()
         now = datetime.now()
         service = models.Service(created_at=now,
                                  updated_at=now,
-                                 description=utils.deepcopy_with_locators(self.description),
+                                 description=deepcopy_with_locators(self.description),
                                  service_template=self)
         #service.name = '{0}_{1}'.format(self.name, service.id)
 
         context.modeling.instance = service
 
-        utils.instantiate_dict(context, self, service.meta_data, self.meta_data)
+        utils.instantiate_dict(self, service.meta_data, self.meta_data)
 
         for node_template in self.node_templates:
             for _ in range(node_template.default_instances):
-                node = node_template.instantiate(context, container)
+                node = node_template.instantiate(container)
                 service.nodes.append(node)
 
-        utils.instantiate_list(context, self, service.groups, self.group_templates)
-        utils.instantiate_list(context, self, service.policies, self.policy_templates)
-        utils.instantiate_dict(context, self, service.workflows, self.workflow_templates)
+        utils.instantiate_list(self, service.groups, self.group_templates)
+        utils.instantiate_list(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(context, container)
+            service.substitution = self.substitution_template.instantiate(container)
 
-        utils.instantiate_dict(context, self, service.inputs, self.inputs)
-        utils.instantiate_dict(context, self, service.outputs, self.outputs)
+        utils.instantiate_dict(self, service.inputs, self.inputs)
+        utils.instantiate_dict(self, service.outputs, self.outputs)
 
         for name, the_input in context.modeling.inputs.iteritems():
             if name not in service.inputs:
@@ -303,83 +306,81 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
 
         return service
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.meta_data)
-        utils.validate_list_values(context, self.node_templates)
-        utils.validate_list_values(context, self.group_templates)
-        utils.validate_list_values(context, self.policy_templates)
+    def validate(self):
+        utils.validate_dict_values(self.meta_data)
+        utils.validate_list_values(self.node_templates)
+        utils.validate_list_values(self.group_templates)
+        utils.validate_list_values(self.policy_templates)
         if self.substitution_template is not None:
-            self.substitution_template.validate(context)
-        utils.validate_dict_values(context, self.inputs)
-        utils.validate_dict_values(context, self.outputs)
-        utils.validate_dict_values(context, self.workflow_templates)
+            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(context)
+            self.node_types.validate()
         if self.group_types is not None:
-            self.group_types.validate(context)
+            self.group_types.validate()
         if self.policy_types is not None:
-            self.policy_types.validate(context)
+            self.policy_types.validate()
         if self.relationship_types is not None:
-            self.relationship_types.validate(context)
+            self.relationship_types.validate()
         if self.capability_types is not None:
-            self.capability_types.validate(context)
+            self.capability_types.validate()
         if self.interface_types is not None:
-            self.interface_types.validate(context)
+            self.interface_types.validate()
         if self.artifact_types is not None:
-            self.artifact_types.validate(context)
+            self.artifact_types.validate()
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.meta_data, report_issues)
-        utils.coerce_list_values(context, container, self.node_templates, report_issues)
-        utils.coerce_list_values(context, container, self.group_templates, report_issues)
-        utils.coerce_list_values(context, container, self.policy_templates, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.meta_data, report_issues)
+        utils.coerce_list_values(container, self.node_templates, report_issues)
+        utils.coerce_list_values(container, self.group_templates, report_issues)
+        utils.coerce_list_values(container, self.policy_templates, report_issues)
         if self.substitution_template is not None:
-            self.substitution_template.coerce_values(context, container, report_issues)
-        utils.coerce_dict_values(context, container, self.inputs, report_issues)
-        utils.coerce_dict_values(context, container, self.outputs, report_issues)
-        utils.coerce_dict_values(context, container, self.workflow_templates, report_issues)
+            self.substitution_template.coerce_values(container, report_issues)
+        utils.coerce_dict_values(container, self.inputs, report_issues)
+        utils.coerce_dict_values(container, self.outputs, report_issues)
+        utils.coerce_dict_values(container, self.workflow_templates, report_issues)
 
-    def dump(self, context):
+    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(context, self.meta_data, 'Metadata')
+        utils.dump_dict_values(self.meta_data, 'Metadata')
         for node_template in self.node_templates:
-            node_template.dump(context)
+            node_template.dump()
         for group_template in self.group_templates:
-            group_template.dump(context)
+            group_template.dump()
         for policy_template in self.policy_templates:
-            policy_template.dump(context)
+            policy_template.dump()
         if self.substitution_template is not None:
-            self.substitution_template.dump(context)
-        utils.dump_dict_values(context, self.inputs, 'Inputs')
-        utils.dump_dict_values(context, self.outputs, 'Outputs')
-        utils.dump_dict_values(context, self.workflow_templates, 'Workflow templates')
+            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, context):
+    def dump_types(self):
         if self.node_types.children:
             console.puts('Node types:')
-            self.node_types.dump(context)
+            self.node_types.dump()
         if self.group_types.children:
             console.puts('Group types:')
-            self.group_types.dump(context)
+            self.group_types.dump()
         if self.capability_types.children:
             console.puts('Capability types:')
-            self.capability_types.dump(context)
+            self.capability_types.dump()
         if self.relationship_types.children:
             console.puts('Relationship types:')
-            self.relationship_types.dump(context)
+            self.relationship_types.dump()
         if self.policy_types.children:
             console.puts('Policy types:')
-            self.policy_types.dump(context)
-        if self.policy_trigger_types.children:
-            console.puts('Policy trigger types:')
-            self.policy_trigger_types.dump(context)
+            self.policy_types.dump()
         if self.artifact_types.children:
             console.puts('Artifact types:')
-            self.artifact_types.dump(context)
+            self.artifact_types.dump()
         if self.interface_types.children:
             console.puts('Interface types:')
-            self.interface_types.dump(context)
+            self.interface_types.dump()
 
 
 class NodeTemplateBase(TemplateModelMixin):
@@ -505,35 +506,37 @@ class NodeTemplateBase(TemplateModelMixin):
             ('capability_templates', formatting.as_raw_list(self.capability_templates)),
             ('requirement_templates', formatting.as_raw_list(self.requirement_templates))))
 
-    def instantiate(self, context, *args, **kwargs):
+    def instantiate(self, container):
+        context = ConsumptionContext.get_thread_local()
         from . import models
         name = context.modeling.generate_node_id(self.name)
         node = models.Node(name=name,
                            type=self.type,
-                           description=utils.deepcopy_with_locators(self.description),
+                           description=deepcopy_with_locators(self.description),
                            state='',
                            node_template=self)
-        utils.instantiate_dict(context, node, node.properties, self.properties)
-        utils.instantiate_dict(context, node, node.interfaces, self.interface_templates)
-        utils.instantiate_dict(context, node, node.artifacts, self.artifact_templates)
-        utils.instantiate_dict(context, node, node.capabilities, self.capability_templates)
+        utils.instantiate_dict(node, node.properties, self.properties)
+        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)
         return node
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
-        utils.validate_dict_values(context, self.interface_templates)
-        utils.validate_dict_values(context, self.artifact_templates)
-        utils.validate_dict_values(context, self.capability_templates)
-        utils.validate_list_values(context, self.requirement_templates)
-
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.properties, report_issues)
-        utils.coerce_dict_values(context, self, self.interface_templates, report_issues)
-        utils.coerce_dict_values(context, self, self.artifact_templates, report_issues)
-        utils.coerce_dict_values(context, self, self.capability_templates, report_issues)
-        utils.coerce_list_values(context, self, self.requirement_templates, report_issues)
-
-    def dump(self, context):
+    def validate(self):
+        utils.validate_dict_values(self.properties)
+        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, container, report_issues):
+        utils.coerce_dict_values(self, self.properties, report_issues)
+        utils.coerce_dict_values(self, self.interface_templates, report_issues)
+        utils.coerce_dict_values(self, self.artifact_templates, report_issues)
+        utils.coerce_dict_values(self, self.capability_templates, report_issues)
+        utils.coerce_list_values(self, 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))
@@ -545,11 +548,11 @@ class NodeTemplateBase(TemplateModelMixin):
                 ' to {0:d}'.format(self.max_instances)
                 if self.max_instances is not None
                 else ' or more'))
-            utils.dump_dict_values(context, self.properties, 'Properties')
-            utils.dump_interfaces(context, self.interface_templates)
-            utils.dump_dict_values(context, self.artifact_templates, 'Artifact templates')
-            utils.dump_dict_values(context, self.capability_templates, 'Capability templates')
-            utils.dump_list_values(context, self.requirement_templates, 'Requirement templates')
+            utils.dump_dict_values(self.properties, 'Properties')
+            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):
@@ -626,35 +629,36 @@ class GroupTemplateBase(TemplateModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interface_templates', formatting.as_raw_list(self.interface_templates))))
 
-    def instantiate(self, context, *args, **kwargs):
+    def instantiate(self, container):
         from . import models
         group = models.Group(name=self.name,
                              type=self.type,
-                             description=utils.deepcopy_with_locators(self.description),
+                             description=deepcopy_with_locators(self.description),
                              group_template=self)
-        utils.instantiate_dict(context, self, group.properties, self.properties)
-        utils.instantiate_dict(context, self, group.interfaces, self.interface_templates)
+        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.all()
         return group
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
-        utils.validate_dict_values(context, self.interface_templates)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
+        utils.validate_dict_values(self.interface_templates)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.properties, report_issues)
-        utils.coerce_dict_values(context, self, self.interface_templates, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(self, self.properties, report_issues)
+        utils.coerce_dict_values(self, self.interface_templates, report_issues)
 
-    def dump(self, context):
+    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(context, self.properties, 'Properties')
-            utils.dump_interfaces(context, self.interface_templates)
+            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))))
@@ -730,13 +734,13 @@ class PolicyTemplateBase(TemplateModelMixin):
             ('type_name', self.type.name),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def instantiate(self, context, *args, **kwargs):
+    def instantiate(self, container):
         from . import models
         policy = models.Policy(name=self.name,
                                type=self.type,
-                               description=utils.deepcopy_with_locators(self.description),
+                               description=deepcopy_with_locators(self.description),
                                policy_template=self)
-        utils.instantiate_dict(context, self, policy.properties, self.properties)
+        utils.instantiate_dict(self, policy.properties, self.properties)
         if self.node_templates:
             for node_template in self.node_templates:
                 policy.nodes += node_template.nodes.all()
@@ -745,19 +749,20 @@ class PolicyTemplateBase(TemplateModelMixin):
                 policy.groups += group_template.groups.all()
         return policy
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.properties, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(self, self.properties, report_issues)
 
-    def dump(self, context):
+    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(context, self.properties, 'Properties')
+            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))))
@@ -809,24 +814,25 @@ class SubstitutionTemplateBase(TemplateModelMixin):
             ('node_type_name', self.node_type.name),
             ('mappings', formatting.as_raw_dict(self.mappings))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         substitution = models.Substitution(node_type=self.node_type,
                                            substitution_template=self)
-        utils.instantiate_dict(context, container, substitution.mappings, self.mappings)
+        utils.instantiate_dict(container, substitution.mappings, self.mappings)
         return substitution
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.mappings)
+    def validate(self):
+        utils.validate_dict_values(self.mappings)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.mappings, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(self, self.mappings, report_issues)
 
-    def dump(self, context):
+    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(context, self.mappings, 'Mappings')
+            utils.dump_dict_values(self.mappings, 'Mappings')
 
 
 class SubstitutionTemplateMappingBase(TemplateModelMixin):
@@ -896,8 +902,9 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
         return collections.OrderedDict((
             ('name', self.name)))
 
-    def instantiate(self, context, *args, **kwargs):
+    def instantiate(self, container):
         from . import models
+        context = ConsumptionContext.get_thread_local()
         nodes = context.modeling.instance.find_nodes(self.node_template.name)
         if len(nodes) == 0:
             context.validation.report(
@@ -918,7 +925,8 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
                                           capability=capability,
                                           requirement_template=self.requirement_template)
 
-    def validate(self, context):
+    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(
@@ -926,7 +934,8 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
                                           formatting.safe_repr(self.node_template.name)),
                                       level=validation.Issue.BETWEEN_TYPES)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         console.puts('{0} -> {1}.{2}'.format(
             context.style.node(self.name),
             context.style.node(self.node_template.name),
@@ -1025,7 +1034,9 @@ class RequirementTemplateBase(TemplateModelMixin):
 
     # endregion
 
-    def find_target(self, context, source_node_template):
+    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_valid(self.target_node_template):
@@ -1037,8 +1048,7 @@ class RequirementTemplateBase(TemplateModelMixin):
                                           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(context,
-                                                                     source_node_template,
+                target_node_capability = self.find_target_capability(source_node_template,
                                                                      self.target_node_template)
                 if target_node_capability is None:
                     return None, None
@@ -1056,8 +1066,7 @@ class RequirementTemplateBase(TemplateModelMixin):
                 if not source_node_template.is_target_node_valid(target_node_template):
                     continue
 
-                target_node_capability = self.find_target_capability(context,
-                                                                     source_node_template,
+                target_node_capability = self.find_target_capability(source_node_template,
                                                                      target_node_template)
                 if target_node_capability is None:
                     continue
@@ -1066,10 +1075,9 @@ class RequirementTemplateBase(TemplateModelMixin):
 
         return None, None
 
-    def find_target_capability(self, context, source_node_template, target_node_template):
+    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(context,
-                                                         source_node_template,
+            if capability_template.satisfies_requirement(source_node_template,
                                                          self,
                                                          target_node_template):
                 return capability_template
@@ -1085,15 +1093,16 @@ class RequirementTemplateBase(TemplateModelMixin):
             ('target_capability_name', self.target_capability_name),
             ('relationship_template', formatting.as_raw(self.relationship_template))))
 
-    def validate(self, context):
+    def validate(self):
         if self.relationship_template:
-            self.relationship_template.validate(context)
+            self.relationship_template.validate()
 
-    def coerce_values(self, context, container, report_issues):
+    def coerce_values(self, container, report_issues):
         if self.relationship_template is not None:
-            self.relationship_template.coerce_values(context, container, report_issues)
+            self.relationship_template.coerce_values(container, report_issues)
 
-    def dump(self, context):
+    def dump(self):
+        context = ConsumptionContext.get_thread_local()
         if self.name:
             console.puts(context.style.node(self.name))
         else:
@@ -1119,7 +1128,7 @@ class RequirementTemplateBase(TemplateModelMixin):
             if self.relationship_template:
                 console.puts('Relationship:')
                 with context.style.indent:
-                    self.relationship_template.dump(context)
+                    self.relationship_template.dump()
 
 
 class RelationshipTemplateBase(TemplateModelMixin):
@@ -1185,26 +1194,27 @@ class RelationshipTemplateBase(TemplateModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interface_templates', formatting.as_raw_list(self.interface_templates))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         relationship = models.Relationship(type=self.type,
                                            relationship_template=self)
-        utils.instantiate_dict(context, container,
+        utils.instantiate_dict(container,
                                relationship.properties, self.properties)
-        utils.instantiate_dict(context, container,
+        utils.instantiate_dict(container,
                                relationship.interfaces, self.interface_templates)
         return relationship
 
-    def validate(self, context):
+    def validate(self):
         # TODO: either type or name must be set
-        utils.validate_dict_values(context, self.properties)
-        utils.validate_dict_values(context, self.interface_templates)
+        utils.validate_dict_values(self.properties)
+        utils.validate_dict_values(self.interface_templates)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.properties, report_issues)
-        utils.coerce_dict_values(context, self, self.interface_templates, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(self, self.properties, report_issues)
+        utils.coerce_dict_values(self, self.interface_templates, report_issues)
 
-    def dump(self, context):
+    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:
@@ -1213,8 +1223,8 @@ class RelationshipTemplateBase(TemplateModelMixin):
         if self.description:
             console.puts(context.style.meta(self.description))
         with context.style.indent:
-            utils.dump_dict_values(context, self.properties, 'Properties')
-            utils.dump_interfaces(context, self.interface_templates, 'Interface templates')
+            utils.dump_dict_values(self.properties, 'Properties')
+            utils.dump_interfaces(self.interface_templates, 'Interface templates')
 
 
 class CapabilityTemplateBase(TemplateModelMixin):
@@ -1282,7 +1292,6 @@ class CapabilityTemplateBase(TemplateModelMixin):
     # endregion
 
     def satisfies_requirement(self,
-                              context, # pylint: disable=unused-argument
                               source_node_template,
                               requirement,
                               target_node_template):
@@ -1316,7 +1325,7 @@ class CapabilityTemplateBase(TemplateModelMixin):
             ('valid_source_node_type_names', self.valid_source_node_type_names),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         capability = models.Capability(name=self.name,
                                        type=self.type,
@@ -1324,16 +1333,17 @@ class CapabilityTemplateBase(TemplateModelMixin):
                                        max_occurrences=self.max_occurrences,
                                        occurrences=0,
                                        capability_template=self)
-        utils.instantiate_dict(context, container, capability.properties, self.properties)
+        utils.instantiate_dict(container, capability.properties, self.properties)
         return capability
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, self, self.properties, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(self, self.properties, report_issues)
 
-    def dump(self, context):
+    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))
@@ -1349,7 +1359,7 @@ class CapabilityTemplateBase(TemplateModelMixin):
                 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(context, self.properties, 'Properties')
+            utils.dump_dict_values(self.properties, 'Properties')
 
 
 class InterfaceTemplateBase(TemplateModelMixin):
@@ -1432,32 +1442,33 @@ class InterfaceTemplateBase(TemplateModelMixin):
             # TODO fix self.properties reference
             ('operation_templates', formatting.as_raw_list(self.operation_templates))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         interface = models.Interface(name=self.name,
                                      type=self.type,
-                                     description=utils.deepcopy_with_locators(self.description),
+                                     description=deepcopy_with_locators(self.description),
                                      interface_template=self)
-        utils.instantiate_dict(context, container, interface.inputs, self.inputs)
-        utils.instantiate_dict(context, container, interface.operations, self.operation_templates)
+        utils.instantiate_dict(container, interface.inputs, self.inputs)
+        utils.instantiate_dict(container, interface.operations, self.operation_templates)
         return interface
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.inputs)
-        utils.validate_dict_values(context, self.operation_templates)
+    def validate(self):
+        utils.validate_dict_values(self.inputs)
+        utils.validate_dict_values(self.operation_templates)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.inputs, report_issues)
-        utils.coerce_dict_values(context, container, self.operation_templates, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.inputs, report_issues)
+        utils.coerce_dict_values(container, self.operation_templates, report_issues)
 
-    def dump(self, context):
+    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(context, self.inputs, 'Inputs')
-            utils.dump_dict_values(context, self.operation_templates, 'Operation templates')
+            utils.dump_dict_values(self.inputs, 'Inputs')
+            utils.dump_dict_values(self.operation_templates, 'Operation templates')
 
 
 class OperationTemplateBase(TemplateModelMixin):
@@ -1548,10 +1559,10 @@ class OperationTemplateBase(TemplateModelMixin):
             ('retry_interval', self.retry_interval),
             ('inputs', formatting.as_raw_dict(self.inputs))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         operation = models.Operation(name=self.name,
-                                     description=utils.deepcopy_with_locators(self.description),
+                                     description=deepcopy_with_locators(self.description),
                                      implementation=self.implementation,
                                      dependencies=self.dependencies,
                                      plugin_specification=self.plugin_specification,
@@ -1559,16 +1570,17 @@ class OperationTemplateBase(TemplateModelMixin):
                                      max_retries=self.max_retries,
                                      retry_interval=self.retry_interval,
                                      operation_template=self)
-        utils.instantiate_dict(context, container, operation.inputs, self.inputs)
+        utils.instantiate_dict(container, operation.inputs, self.inputs)
         return operation
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.inputs)
+    def validate(self):
+        utils.validate_dict_values(self.inputs)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.inputs, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.inputs, report_issues)
 
-    def dump(self, context):
+    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))
@@ -1586,7 +1598,7 @@ class OperationTemplateBase(TemplateModelMixin):
             if self.retry_interval is not None:
                 console.puts('Retry interval: {0}'.format(
                     context.style.literal(self.retry_interval)))
-            utils.dump_dict_values(context, self.inputs, 'Inputs')
+            utils.dump_dict_values(self.inputs, 'Inputs')
 
 
 class ArtifactTemplateBase(TemplateModelMixin):
@@ -1662,26 +1674,27 @@ class ArtifactTemplateBase(TemplateModelMixin):
             ('repository_credential', formatting.as_agnostic(self.repository_credential)),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def instantiate(self, context, container):
+    def instantiate(self, container):
         from . import models
         artifact = models.Artifact(name=self.name,
                                    type=self.type,
-                                   description=utils.deepcopy_with_locators(self.description),
+                                   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(context, container, artifact.properties, self.properties)
+        utils.instantiate_dict(container, artifact.properties, self.properties)
         return artifact
 
-    def validate(self, context):
-        utils.validate_dict_values(context, self.properties)
+    def validate(self):
+        utils.validate_dict_values(self.properties)
 
-    def coerce_values(self, context, container, report_issues):
-        utils.coerce_dict_values(context, container, self.properties, report_issues)
+    def coerce_values(self, container, report_issues):
+        utils.coerce_dict_values(container, self.properties, report_issues)
 
-    def dump(self, context):
+    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))
@@ -1696,4 +1709,4 @@ class ArtifactTemplateBase(TemplateModelMixin):
             if self.repository_credential:
                 console.puts('Repository credential: {0}'.format(
                     context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(context, self.properties, 'Properties')
+            utils.dump_dict_values(self.properties, 'Properties')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index a071d69..762754f 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from copy import deepcopy
-
+from ..parser.consumption import ConsumptionContext
 from ..parser.exceptions import InvalidValueError
 from ..parser.presentation import Value
 from ..utils.collections import OrderedDict
@@ -22,19 +21,20 @@ from ..utils.console import puts
 from .exceptions import CannotEvaluateFunctionException
 
 
-def coerce_value(context, container, value, report_issues=False):
+def coerce_value(container, value, report_issues=False):
     if isinstance(value, Value):
         value = value.value
 
     if isinstance(value, list):
-        return [coerce_value(context, container, v, report_issues) for v in value]
+        return [coerce_value(container, v, report_issues) for v in value]
     elif isinstance(value, dict):
-        return OrderedDict((k, coerce_value(context, container, v, report_issues))
+        return OrderedDict((k, coerce_value(container, v, report_issues))
                            for k, v in value.items())
     elif hasattr(value, '_evaluate'):
+        context = ConsumptionContext.get_thread_local()
         try:
             value = value._evaluate(context, container)
-            value = coerce_value(context, container, value, report_issues)
+            value = coerce_value(container, value, report_issues)
         except CannotEvaluateFunctionException:
             pass
         except InvalidValueError as e:
@@ -43,106 +43,74 @@ def coerce_value(context, container, value, report_issues=False):
     return value
 
 
-def validate_dict_values(context, the_dict):
+def validate_dict_values(the_dict):
     if not the_dict:
         return
-    validate_list_values(context, the_dict.itervalues())
+    validate_list_values(the_dict.itervalues())
 
 
-def validate_list_values(context, the_list):
+def validate_list_values(the_list):
     if not the_list:
         return
     for value in the_list:
-        value.validate(context)
+        value.validate()
 
 
-def coerce_dict_values(context, container, the_dict, report_issues=False):
+def coerce_dict_values(container, the_dict, report_issues=False):
     if not the_dict:
         return
-    coerce_list_values(context, container, the_dict.itervalues(), report_issues)
+    coerce_list_values(container, the_dict.itervalues(), report_issues)
 
 
-def coerce_list_values(context, container, the_list, report_issues=False):
+def coerce_list_values(container, the_list, report_issues=False):
     if not the_list:
         return
     for value in the_list:
-        value.coerce_values(context, container, report_issues)
+        value.coerce_values(container, report_issues)
 
 
-def instantiate_dict(context, container, the_dict, from_dict):
+def instantiate_dict(container, the_dict, from_dict):
     if not from_dict:
         return
     for name, value in from_dict.iteritems():
-        value = value.instantiate(context, container)
+        value = value.instantiate(container)
         if value is not None:
             the_dict[name] = value
 
 
-def instantiate_list(context, container, the_list, from_list):
+def instantiate_list(container, the_list, from_list):
     if not from_list:
         return
     for value in from_list:
-        value = value.instantiate(context, container)
+        value = value.instantiate(container)
         if value is not None:
             the_list.append(value)
 
 
-def dump_list_values(context, the_list, name):
+def dump_list_values(the_list, name):
     if not the_list:
         return
     puts('%s:' % name)
+    context = ConsumptionContext.get_thread_local()
     with context.style.indent:
         for value in the_list:
-            value.dump(context)
+            value.dump()
 
 
-def dump_dict_values(context, the_dict, name):
+def dump_dict_values(the_dict, name):
     if not the_dict:
         return
-    dump_list_values(context, the_dict.itervalues(), name)
+    dump_list_values(the_dict.itervalues(), name)
 
 
-def dump_interfaces(context, interfaces, name='Interfaces'):
+def dump_interfaces(interfaces, name='Interfaces'):
     if not interfaces:
         return
     puts('%s:' % name)
+    context = ConsumptionContext.get_thread_local()
     with context.style.indent:
         for interface in interfaces.itervalues():
-            interface.dump(context)
-
-
-
-
-def deepcopy_with_locators(value):
-    """
-    Like :code:`deepcopy`, but also copies over locators.
-    """
-
-    res = deepcopy(value)
-    copy_locators(res, value)
-    return res
-
-
-def copy_locators(target, source):
-    """
-    Copies over :code:`_locator` for all elements, recursively.
-
-    Assumes that target and source have exactly the same list/dict structure.
-    """
-
-    locator = getattr(source, '_locator', None)
-    if locator is not None:
-        try:
-            setattr(target, '_locator', locator)
-        except AttributeError:
-            pass
-
-    if isinstance(target, list) and isinstance(source, list):
-        for i, _ in enumerate(target):
-            copy_locators(target[i], source[i])
-    elif isinstance(target, dict) and isinstance(source, dict):
-        for k, v in target.items():
-            copy_locators(v, source[k])
+            interface.dump()
 
 
 class classproperty(object):                                                                        # pylint: disable=invalid-name

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/16a94538/aria/parser/consumption/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/__init__.py b/aria/parser/consumption/__init__.py
index 7b7590e..7da8490 100644
--- a/aria/parser/consumption/__init__.py
+++ b/aria/parser/consumption/__init__.py
@@ -20,7 +20,7 @@ from .style import Style
 from .consumer import Consumer, ConsumerChain
 from .presentation import Read
 from .validation import Validate
-from .modeling import Model, Types, Instance
+from .modeling import ServiceTemplate, Types, ServiceInstance
 from .inputs import Inputs
 
 __all__ = (
@@ -31,7 +31,7 @@ __all__ = (
     'ConsumerChain',
     'Read',
     'Validate',
-    'Model',
+    'ServiceTemplate',
     'Types',
-    'Instance',
+    'ServiceInstance',
     'Inputs')