async def test_cdm_folder_to_data_type_attribute(self): """ Testing that "is.localized.describedAs" trait with a table of three entries (en, rs and cn) is fully preserved when running CdmFolder TypeAttributePersistence ToData. """ corpus = CdmCorpusDefinition() corpus.ctx.report_at_level = CdmStatusLevel.WARNING corpus.storage.mount('local', LocalAdapter('C:\\Root\\Path')) corpus.storage.default_namespace = 'local' cdm_type_attribute_definition = corpus.make_object(CdmObjectType.TYPE_ATTRIBUTE_DEF, 'TestSavingTraitAttribute', False) english_constants_list = ['en', 'Some description in English language'] serbian_constants_list = ['sr', 'Opis na srpskom jeziku'] chinese_constants_list = ['cn', '一些中文描述'] list_of_const_lists = [english_constants_list, serbian_constants_list, chinese_constants_list] const_ent_def = corpus.make_object(CdmObjectType.CONSTANT_ENTITY_DEF, 'localizedDescriptions', False) const_ent_def.constant_values = list_of_const_lists const_ent_def.entity_shape = corpus.make_ref(CdmObjectType.ENTITY_REF, 'localizedTable', True) trait_reference2 = corpus.make_object(CdmObjectType.TRAIT_REF, 'is.localized.describedAs', False) trait_reference2.arguments.append('localizedDisplayText', corpus.make_ref(CdmObjectType.ENTITY_REF, const_ent_def, True)) cdm_type_attribute_definition.applied_traits.append(trait_reference2) result = TypeAttribute().decode(PersistenceLayer.to_data(cdm_type_attribute_definition, None, None, PersistenceLayer.CDM_FOLDER)) self.assertIsNotNone(result.appliedTraits) argument = result.appliedTraits[0].arguments[0] constant_values = argument.value.entityReference.constantValues self.assertEqual('en', constant_values[0][0]) self.assertEqual('Some description in English language', constant_values[0][1]) self.assertEqual('sr', constant_values[1][0]) self.assertEqual('Opis na srpskom jeziku', constant_values[1][1]) self.assertEqual('cn', constant_values[2][0]) self.assertEqual('一些中文描述', constant_values[2][1])
async def test_resolving_manifest_not_in_folder(self): """Test that resolving a manifest that hasn't been added to a folder doesn't throw any exceptions.""" try: corpus = CdmCorpusDefinition() corpus.storage.mount('local', LocalAdapter('C:\\path')) corpus.storage.default_namespace = 'local' def callback(level, message): # We should see the following error message be logged. If not, fail. if 'Cannot resolve the manifest \'test\' because it has not been added to a folder' not in message: self.fail() corpus.set_event_callback(callback, CdmStatusLevel.WARNING) manifest = corpus.make_object(CdmObjectType.MANIFEST_DEF, 'test') entity = corpus.make_object(CdmObjectType.ENTITY_DEF, 'entity') document = corpus.make_object(CdmObjectType.DOCUMENT_DEF, 'entity{}'.format(PersistenceLayer.CDM_EXTENSION)) document.definitions.append(entity) # Don't add the document containing the entity to a folder either. manifest.entities.append(entity) await manifest.create_resolved_manifest_async('resolved', None) except Exception: self.fail('Exception should not be thrown when resolving a manifest that is not in a folder.')
async def test_programmatically_create_partitions(self): corpus = CdmCorpusDefinition() corpus.storage.mount('local', LocalAdapter()) manifest = corpus.make_object(CdmObjectType.MANIFEST_DEF, 'manifest') entity = manifest.entities.append('entity') relative_partition = corpus.make_object( CdmObjectType.DATA_PARTITION_DEF, 'relative partition') relative_partition.location = 'relative/path' absolute_partition = corpus.make_object( CdmObjectType.DATA_PARTITION_DEF, 'absolute partition') absolute_partition.location = 'local:/absolute/path' entity.data_partitions.append(relative_partition) entity.data_partitions.append(absolute_partition) manifest_data = await ManifestPersistence.to_data(manifest, None, None) self.assertEqual(len(manifest_data.entities), 1) entityData = manifest_data.entities[0] partitions_list = entityData.dataPartitions self.assertEqual(len(partitions_list), 2) relative_partition_data = partitions_list[0] absolute_partition_data = partitions_list[-1] self.assertEqual(relative_partition_data.location, relative_partition.location) self.assertEqual(absolute_partition_data.location, absolute_partition.location)
async def read_local_save_adls(self, corpus: CdmCorpusDefinition): # --------------------------------------------------------------------------------------------- # Create manifest from a local model.json file manifest = await corpus.fetch_object_async('local:/model.json') # ------------------------------------------------------------------------------------------------------------ # Explore entities and partitions defined in the model print('Listing entity declarations:') for decl in manifest.entities: print(' ' + decl.entity_name) if decl.object_type == CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF: for data_part in decl.data_partitions: print(' ' + data_part.location) # --------------------------------------------------------------------------------------------- # Make a few changes to the model # Create a new document where the new entity's definition will be stored new_entity_doc = corpus.make_object( CdmObjectType.DOCUMENT_DEF, 'NewEntity.cdm.json') # type: CdmDocumentDefinition new_entity_doc.imports.append('cdm:/foundations.cdm.json') corpus.storage.fetch_root_folder('local').documents.append( new_entity_doc) new_entity = new_entity_doc.definitions.append( 'NewEntity', CdmObjectType.ENTITY_DEF, False) # type: CdmEntityDefinition # Define new string attribute and add it to the entity definition new_attribute = corpus.make_object( CdmObjectType.TYPE_ATTRIBUTE_DEF, 'NewAttribute') # type: CdmTypeAttributeDefinition new_attribute.data_format = CdmDataFormat.STRING new_entity.attributes.append(new_attribute) # Call will create entity_declaration_definition based on entity definition and add it to manifest.entities new_entity_decl = manifest.entities.append( new_entity) # type: CdmLocalEntityDeclaration # Define a partition and add it to the local declaration new_partition = corpus.make_object( CdmObjectType.DATA_PARTITION_DEF, 'NewPartition', False) # type: CdmDataPartitionDefinition new_partition.location = 'adls:/NewPartition.csv' new_entity_decl.data_partitions.append(new_partition) # --------------------------------------------------------------------------------------------- # Save the file to ADLSg2 - we achieve that by adding the manifest to the root folder of # the ADLS file-system and performing a save on the manifest adls_folder = corpus.storage.fetch_root_folder( 'adls') # type: CdmFolderDefinition adls_folder.documents.append(manifest) await manifest.save_as_async('model.json', True)
async def create_manifest(self, cdm_corpus: CdmCorpusDefinition): print('Make placeholder manifest') # Make the temp manifest and add it to the root of the local documents in the corpus. manifest_abstract = cdm_corpus.make_object(CdmObjectType.MANIFEST_DEF, 'temp_abstract') # type: CdmManifestDefinition # Add each declaration, this example is about medical appointments and care plans manifest_abstract.entities.append('Account', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account') manifest_abstract.entities.append('Address', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Address.cdm.json/Address') manifest_abstract.entities.append('CarePlan', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CarePlan.cdm.json/CarePlan') manifest_abstract.entities.append('CodeableConcept', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CodeableConcept.cdm.json/CodeableConcept') manifest_abstract.entities.append('Contact', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Contact.cdm.json/Contact') manifest_abstract.entities.append('Device', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Device.cdm.json/Device') manifest_abstract.entities.append('EmrAppointment', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EmrAppointment.cdm.json/EmrAppointment') manifest_abstract.entities.append('Encounter', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Encounter.cdm.json/Encounter') manifest_abstract.entities.append('EpisodeOfCare', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EpisodeOfCare.cdm.json/EpisodeOfCare') manifest_abstract.entities.append('Location', 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Location.cdm.json/Location') # Add the temp manifest to the root of the local documents in the corpus. local_root = cdm_corpus.storage.fetch_root_folder('local') local_root.documents.append(manifest_abstract) # Create the resolved version of everything in the root folder too. print('Resolve the placeholder') manifest_resolved = await manifest_abstract.create_resolved_manifest_async('default', '') # Add an import to the foundations doc so the traits about partitons will resolve nicely. manifest_resolved.imports.append('cdm:/foundations.cdm.json', '') print('Save the documents') for e_def in manifest_resolved.entities: # Get the entity being pointed at. local_e_def = cast(CdmLocalEntityDeclarationDefinition, e_def) # Turns a relative path from manifest_resolved into an absolute path. ent_def = cast(CdmEntityDefinition, await cdm_corpus.fetch_object_async(local_e_def.entity_path, manifest_resolved)) # Make a fake partition, just to demo that. part = cdm_corpus.make_object(CdmObjectType.DATA_PARTITION_DEF, '{}-data-description'.format(ent_def.entity_name)) # type: CdmDataPartitionDefinition local_e_def.data_partitions.append(part) part.explanation = 'not real data, just for demo' # Define the location of the partition, relative to the manifest local_location = 'local:/{}/partition-data.csv'.format(ent_def.entity_name) part.location = cdm_corpus.storage.create_relative_corpus_path(local_location, manifest_resolved) # Add trait to partition for csv params. csv_trait = part.exhibits_traits.append('is.partition.format.CSV', False) csv_trait.arguments.append('columnHeaders', 'true') csv_trait.arguments.append('delimiter', ',') # Get the actual location of the partition file from the corpus. part_path = cdm_corpus.storage.corpus_path_to_adapter_path(local_location) # Make a fake file with nothing but header for columns. header = ','.join([att.name for att in ent_def.attributes]) os.makedirs(cdm_corpus.storage.corpus_path_to_adapter_path('local:/{}'.format(ent_def.entity_name)), exist_ok=True) with open(part_path, 'w') as file: file.write(header) await manifest_resolved.save_as_async('{}.manifest.cdm.json'.format(manifest_resolved.manifest_name), True)
async def test_programmatically_create_partitions(self): corpus = CdmCorpusDefinition() corpus.ctx.report_at_level = CdmStatusLevel.WARNING manifest = corpus.make_object(CdmObjectType.MANIFEST_DEF, 'manifest') entity = manifest.entities.append('entity') relative_partition = corpus.make_object( CdmObjectType.DATA_PARTITION_DEF, 'relative partition') relative_partition.location = 'relative/path' relative_partition.arguments['test1'] = ['argument1'] relative_partition.arguments['test2'] = ['argument2', 'argument3'] absolute_partition = corpus.make_object( CdmObjectType.DATA_PARTITION_DEF, 'absolute partition') absolute_partition.location = 'local:/absolute/path' # add an empty arguments list to test empty list should not be displayed in ToData json. absolute_partition.arguments['test'] = [] entity.data_partitions.append(relative_partition) entity.data_partitions.append(absolute_partition) manifest_data = ManifestPersistence.to_data(manifest, None, None) self.assertEqual(len(manifest_data.entities), 1) entityData = manifest_data.entities[0] partitions_list = entityData.dataPartitions self.assertEqual(len(partitions_list), 2) relative_partition_data = partitions_list[0] absolute_partition_data = partitions_list[-1] self.assertEqual(relative_partition_data.location, relative_partition.location) arguments_list = relative_partition_data.arguments self.assertEqual(3, len(arguments_list)) checked_arguments = [] for argument in arguments_list: self.assertEqual(3, len(argument)) checked_arguments.append(argument.value) if argument.value == 'argument1': self.assertEqual('test1', argument.name) elif argument.value == 'argument2': self.assertEqual('test2', argument.name) elif argument.value == 'argument3': self.assertEqual('test2', argument.name) else: raise Exception('unexpected argument in data partitions') self.assertTrue('argument1' in checked_arguments) self.assertTrue('argument2' in checked_arguments) self.assertTrue('argument3' in checked_arguments) self.assertEqual(absolute_partition_data.location, absolute_partition.location) # test if empty argument list is set to null self.assertEqual(absolute_partition_data.arguments, None)
def test_cdm_collection_appending_list(self): cdm_corpus = CdmCorpusDefinition() cdm_corpus.storage.default_namespace = 'local' cdm_corpus.storage.mount('local', LocalAdapter('CdmCorpus/LocalPath')) ctx = cdm_corpus.ctx cdm_document = CdmDocumentDefinition(ctx, 'NameOfDocument') collection = CdmCollection(ctx, cdm_document, CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF) entity_list = [] for i in range(0, 2): entity = CdmEntityDefinition(cdm_corpus.ctx, 'entityName_{}'.format(i), None) create_document_for_entity(cdm_corpus, entity) entity_declaration = cdm_corpus.make_object( CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, entity.entity_name, False) # type: CdmLocalEntityDeclarationDefinition entity_declaration.entity_path = '{}/{}'.format( entity.owner.at_corpus_path, entity.entity_name) entity_declaration.owner = entity.owner entity_list.append(entity_declaration) self.assertEqual(0, len(collection)) collection.extend(entity_list) self.assertEqual(2, len(collection)) for i in range(0, 2): self.assertEqual('entityName_{}'.format(i), collection[i].entity_name)
def test_data_format(self): corpus = CdmCorpusDefinition() att = corpus.make_object(CdmObjectType.TYPE_ATTRIBUTE_DEF, 'att') for format in CdmDataFormat: att.dataFormat = format self.assertEqual(att.dataFormat, format)
async def test_setting_model_json_entity_description(self): """Tests that a description on a CdmFolder entity sets the description on the ModelJson entity.""" corpus = CdmCorpusDefinition() manifest = corpus.make_object(CdmObjectType.MANIFEST_DEF, 'test') document = corpus.make_object(CdmObjectType.DOCUMENT_DEF, 'entity{}'.format(PersistenceLayer.CDM_EXTENSION)) folder = corpus.storage.fetch_root_folder('local') folder.documents.append(document) entity = document.definitions.append(CdmObjectType.ENTITY_DEF.name, 'entity') entity.description = 'test description' manifest.entities.append(entity) folder.documents.append(manifest) obtained_model_json = await ManifestPersistence.to_data(manifest, None, None) self.assertEqual('test description', obtained_model_json.entities[0].get('description'))
async def main(): # Make a corpus, the corpus is the collection of all documents and folders created or discovered while navigating # objects and paths. cdm_corpus = CdmCorpusDefinition() cdm_corpus.ctx.update_logging_options(level='ERROR') print('configure storage adapters') cdm_corpus.storage.mount('local', LocalAdapter(root='..')) # Local is our default. So any paths that start out navigating without a device tag will assume local. cdm_corpus.default_namespace = 'local' # Fake cdm, normally use the github adapter. cdm_corpus.storage.mount('cdm', LocalAdapter(root='../../example-public-standards')) # This sample is going to simulate the steps a tool would follow in order to create a new manifest document in some user # Storage folder when the shapes of the entities in that folder are all taken from some public standards with no # extensions or additions # The steps are: # 1. Create a temporary 'manifest' object at the root of the corpus that contains a list of the selected entities. # 2. Each selected entity points at an 'abstract' schema defintion in the public standards. These entity docs are too # hard to deal with because of abstractions and inheritence, etc. So to make things concrete, we want to make a # 'resolved' version of each entity doc in our local folder. To do this, we call create_resolved_manifest on our # starting manifest. this will resolve everything and find all of the relationships between entities for us. # 3. Save the new documents. print('make placeholder manifest') # Make the temp manifest and add it to the root of the local documents in the corpus. manifest_abstract = cdm_corpus.make_object(CdmObjectType.MANIFEST_DEF, 'temp_abstract') # type: CdmManifestDefinition # Add each declaration, this example is about medical appointments and care plans. ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'Account') # type: CdmLocalEntityDeclarationDefinition ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'Address') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Address.cdm.json/Address' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'CarePlan') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CarePlan.cdm.json/CarePlan' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'CodeableConcept') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CodeableConcept.cdm.json/CodeableConcept' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'Contact') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Contact.cdm.json/Contact' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'Device') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Device.cdm.json/Device' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'EmrAppointment') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EmrAppointment.cdm.json/EmrAppointment' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'Encounter') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Encounter.cdm.json/Encounter' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'EpisodeOfCare') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EpisodeOfCare.cdm.json/EpisodeOfCare' manifest_abstract.entities.add(ent_dec) ent_dec = cdm_corpus.make_object(CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF, 'Location') ent_dec.entity_path = 'cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Location.cdm.json/Location' manifest_abstract.entities.add(ent_dec) # Add the temp manifest to the root of the local documents in the corpus. local_root = cdm_corpus.storage.fetch_root_folder('local') local_root.add_document('temp_abstract.manifest.cdm.json', manifest_abstract) # Create the resolved version of everything in the root folder too. print('resolve the placeholder') manifest_resolved = await manifest_abstract.create_resolved_manifest_async('default', '') # Add an import to the foundations doc so the traits about partitons will resolve nicely. manifest_resolved.add_import('cdm:/foundations.cdm.json', '') print('save the docs') for e_def in manifest_resolved.entities: # Get the entity being pointed at. local_e_def = cast(CdmLocalEntityDeclarationDefinition, e_def) # Turns a relative path from manifest_resolved into an absolute path. ent_def = cast(CdmEntityDefinition, await cdm_corpus.fetch_object_async(local_e_def.entity_path, manifest_resolved)) # Make a fake partition, just to demo that. part = cdm_corpus.make_object(CdmObjectType.DATA_PARTITION_DEF, '{}-data-description'.format(ent_def.entity_name)) # type: CdmDataPartitionDefinition local_e_def.data_partitions.add(part) part.explanation = 'not real data, just for demo' # Define the location of the partition, relative to the manifest local_location = 'local:/{}/partition-data.csv'.format(ent_def.entity_name) part.location = cdm_corpus.storage.create_relative_corpus_path(local_location, manifest_resolved) # Add trait to partition for csv params. csv_trait = part.add_exhibited_trait('is.partition.format.CSV', False) csv_trait.add_argument('columnHeaders', 'true') csv_trait.add_argument('delimiter', ',') # Get the actual location of the partition file from the corpus. part_path = cdm_corpus.storage.corpus_path_to_adapter_path(location) # Make a fake file with nothing but header for columns. header = ','.join([att.name for att in ent_def.has_attributes]) os.makedirs(cdm_corpus.storage.corpus_path_to_adapter_path('local:/{}'.format(ent_def.entity_name)), exist_ok=True) with open(part_path, 'w') as file: file.write(header) await manifest_resolved.save_as_async('{}.manifest.cdm.json'.format(manifest_resolved.manifest_name), True)
# Explore entities and partitions defined in the model print('Listing entity declarations:') for decl in manifest.entities: print(' ' + decl.entity_name) if decl.object_type == CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF: for data_part in decl.data_partitions: print(' ' + data_part.location) # --------------------------------------------------------------------------------------------- # Make a few changes to the model # Create a new document where the new entity's definition will be stored new_entity_doc = corpus.make_object( CdmObjectType.DOCUMENT_DEF, 'NewEntity.cdm.json') # type: CdmDocumentDefinition new_entity_doc.imports.append('cdm:/foundations.cdm.json') corpus.storage.fetch_root_folder('local').documents.append(new_entity_doc) new_entity = new_entity_doc.definitions.append( 'NewEntity', CdmObjectType.ENTITY_DEF, False) # type: CdmEntityDefinition # Define new string attribute and add it to the entity definition new_attribute = corpus.make_object( CdmObjectType.TYPE_ATTRIBUTE_DEF, 'NewAttribute') # type: CdmTypeAttributeDefinition new_attribute.data_format = CdmDataFormat.STRING new_entity.attributes.append(new_attribute) # Call will create entity_declaration_definition based on entity definition and add it to manifest.entities
# Explore entities and partitions defined in the model print('Listing entity declarations:') for decl in manifest.entities: print(' ' + decl.entity_name) if decl.object_type == CdmObjectType.LOCAL_ENTITY_DECLARATION_DEF: for data_part in decl.data_partitions: print(' ' + data_part.location) # --------------------------------------------------------------------------------------------- # Make a few changes to the model # Create a new document where the new entity's definition will be stored new_entity_doc = corpus.make_object( CdmObjectType.DOCUMENT_DEF, 'NewEntity.cdm.json') # type: CdmDocumentDefinition corpus.storage.fetch_root_folder('local').add_document(new_entity_doc.name, new_entity_doc) new_entity = new_entity_doc.add_definition( CdmObjectType.ENTITY_DEF, 'NewEntity') # type: CdmEntityDefinition # Define new string attribute and add it to the entity definition new_attribute = corpus.make_object( CdmObjectType.TYPE_ATTRIBUTE_DEF, 'NewAttribute') # type: CdmTypeAttributeDefinition new_attribute.data_format = CdmDataFormat.STRING new_entity.has_attributes.add(new_attribute) # Create a local declaration of the entity and point it to the new entity document