def apply_default_behavior(entity_attr: 'CdmEntityAttributeDefinition', fk_attr_name: Optional[str], attr_group_name: Optional[str]): '''Applies the replaceAsForeignKey and addAttributeGroup operations to the entity attribute provided.''' ctx = entity_attr.ctx projection = CdmProjection(ctx) # Link for the Source property documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#source projection.source = entity_attr.entity # Link for the RunSequentially property documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#run-sequentially projection.run_sequentially = True entity_attr.entity = CdmEntityReference(ctx, projection, False) if fk_attr_name: foreign_key_attr = CdmTypeAttributeDefinition(ctx, fk_attr_name) foreign_key_attr.data_type = CdmDataTypeReference(ctx, 'entityId', True) # Link for the ReplaceAsForeignKey operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/replaceasforeignkey replace_as_fk_operation = CdmOperationReplaceAsForeignKey(ctx) replace_as_fk_operation.condition = 'referenceOnly' replace_as_fk_operation.reference = 'addressLine' replace_as_fk_operation.replace_with = foreign_key_attr projection.operations.append(replace_as_fk_operation) if attr_group_name: # Link for the AddAttributeGroup operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addattributegroup add_attr_group_operation = CdmOperationAddAttributeGroup(ctx) add_attr_group_operation.condition = 'structured' add_attr_group_operation.attribute_group_name = attr_group_name projection.operations.append(add_attr_group_operation)
def apply_array_expansion(entity_attr: 'CdmEntityAttributeDefinition', start_ordinal: int, end_ordinal: int, rename_format: str, count_att_name: Optional[str]): '''Applies the arrayExpansion operation to the entity attribute provided. It also takes care of applying a renameattributes operation and optionally applying a addCountAttribute operation.''' ctx = entity_attr.ctx projection = CdmProjection(ctx) projection.source = entity_attr.entity projection.run_sequentially = True # Link for the Condition property documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#condition projection.condition = '!normalized' entity_attr.entity = CdmEntityReference(ctx, projection, False) # Link for the ArrayExpansion operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/arrayexpansion arr_expansion_operation = CdmOperationArrayExpansion(ctx) arr_expansion_operation.start_ordinal = start_ordinal arr_expansion_operation.end_ordinal = end_ordinal projection.operations.append(arr_expansion_operation) # Link for the Renameattributes operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/renameattributes # Doing an ArrayExpansion without a RenameAttributes afterwards will result in the expanded attributes being merged in the final resolved entity. # This is because ArrayExpansion does not rename the attributes it expands by default. The expanded attributes end up with the same name and gets merged. # Example: We expand A to A[1], A[2], A[3], but A[1], A[2], A[3] are still named "A". rename_attrs_operation = CdmOperationRenameAttributes(ctx) rename_attrs_operation.rename_format = rename_format projection.operations.append(rename_attrs_operation) if count_att_name: count_attribute = CdmTypeAttributeDefinition(ctx, count_att_name) count_attribute.data_type = CdmDataTypeReference(ctx, 'integer', True) # Link for the AddCountAttribute operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addcountattribute # It is recommended, but not mandated, to be used with the ArrayExpansion operation to provide an ArrayExpansion a count attribute that # represents the total number of expanded elements. AddCountAttribute can also be used by itself. add_count_attr_operation = CdmOperationAddCountAttribute(ctx) add_count_attr_operation.count_attribute = count_attribute projection.operations.append(add_count_attr_operation)
def apply_array_expansion(entity_attr: 'CdmEntityAttributeDefinition', start_ordinal: int, end_ordinal: int, rename_format: str, count_att_name: Optional[str]): '''Applies the arrayExpansion operation to the entity attribute provided. It also takes care of applying a renameattributes operation and optionally applying a addCountAttribute operation.''' ctx = entity_attr.ctx projection = CdmProjection(ctx) projection.source = entity_attr.entity projection.run_sequentially = True # Link for the Condition property documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#condition projection.condition = '!normalized' entity_attr.entity = CdmEntityReference(ctx, projection, False) # Link for the ArrayExpansion operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/arrayexpansion arr_expansion_operation = CdmOperationArrayExpansion(ctx) arr_expansion_operation.start_ordinal = start_ordinal arr_expansion_operation.end_ordinal = end_ordinal projection.operations.append(arr_expansion_operation) # Link for the Renameattributes operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/renameattributes rename_attrs_operation = CdmOperationRenameAttributes(ctx) rename_attrs_operation.rename_format = rename_format projection.operations.append(rename_attrs_operation) if count_att_name: count_attribute = CdmTypeAttributeDefinition(ctx, count_att_name) count_attribute.data_type = CdmDataTypeReference(ctx, 'integer', True) # Link for the AddCountAttribute operation documentation. # https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addcountattribute add_count_attr_operation = CdmOperationAddCountAttribute(ctx) add_count_attr_operation.count_attribute = count_attribute projection.operations.append(add_count_attr_operation)
def test_type_attribute_source(self): """Tests if setting the projection "source" on a type attribute triggers an error log""" corpus = CdmCorpusDefinition() error_count = 0 def callback(level: 'CdmStatusLevel', message: str): nonlocal error_count error_count += 1 corpus.set_event_callback(callback, CdmStatusLevel.ERROR) projection = CdmProjection(corpus.ctx) type_attribute = CdmTypeAttributeDefinition(corpus.ctx, 'attribute') type_attribute.projection = projection # First case, a projection without source. projection.validate() self.assertEqual(0, error_count) # Second case, a projection with a nested projection. inner_projection = CdmProjection(corpus.ctx) projection.source = CdmEntityReference(corpus.ctx, inner_projection, False) projection.validate() inner_projection.validate() self.assertEqual(0, error_count) # Third case, a projection with an explicit entity definition. inner_projection.source = CdmEntityReference( corpus.ctx, CdmEntityDefinition(corpus.ctx, 'Entity'), False) projection.validate() inner_projection.validate() self.assertEqual(1, error_count) error_count = 0 # Third case, a projection with a named reference. inner_projection.source = CdmEntityReference(corpus.ctx, 'Entity', False) projection.validate() inner_projection.validate() self.assertEqual(1, error_count)