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)
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