示例#1
0
    def test_entity_string_reference(self):
        """Test evaluate_expression function"""
        input_values = InputValues(None)
        input_values.max_cardinality = 1
        input_values.min_cardinality = 0
        input_values.max_depth = 32
        input_values.next_depth = 1
        input_values.no_max_depth = True
        input_values.is_array = True
        input_values.normalized = False
        input_values.reference_only = True
        input_values.structured = True

        expr_and_expected_result_list = []
        expr_and_expected_result_list.append(
            ('(cardinality.maximum > 1) && (!referenceOnly)', False))
        expr_and_expected_result_list.append(('', True))
        expr_and_expected_result_list.append(('  ', True))
        expr_and_expected_result_list.append(('always', True))
        expr_and_expected_result_list.append(('!structured', False))
        expr_and_expected_result_list.append(
            ('referenceOnly || (depth > 5)', True))
        expr_and_expected_result_list.append(('!(referenceOnly)', False))
        expr_and_expected_result_list.append(
            ('!(normalized && cardinality.maximum > 1)', True))
        expr_and_expected_result_list.append(('true', True))
        expr_and_expected_result_list.append(('(((true==true)))', True))
        expr_and_expected_result_list.append(
            ('!(normalized && isArray) || noMaxDepth', False))

        for item in expr_and_expected_result_list:
            actual = ExpressionTree._evaluate_condition(item[0], input_values)
            expected = item[1]

            self.assertEqual(expected, actual)
    def test_entity_string_reference(self):
        """Test evaluate_expression function"""
        input = InputValues()
        input.max_cardinality = 1
        input.min_cardinality = 0
        input.max_depth = 32
        input.next_depth = 1
        input.no_max_depth = True
        input.is_array = True
        input.normalized = False
        input.reference_only = True
        input.structured = True

        expr_and_expected_result_list = []
        expr_and_expected_result_list.append(
            ('(cardinality.maximum > 1) && (!referenceOnly)', 'False'))
        expr_and_expected_result_list.append(('', 'False'))
        expr_and_expected_result_list.append(('  ', 'False'))
        expr_and_expected_result_list.append(('always', 'True'))
        expr_and_expected_result_list.append(('!structured', 'False'))
        expr_and_expected_result_list.append(
            ('referenceOnly || (depth > 5)', 'True'))
        expr_and_expected_result_list.append(('!(referenceOnly)', 'False'))
        expr_and_expected_result_list.append(
            ('!(normalized && cardinality.maximum > 1)', 'True'))
        expr_and_expected_result_list.append(('true', 'True'))
        expr_and_expected_result_list.append(('(((true==true)))', 'True'))
        expr_and_expected_result_list.append(
            ('!(normalized && isArray) || noMaxDepth', 'False'))

        for item in expr_and_expected_result_list:
            tree = ExpressionTree()
            tree_top = tree._construct_expression_tree(item[0])
            expected = item[1]
            actual = str(
                ExpressionTree._evaluate_expression_tree(tree_top, input))

            self.assertEqual(expected, actual)
示例#3
0
    def _construct_projection_context(self, proj_directive: 'ProjectionDirective', attr_ctx: 'CdmAttributeContext', ras: Optional['ResolvedAttributeSet'] = None) -> 'ProjectionContext':
        """
        A function to construct projection context and populate the resolved attribute set that ExtractResolvedAttributes method can then extract
        This function is the entry point for projection resolution.
        This function is expected to do the following 3 things:
        - Create an condition expression tree & default if appropriate
        - Create and initialize Projection Context
        - Process operations
        """
        proj_context = None

        condition =  self.condition if self.condition  else "(true)"

        # create an expression tree based on the condition
        tree = ExpressionTree()
        self._condition_expression_tree_root = tree._construct_expression_tree(condition)

        if attr_ctx:
            # Add projection to context tree
            acp_proj = AttributeContextParameters()
            acp_proj._under = attr_ctx
            acp_proj._type = CdmAttributeContextType.PROJECTION
            acp_proj._name = self.fetch_object_definition_name()
            acp_proj._regarding = proj_directive._owner_ref
            acp_proj._include_traits = False

            ac_proj = CdmAttributeContext._create_child_under(proj_directive._res_opt, acp_proj)

            acp_source = AttributeContextParameters()
            acp_source._under = ac_proj
            acp_source._type = CdmAttributeContextType.SOURCE
            acp_source._name = 'source'
            acp_source._regarding = None
            acp_source._include_traits = False

            ac_source = CdmAttributeContext._create_child_under(proj_directive._res_opt, acp_source)

            # Initialize the projection context
            ctx = proj_directive._owner.ctx if proj_directive._owner else None

            if self.source:
                source = self.source.fetch_object_definition(proj_directive._res_opt)
                if source.object_type == CdmObjectType.PROJECTION_DEF:
                    # A Projection

                    proj_context = self.source.explicit_reference._construct_projection_context(proj_directive, ac_source, ras)
                else:
                    # An Entity Reference

                    acp_source_projection = AttributeContextParameters()
                    acp_source_projection._under = ac_source
                    acp_source_projection._type = CdmAttributeContextType.ENTITY
                    acp_source_projection._name = self.source.named_reference if self.source.named_reference else self.source.explicit_reference.get_name()
                    acp_source_projection._regarding = self.source
                    acp_source_projection._include_traits = False

                    ras = self.source._fetch_resolved_attributes(proj_directive._res_opt, acp_source_projection)

                    # If polymorphic keep original source as previous state
                    poly_source_set = None
                    if proj_directive._is_source_polymorphic:
                        poly_source_set = ProjectionResolutionCommonUtil._get_polymorphic_source_set(proj_directive, ctx, self.source, acp_source_projection)

                    # Now initialize projection attribute state
                    pas_set = ProjectionResolutionCommonUtil._initialize_projection_attribute_state_set(
                        proj_directive,
                        ctx,
                        ras,
                        proj_directive._is_source_polymorphic,
                        poly_source_set
                    )

                    proj_context = ProjectionContext(proj_directive, ras.attribute_context)
                    proj_context._current_attribute_state_set = pas_set
            else:
                # A type attribute

                # Initialize projection attribute state
                pas_set = ProjectionResolutionCommonUtil._initialize_projection_attribute_state_set(
                    proj_directive,
                    ctx,
                    ras,
                    is_source_polymorphic=False,
                    polymorphic_set=None
                )

                proj_context = ProjectionContext(proj_directive, ras.attribute_context)
                proj_context._current_attribute_state_set = pas_set

            is_condition_valid = False
            if self._condition_expression_tree_root:
                input = InputValues()
                input.no_max_depth = proj_directive._has_no_maximum_depth
                input.is_array = proj_directive._is_array
                input.reference_only = proj_directive._is_reference_only
                input.normalized = proj_directive._is_normalized
                input.structured = proj_directive._is_structured
                input.is_virtual = proj_directive._is_virtual

                current_depth = proj_directive._current_depth
                current_depth += 1
                input.next_depth = current_depth
                proj_directive._current_depth = current_depth

                input.max_depth = proj_directive._maximum_depth
                input.min_cardinality = proj_directive._cardinality._minimum_number if proj_directive._cardinality else None
                input.max_cardinality = proj_directive._cardinality._maximum_number if proj_directive._cardinality else None

                is_condition_valid = ExpressionTree._evaluate_expression_tree(self._condition_expression_tree_root, input)

            if is_condition_valid and self.operations and len(self.operations) > 0:
                # Just in case operations were added programmatically, reindex operations
                for i in range(len(self.operations)):
                    self.operations[i]._index = i + 1

                # Operation

                acp_gen_attr_set = AttributeContextParameters()
                acp_gen_attr_set._under = attr_ctx
                acp_gen_attr_set._type = CdmAttributeContextType.GENERATED_SET
                acp_gen_attr_set._name = '_generatedAttributeSet'

                ac_gen_attr_set = CdmAttributeContext._create_child_under(proj_directive._res_opt, acp_gen_attr_set)

                # Start with an empty list for each projection
                pas_operations = ProjectionAttributeStateSet(proj_context._current_attribute_state_set._ctx)
                for operation in self.operations:
                    # Evaluate projections and apply to empty state
                    new_pas_operations = operation._append_projection_attribute_state(proj_context, pas_operations, ac_gen_attr_set)

                    # If the operations fails or it is not implemented the projection cannot be evaluated so keep previous valid state.
                    if new_pas_operations is not None:
                        pas_operations = new_pas_operations

                # Finally update the current state to the projection context
                proj_context._current_attribute_state_set = pas_operations

        return proj_context