http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/definitions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/definitions.py 
b/extensions/aria_extension_tosca/simple_v1_0/definitions.py
index b60a797..8564249 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/definitions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/definitions.py
@@ -15,7 +15,7 @@
 
 from aria.utils.collections import FrozenDict
 from aria.utils.caching import cachedmethod
-from aria.parser import dsl_specification
+from aria.parser import implements_specification
 from aria.parser.presentation import (has_fields, short_form_field, 
allow_unknown_fields,
                                       primitive_field, primitive_list_field, 
object_field,
                                       object_list_field, object_dict_field,
@@ -35,7 +35,7 @@ from .modeling.interfaces import 
(get_and_override_input_definitions_from_type,
                                   
get_and_override_operation_definitions_from_type)
 
 @has_fields
-@dsl_specification('3.5.8', 'tosca-simple-1.0')
+@implements_specification('3.5.8', 'tosca-simple-1.0')
 class PropertyDefinition(ExtensiblePresentation):
     """
     A property definition defines a named, typed value and related data that 
can be associated with
@@ -86,7 +86,7 @@ class PropertyDefinition(ExtensiblePresentation):
 
     @primitive_field(str, default='supported', allowed=('supported', 
'unsupported', 'experimental',
                                                         'deprecated'))
-    @dsl_specification(section='3.5.8.3', spec='tosca-simple-1.0')
+    @implements_specification(section='3.5.8.3', spec='tosca-simple-1.0')
     def status(self):
         """
         The optional status of the property relative to the specification or 
implementation.
@@ -121,7 +121,7 @@ class PropertyDefinition(ExtensiblePresentation):
         return get_property_constraints(context, self)
 
 @has_fields
-@dsl_specification('3.5.10', 'tosca-simple-1.0')
+@implements_specification('3.5.10', 'tosca-simple-1.0')
 class AttributeDefinition(ExtensiblePresentation):
     """
     An attribute definition defines a named, typed value that can be 
associated with an entity
@@ -190,7 +190,7 @@ class AttributeDefinition(ExtensiblePresentation):
         return get_data_type(context, self, 'type')
 
 @has_fields
-@dsl_specification('3.5.12', 'tosca-simple-1.0')
+@implements_specification('3.5.12', 'tosca-simple-1.0')
 class ParameterDefinition(PropertyDefinition):
     """
     A parameter definition is essentially a TOSCA property definition; 
however, it also allows a
@@ -225,7 +225,7 @@ class ParameterDefinition(PropertyDefinition):
 
 @short_form_field('implementation')
 @has_fields
-@dsl_specification('3.5.13-1', 'tosca-simple-1.0')
+@implements_specification('3.5.13-1', 'tosca-simple-1.0')
 class OperationDefinition(ExtensiblePresentation):
     """
     An operation definition defines a named function or procedure that can be 
bound to an
@@ -266,7 +266,7 @@ class OperationDefinition(ExtensiblePresentation):
 
 @allow_unknown_fields
 @has_fields
-@dsl_specification('3.5.14-1', 'tosca-simple-1.0')
+@implements_specification('3.5.14-1', 'tosca-simple-1.0')
 class InterfaceDefinition(ExtensiblePresentation):
     """
     An interface definition defines a named interface that can be associated 
with a Node or
@@ -352,7 +352,7 @@ class RelationshipDefinition(ExtensiblePresentation):
 
 @short_form_field('capability')
 @has_fields
-@dsl_specification('3.6.2', 'tosca-simple-1.0')
+@implements_specification('3.6.2', 'tosca-simple-1.0')
 class RequirementDefinition(ExtensiblePresentation):
     """
     The Requirement definition describes a named requirement (dependencies) of 
a TOSCA Node Type or
@@ -418,7 +418,7 @@ class RequirementDefinition(ExtensiblePresentation):
 
 @short_form_field('type')
 @has_fields
-@dsl_specification('3.6.1', 'tosca-simple-1.0')
+@implements_specification('3.6.1', 'tosca-simple-1.0')
 class CapabilityDefinition(ExtensiblePresentation):
     """
     A capability definition defines a named, typed set of data that can be 
associated with Node Type

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/filters.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/filters.py 
b/extensions/aria_extension_tosca/simple_v1_0/filters.py
index 617ce7a..838b505 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/filters.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/filters.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 from aria.utils.caching import cachedmethod
-from aria.parser import dsl_specification
+from aria.parser import implements_specification
 from aria.parser.presentation import (has_fields, object_sequenced_list_field, 
field_validator)
 
 from .misc import ConstraintClause
@@ -45,7 +45,7 @@ class CapabilityFilter(ExtensiblePresentation):
         return None
 
 @has_fields
-@dsl_specification('3.5.4', 'tosca-simple-1.0')
+@implements_specification('3.5.4', 'tosca-simple-1.0')
 class NodeFilter(ExtensiblePresentation):
     """
     A node filter definition defines criteria for selection of a TOSCA Node 
Template based upon the
@@ -58,7 +58,7 @@ class NodeFilter(ExtensiblePresentation):
 
     @field_validator(node_filter_properties_validator)
     @object_sequenced_list_field(ConstraintClause)
-    @dsl_specification('3.5.3', 'tosca-simple-1.0')
+    @implements_specification('3.5.3', 'tosca-simple-1.0')
     def properties(self):
         """
         An optional sequenced list of property filters that would be used to 
select (filter)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/functions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/functions.py 
b/extensions/aria_extension_tosca/simple_v1_0/functions.py
deleted file mode 100644
index 2f77420..0000000
--- a/extensions/aria_extension_tosca/simple_v1_0/functions.py
+++ /dev/null
@@ -1,536 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from cStringIO import StringIO
-
-from aria.utils.collections import FrozenList
-from aria.utils.formatting import as_raw, safe_repr
-from aria.parser import dsl_specification
-from aria.parser.exceptions import InvalidValueError
-from aria.parser.validation import Issue
-from aria.modeling.exceptions import CannotEvaluateFunctionException
-from aria.modeling.functions import Function
-
-#
-# Intrinsic
-#
-
-@dsl_specification('4.3.1', 'tosca-simple-1.0')
-class Concat(Function):
-    """
-    The :code:`concat` function is used to concatenate two or more string 
values within a TOSCA
-    service template.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        if not isinstance(argument, list):
-            raise InvalidValueError(
-                'function "concat" argument must be a list of string 
expressions: %s'
-                % safe_repr(argument),
-                locator=self.locator)
-
-        string_expressions = []
-        for index, an_argument in enumerate(argument):
-            string_expressions.append(parse_string_expression(context, 
presentation, 'concat',
-                                                              index, None, 
an_argument))
-        self.string_expressions = FrozenList(string_expressions)
-
-    @property
-    def as_raw(self):
-        string_expressions = []
-        for string_expression in self.string_expressions:
-            if hasattr(string_expression, 'as_raw'):
-                string_expression = as_raw(string_expression)
-            string_expressions.append(string_expression)
-        return {'concat': string_expressions}
-
-    def _evaluate(self, context, container):
-        value = StringIO()
-        for e in self.string_expressions:
-            if hasattr(e, '_evaluate'):
-                e = e._evaluate(context, container)
-            value.write(str(e))
-        return value.getvalue()
-
-@dsl_specification('4.3.2', 'tosca-simple-1.0')
-class Token(Function):
-    """
-    The :code:`token` function is used within a TOSCA service template on a 
string to parse out
-    (tokenize) substrings separated by one or more token characters within a 
larger string.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        if (not isinstance(argument, list)) or (len(argument) != 3):
-            raise InvalidValueError('function "token" argument must be a list 
of 3 parameters: %s'
-                                    % safe_repr(argument),
-                                    locator=self.locator)
-
-        self.string_with_tokens = parse_string_expression(context, 
presentation, 'token', 0,
-                                                          'the string to 
tokenize', argument[0])
-        self.string_of_token_chars = parse_string_expression(context, 
presentation, 'token', 1,
-                                                             'the token 
separator characters',
-                                                             argument[1])
-        self.substring_index = parse_int(context, presentation, 'token', 2,
-                                         'the 0-based index of the token to 
return', argument[2])
-
-    @property
-    def as_raw(self):
-        string_with_tokens = self.string_with_tokens
-        if hasattr(string_with_tokens, 'as_raw'):
-            string_with_tokens = as_raw(string_with_tokens)
-        string_of_token_chars = self.string_with_tokens
-        if hasattr(string_of_token_chars, 'as_raw'):
-            string_of_token_chars = as_raw(string_of_token_chars)
-        return {'token': [string_with_tokens, string_of_token_chars, 
self.substring_index]}
-
-    def _evaluate(self, context, container):
-        string_with_tokens = self.string_with_tokens
-        if hasattr(string_with_tokens, '_evaluate'):
-            string_with_tokens = string_with_tokens._evaluate(context, 
container) # pylint: disable=no-member
-
-#
-# Property
-#
-
-@dsl_specification('4.4.1', 'tosca-simple-1.0')
-class GetInput(Function):
-    """
-    The :code:`get_input` function is used to retrieve the values of 
properties declared within the
-    inputs section of a TOSCA Service Template.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        self.input_property_name = parse_string_expression(context, 
presentation, 'get_input',
-                                                           None, 'the input 
property name',
-                                                           argument)
-
-        if isinstance(self.input_property_name, basestring):
-            the_input = context.presentation.get_from_dict('service_template', 
'topology_template',
-                                                           'inputs', 
self.input_property_name)
-            if the_input is None:
-                raise InvalidValueError(
-                    'function "get_input" argument is not a valid input name: 
%s'
-                    % safe_repr(argument),
-                    locator=self.locator)
-
-    @property
-    def as_raw(self):
-        return {'get_input': as_raw(self.input_property_name)}
-
-    def _evaluate(self, context, container): # pylint: disable=unused-argument
-        if not context.modeling.instance:
-            raise CannotEvaluateFunctionException()
-        the_input = context.modeling.instance.inputs.get(
-            self.input_property_name,
-            context.modeling.template.inputs.get(self.input_property_name))
-        return as_raw(the_input.value) if the_input is not None else None
-
-@dsl_specification('4.4.2', 'tosca-simple-1.0')
-class GetProperty(Function):
-    """
-    The :code:`get_property` function is used to retrieve property values 
between modelable entities
-    defined in the same service template.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        if (not isinstance(argument, list)) or (len(argument) < 2):
-            raise InvalidValueError(
-                'function "get_property" argument must be a list of at least 2 
string expressions: '
-                '%s'
-                % safe_repr(argument),
-                locator=self.locator)
-
-        self.modelable_entity_name = parse_modelable_entity_name(context, 
presentation,
-                                                                 
'get_property', 0, argument[0])
-        # The first of these will be tried as a req-or-cap name:
-        self.nested_property_name_or_index = argument[1:]
-
-    @property
-    def as_raw(self):
-        return {'get_property': [self.modelable_entity_name] + 
self.nested_property_name_or_index}
-
-    def _evaluate(self, context, container):
-        modelable_entities = get_modelable_entities(context, container, 
self.locator,
-                                                    self.modelable_entity_name)
-        req_or_cap_name = self.nested_property_name_or_index[0]
-
-        for modelable_entity in modelable_entities:
-            properties = None
-
-            if hasattr(modelable_entity, 'requirement_templates') \
-                and modelable_entity.requirement_templates \
-                and (req_or_cap_name in [v.name for v in 
modelable_entity.requirement_templates]):
-                for requirement_template in 
modelable_entity.requirement_templates:
-                    if requirement_template.name == req_or_cap_name:
-                        # First argument refers to a requirement
-                        # TODO: should follow to matched capability in other 
node...
-                        raise CannotEvaluateFunctionException()
-                        # break
-                nested_property_name_or_index = 
self.nested_property_name_or_index[1:]
-            elif hasattr(modelable_entity, 'capability_templates') \
-                and modelable_entity.capability_templates \
-                and (req_or_cap_name in modelable_entity.capability_templates):
-                # First argument refers to a capability
-                properties = 
modelable_entity.capability_templates[req_or_cap_name].properties
-                nested_property_name_or_index = 
self.nested_property_name_or_index[1:]
-            else:
-                properties = modelable_entity.properties
-                nested_property_name_or_index = 
self.nested_property_name_or_index
-
-            if properties:
-                found = True
-                value = properties
-                for name in nested_property_name_or_index:
-                    if (isinstance(value, dict) and (name in value)) \
-                        or (isinstance(value, list) and name < len(list)):
-                        value = value[name]
-                        if hasattr(value, '_evaluate'):
-                            value = value._evaluate(context, modelable_entity)
-                    else:
-                        found = False
-                        break
-                if found:
-                    return as_raw(value)
-
-        raise InvalidValueError(
-            'function "get_property" could not find "%s" in modelable entity 
"%s"' \
-            % ('.'.join(self.nested_property_name_or_index), 
self.modelable_entity_name),
-            locator=self.locator)
-
-#
-# Attribute
-#
-
-@dsl_specification('4.5.1', 'tosca-simple-1.0')
-class GetAttribute(Function):
-    """
-    The :code:`get_attribute` function is used to retrieve the values of named 
attributes declared
-    by the referenced node or relationship template name.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        if (not isinstance(argument, list)) or (len(argument) < 2):
-            raise InvalidValueError(
-                'function "get_attribute" argument must be a list of at least 
2 string expressions:'
-                ' %s'
-                % safe_repr(argument),
-                locator=self.locator)
-
-        self.modelable_entity_name = parse_modelable_entity_name(context, 
presentation,
-                                                                 
'get_attribute', 0, argument[0])
-        # The first of these will be tried as a req-or-cap name:
-        self.nested_property_name_or_index = argument[1:]
-
-    @property
-    def as_raw(self):
-        return {'get_attribute': [self.modelable_entity_name] + 
self.nested_property_name_or_index}
-
-    def _evaluate(self, context, container): # pylint: 
disable=no-self-use,unused-argument
-        raise CannotEvaluateFunctionException()
-
-#
-# Operation
-#
-
-@dsl_specification('4.6.1', 'tosca-simple-1.0')  # pylint: 
disable=abstract-method
-class GetOperationOutput(Function):
-    """
-    The :code:`get_operation_output` function is used to retrieve the values 
of variables exposed /
-    exported from an interface operation.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        if (not isinstance(argument, list)) or (len(argument) != 4):
-            raise InvalidValueError(
-                'function "get_operation_output" argument must be a list of 4 
parameters: %s'
-                % safe_repr(argument),
-                locator=self.locator)
-
-        self.modelable_entity_name = parse_string_expression(context, 
presentation,
-                                                             
'get_operation_output', 0,
-                                                             'modelable entity 
name', argument[0])
-        self.interface_name = parse_string_expression(context, presentation, 
'get_operation_output',
-                                                      1, 'the interface name', 
argument[1])
-        self.operation_name = parse_string_expression(context, presentation, 
'get_operation_output',
-                                                      2, 'the operation name', 
argument[2])
-        self.output_variable_name = parse_string_expression(context, 
presentation,
-                                                            
'get_operation_output', 3,
-                                                            'the output name', 
argument[3])
-
-    @property
-    def as_raw(self):
-        interface_name = self.interface_name
-        if hasattr(interface_name, 'as_raw'):
-            interface_name = as_raw(interface_name)
-        operation_name = self.operation_name
-        if hasattr(operation_name, 'as_raw'):
-            operation_name = as_raw(operation_name)
-        output_variable_name = self.output_variable_name
-        if hasattr(output_variable_name, 'as_raw'):
-            output_variable_name = as_raw(output_variable_name)
-        return {'get_operation_output': [self.modelable_entity_name, 
interface_name, operation_name,
-                                         output_variable_name]}
-
-#
-# Navigation
-#
-
-@dsl_specification('4.7.1', 'tosca-simple-1.0')
-class GetNodesOfType(Function):
-    """
-    The :code:`get_nodes_of_type` function can be used to retrieve a list of 
all known instances of
-    nodes of the declared Node Type.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        self.node_type_name = parse_string_expression(context, presentation, 
'get_nodes_of_type',
-                                                      None, 'the node type 
name', argument)
-
-        if isinstance(self.node_type_name, basestring):
-            node_types = context.presentation.get('service_template', 
'node_types')
-            if (node_types is None) or (self.node_type_name not in node_types):
-                raise InvalidValueError(
-                    'function "get_nodes_of_type" argument is not a valid node 
type name: %s'
-                    % safe_repr(argument),
-                    locator=self.locator)
-
-    @property
-    def as_raw(self):
-        node_type_name = self.node_type_name
-        if hasattr(node_type_name, 'as_raw'):
-            node_type_name = as_raw(node_type_name)
-        return {'get_nodes_of_type': node_type_name}
-
-    def _evaluate(self, context, container):
-        pass
-
-#
-# Artifact
-#
-
-@dsl_specification('4.8.1', 'tosca-simple-1.0') # pylint: 
disable=abstract-method
-class GetArtifact(Function):
-    """
-    The :code:`get_artifact` function is used to retrieve artifact location 
between modelable
-    entities defined in the same service template.
-    """
-
-    def __init__(self, context, presentation, argument):
-        self.locator = presentation._locator
-
-        if (not isinstance(argument, list)) or (len(argument) < 2) or 
(len(argument) > 4):
-            raise InvalidValueError(
-                'function "get_artifact" argument must be a list of 2 to 4 
parameters: %s'
-                % safe_repr(argument),
-                locator=self.locator)
-
-        self.modelable_entity_name = parse_string_expression(context, 
presentation, 'get_artifact',
-                                                             0, 'modelable 
entity name',
-                                                             argument[0])
-        self.artifact_name = parse_string_expression(context, presentation, 
'get_artifact', 1,
-                                                     'the artifact name', 
argument[1])
-        self.location = parse_string_expression(context, presentation, 
'get_artifact', 2,
-                                                'the location or 
"LOCAL_FILE"', argument[2])
-        self.remove = parse_bool(context, presentation, 'get_artifact', 3, 
'the removal flag',
-                                 argument[3])
-
-    @property
-    def as_raw(self):
-        artifact_name = self.artifact_name
-        if hasattr(artifact_name, 'as_raw'):
-            artifact_name = as_raw(artifact_name)
-        location = self.location
-        if hasattr(location, 'as_raw'):
-            location = as_raw(location)
-        return {'get_artifacts': [self.modelable_entity_name, artifact_name, 
location, self.remove]}
-
-#
-# Utils
-#
-
-def get_function(context, presentation, value):
-    functions = context.presentation.presenter.functions
-    if isinstance(value, dict) and (len(value) == 1):
-        key = value.keys()[0]
-        if key in functions:
-            try:
-                return True, functions[key](context, presentation, value[key])
-            except InvalidValueError as e:
-                context.validation.report(issue=e.issue)
-                return True, None
-    return False, None
-
-def parse_string_expression(context, presentation, name, index, explanation, 
value): # pylint: disable=unused-argument
-    is_function, func = get_function(context, presentation, value)
-    if is_function:
-        return func
-    else:
-        value = str(value)
-    return value
-
-def parse_int(context, presentation, name, index, explanation, value): # 
pylint: disable=unused-argument
-    if not isinstance(value, int):
-        try:
-            value = int(value)
-        except ValueError:
-            raise invalid_value(name, index, 'an integer', explanation, value,
-                                presentation._locator)
-    return value
-
-def parse_bool(context, presentation, name, index, explanation, value): # 
pylint: disable=unused-argument
-    if not isinstance(value, bool):
-        raise invalid_value(name, index, 'a boolean', explanation, value, 
presentation._locator)
-    return value
-
-def parse_modelable_entity_name(context, presentation, name, index, value):
-    value = parse_string_expression(context, presentation, name, index, 'the 
modelable entity name',
-                                    value)
-    if value == 'SELF':
-        the_self, _ = parse_self(presentation)
-        if the_self is None:
-            raise invalid_modelable_entity_name(name, index, value, 
presentation._locator,
-                                                'a node template or a 
relationship template')
-    elif value == 'HOST':
-        _, self_variant = parse_self(presentation)
-        if self_variant != 'node_template':
-            raise invalid_modelable_entity_name(name, index, value, 
presentation._locator,
-                                                'a node template')
-    elif (value == 'SOURCE') or (value == 'TARGET'):
-        _, self_variant = parse_self(presentation)
-        if self_variant != 'relationship_template':
-            raise invalid_modelable_entity_name(name, index, value, 
presentation._locator,
-                                                'a relationship template')
-    elif isinstance(value, basestring):
-        node_templates = \
-            context.presentation.get('service_template', 'topology_template', 
'node_templates') \
-            or {}
-        relationship_templates = \
-            context.presentation.get('service_template', 'topology_template',
-                                     'relationship_templates') \
-            or {}
-        if (value not in node_templates) and (value not in 
relationship_templates):
-            raise InvalidValueError(
-                'function "%s" parameter %d is not a valid modelable entity 
name: %s'
-                % (name, index + 1, safe_repr(value)),
-                locator=presentation._locator, level=Issue.BETWEEN_TYPES)
-    return value
-
-def parse_self(presentation):
-    from .templates import NodeTemplate, RelationshipTemplate
-    from .types import NodeType, RelationshipType
-
-    if presentation is None:
-        return None, None
-    elif isinstance(presentation, NodeTemplate) or isinstance(presentation, 
NodeType):
-        return presentation, 'node_template'
-    elif isinstance(presentation, RelationshipTemplate) \
-        or isinstance(presentation, RelationshipType):
-        return presentation, 'relationship_template'
-    else:
-        return parse_self(presentation._container)
-
-@dsl_specification('4.1', 'tosca-simple-1.0')
-def get_modelable_entities(context, container, locator, modelable_entity_name):
-    """
-    The following keywords MAY be used in some TOSCA function in place of a 
TOSCA Node or
-    Relationship Template name.
-    """
-
-    if modelable_entity_name == 'SELF':
-        return get_self(context, container)
-    elif modelable_entity_name == 'HOST':
-        return get_host(context, container)
-    elif modelable_entity_name == 'SOURCE':
-        return get_source(context, container)
-    elif modelable_entity_name == 'TARGET':
-        return get_target(context, container)
-    elif isinstance(modelable_entity_name, basestring):
-        node_templates = \
-            context.presentation.get('service_template', 'topology_template', 
'node_templates') \
-            or {}
-        if modelable_entity_name in node_templates:
-            return [node_templates[modelable_entity_name]]
-        relationship_templates = \
-            context.presentation.get('service_template', 'topology_template',
-                                     'relationship_templates') \
-            or {}
-        if modelable_entity_name in relationship_templates:
-            return [relationship_templates[modelable_entity_name]]
-
-    raise InvalidValueError('function "get_property" could not find modelable 
entity "%s"'
-                            % modelable_entity_name,
-                            locator=locator)
-
-def get_self(context, container): # pylint: disable=unused-argument
-    """
-    A TOSCA orchestrator will interpret this keyword as the Node or 
Relationship Template instance
-    that contains the function at the time the function is evaluated.
-    """
-
-    return [container]
-
-def get_host(context, container): # pylint: disable=unused-argument
-    """
-    A TOSCA orchestrator will interpret this keyword to refer to the all nodes 
that "host" the node
-    using this reference (i.e., as identified by its HostedOn relationship).
-
-    Specifically, TOSCA orchestrators that encounter this keyword when 
evaluating the get_attribute
-    or :code:`get_property` functions SHALL search each node along the 
"HostedOn" relationship chain
-    starting at the immediate node that hosts the node where the function was 
evaluated (and then
-    that node's host node, and so forth) until a match is found or the 
"HostedOn" relationship chain
-    ends.
-    """
-
-    return []
-
-def get_source(context, container): # pylint: disable=unused-argument
-    """
-    A TOSCA orchestrator will interpret this keyword as the Node Template 
instance that is at the
-    source end of the relationship that contains the referencing function.
-    """
-
-    return []
-
-def get_target(context, container): # pylint: disable=unused-argument
-    """
-    A TOSCA orchestrator will interpret this keyword as the Node Template 
instance that is at the
-    target end of the relationship that contains the referencing function.
-    """
-
-def invalid_modelable_entity_name(name, index, value, locator, contexts):
-    return InvalidValueError('function "%s" parameter %d can be "%s" only in 
%s'
-                             % (name, index + 1, value, contexts),
-                             locator=locator, level=Issue.FIELD)
-
-def invalid_value(name, index, the_type, explanation, value, locator):
-    return InvalidValueError(
-        'function "%s" %s is not %s%s: %s'
-        % (name, ('parameter %d' % (index + 1)) if index is not None else 
'argument',
-           the_type, (', %s' % explanation) if explanation is not None else 
'', safe_repr(value)),
-        locator=locator, level=Issue.FIELD)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/misc.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/misc.py 
b/extensions/aria_extension_tosca/simple_v1_0/misc.py
index 42fc1ad..74eba18 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/misc.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/misc.py
@@ -16,7 +16,7 @@
 from aria.utils.caching import cachedmethod
 from aria.utils.console import puts
 from aria.utils.formatting import as_raw
-from aria.parser import dsl_specification
+from aria.parser import implements_specification
 from aria.parser.presentation import (AsIsPresentation, has_fields, 
allow_unknown_fields,
                                       short_form_field, primitive_field, 
primitive_list_field,
                                       primitive_dict_unknown_fields, 
object_field,
@@ -36,7 +36,7 @@ from .presentation.field_validators import 
(constraint_clause_field_validator,
 from .presentation.types import (convert_shorthand_to_full_type_name,
                                  get_type_by_full_or_shorthand_name)
 
-@dsl_specification('3.5.1', 'tosca-simple-1.0')
+@implements_specification('3.5.1', 'tosca-simple-1.0')
 class Description(AsIsPresentation):
     """
     See the `TOSCA Simple Profile v1.0 cos01 specification 
<http://docs.oasis-open.org/tosca
@@ -53,10 +53,10 @@ class Description(AsIsPresentation):
 
 @allow_unknown_fields
 @has_fields
-@dsl_specification('3.9.3.2', 'tosca-simple-1.0')
+@implements_specification('3.9.3.2', 'tosca-simple-1.0')
 class MetaData(ExtensiblePresentation):
     @primitive_field(str)
-    @dsl_specification('3.9.3.3', 'tosca-simple-1.0')
+    @implements_specification('3.9.3.3', 'tosca-simple-1.0')
     def template_name(self):
         """
         This optional metadata keyname can be used to declare the name of 
service template as a
@@ -64,7 +64,7 @@ class MetaData(ExtensiblePresentation):
         """
 
     @primitive_field(str)
-    @dsl_specification('3.9.3.4', 'tosca-simple-1.0')
+    @implements_specification('3.9.3.4', 'tosca-simple-1.0')
     def template_author(self):
         """
         This optional metadata keyname can be used to declare the author(s) of 
the service template
@@ -72,7 +72,7 @@ class MetaData(ExtensiblePresentation):
         """
 
     @primitive_field(str)
-    @dsl_specification('3.9.3.5', 'tosca-simple-1.0')
+    @implements_specification('3.9.3.5', 'tosca-simple-1.0')
     def template_version(self):
         """
         This optional metadata keyname can be used to declare a domain 
specific version of the
@@ -87,7 +87,7 @@ class MetaData(ExtensiblePresentation):
 
 @short_form_field('url')
 @has_fields
-@dsl_specification('3.5.5', 'tosca-simple-1.0')
+@implements_specification('3.5.5', 'tosca-simple-1.0')
 class Repository(ExtensiblePresentation):
     """
     A repository definition defines a named external repository which contains 
deployment and
@@ -128,7 +128,7 @@ class Repository(ExtensiblePresentation):
 
 @short_form_field('file')
 @has_fields
-@dsl_specification('3.5.7', 'tosca-simple-1.0')
+@implements_specification('3.5.7', 'tosca-simple-1.0')
 class Import(ExtensiblePresentation):
     """
     An import definition is used within a TOSCA Service Template to locate and 
uniquely name another
@@ -177,7 +177,7 @@ class Import(ExtensiblePresentation):
         """
 
 @has_fields
-@dsl_specification('3.5.2', 'tosca-simple-1.0')
+@implements_specification('3.5.2-1', 'tosca-simple-1.0')
 class ConstraintClause(ExtensiblePresentation):
     """
     A constraint clause defines an operation along with one or more compatible 
values that can be
@@ -376,7 +376,7 @@ class SubstitutionMappingsCapability(AsIsPresentation):
         validate_subtitution_mappings_capability(context, self)
 
 @has_fields
-@dsl_specification('2.10', 'tosca-simple-1.0')
+@implements_specification('2.10', 'tosca-simple-1.0')
 class SubstitutionMappings(ExtensiblePresentation):
     @field_validator(type_validator('node type', 
convert_shorthand_to_full_type_name, 'node_types'))
     @primitive_field(str, required=True)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py 
b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index 3bda7e2..99389e4 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -34,6 +34,8 @@ from aria.modeling.models import (Type, ServiceTemplate, 
NodeTemplate,
                                   SubstitutionTemplateMapping, 
InterfaceTemplate, OperationTemplate,
                                   ArtifactTemplate, Metadata, Parameter, 
PluginSpecification)
 
+from .constraints import (Equal, GreaterThan, GreaterOrEqual, LessThan, 
LessOrEqual, InRange,
+                          ValidValues, Length, MinLength, MaxLength, Pattern)
 from ..data_types import coerce_value
 
 
@@ -166,6 +168,8 @@ def create_node_template_model(context, service_template, 
node_template):
 
     create_parameter_models_from_values(model.properties,
                                         
node_template._get_property_values(context))
+    create_parameter_models_from_values(model.attributes,
+                                        
node_template._get_attribute_default_values(context))
     create_interface_template_models(context, service_template, 
model.interface_templates,
                                      node_template._get_interfaces(context))
 
@@ -181,10 +185,10 @@ def create_node_template_model(context, service_template, 
node_template):
             model.capability_templates[capability_name] = \
                 create_capability_template_model(context, service_template, 
capability)
 
-    if model.target_node_template_constraints:
+    if node_template.node_filter:
         model.target_node_template_constraints = []
-        create_node_filter_constraint_lambdas(context, 
node_template.node_filter,
-                                              
model.target_node_template_constraints)
+        create_node_filter_constraints(context, node_template.node_filter,
+                                       model.target_node_template_constraints)
 
     return model
 
@@ -273,10 +277,10 @@ def create_requirement_template_model(context, 
service_template, requirement):
 
     model = RequirementTemplate(**model)
 
-    if model.target_node_template_constraints:
+    if requirement.node_filter:
         model.target_node_template_constraints = []
-        create_node_filter_constraint_lambdas(context, requirement.node_filter,
-                                              
model.target_node_template_constraints)
+        create_node_filter_constraints(context, requirement.node_filter,
+                                       model.target_node_template_constraints)
 
     relationship = requirement.relationship
     if relationship is not None:
@@ -348,7 +352,7 @@ def create_interface_template_model(context, 
service_template, interface):
     inputs = interface.inputs
     if inputs:
         for input_name, the_input in inputs.iteritems():
-            model.inputs[input_name] = Parameter(name=input_name,
+            model.inputs[input_name] = Parameter(name=input_name, # pylint: 
disable=unexpected-keyword-arg
                                                  
type_name=the_input.value.type,
                                                  value=the_input.value.value,
                                                  
description=the_input.value.description)
@@ -395,7 +399,7 @@ def create_operation_template_model(context, 
service_template, operation):
     inputs = operation.inputs
     if inputs:
         for input_name, the_input in inputs.iteritems():
-            model.inputs[input_name] = Parameter(name=input_name,
+            model.inputs[input_name] = Parameter(name=input_name, # pylint: 
disable=unexpected-keyword-arg
                                                  
type_name=the_input.value.type,
                                                  value=the_input.value.value,
                                                  
description=the_input.value.description)
@@ -491,7 +495,7 @@ def create_workflow_operation_template_model(context, 
service_template, policy):
         elif prop_name == 'dependencies':
             model.dependencies = prop.value
         else:
-            model.inputs[prop_name] = Parameter(name=prop_name,
+            model.inputs[prop_name] = Parameter(name=prop_name, # pylint: 
disable=unexpected-keyword-arg
                                                 type_name=prop.type,
                                                 value=prop.value,
                                                 description=prop.description)
@@ -536,7 +540,7 @@ def create_types(context, root, types):
 def create_parameter_models_from_values(properties, source_properties):
     if source_properties:
         for property_name, prop in source_properties.iteritems():
-            properties[property_name] = Parameter(name=property_name,
+            properties[property_name] = Parameter(name=property_name, # 
pylint: disable=unexpected-keyword-arg
                                                   type_name=prop.type,
                                                   value=prop.value,
                                                   description=prop.description)
@@ -545,7 +549,7 @@ def create_parameter_models_from_values(properties, 
source_properties):
 def create_parameter_models_from_assignments(properties, source_properties):
     if source_properties:
         for property_name, prop in source_properties.iteritems():
-            properties[property_name] = Parameter(name=property_name,
+            properties[property_name] = Parameter(name=property_name, # 
pylint: disable=unexpected-keyword-arg
                                                   type_name=prop.value.type,
                                                   value=prop.value.value,
                                                   
description=prop.value.description)
@@ -559,17 +563,13 @@ def create_interface_template_models(context, 
service_template, interfaces, sour
                 interfaces[interface_name] = interface
 
 
-def create_node_filter_constraint_lambdas(context, node_filter, 
target_node_template_constraints):
-    if node_filter is None:
-        return
-
+def create_node_filter_constraints(context, node_filter, 
target_node_template_constraints):
     properties = node_filter.properties
     if properties is not None:
         for property_name, constraint_clause in properties:
-            func = create_constraint_clause_lambda(context, node_filter, 
constraint_clause,
-                                                   property_name, None)
-            if func is not None:
-                target_node_template_constraints.append(func)
+            constraint = create_constraint(context, node_filter, 
constraint_clause, property_name,
+                                           None)
+            target_node_template_constraints.append(constraint)
 
     capabilities = node_filter.capabilities
     if capabilities is not None:
@@ -577,129 +577,64 @@ def create_node_filter_constraint_lambdas(context, 
node_filter, target_node_temp
             properties = capability.properties
             if properties is not None:
                 for property_name, constraint_clause in properties:
-                    func = create_constraint_clause_lambda(context, 
node_filter, constraint_clause,
-                                                           property_name, 
capability_name)
-                    if func is not None:
-                        target_node_template_constraints.append(func)
+                    constraint = create_constraint(context, node_filter, 
constraint_clause,
+                                                   property_name, 
capability_name)
+                    target_node_template_constraints.append(constraint)
 
 
-def create_constraint_clause_lambda(context, node_filter, constraint_clause, 
property_name, # pylint: disable=too-many-return-statements
-                                    capability_name):
+def create_constraint(context, node_filter, constraint_clause, property_name, 
capability_name): # pylint: disable=too-many-return-statements
     constraint_key = constraint_clause._raw.keys()[0]
-    the_type = constraint_clause._get_type(context)
 
-    def coerce_constraint(constraint, container):
-        constraint = coerce_value(context, node_filter, the_type, None, None, 
constraint,
-                                  constraint_key) if the_type is not None else 
constraint
-        if hasattr(constraint, '_evaluate'):
-            constraint = constraint._evaluate(context, container)
-        return constraint
-
-    def get_value(node_type):
-        if capability_name is not None:
-            capability = node_type.capability_templates.get(capability_name)
-            prop = capability.properties.get(property_name) if capability is 
not None else None
-            return prop.value if prop is not None else None
-        value = node_type.properties.get(property_name)
-        return value.value if value is not None else None
+    the_type = constraint_clause._get_type(context)
 
-    if constraint_key == 'equal':
-        def equal(node_type, container):
-            constraint = coerce_constraint(constraint_clause.equal, container)
-            value = get_value(node_type)
-            return value == constraint
+    def coerce_constraint(constraint):
+        if the_type is not None:
+            return coerce_value(context, node_filter, the_type, None, None, 
constraint,
+                                constraint_key)
+        else:
+            return constraint
 
-        return equal
+    def coerce_constraints(constraints):
+        if the_type is not None:
+            return tuple(coerce_constraint(constraint) for constraint in 
constraints)
+        else:
+            return constraints
 
+    if constraint_key == 'equal':
+        return Equal(property_name, capability_name,
+                     coerce_constraint(constraint_clause.equal))
     elif constraint_key == 'greater_than':
-        def greater_than(node_type, container):
-            constraint = coerce_constraint(constraint_clause.greater_than, 
container)
-            value = get_value(node_type)
-            return value > constraint
-
-        return greater_than
-
+        return GreaterThan(property_name, capability_name,
+                           coerce_constraint(constraint_clause.greater_than))
     elif constraint_key == 'greater_or_equal':
-        def greater_or_equal(node_type, container):
-            constraint = coerce_constraint(constraint_clause.greater_or_equal, 
container)
-            value = get_value(node_type)
-            return value >= constraint
-
-        return greater_or_equal
-
+        return GreaterOrEqual(property_name, capability_name,
+                              
coerce_constraint(constraint_clause.greater_or_equal))
     elif constraint_key == 'less_than':
-        def less_than(node_type, container):
-            constraint = coerce_constraint(constraint_clause.less_than, 
container)
-            value = get_value(node_type)
-            return value < constraint
-
-        return less_than
-
+        return LessThan(property_name, capability_name,
+                        coerce_constraint(constraint_clause.less_than))
     elif constraint_key == 'less_or_equal':
-        def less_or_equal(node_type, container):
-            constraint = coerce_constraint(constraint_clause.less_or_equal, 
container)
-            value = get_value(node_type)
-            return value <= constraint
-
-        return less_or_equal
-
+        return LessOrEqual(property_name, capability_name,
+                           coerce_constraint(constraint_clause.less_or_equal))
     elif constraint_key == 'in_range':
-        def in_range(node_type, container):
-            lower, upper = constraint_clause.in_range
-            lower, upper = coerce_constraint(lower, container), 
coerce_constraint(upper, container)
-            value = get_value(node_type)
-            if value < lower:
-                return False
-            if (upper != 'UNBOUNDED') and (value > upper):
-                return False
-            return True
-
-        return in_range
-
+        return InRange(property_name, capability_name,
+                       coerce_constraints(constraint_clause.in_range))
     elif constraint_key == 'valid_values':
-        def valid_values(node_type, container):
-            constraint = tuple(coerce_constraint(v, container)
-                               for v in constraint_clause.valid_values)
-            value = get_value(node_type)
-            return value in constraint
-
-        return valid_values
-
+        return ValidValues(property_name, capability_name,
+                           coerce_constraints(constraint_clause.valid_values))
     elif constraint_key == 'length':
-        def length(node_type, container): # pylint: disable=unused-argument
-            constraint = constraint_clause.length
-            value = get_value(node_type)
-            return len(value) == constraint
-
-        return length
-
+        return Length(property_name, capability_name,
+                      coerce_constraint(constraint_clause.length))
     elif constraint_key == 'min_length':
-        def min_length(node_type, container): # pylint: disable=unused-argument
-            constraint = constraint_clause.min_length
-            value = get_value(node_type)
-            return len(value) >= constraint
-
-        return min_length
-
+        return MinLength(property_name, capability_name,
+                         coerce_constraint(constraint_clause.min_length))
     elif constraint_key == 'max_length':
-        def max_length(node_type, container): # pylint: disable=unused-argument
-            constraint = constraint_clause.max_length
-            value = get_value(node_type)
-            return len(value) >= constraint
-
-        return max_length
-
+        return MaxLength(property_name, capability_name,
+                         coerce_constraint(constraint_clause.max_length))
     elif constraint_key == 'pattern':
-        def pattern(node_type, container): # pylint: disable=unused-argument
-            constraint = constraint_clause.pattern
-            # Note: the TOSCA 1.0 spec does not specify the regular expression 
grammar, so we will
-            # just use Python's
-            value = node_type.properties.get(property_name)
-            return re.match(constraint, str(value)) is not None
-
-        return pattern
-
-    return None
+        return Pattern(property_name, capability_name,
+                       coerce_constraint(constraint_clause.pattern))
+    else:
+        raise ValueError('malformed node_filter: {0}'.format(constraint_key))
 
 
 def split_prefix(string):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
----------------------------------------------------------------------
diff --git 
a/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py 
b/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
new file mode 100644
index 0000000..7c99eab
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/constraints.py
@@ -0,0 +1,144 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import re
+
+from aria.modeling.contraints import NodeTemplateConstraint
+from aria.modeling.utils import NodeTemplateContainerHolder
+from aria.modeling.functions import evaluate
+from aria.parser import implements_specification
+
+
+@implements_specification('3.5.2-2', 'tosca-simple-1.0')
+class EvaluatingNodeTemplateConstraint(NodeTemplateConstraint):
+    """
+    A version of :class:`NodeTemplateConstraint` with boilerplate 
initialization for TOSCA
+    constraints.
+    """
+
+    def __init__(self, property_name, capability_name, constraint, 
as_list=False):
+        self.property_name = property_name
+        self.capability_name = capability_name
+        self.constraint = constraint
+        self.as_list = as_list
+
+    def matches(self, source_node_template, target_node_template):
+        # TOSCA node template constraints can refer to either capability 
properties or node
+        # template properties
+        if self.capability_name is not None:
+            # Capability property
+            capability = 
target_node_template.capability_templates.get(self.capability_name)
+            value = capability.properties.get(self.property_name) \
+                if capability is not None else None # Parameter
+        else:
+            # Node template property
+            value = target_node_template.properties.get(self.property_name) # 
Parameter
+
+        value = value.value if value is not None else None
+
+        container_holder = NodeTemplateContainerHolder(source_node_template)
+
+        if self.as_list:
+            constraints = []
+            for constraint in self.constraint:
+                evaluation = evaluate(constraint, container_holder)
+                if evaluation is not None:
+                    constraints.append(evaluation.value)
+                else:
+                    constraints.append(constraint)
+            constraint = constraints
+        else:
+            evaluation = evaluate(self.constraint, container_holder)
+            if evaluation is not None:
+                constraint = evaluation.value
+            else:
+                constraint = self.constraint
+
+        return self.matches_evaluated(value, constraint)
+
+    def matches_evaluated(self, value, constraint):
+        raise NotImplementedError
+
+
+class Equal(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return value == constraint
+
+
+class GreaterThan(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return value > constraint
+
+
+class GreaterOrEqual(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return value >= constraint
+
+
+class LessThan(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return value < constraint
+
+
+class LessOrEqual(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return value <= constraint
+
+
+class InRange(EvaluatingNodeTemplateConstraint):
+    def __init__(self, property_name, capability_name, constraint):
+        super(InRange, self).__init__(property_name, capability_name, 
constraint, as_list=True)
+
+    def matches_evaluated(self, value, constraints):
+        lower, upper = constraints
+        if value < lower:
+            return False
+        if (upper != 'UNBOUNDED') and (value > upper):
+            return False
+        return True
+
+
+class ValidValues(EvaluatingNodeTemplateConstraint):
+    def __init__(self, property_name, capability_name, constraint):
+        super(ValidValues, self).__init__(property_name, capability_name, 
constraint, as_list=True)
+
+    def matches_evaluated(self, value, constraints):
+        return value in constraints
+
+
+class Length(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return len(value) == constraint
+
+
+class MinLength(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return len(value) >= constraint
+
+
+class MaxLength(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        return len(value) <= constraint
+
+
+class Pattern(EvaluatingNodeTemplateConstraint):
+    def matches_evaluated(self, value, constraint):
+        # From TOSCA 1.0 3.5.2.1:
+        #
+        # "Note: Future drafts of this specification will detail the use of 
regular expressions and
+        # reference an appropriate standardized grammar."
+        #
+        # So we will just use Python's.
+        return re.match(constraint, unicode(value)) is not None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py 
b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
index 99dcfea..3952785 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
@@ -16,13 +16,14 @@
 import re
 
 from aria.utils.collections import OrderedDict
-from aria.utils.formatting import full_type_name, safe_repr
+from aria.utils.formatting import safe_repr
+from aria.utils.type import full_type_name
 from aria.utils.imports import import_fullname
-from aria.parser import dsl_specification
+from aria.parser import implements_specification
 from aria.parser.presentation import (get_locator, validate_primitive)
 from aria.parser.validation import Issue
 
-from ..functions import get_function
+from .functions import get_function
 from ..presentation.types import get_type_by_full_or_shorthand_name
 
 #
@@ -295,8 +296,12 @@ def apply_constraint_to_value(context, presentation, 
constraint_clause, value):
     elif constraint_key == 'pattern':
         constraint = constraint_clause.pattern
         try:
-            # Note: the TOSCA 1.0 spec does not specify the regular expression 
grammar, so we will
-            # just use Python's
+            # From TOSCA 1.0 3.5.2.1:
+            #
+            # "Note: Future drafts of this specification will detail the use 
of regular expressions
+            # and reference an appropriate standardized grammar."
+            #
+            # So we will just use Python's.
             if re.match(constraint, str(value)) is None:
                 report('does not match regular expression', constraint)
                 return False
@@ -327,20 +332,20 @@ def get_data_type_value(context, presentation, 
field_name, type_name):
 
 PRIMITIVE_DATA_TYPES = {
     # YAML 1.2:
-    'tag:yaml.org,2002:str': str,
+    'tag:yaml.org,2002:str': unicode,
     'tag:yaml.org,2002:integer': int,
     'tag:yaml.org,2002:float': float,
     'tag:yaml.org,2002:bool': bool,
     'tag:yaml.org,2002:null': None.__class__,
 
     # TOSCA aliases:
-    'string': str,
+    'string': unicode,
     'integer': int,
     'float': float,
     'boolean': bool,
     'null': None.__class__}
 
-@dsl_specification('3.2.1', 'tosca-simple-1.0')
+@implements_specification('3.2.1-3', 'tosca-simple-1.0')
 def get_primitive_data_type(type_name):
     """
     Many of the types we use in this profile are built-in types from the YAML 
1.2 specification
@@ -371,6 +376,8 @@ def coerce_value(context, presentation, the_type, 
entry_schema, constraints, val
     If the extension is present, we will delegate to that hook.
     """
 
+    # TODO: should support models as well as presentations
+
     is_function, func = get_function(context, presentation, value)
     if is_function:
         return func

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/60ea3ebb/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py 
b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
new file mode 100644
index 0000000..7089ed9
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
@@ -0,0 +1,677 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from cStringIO import StringIO
+import re
+
+from aria.utils.collections import FrozenList
+from aria.utils.formatting import (as_raw, safe_repr)
+from aria.utils.type import full_type_name
+from aria.parser import implements_specification
+from aria.parser.exceptions import InvalidValueError
+from aria.parser.validation import Issue
+from aria.modeling.exceptions import CannotEvaluateFunctionException
+from aria.modeling.models import (Node, NodeTemplate, Relationship, 
RelationshipTemplate)
+from aria.modeling.functions import (Function, Evaluation)
+
+
+#
+# Intrinsic
+#
+
+@implements_specification('4.3.1', 'tosca-simple-1.0')
+class Concat(Function):
+    """
+    The :code:`concat` function is used to concatenate two or more string 
values within a TOSCA
+    service template.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        if not isinstance(argument, list):
+            raise InvalidValueError(
+                'function "concat" argument must be a list of string 
expressions: {0}'
+                .format(safe_repr(argument)),
+                locator=self.locator)
+
+        string_expressions = []
+        for index, an_argument in enumerate(argument):
+            string_expressions.append(parse_string_expression(context, 
presentation, 'concat',
+                                                              index, None, 
an_argument))
+        self.string_expressions = FrozenList(string_expressions)
+
+    @property
+    def as_raw(self):
+        string_expressions = []
+        for string_expression in self.string_expressions:
+            if hasattr(string_expression, 'as_raw'):
+                string_expression = as_raw(string_expression)
+            string_expressions.append(string_expression)
+        return {'concat': string_expressions}
+
+    def __evaluate__(self, container_holder):
+        final = True
+        value = StringIO()
+        for e in self.string_expressions:
+            e, final = evaluate(e, final, container_holder)
+            if e is not None:
+                value.write(unicode(e))
+        value = value.getvalue()
+        return Evaluation(value, final)
+
+
+@implements_specification('4.3.2', 'tosca-simple-1.0')
+class Token(Function):
+    """
+    The :code:`token` function is used within a TOSCA service template on a 
string to parse out
+    (tokenize) substrings separated by one or more token characters within a 
larger string.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        if (not isinstance(argument, list)) or (len(argument) != 3):
+            raise InvalidValueError('function "token" argument must be a list 
of 3 parameters: {0}'
+                                    .format(safe_repr(argument)),
+                                    locator=self.locator)
+
+        self.string_with_tokens = parse_string_expression(context, 
presentation, 'token', 0,
+                                                          'the string to 
tokenize', argument[0])
+        self.string_of_token_chars = parse_string_expression(context, 
presentation, 'token', 1,
+                                                             'the token 
separator characters',
+                                                             argument[1])
+        self.substring_index = parse_int(context, presentation, 'token', 2,
+                                         'the 0-based index of the token to 
return', argument[2])
+
+    @property
+    def as_raw(self):
+        string_with_tokens = self.string_with_tokens
+        if hasattr(string_with_tokens, 'as_raw'):
+            string_with_tokens = as_raw(string_with_tokens)
+        string_of_token_chars = self.string_of_token_chars
+        if hasattr(string_of_token_chars, 'as_raw'):
+            string_of_token_chars = as_raw(string_of_token_chars)
+        return {'token': [string_with_tokens, string_of_token_chars, 
self.substring_index]}
+
+    def __evaluate__(self, container_holder):
+        final = True
+        string_with_tokens, final = evaluate(self.string_with_tokens, final, 
container_holder)
+        string_of_token_chars, final = evaluate(self.string_of_token_chars, 
final, container_holder)
+
+        if string_of_token_chars:
+            regex = '[' + ''.join(re.escape(c) for c in string_of_token_chars) 
+ ']'
+            split = re.split(regex, string_with_tokens)
+            if self.substring_index < len(split):
+                return Evaluation(split[self.substring_index], final)
+
+        raise CannotEvaluateFunctionException()
+
+
+#
+# Property
+#
+
+@implements_specification('4.4.1', 'tosca-simple-1.0')
+class GetInput(Function):
+    """
+    The :code:`get_input` function is used to retrieve the values of 
properties declared within the
+    inputs section of a TOSCA Service Template.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        self.input_property_name = parse_string_expression(context, 
presentation, 'get_input',
+                                                           None, 'the input 
property name',
+                                                           argument)
+
+        if isinstance(self.input_property_name, basestring):
+            the_input = context.presentation.get_from_dict('service_template', 
'topology_template',
+                                                           'inputs', 
self.input_property_name)
+            if the_input is None:
+                raise InvalidValueError(
+                    'function "get_input" argument is not a valid input name: 
{0}'
+                    .format(safe_repr(argument)),
+                    locator=self.locator)
+
+    @property
+    def as_raw(self):
+        return {'get_input': as_raw(self.input_property_name)}
+
+    def __evaluate__(self, container_holder):
+        service = container_holder.service
+        if service is None:
+            raise CannotEvaluateFunctionException()
+
+        value = service.inputs.get(self.input_property_name)
+        if value is not None:
+            value = value.value
+            return Evaluation(value, False) # We never return final 
evaluations!
+
+        raise InvalidValueError(
+            'function "get_input" argument is not a valid input name: {0}'
+            .format(safe_repr(self.input_property_name)),
+            locator=self.locator)
+
+
+@implements_specification('4.4.2', 'tosca-simple-1.0')
+class GetProperty(Function):
+    """
+    The :code:`get_property` function is used to retrieve property values 
between modelable entities
+    defined in the same service template.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        if (not isinstance(argument, list)) or (len(argument) < 2):
+            raise InvalidValueError(
+                'function "get_property" argument must be a list of at least 2 
string expressions: '
+                '{0}'.format(safe_repr(argument)),
+                locator=self.locator)
+
+        self.modelable_entity_name = parse_modelable_entity_name(context, 
presentation,
+                                                                 
'get_property', 0, argument[0])
+        # The first of these will be tried as a req-or-cap name:
+        self.nested_property_name_or_index = argument[1:]
+
+    @property
+    def as_raw(self):
+        return {'get_property': [self.modelable_entity_name] + 
self.nested_property_name_or_index}
+
+    def __evaluate__(self, container_holder):
+        modelable_entities = get_modelable_entities(container_holder, 
'get_property', self.locator,
+                                                    self.modelable_entity_name)
+        req_or_cap_name = self.nested_property_name_or_index[0]
+
+        for modelable_entity in modelable_entities:
+            properties = None
+
+            if hasattr(modelable_entity, 'requirement_templates') \
+                and modelable_entity.requirement_templates \
+                and (req_or_cap_name in [v.name for v in 
modelable_entity.requirement_templates]):
+                for requirement_template in 
modelable_entity.requirement_templates:
+                    if requirement_template.name == req_or_cap_name:
+                        # First argument refers to a requirement
+                        # TODO: should follow to matched capability in other 
node...
+                        raise CannotEvaluateFunctionException()
+                        # break
+                nested_property_name_or_index = 
self.nested_property_name_or_index[1:]
+            elif hasattr(modelable_entity, 'capability_templates') \
+                and modelable_entity.capability_templates \
+                and (req_or_cap_name in modelable_entity.capability_templates):
+                # First argument refers to a capability
+                properties = 
modelable_entity.capability_templates[req_or_cap_name].properties
+                nested_property_name_or_index = 
self.nested_property_name_or_index[1:]
+            else:
+                properties = modelable_entity.properties
+                nested_property_name_or_index = 
self.nested_property_name_or_index
+
+            evaluation = get_modelable_entity_parameter(modelable_entity, 
properties,
+                                                        
nested_property_name_or_index)
+            if evaluation is not None:
+                return evaluation
+
+        raise InvalidValueError(
+            'function "get_property" could not find "{0}" in modelable entity 
"{1}"'
+            .format('.'.join(self.nested_property_name_or_index), 
self.modelable_entity_name),
+            locator=self.locator)
+
+
+#
+# Attribute
+#
+
+@implements_specification('4.5.1', 'tosca-simple-1.0')
+class GetAttribute(Function):
+    """
+    The :code:`get_attribute` function is used to retrieve the values of named 
attributes declared
+    by the referenced node or relationship template name.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        if (not isinstance(argument, list)) or (len(argument) < 2):
+            raise InvalidValueError(
+                'function "get_attribute" argument must be a list of at least 
2 string expressions:'
+                ' {0}'.format(safe_repr(argument)),
+                locator=self.locator)
+
+        self.modelable_entity_name = parse_modelable_entity_name(context, 
presentation,
+                                                                 
'get_attribute', 0, argument[0])
+        # The first of these will be tried as a req-or-cap name:
+        self.nested_attribute_name_or_index = argument[1:]
+
+    @property
+    def as_raw(self):
+        return {'get_attribute': [self.modelable_entity_name] + 
self.nested_attribute_name_or_index}
+
+    def __evaluate__(self, container_holder):
+        modelable_entities = get_modelable_entities(container_holder, 
'get_attribute', self.locator,
+                                                    self.modelable_entity_name)
+        for modelable_entity in modelable_entities:
+            attributes = modelable_entity.attributes
+            nested_attribute_name_or_index = 
self.nested_attribute_name_or_index
+            evaluation = get_modelable_entity_parameter(modelable_entity, 
attributes,
+                                                        
nested_attribute_name_or_index)
+            if evaluation is not None:
+                evaluation.final = False # We never return final evaluations!
+                return evaluation
+
+        raise InvalidValueError(
+            'function "get_attribute" could not find "{0}" in modelable entity 
"{1}"'
+            .format('.'.join(self.nested_attribute_name_or_index), 
self.modelable_entity_name),
+            locator=self.locator)
+
+
+#
+# Operation
+#
+
+@implements_specification('4.6.1', 'tosca-simple-1.0') # pylint: 
disable=abstract-method
+class GetOperationOutput(Function):
+    """
+    The :code:`get_operation_output` function is used to retrieve the values 
of variables exposed /
+    exported from an interface operation.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        if (not isinstance(argument, list)) or (len(argument) != 4):
+            raise InvalidValueError(
+                'function "get_operation_output" argument must be a list of 4 
parameters: {0}'
+                .format(safe_repr(argument)),
+                locator=self.locator)
+
+        self.modelable_entity_name = parse_string_expression(context, 
presentation,
+                                                             
'get_operation_output', 0,
+                                                             'modelable entity 
name', argument[0])
+        self.interface_name = parse_string_expression(context, presentation, 
'get_operation_output',
+                                                      1, 'the interface name', 
argument[1])
+        self.operation_name = parse_string_expression(context, presentation, 
'get_operation_output',
+                                                      2, 'the operation name', 
argument[2])
+        self.output_variable_name = parse_string_expression(context, 
presentation,
+                                                            
'get_operation_output', 3,
+                                                            'the output name', 
argument[3])
+
+    @property
+    def as_raw(self):
+        interface_name = self.interface_name
+        if hasattr(interface_name, 'as_raw'):
+            interface_name = as_raw(interface_name)
+        operation_name = self.operation_name
+        if hasattr(operation_name, 'as_raw'):
+            operation_name = as_raw(operation_name)
+        output_variable_name = self.output_variable_name
+        if hasattr(output_variable_name, 'as_raw'):
+            output_variable_name = as_raw(output_variable_name)
+        return {'get_operation_output': [self.modelable_entity_name, 
interface_name, operation_name,
+                                         output_variable_name]}
+
+
+#
+# Navigation
+#
+
+@implements_specification('4.7.1', 'tosca-simple-1.0')
+class GetNodesOfType(Function):
+    """
+    The :code:`get_nodes_of_type` function can be used to retrieve a list of 
all known instances of
+    nodes of the declared Node Type.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        self.node_type_name = parse_string_expression(context, presentation, 
'get_nodes_of_type',
+                                                      None, 'the node type 
name', argument)
+
+        if isinstance(self.node_type_name, basestring):
+            node_types = context.presentation.get('service_template', 
'node_types')
+            if (node_types is None) or (self.node_type_name not in node_types):
+                raise InvalidValueError(
+                    'function "get_nodes_of_type" argument is not a valid node 
type name: {0}'
+                    .format(safe_repr(argument)),
+                    locator=self.locator)
+
+    @property
+    def as_raw(self):
+        node_type_name = self.node_type_name
+        if hasattr(node_type_name, 'as_raw'):
+            node_type_name = as_raw(node_type_name)
+        return {'get_nodes_of_type': node_type_name}
+
+    def __evaluate__(self, container):
+        pass
+
+
+#
+# Artifact
+#
+
+@implements_specification('4.8.1', 'tosca-simple-1.0') # pylint: 
disable=abstract-method
+class GetArtifact(Function):
+    """
+    The :code:`get_artifact` function is used to retrieve artifact location 
between modelable
+    entities defined in the same service template.
+    """
+
+    def __init__(self, context, presentation, argument):
+        self.locator = presentation._locator
+
+        if (not isinstance(argument, list)) or (len(argument) < 2) or 
(len(argument) > 4):
+            raise InvalidValueError(
+                'function "get_artifact" argument must be a list of 2 to 4 
parameters: {0}'
+                .format(safe_repr(argument)),
+                locator=self.locator)
+
+        self.modelable_entity_name = parse_string_expression(context, 
presentation, 'get_artifact',
+                                                             0, 'modelable 
entity name',
+                                                             argument[0])
+        self.artifact_name = parse_string_expression(context, presentation, 
'get_artifact', 1,
+                                                     'the artifact name', 
argument[1])
+        self.location = parse_string_expression(context, presentation, 
'get_artifact', 2,
+                                                'the location or 
"LOCAL_FILE"', argument[2])
+        self.remove = parse_bool(context, presentation, 'get_artifact', 3, 
'the removal flag',
+                                 argument[3])
+
+    @property
+    def as_raw(self):
+        artifact_name = self.artifact_name
+        if hasattr(artifact_name, 'as_raw'):
+            artifact_name = as_raw(artifact_name)
+        location = self.location
+        if hasattr(location, 'as_raw'):
+            location = as_raw(location)
+        return {'get_artifacts': [self.modelable_entity_name, artifact_name, 
location, self.remove]}
+
+
+#
+# Utils
+#
+
+def get_function(context, presentation, value):
+    functions = context.presentation.presenter.functions
+    if isinstance(value, dict) and (len(value) == 1):
+        key = value.keys()[0]
+        if key in functions:
+            try:
+                return True, functions[key](context, presentation, value[key])
+            except InvalidValueError as e:
+                context.validation.report(issue=e.issue)
+                return True, None
+    return False, None
+
+
+def parse_string_expression(context, presentation, name, index, explanation, 
value): # pylint: disable=unused-argument
+    is_function, func = get_function(context, presentation, value)
+    if is_function:
+        return func
+    else:
+        value = str(value)
+    return value
+
+
+def parse_int(context, presentation, name, index, explanation, value): # 
pylint: disable=unused-argument
+    if not isinstance(value, int):
+        try:
+            value = int(value)
+        except ValueError:
+            raise invalid_value(name, index, 'an integer', explanation, value,
+                                presentation._locator)
+    return value
+
+
+def parse_bool(context, presentation, name, index, explanation, value): # 
pylint: disable=unused-argument
+    if not isinstance(value, bool):
+        raise invalid_value(name, index, 'a boolean', explanation, value, 
presentation._locator)
+    return value
+
+
+def parse_modelable_entity_name(context, presentation, name, index, value):
+    value = parse_string_expression(context, presentation, name, index, 'the 
modelable entity name',
+                                    value)
+    if value == 'SELF':
+        the_self, _ = parse_self(presentation)
+        if the_self is None:
+            raise invalid_modelable_entity_name(name, index, value, 
presentation._locator,
+                                                'a node template or a 
relationship template')
+    elif value == 'HOST':
+        _, self_variant = parse_self(presentation)
+        if self_variant != 'node_template':
+            raise invalid_modelable_entity_name(name, index, value, 
presentation._locator,
+                                                'a node template')
+    elif (value == 'SOURCE') or (value == 'TARGET'):
+        _, self_variant = parse_self(presentation)
+        if self_variant != 'relationship_template':
+            raise invalid_modelable_entity_name(name, index, value, 
presentation._locator,
+                                                'a relationship template')
+    elif isinstance(value, basestring):
+        node_templates = \
+            context.presentation.get('service_template', 'topology_template', 
'node_templates') \
+            or {}
+        relationship_templates = \
+            context.presentation.get('service_template', 'topology_template',
+                                     'relationship_templates') \
+            or {}
+        if (value not in node_templates) and (value not in 
relationship_templates):
+            raise InvalidValueError(
+                'function "{0}" parameter {1:d} is not a valid modelable 
entity name: {2}'
+                .format(name, index + 1, safe_repr(value)),
+                locator=presentation._locator, level=Issue.BETWEEN_TYPES)
+    return value
+
+
+def parse_self(presentation):
+    from ..types import (NodeType, RelationshipType)
+    from ..templates import (
+        NodeTemplate as NodeTemplatePresentation,
+        RelationshipTemplate as RelationshipTemplatePresentation
+    )
+
+    if presentation is None:
+        return None, None
+    elif isinstance(presentation, NodeTemplatePresentation) or 
isinstance(presentation, NodeType):
+        return presentation, 'node_template'
+    elif isinstance(presentation, RelationshipTemplatePresentation) \
+        or isinstance(presentation, RelationshipType):
+        return presentation, 'relationship_template'
+    else:
+        return parse_self(presentation._container)
+
+
+def evaluate(value, final, container_holder):
+    """
+    Calls ``__evaluate__`` and passes on ``final`` state.
+    """
+
+    if hasattr(value, '__evaluate__'):
+        value = value.__evaluate__(container_holder)
+        if not value.final:
+            final = False
+        return value.value, final
+    else:
+        return value, final
+
+
+@implements_specification('4.1', 'tosca-simple-1.0')
+def get_modelable_entities(container_holder, name, locator, 
modelable_entity_name):
+    """
+    The following keywords MAY be used in some TOSCA function in place of a 
TOSCA Node or
+    Relationship Template name.
+    """
+
+    if modelable_entity_name == 'SELF':
+        return get_self(container_holder, name, locator)
+    elif modelable_entity_name == 'HOST':
+        return get_hosts(container_holder, name, locator)
+    elif modelable_entity_name == 'SOURCE':
+        return get_source(container_holder, name, locator)
+    elif modelable_entity_name == 'TARGET':
+        return get_target(container_holder, name, locator)
+    elif isinstance(modelable_entity_name, basestring):
+        modelable_entities = []
+
+        service = container_holder.service
+        if service is not None:
+            for node in service.nodes.itervalues():
+                if node.node_template.name == modelable_entity_name:
+                    modelable_entities.append(node)
+        else:
+            service_template = container_holder.service_template
+            if service_template is not None:
+                for node_template in 
service_template.node_templates.itervalues():
+                    if node_template.name == modelable_entity_name:
+                        modelable_entities.append(node_template)
+
+        if not modelable_entities:
+            raise CannotEvaluateFunctionException()
+
+        return modelable_entities
+
+    raise InvalidValueError('function "{0}" could not find modelable entity 
"{1}"'
+                            .format(name, modelable_entity_name),
+                            locator=locator)
+
+
+def get_self(container_holder, name, locator):
+    """
+    A TOSCA orchestrator will interpret this keyword as the Node or 
Relationship Template instance
+    that contains the function at the time the function is evaluated.
+    """
+
+    container = container_holder.container
+    if (not isinstance(container, Node)) and \
+        (not isinstance(container, NodeTemplate)) and \
+        (not isinstance(container, Relationship)) and \
+        (not isinstance(container, RelationshipTemplate)):
+        raise InvalidValueError('function "{0}" refers to "SELF" but it is not 
contained in '
+                                'a node or a relationship: {1}'.format(name,
+                                                                       
full_type_name(container)),
+                                locator=locator)
+
+    return [container]
+
+
+def get_hosts(container_holder, name, locator):
+    """
+    A TOSCA orchestrator will interpret this keyword to refer to the all nodes 
that "host" the node
+    using this reference (i.e., as identified by its HostedOn relationship).
+
+    Specifically, TOSCA orchestrators that encounter this keyword when 
evaluating the get_attribute
+    or :code:`get_property` functions SHALL search each node along the 
"HostedOn" relationship chain
+    starting at the immediate node that hosts the node where the function was 
evaluated (and then
+    that node's host node, and so forth) until a match is found or the 
"HostedOn" relationship chain
+    ends.
+    """
+
+    container = container_holder.container
+    if (not isinstance(container, Node)) and (not isinstance(container, 
NodeTemplate)):
+        raise InvalidValueError('function "{0}" refers to "HOST" but it is not 
contained in '
+                                'a node: {1}'.format(name, 
full_type_name(container)),
+                                locator=locator)
+
+    if not isinstance(container, Node):
+        # NodeTemplate does not have "host"; we'll wait until instantiation
+        raise CannotEvaluateFunctionException()
+
+    host = container.host
+    if host is None:
+        # We might have a host later
+        raise CannotEvaluateFunctionException()
+
+    return [host]
+
+
+def get_source(container_holder, name, locator):
+    """
+    A TOSCA orchestrator will interpret this keyword as the Node Template 
instance that is at the
+    source end of the relationship that contains the referencing function.
+    """
+
+    container = container_holder.container
+    if (not isinstance(container, Relationship)) and \
+        (not isinstance(container, RelationshipTemplate)):
+        raise InvalidValueError('function "{0}" refers to "SOURCE" but it is 
not contained in '
+                                'a relationship: {1}'.format(name, 
full_type_name(container)),
+                                locator=locator)
+
+    if not isinstance(container, RelationshipTemplate):
+        # RelationshipTemplate does not have "source_node"; we'll wait until 
instantiation
+        raise CannotEvaluateFunctionException()
+
+    return [container.source_node]
+
+
+def get_target(container_holder, name, locator):
+    """
+    A TOSCA orchestrator will interpret this keyword as the Node Template 
instance that is at the
+    target end of the relationship that contains the referencing function.
+    """
+
+    container = container_holder.container
+    if (not isinstance(container, Relationship)) and \
+        (not isinstance(container, RelationshipTemplate)):
+        raise InvalidValueError('function "{0}" refers to "TARGET" but it is 
not contained in '
+                                'a relationship: {1}'.format(name, 
full_type_name(container)),
+                                locator=locator)
+
+    if not isinstance(container, RelationshipTemplate):
+        # RelationshipTemplate does not have "target_node"; we'll wait until 
instantiation
+        raise CannotEvaluateFunctionException()
+
+    return [container.target_node]
+
+
+def get_modelable_entity_parameter(modelable_entity, parameters, 
nested_parameter_name_or_index):
+    if not parameters:
+        return False, True, None
+
+    found = True
+    final = True
+    value = parameters
+
+    for name_or_index in nested_parameter_name_or_index:
+        if (isinstance(value, dict) and (name_or_index in value)) \
+            or ((isinstance(value, list) and (name_or_index < len(value)))):
+            value = value[name_or_index] # Parameter
+            # We are not using Parameter.value, but rather Parameter._value, 
because we want to make
+            # sure to get "final" (it is swallowed by Parameter.value)
+            value, final = evaluate(value._value, final, value)
+        else:
+            found = False
+            break
+
+    return Evaluation(value, final) if found else None
+
+
+def invalid_modelable_entity_name(name, index, value, locator, contexts):
+    return InvalidValueError('function "{0}" parameter {1:d} can be "{2}" only 
in {3}'
+                             .format(name, index + 1, value, contexts),
+                             locator=locator, level=Issue.FIELD)
+
+
+def invalid_value(name, index, the_type, explanation, value, locator):
+    return InvalidValueError(
+        'function "{0}" {1} is not {2}{3}: {4}'
+        .format(name,
+                'parameter {0:d}'.format(index + 1) if index is not None else 
'argument',
+                the_type,
+                ', {0}'.format(explanation) if explanation is not None else '',
+                safe_repr(value)),
+        locator=locator, level=Issue.FIELD)


Reply via email to