| # 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.utils.collections import deepcopy_with_locators, OrderedDict |
| from aria.parser.validation import Issue |
| |
| from .parameters import (convert_parameter_definitions_to_values, merge_raw_parameter_definitions, |
| get_assigned_and_defined_parameter_values) |
| |
| |
| # |
| # CapabilityType |
| # |
| |
| def get_inherited_valid_source_types(context, presentation): |
| """ |
| If we haven't set the ``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) |
| if isinstance(capability_definition._raw, basestring): |
| # Make sure we have a dict |
| the_type = capability_definition._raw |
| capability_definition._raw = OrderedDict() |
| capability_definition._raw['type'] = the_type |
| 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_parameter_values(context, |
| our_capability_assignment, |
| 'property') |
| 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_parameter_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_parameter_definitions(context, presentation, raw_properties, type_property_defintions, |
| 'properties') |
| |
| # Merge our properties |
| merge_raw_parameter_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) |