ariatosca-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@apache.org
Subject [07/14] incubator-ariatosca git commit: ARIA-18 Migrate DSL parser and TOSCA extension code
Date Tue, 15 Nov 2016 02:26:42 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b2c8379c/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
new file mode 100644
index 0000000..7ead633
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/filters.py
@@ -0,0 +1,101 @@
+# 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 aria.parser import dsl_specification
+from aria.parser.utils import cachedmethod
+from aria.parser.presentation import (has_fields, object_sequenced_list_field, field_validator)
+
+from .misc import ConstraintClause
+from .presentation.extensible import ExtensiblePresentation
+from .presentation.field_validators import (node_filter_properties_validator,
+                                            node_filter_capabilities_validator)
+
+@has_fields
+class CapabilityFilter(ExtensiblePresentation):
+    @object_sequenced_list_field(ConstraintClause)
+    def properties(self):
+        pass
+
+    @cachedmethod
+    def _get_node_type(self, context):
+        return self._container._get_node_type(context)
+
+    @cachedmethod
+    def _get_type_for_name(self, context, name):
+        node_type = self._get_node_type(context)
+        if node_type is not None:
+            capabilities = node_type._get_capabilities(context)
+            capability = capabilities.get(self._name)
+            properties = capability.properties if capability is not None else None
+            prop = properties.get(name) if properties is not None else None
+            return prop._get_type(context) if prop is not None else None
+
+        return None
+
+@has_fields
+@dsl_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
+    template's property values, capabilities and capability properties.
+
+    See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+    /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
+    #DEFN_ELEMENT_NODE_FILTER_DEFN>`__
+    """
+
+    @field_validator(node_filter_properties_validator)
+    @object_sequenced_list_field(ConstraintClause)
+    @dsl_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)
+        matching TOSCA entities (e.g., Node Template, Node Type, Capability Types, etc.) based upon
+        their property definitions' values.
+
+        See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+        /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
+        #DEFN_ELEMENT_PROPERTY_FILTER_DEFN>`__
+
+        :rtype: list of (str, :class:`ConstraintClause`)
+        """
+
+    @field_validator(node_filter_capabilities_validator)
+    @object_sequenced_list_field(CapabilityFilter)
+    def capabilities(self):
+        """
+        An optional sequenced list of property filters that would be used to select (filter)
+        matching TOSCA entities (e.g., Node Template, Node Type, Capability Types, etc.) based upon
+        their capabilities' property definitions' values.
+
+        :rtype: list of (str, :class:`CapabilityDefinition`)
+        """
+
+    @cachedmethod
+    def _get_node_type(self, context):
+        if hasattr(self._container, '_get_node'):
+            node_type, node_type_variant = self._container._get_node(context)
+            return node_type if node_type_variant == 'node_type' else None
+        return None
+
+    @cachedmethod
+    def _get_type_for_name(self, context, name):
+        node_type = self._get_node_type(context)
+        if node_type is not None:
+            properties = node_type._get_properties(context)
+            prop = properties.get(name)
+            return prop._get_type(context) if prop is not None else None
+
+        return None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b2c8379c/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
new file mode 100644
index 0000000..bf2f69d
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/functions.py
@@ -0,0 +1,527 @@
+# 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.parser import (dsl_specification, InvalidValueError)
+from aria.parser.modeling import (Function, CannotEvaluateFunctionException)
+from aria.parser.utils import (FrozenList, as_raw, safe_repr)
+from aria.parser.validation import Issue
+
+#
+# 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.model.inputs.get(self.input_property_name))
+        return 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:
+            if hasattr(modelable_entity, 'requirement_templates') \
+                and modelable_entity.requirement_templates \
+                and (req_or_cap_name in modelable_entity.requirement_templates):
+                # First argument refers to a requirement
+                properties = modelable_entity.requirement_templates[req_or_cap_name].properties
+                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 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')
+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')
+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.
+    """
+
+    print container.relationships
+    exit()
+
+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.
+    """
+
+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/b2c8379c/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
new file mode 100644
index 0000000..5e41378
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/misc.py
@@ -0,0 +1,409 @@
+# 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 aria.parser import dsl_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,
+                                      object_list_field, object_dict_field, field_validator,
+                                      type_validator)
+from aria.parser.utils import (cachedmethod, puts, as_raw)
+
+from .modeling.data_types import (get_data_type, get_data_type_value, get_property_constraints,
+                                  apply_constraint_to_value)
+from .modeling.substitution_mappings import (validate_subtitution_mappings_requirement,
+                                             validate_subtitution_mappings_capability)
+from .presentation.extensible import ExtensiblePresentation
+from .presentation.field_validators import (constraint_clause_field_validator,
+                                            constraint_clause_in_range_validator,
+                                            constraint_clause_valid_values_validator,
+                                            constraint_clause_pattern_validator,
+                                            data_type_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')
+class Description(AsIsPresentation):
+    """
+    See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+    /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
+    #DEFN_ELEMENT_DESCRIPTION>`__
+    """
+
+    def __init__(self, name=None, raw=None, container=None, cls=None): # pylint: disable=unused-argument
+        super(Description, self).__init__(name, raw, container, cls=unicode)
+
+    def _dump(self, context):
+        value = as_raw(self.value)
+        puts(context.style.meta(value))
+
+@allow_unknown_fields
+@has_fields
+@dsl_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')
+    def template_name(self):
+        """
+        This optional metadata keyname can be used to declare the name of service template as a
+        single-line string value.
+        """
+
+    @primitive_field(str)
+    @dsl_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
+        as a single-line string value.
+        """
+
+    @primitive_field(str)
+    @dsl_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
+        service template as a single-line string value.
+        """
+
+    @primitive_dict_unknown_fields()
+    def custom(self):
+        """
+        :rtype: dict
+        """
+
+@has_fields
+@dsl_specification('3.5.5', 'tosca-simple-1.0')
+class Repository(ExtensiblePresentation):
+    """
+    A repository definition defines a named external repository which contains deployment and
+    implementation artifacts that are referenced within the TOSCA Service Template.
+
+    See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+    /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
+    #DEFN_ELEMENT_REPOSITORY_DEF>`__
+    """
+
+    @object_field(Description)
+    def description(self):
+        """
+        The optional description for the repository.
+
+        :rtype: :class:`Description`
+        """
+
+    @primitive_field(str, required=True)
+    def url(self):
+        """
+        The required URL or network address used to access the repository.
+
+        :rtype: str
+        """
+
+    @primitive_field()
+    def credential(self):
+        """
+        The optional Credential used to authorize access to the repository.
+
+        :rtype: tosca.datatypes.Credential
+        """
+
+    @cachedmethod
+    def _get_credential(self, context):
+        return get_data_type_value(context, self, 'credential', 'tosca.datatypes.Credential')
+
+@short_form_field('file')
+@has_fields
+@dsl_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
+    TOSCA Service Template file which has type and template definitions to be imported (included)
+    and referenced within another Service Template.
+
+    See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+    /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
+    #DEFN_ELEMENT_IMPORT_DEF>`__
+    """
+
+    @primitive_field(str, required=True)
+    def file(self):
+        """
+        The required symbolic name for the imported file.
+
+        :rtype: str
+        """
+
+    @primitive_field(str)
+    def repository(self):
+        """
+        The optional symbolic name of the repository definition where the imported file can be found
+        as a string.
+
+        :rtype: str
+        """
+
+    @primitive_field(str)
+    def namespace_uri(self):
+        """
+        The optional namespace URI to that will be applied to type definitions found within the
+        imported file as a string.
+
+        :rtype: str
+        """
+
+    @primitive_field(str)
+    def namespace_prefix(self):
+        """
+        The optional namespace prefix (alias) that will be used to indicate the namespace_uri when
+        forming a qualified name (i.e., qname) when referencing type definitions from the imported
+        file.
+
+        :rtype: str
+        """
+
+@has_fields
+@dsl_specification('3.5.2', 'tosca-simple-1.0')
+class ConstraintClause(ExtensiblePresentation):
+    """
+    A constraint clause defines an operation along with one or more compatible values that can be
+    used to define a constraint on a property or parameter's allowed values when it is defined in a
+    TOSCA Service Template or one of its entities.
+
+    See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
+    /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
+    #DEFN_ELEMENT_CONSTRAINTS_CLAUSE>`__
+    """
+
+    @field_validator(constraint_clause_field_validator)
+    @primitive_field()
+    def equal(self):
+        """
+        Constrains a property or parameter to a value equal to ('=') the value declared.
+        """
+
+    @field_validator(constraint_clause_field_validator)
+    @primitive_field()
+    def greater_than(self):
+        """
+        Constrains a property or parameter to a value greater than ('>') the value declared.
+        """
+
+    @field_validator(constraint_clause_field_validator)
+    @primitive_field()
+    def greater_or_equal(self):
+        """
+        Constrains a property or parameter to a value greater than or equal to ('>=') the value
+        declared.
+        """
+
+    @field_validator(constraint_clause_field_validator)
+    @primitive_field()
+    def less_than(self):
+        """
+        Constrains a property or parameter to a value less than ('<') the value declared.
+        """
+
+    @field_validator(constraint_clause_field_validator)
+    @primitive_field()
+    def less_or_equal(self):
+        """
+        Constrains a property or parameter to a value less than or equal to ('<=') the value
+        declared.
+        """
+
+    @field_validator(constraint_clause_in_range_validator)
+    @primitive_list_field()
+    def in_range(self):
+        """
+        Constrains a property or parameter to a value in range of (inclusive) the two values
+        declared.
+
+        Note: subclasses or templates of types that declare a property with the :code:`in_range`
+        constraint MAY only further restrict the range specified by the parent type.
+        """
+
+    @field_validator(constraint_clause_valid_values_validator)
+    @primitive_list_field()
+    def valid_values(self):
+        """
+        Constrains a property or parameter to a value that is in the list of declared values.
+        """
+
+    @primitive_field(int)
+    def length(self):
+        """
+        Constrains the property or parameter to a value of a given length.
+        """
+
+    @primitive_field(int)
+    def min_length(self):
+        """
+        Constrains the property or parameter to a value to a minimum length.
+        """
+
+    @primitive_field(int)
+    def max_length(self):
+        """
+        Constrains the property or parameter to a value to a maximum length.
+        """
+
+    @field_validator(constraint_clause_pattern_validator)
+    @primitive_field(str)
+    def pattern(self):
+        """
+        Constrains the property or parameter to a value that is allowed by the provided regular
+        expression.
+
+        Note: Future drafts of this specification will detail the use of regular expressions and
+        reference an appropriate standardized grammar.
+        """
+
+    @cachedmethod
+    def _get_type(self, context):
+        if hasattr(self._container, '_get_type_for_name'):
+            # NodeFilter or CapabilityFilter
+            return self._container._get_type_for_name(context, self._name)
+        elif hasattr(self._container, '_get_type'):
+            # Properties
+            return self._container._get_type(context)
+        else:
+            # DataType (the DataType itself is our type)
+            return self._container
+
+    def _apply_to_value(self, context, presentation, value):
+        return apply_constraint_to_value(context, presentation, self, value)
+
+@short_form_field('type')
+@has_fields
+class EntrySchema(ExtensiblePresentation):
+    """
+    ARIA NOTE: The specification does not properly explain this type, however it is implied by
+    examples.
+    """
+
+    @field_validator(data_type_validator('entry schema data type'))
+    @primitive_field(str, required=True)
+    def type(self):
+        """
+        :rtype: str
+        """
+
+    @object_field(Description)
+    def description(self):
+        """
+        :rtype: :class:`Description`
+        """
+
+    @object_list_field(ConstraintClause)
+    def constraints(self):
+        """
+        :rtype: list of (str, :class:`ConstraintClause`)
+        """
+
+    @cachedmethod
+    def _get_type(self, context):
+        return get_data_type(context, self, 'type')
+
+    @cachedmethod
+    def _get_constraints(self, context):
+        return get_property_constraints(context, self)
+
+@short_form_field('primary')
+@has_fields
+class OperationImplementation(ExtensiblePresentation):
+    @primitive_field(str)
+    def primary(self):
+        """
+        The optional implementation artifact name (i.e., the primary script file name within a
+        TOSCA CSAR file).
+
+        :rtype: str
+        """
+
+    @primitive_list_field(str)
+    def dependencies(self):
+        """
+        The optional ordered list of one or more dependent or secondary implementation artifact name
+        which are referenced by the primary implementation artifact (e.g., a library the script
+        installs or a secondary script).
+
+        :rtype: list of str
+        """
+
+class SubstitutionMappingsRequirement(AsIsPresentation):
+    @property
+    @cachedmethod
+    def node_template(self):
+        return str(self._raw[0])
+
+    @property
+    @cachedmethod
+    def requirement(self):
+        return str(self._raw[1])
+
+    def _validate(self, context):
+        super(SubstitutionMappingsRequirement, self)._validate(context)
+        validate_subtitution_mappings_requirement(context, self)
+
+class SubstitutionMappingsCapability(AsIsPresentation):
+    @property
+    @cachedmethod
+    def node_template(self):
+        return str(self._raw[0])
+
+    @property
+    @cachedmethod
+    def capability(self):
+        return str(self._raw[1])
+
+    def _validate(self, context):
+        super(SubstitutionMappingsCapability, self)._validate(context)
+        validate_subtitution_mappings_capability(context, self)
+
+@has_fields
+@dsl_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)
+    def node_type(self):
+        """
+        :rtype: str
+        """
+
+    @object_dict_field(SubstitutionMappingsRequirement)
+    def requirements(self):
+        """
+        :rtype: dict of str, :class:`SubstitutionMappingsRequirement`
+        """
+
+    @object_dict_field(SubstitutionMappingsCapability)
+    def capabilities(self):
+        """
+        :rtype: dict of str, :class:`SubstitutionMappingsCapability`
+        """
+
+    @cachedmethod
+    def _get_type(self, context):
+        return get_type_by_full_or_shorthand_name(context, self.node_type, 'node_types')
+
+    def _validate(self, context):
+        super(SubstitutionMappings, self)._validate(context)
+        self._get_type(context)
+
+    def _dump(self, context):
+        self._dump_content(context, (
+            'node_type',
+            'requirements',
+            'capabilities'))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b2c8379c/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
new file mode 100644
index 0000000..5c3206b
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -0,0 +1,497 @@
+# 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.parser.modeling import (Type, RelationshipType, PolicyType, ServiceModel, NodeTemplate,
+                                  RequirementTemplate, RelationshipTemplate, CapabilityTemplate,
+                                  GroupTemplate, PolicyTemplate, SubstitutionTemplate,
+                                  MappingTemplate, InterfaceTemplate, OperationTemplate,
+                                  ArtifactTemplate, Metadata, Parameter)
+
+from ..data_types import coerce_value
+
+def create_service_model(context): # pylint: disable=too-many-locals,too-many-branches
+    model = ServiceModel()
+
+    model.description = context.presentation.get('service_template', 'description', 'value')
+
+    metadata = context.presentation.get('service_template', 'metadata')
+    if metadata is not None:
+        substitution_template = Metadata()
+        substitution_template.values['template_name'] = metadata.template_name
+        substitution_template.values['template_author'] = metadata.template_author
+        substitution_template.values['template_version'] = metadata.template_version
+        custom = metadata.custom
+        if custom:
+            for name, v in custom.iteritems():
+                substitution_template.values[name] = v
+        model.metadata = substitution_template
+
+    create_types(context,
+                 context.modeling.node_types,
+                 context.presentation.get('service_template', 'node_types'))
+    create_types(context,
+                 context.modeling.group_types,
+                 context.presentation.get('service_template', 'group_types'))
+    create_types(context,
+                 context.modeling.capability_types,
+                 context.presentation.get('service_template', 'capability_types'))
+    create_types(context,
+                 context.modeling.relationship_types,
+                 context.presentation.get('service_template', 'relationship_types'),
+                 create_relationship_type)
+    create_types(context,
+                 context.modeling.policy_types,
+                 context.presentation.get('service_template', 'policy_types'),
+                 create_policy_type)
+    create_types(context,
+                 context.modeling.artifact_types,
+                 context.presentation.get('service_template', 'artifact_types'))
+    create_types(context,
+                 context.modeling.interface_types,
+                 context.presentation.get('service_template', 'interface_types'))
+
+    topology_template = context.presentation.get('service_template', 'topology_template')
+    if topology_template is not None:
+        create_properties_from_values(model.inputs, topology_template._get_input_values(context))
+        create_properties_from_values(model.outputs, topology_template._get_output_values(context))
+
+    node_templates = context.presentation.get('service_template', 'topology_template',
+                                              'node_templates')
+    if node_templates:
+        for node_template_name, node_template in node_templates.iteritems():
+            model.node_templates[node_template_name] = create_node_template(context, node_template)
+
+    groups = context.presentation.get('service_template', 'topology_template', 'groups')
+    if groups:
+        for group_name, group in groups.iteritems():
+            model.group_templates[group_name] = create_group_template(context, group)
+
+    policies = context.presentation.get('service_template', 'topology_template', 'policies')
+    if policies:
+        for policy_name, policy in policies.iteritems():
+            model.policy_templates[policy_name] = create_policy_template(context, policy)
+
+    substitution_mappings = context.presentation.get('service_template', 'topology_template',
+                                                     'substitution_mappings')
+    if substitution_mappings is not None:
+        substitution_template = SubstitutionTemplate(substitution_mappings.node_type)
+        capabilities = substitution_mappings.capabilities
+        if capabilities:
+            for mapped_capability_name, capability in capabilities.iteritems():
+                substitution_template.capability_templates[mapped_capability_name] = \
+                    MappingTemplate(mapped_capability_name, capability.node_template,
+                                    capability.capability)
+        requirements = substitution_mappings.requirements
+        if requirements:
+            for mapped_requirement_name, requirement in requirements.iteritems():
+                substitution_template.requirement_templates[mapped_requirement_name] = \
+                    MappingTemplate(mapped_requirement_name, requirement.node_template,
+                                    requirement.requirement)
+        model.substitution_template = substitution_template
+
+    return model
+
+def create_node_template(context, node_template):
+    model = NodeTemplate(name=node_template._name, type_name=node_template.type)
+
+    if node_template.description:
+        model.description = node_template.description.value
+
+    create_properties_from_values(model.properties, node_template._get_property_values(context))
+    create_interface_templates(context, model.interface_templates,
+                               node_template._get_interfaces(context))
+
+    artifacts = node_template._get_artifacts(context)
+    if artifacts:
+        for artifact_name, artifact in artifacts.iteritems():
+            model.artifact_templates[artifact_name] = create_artifact_template(context, artifact)
+
+    requirements = node_template._get_requirements(context)
+    if requirements:
+        for _, requirement in requirements:
+            model.requirement_templates.append(create_requirement_template(context, requirement))
+
+    capabilities = node_template._get_capabilities(context)
+    if capabilities:
+        for capability_name, capability in capabilities.iteritems():
+            model.capability_templates[capability_name] = create_capability_template(context,
+                                                                                     capability)
+
+    create_node_filter_constraint_lambdas(context, node_template.node_filter,
+                                          model.target_node_template_constraints)
+
+    return model
+
+def create_interface_template(context, interface):
+    the_type = interface._get_type(context)
+
+    model = InterfaceTemplate(name=interface._name, type_name=the_type._name)
+
+    if the_type.description:
+        model.description = the_type.description.value
+
+    inputs = interface.inputs
+    if inputs:
+        for input_name, the_input in inputs.iteritems():
+            model.inputs[input_name] = Parameter(the_input.value.type, the_input.value.value,
+                                                 the_input.value.description)
+
+    operations = interface.operations
+    if operations:
+        for operation_name, operation in operations.iteritems():
+            model.operation_templates[operation_name] = create_operation_template(context,
+                                                                                  operation)
+
+    return model if model.operation_templates else None
+
+def create_operation_template(context, operation): # pylint: disable=unused-argument
+    model = OperationTemplate(name=operation._name)
+
+    if operation.description:
+        model.description = operation.description.value
+
+    implementation = operation.implementation
+    if implementation is not None:
+        model.implementation = implementation.primary
+        dependencies = implementation.dependencies
+        if dependencies is not None:
+            model.dependencies = dependencies
+
+    inputs = operation.inputs
+    if inputs:
+        for input_name, the_input in inputs.iteritems():
+            model.inputs[input_name] = Parameter(the_input.value.type, the_input.value.value,
+                                                 the_input.value.description)
+
+    return model
+
+def create_artifact_template(context, artifact):
+    model = ArtifactTemplate(name=artifact._name, type_name=artifact.type,
+                             source_path=artifact.file)
+
+    if artifact.description:
+        model.description = artifact.description.value
+
+    model.target_path = artifact.deploy_path
+
+    repository = artifact._get_repository(context)
+    if repository is not None:
+        model.repository_url = repository.url
+        credential = repository._get_credential(context)
+        if credential:
+            for k, v in credential.iteritems():
+                model.repository_credential[k] = v
+
+    create_properties_from_values(model.properties, artifact._get_property_values(context))
+
+    return model
+
+def create_requirement_template(context, requirement):
+    model = {'name': requirement._name}
+
+    node, node_variant = requirement._get_node(context)
+    if node is not None:
+        if node_variant == 'node_type':
+            model['target_node_type_name'] = node._name
+        else:
+            model['target_node_template_name'] = node._name
+
+    capability, capability_variant = requirement._get_capability(context)
+    if capability is not None:
+        if capability_variant == 'capability_type':
+            model['target_capability_type_name'] = capability._name
+        else:
+            model['target_capability_name'] = capability._name
+
+    model = RequirementTemplate(**model)
+
+    create_node_filter_constraint_lambdas(context, requirement.node_filter,
+                                          model.target_node_template_constraints)
+
+    relationship = requirement.relationship
+    if relationship is not None:
+        model.relationship_template = create_relationship_template(context, relationship)
+
+    return model
+
+def create_relationship_type(context, relationship_type): # pylint: disable=unused-argument
+    return RelationshipType(relationship_type._name)
+
+def create_policy_type(context, policy_type): # pylint: disable=unused-argument
+    return PolicyType(policy_type._name)
+
+def create_relationship_template(context, relationship):
+    relationship_type, relationship_type_variant = relationship._get_type(context)
+    if relationship_type_variant == 'relationship_type':
+        model = RelationshipTemplate(type_name=relationship_type._name)
+    else:
+        relationship_template = relationship_type
+        relationship_type = relationship_template._get_type(context)
+        model = RelationshipTemplate(type_name=relationship_type._name,
+                                     template_name=relationship_template._name)
+        if relationship_template.description:
+            model.description = relationship_template.description.value
+
+    create_properties_from_assignments(model.properties, relationship.properties)
+    create_interface_templates(context, model.source_interface_templates, relationship.interfaces)
+
+    return model
+
+def create_capability_template(context, capability):
+    capability_type = capability._get_type(context)
+    model = CapabilityTemplate(name=capability._name, type_name=capability_type._name)
+
+    capability_definition = capability._get_definition(context)
+    if capability_definition.description:
+        model.description = capability_definition.description.value
+    occurrences = capability_definition.occurrences
+    if occurrences is not None:
+        model.min_occurrences = occurrences.value[0]
+        if occurrences.value[1] != 'UNBOUNDED':
+            model.max_occurrences = occurrences.value[1]
+
+    valid_source_types = capability_definition.valid_source_types
+    if valid_source_types:
+        model.valid_source_node_type_names = valid_source_types
+
+    create_properties_from_assignments(model.properties, capability.properties)
+
+    return model
+
+def create_group_template(context, group):
+    group_type = group._get_type(context)
+    model = GroupTemplate(name=group._name, type_name=group_type._name)
+
+    if group.description:
+        model.description = group.description.value
+
+    create_properties_from_values(model.properties, group._get_property_values(context))
+    create_interface_templates(context, model.interface_templates, group._get_interfaces(context))
+
+    members = group.members
+    if members:
+        for member in members:
+            model.member_node_template_names.append(member)
+
+    return model
+
+def create_policy_template(context, policy):
+    policy_type = policy._get_type(context)
+    model = PolicyTemplate(name=policy._name, type_name=policy_type._name)
+
+    if policy.description:
+        model.description = policy.description.value
+
+    create_properties_from_values(model.properties, policy._get_property_values(context))
+
+    node_templates, groups = policy._get_targets(context)
+    for node_template in node_templates:
+        model.target_node_template_names.append(node_template._name)
+    for group in groups:
+        model.target_group_template_names.append(group._name)
+
+    return model
+
+#
+# Utils
+#
+
+def create_types(context, root, types, normalize=None):
+    if types is None:
+        return
+
+    def added_all():
+        for name in types:
+            if root.get_descendant(name) is None:
+                return False
+        return True
+
+    while not added_all():
+        for name, the_type in types.iteritems():
+            if root.get_descendant(name) is None:
+                parent_type = the_type._get_parent(context)
+                if normalize:
+                    model = normalize(context, the_type)
+                else:
+                    model = Type(the_type._name)
+                if the_type.description:
+                    model.description = the_type.description.value
+                if parent_type is None:
+                    root.children.append(model)
+                else:
+                    container = root.get_descendant(parent_type._name)
+                    if container is not None:
+                        container.children.append(model)
+
+def create_properties_from_values(properties, source_properties):
+    if source_properties:
+        for property_name, prop in source_properties.iteritems():
+            properties[property_name] = Parameter(prop.type, prop.value, prop.description)
+
+def create_properties_from_assignments(properties, source_properties):
+    if source_properties:
+        for property_name, prop in source_properties.iteritems():
+            properties[property_name] = Parameter(prop.value.type, prop.value.value,
+                                                  prop.value.description)
+
+def create_interface_templates(context, interfaces, source_interfaces):
+    if source_interfaces:
+        for interface_name, interface in source_interfaces.iteritems():
+            interface = create_interface_template(context, interface)
+            if interface is not None:
+                interfaces[interface_name] = interface
+
+def create_node_filter_constraint_lambdas(context, node_filter, node_type_constraints):
+    if node_filter is None:
+        return
+
+    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:
+                node_type_constraints.append(func)
+
+    capabilities = node_filter.capabilities
+    if capabilities is not None:
+        for capability_name, capability in capabilities:
+            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:
+                        node_type_constraints.append(func)
+
+def create_constraint_clause_lambda(context, node_filter, constraint_clause, property_name, # pylint: disable=too-many-return-statements
+                                    capability_name):
+    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
+
+    if constraint_key == 'equal':
+        def equal(node_type, container):
+            constraint = coerce_constraint(constraint_clause.equal, container)
+            value = get_value(node_type)
+            return value == constraint
+
+        return 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
+
+    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
+
+    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
+
+    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
+
+    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
+
+    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
+
+    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
+
+    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
+
+    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
+
+    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

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b2c8379c/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py
new file mode 100644
index 0000000..f28f429
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/artifacts.py
@@ -0,0 +1,41 @@
+# 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 collections import OrderedDict
+
+#
+# NodeType, NodeTemplate
+#
+
+def get_inherited_artifact_definitions(context, presentation, for_presentation=None):
+
+    if hasattr(presentation, '_get_type'):
+        # In NodeTemplate
+        parent = presentation._get_type(context)
+    else:
+        # In NodeType
+        parent = presentation._get_parent(context)
+
+    # Get artifact definitions from parent
+    artifacts = get_inherited_artifact_definitions(context, parent, for_presentation=presentation) \
+        if parent is not None else OrderedDict()
+
+    # Add/override our artifact definitions
+    our_artifacts = presentation.artifacts
+    if our_artifacts:
+        for artifact_name, artifact in our_artifacts.iteritems():
+            artifacts[artifact_name] = artifact._clone(for_presentation)
+
+    return artifacts

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b2c8379c/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
new file mode 100644
index 0000000..f9e293d
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
@@ -0,0 +1,177 @@
+# 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 collections import OrderedDict
+
+from aria.parser.utils import deepcopy_with_locators
+from aria.parser.validation import Issue
+
+from .properties import (convert_property_definitions_to_values, merge_raw_property_definitions,
+                         get_assigned_and_defined_property_values)
+
+#
+# CapabilityType
+#
+
+def get_inherited_valid_source_types(context, presentation):
+    """
+    If we haven't set the :code:`valid_source_types` fields, uses that value from our parent, if
+    we have one (recursively).
+    """
+
+    valid_source_types = presentation.valid_source_types
+
+    if valid_source_types is None:
+        parent = presentation._get_parent(context)
+        valid_source_types = get_inherited_valid_source_types(context, parent) \
+            if parent is not None else None
+
+    return valid_source_types
+
+#
+# NodeType
+#
+
+def get_inherited_capability_definitions(context, presentation, for_presentation=None):
+    """
+    Returns our capability capability definitions added on top of those of our parent, if we have
+    one (recursively).
+
+    Allows overriding all aspects of parent capability properties except data type.
+    """
+
+    # Get capability definitions from parent
+    parent = presentation._get_parent(context)
+    capability_definitions = get_inherited_capability_definitions(context, parent,
+                                                                  for_presentation=presentation) \
+                                                                  if parent is not None \
+                                                                  else OrderedDict()
+
+    # Add/merge our capability definitions
+    our_capability_definitions = presentation.capabilities
+    if our_capability_definitions:
+        for capability_name, our_capability_definition in our_capability_definitions.iteritems():
+            if capability_name in capability_definitions:
+                capability_definition = capability_definitions[capability_name]
+
+                # Check if we changed the type
+                type1 = capability_definition.type
+                type2 = our_capability_definition.type
+                if type1 != type2:
+                    context.validation.report(
+                        'capability definition changes type from "%s" to "%s" in "%s"'
+                        % (type1, type2, presentation._fullname),
+                        locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES)
+
+                # Already cloned?
+                #capability_definition = capability_definition._clone(for_presentation)
+                #capability_definitions[capability_name] = capability_definition
+            else:
+                capability_definition = our_capability_definition._clone(for_presentation)
+                capability_definitions[capability_name] = capability_definition
+
+            merge_capability_definition_from_type(context, presentation, capability_definition)
+
+    for capability_definition in capability_definitions.itervalues():
+        capability_definition._reset_method_cache()
+
+    return capability_definitions
+
+#
+# NodeTemplate
+#
+
+def get_template_capabilities(context, presentation):
+    """
+    Returns the node type's capabilities with our assignments to properties and attributes merged
+    in.
+
+    Capability properties' default values, if available, will be used if we did not assign them.
+
+    Makes sure that required properties indeed end up with a value.
+    """
+
+    capability_assignments = OrderedDict()
+
+    the_type = presentation._get_type(context) # NodeType
+    capability_definitions = the_type._get_capabilities(context) if the_type is not None else None
+
+    # Copy over capability definitions from the type (will initialize properties with default
+    # values)
+    if capability_definitions:
+        for capability_name, capability_definition in capability_definitions.iteritems():
+            capability_assignments[capability_name] = \
+                convert_capability_from_definition_to_assignment(context, capability_definition,
+                                                                 presentation)
+
+    # Fill in our capability assignments
+    our_capability_assignments = presentation.capabilities
+    if our_capability_assignments:
+        for capability_name, our_capability_assignment in our_capability_assignments.iteritems():
+            if capability_name in capability_assignments:
+                capability_assignment = capability_assignments[capability_name]
+
+                # Assign properties
+                values = get_assigned_and_defined_property_values(context,
+                                                                  our_capability_assignment)
+                if values:
+                    capability_assignment._raw['properties'] = values
+            else:
+                context.validation.report(
+                    'capability "%s" not declared at node type "%s" in "%s"'
+                    % (capability_name, presentation.type, presentation._fullname),
+                    locator=our_capability_assignment._locator, level=Issue.BETWEEN_TYPES)
+
+    return capability_assignments
+
+#
+# Utils
+#
+
+def convert_capability_from_definition_to_assignment(context, presentation, container):
+    from ..assignments import CapabilityAssignment
+
+    raw = OrderedDict()
+
+    properties = presentation.properties
+    if properties is not None:
+        raw['properties'] = convert_property_definitions_to_values(context, properties)
+
+    # TODO attributes
+
+    return CapabilityAssignment(name=presentation._name, raw=raw, container=container)
+
+def merge_capability_definition_from_type(context, presentation, capability_definition):
+    raw_properties = OrderedDict()
+
+    # Merge properties from type
+    the_type = capability_definition._get_type(context)
+    type_property_defintions = the_type._get_properties(context)
+    merge_raw_property_definitions(context, presentation, raw_properties, type_property_defintions,
+                                   'properties')
+
+    # Merge our properties
+    merge_raw_property_definitions(context, presentation, raw_properties,
+                                   capability_definition.properties, 'properties')
+
+    if raw_properties:
+        capability_definition._raw['properties'] = raw_properties
+
+    # Override valid_source_types
+    if capability_definition._raw.get('valid_source_types') is None:
+        valid_source_types = the_type._get_valid_source_types(context)
+        if valid_source_types is not None:
+            capability_definition._raw['valid_source_types'] = \
+                deepcopy_with_locators(valid_source_types)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b2c8379c/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
new file mode 100644
index 0000000..b86e8eb
--- /dev/null
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/copy.py
@@ -0,0 +1,32 @@
+# 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.
+
+#
+# NodeTemplate, RelationshipTemplate
+#
+
+def get_default_raw_from_copy(presentation, field_name):
+    """
+    Used for the :code:`_get_default_raw` field hook.
+    """
+
+    copy = presentation._raw.get('copy')
+    if copy is not None:
+        templates = getattr(presentation._container, field_name)
+        if templates is not None:
+            template = templates.get(copy)
+            if template is not None:
+                return template._raw
+    return None


Mime
View raw message