Пример #1
0
        private static DataSource CreateDataSource(CdmManifestDefinition instance)
        {
            var source       = new DataSource();
            var t2pm         = new TraitToPropertyMap(instance);
            var sourceTraits = t2pm.FetchTraitReference(dbLocationTrait);

            if (sourceTraits != null && sourceTraits.Arguments != null && sourceTraits.Arguments.Count == 1 &&
                sourceTraits.Arguments[0].Name == dbLocationTraitArgName)
            {
                source.Location = Utils.CorpusPathToSymsPath(sourceTraits.Arguments[0].Value, instance.Ctx.Corpus.Storage);
            }

            if (source.Location == null)
            {
                Logger.Error((ResolveContext)instance.Ctx, Tag, nameof(ToDataAsync), instance.AtCorpusPath,
                             CdmLogCode.ErrPersistSymsStorageSourceTraitError, dbLocationTrait, dbLocationTraitArgName);
                return(null);
            }

            return(source);
        }
        /// <summary>
        /// Loads an entity, resolves it, and then validates the generated attribute contexts
        /// </summary>
        private async Task LoadEntityForResolutionOptionAndSave(string testName, string entityName, List <string> resOpts)
        {
            string expectedOutputPath = TestHelper.GetExpectedOutputFolderPath(testsSubpath, testName);
            string fileNameSuffix     = ProjectionTestUtils.GetResolutionOptionNameSuffix(resOpts);

            CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, testName);

            corpus.Storage.Mount("expected", new LocalAdapter(expectedOutputPath));
            CdmManifestDefinition manifest = await corpus.FetchObjectAsync <CdmManifestDefinition>($"local:/default.manifest.cdm.json");

            CdmEntityDefinition entity = await corpus.FetchObjectAsync <CdmEntityDefinition>($"local:/{entityName}.cdm.json/{entityName}");

            Assert.IsNotNull(entity);
            CdmEntityDefinition resolvedEntity = await ProjectionTestUtils.GetResolvedEntity(corpus, entity, resOpts, true);

            Assert.IsNotNull(resolvedEntity);

            await ValidateResolvedAttributes(corpus, resolvedEntity, entityName, fileNameSuffix);

            AttributeContextUtil.ValidateAttributeContext(corpus, expectedOutputPath, $"{entityName}{fileNameSuffix}", resolvedEntity);
        }
Пример #3
0
        /// <summary>
        /// Creates a Manifest used for the tests.
        /// </summary>
        /// <param name="localRootPath">A string used as root path for "local" namespace.</param>
        /// <returns>Created Manifest.</returns>
        private CdmManifestDefinition GenerateManifest(string localRootPath)
        {
            var cdmCorpus = new CdmCorpusDefinition();

            cdmCorpus.Storage.DefaultNamespace = "local";
            cdmCorpus.SetEventCallback(new EventCallback {
                Invoke = CommonDataModelLoader.ConsoleStatusReport
            }, CdmStatusLevel.Warning);

            cdmCorpus.Storage.Mount("local", new LocalAdapter(localRootPath));

            // add cdm namespace
            cdmCorpus.Storage.Mount("cdm", new LocalAdapter("C:\\Root\\Path"));

            var manifest = new CdmManifestDefinition(cdmCorpus.Ctx, "manifest");

            manifest.FolderPath = "/";
            manifest.Namespace  = "local";

            return(manifest);
        }
Пример #4
0
        public static async Task <LocalEntity> ToData(dynamic documentObjectOrPath, CdmManifestDefinition manifest, ResolveOptions resOpt, CopyOptions options, CdmCorpusContext ctx)
        {
            if (documentObjectOrPath is string)
            {
                if (await ctx.Corpus.FetchObjectAsync <CdmEntityDefinition>(documentObjectOrPath) is CdmEntityDefinition cdmEntity)
                {
                    var entity = await EntityPersistence.ToData(cdmEntity, resOpt, options, ctx);

                    if (cdmEntity.Owner != null && cdmEntity.Owner is CdmDocumentDefinition document)
                    {
                        if (document.Imports.Count > 0)
                        {
                            entity.Imports = new List <Import>();
                            foreach (var element in document.Imports)
                            {
                                var import = CdmFolder.ImportPersistence.ToData(element, resOpt, options);
                                // the corpus path in the imports are relative to the document where it was defined.
                                // when saving in model.json the documents are flattened to the manifest level
                                // so it is necessary to recalculate the path to be relative to the manifest.
                                var absolutePath = ctx.Corpus.Storage.CreateAbsoluteCorpusPath(import.CorpusPath, document);
                                import.CorpusPath = ctx.Corpus.Storage.CreateRelativeCorpusPath(absolutePath, manifest);
                                entity.Imports.Add(import);
                            }
                        }
                    }
                    else
                    {
                        Logger.Warning(nameof(DocumentPersistence), ctx, $"Entity {cdmEntity.GetName()} is not inside a document or its owner is not a document.");
                    }
                    return(entity);
                }
                else
                {
                    Logger.Error(nameof(DocumentPersistence), ctx, "There was an error while trying to fetch cdm entity doc.");
                    return(null);
                }
            }

            return(null);
        }
Пример #5
0
        public async Task RunAsync(DatabaseOptions options)
        {
            logger.LogInformation("Reading SQL database ...");
            RelationalModel model = relationalModelReader.ReadRelationalModel();

            if (!model.Tables.Any())
            {
                logger.LogWarning("No tables were found ...");
                return;
            }

            logger.LogDebug("Running Annotation Combiner ...");
            annotationCombiner.ReadAnnotationsAndCombineWithModel(model);

            logger.LogInformation("Generating CDM folder ...");
            CdmManifestDefinition manifest = await cdmGenerator.GenerateCdmAsync(model);

            logger.LogInformation("Saving CDM folder at {cdmOutput}...", Path.GetFullPath(options.OutputCdmFolder));
            await manifest.SaveAsync();

            logger.LogInformation("Success!");
        }
Пример #6
0
        public void TestManifestCannotAddEntityDefinitionWithoutCreatingDocument()
        {
            var cdmCorpus = new CdmCorpusDefinition();

            cdmCorpus.Storage.DefaultNamespace = "local";

            var    callback           = new EventCallback();
            var    functionWasCalled  = false;
            var    functionParameter1 = CdmStatusLevel.Info;
            string functionParameter2 = null;

            callback.Invoke = (CdmStatusLevel statusLevel, string message1) =>
            {
                functionWasCalled  = true;
                functionParameter1 = statusLevel;
                functionParameter2 = message1;
            };
            cdmCorpus.SetEventCallback(callback);

            cdmCorpus.Storage.Mount("local", new LocalAdapter("C:\\Root\\Path"));

            var manifest = new CdmManifestDefinition(cdmCorpus.Ctx, "manifest");

            manifest.FolderPath = "/";
            manifest.Namespace  = "local";

            var entity = new CdmEntityDefinition(manifest.Ctx, "entityName", null);

            var corpus = new CdmCorpusDefinition();

            manifest.Entities.Add(entity);

            Assert.IsTrue(functionWasCalled);
            Assert.AreEqual(CdmStatusLevel.Error, functionParameter1);
            Assert.IsTrue(functionParameter2.Contains("Expected entity to have an \"Owner\" document set. Cannot create entity declaration to add to manifest."));


            Assert.AreEqual(0, manifest.Entities.Count);
        }
Пример #7
0
        /// <summary>
        /// Checks if incremental trait is needed from foundations.cdm.json
        /// </summary>
        private static void ImportFoundationsIfIncrementalPartitionTraitExist(CdmManifestDefinition manifest)
        {
            if (manifest.Entities == null)
            {
                return;
            }

            foreach (var ent in manifest.Entities)
            {
                if (ent is CdmLocalEntityDeclarationDefinition localEntityDef)
                {
                    if (localEntityDef.IncrementalPartitions?.Count > 0 || localEntityDef.IncrementalPartitionPatterns?.Count > 0)
                    {
                        if (manifest.Imports.Item(Constants.FoundationsCorpusPath, checkMoniker: false) == null)
                        {
                            manifest.Imports.Add(Constants.FoundationsCorpusPath);
                            // Find one is enough
                            break;
                        }
                    }
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Test that a manifest document is fetched using the syms persistence class.
        /// </summary>
        internal async Task TestSymsFetchManifest(CdmCorpusDefinition corpus, CdmManifestDefinition manifestExpected, string filename, string threadnumber = "")
        {
            var manifestReadDatabases = await corpus.FetchObjectAsync <CdmManifestDefinition>($"syms:/databases.manifest.cdm.json");

            Assert.IsNotNull(manifestReadDatabases);
            Assert.AreEqual("databases.manifest.cdm.json", manifestReadDatabases.ManifestName);

            if (!manifestReadDatabases.SubManifests.AllItems.Exists(item => item.ManifestName == manifestExpected.ManifestName))
            {
                Assert.Fail($"Database {manifestExpected.ManifestName} does not exist.");
            }

            var manifestActual = await corpus.FetchObjectAsync <CdmManifestDefinition>($"syms:/{manifestExpected.ManifestName}/{manifestExpected.ManifestName}.manifest.cdm.json", manifestReadDatabases, null, true);

            await manifestActual.SaveAsAsync($"localActOutput:/{filename}{threadnumber}");

            await manifestExpected.SaveAsAsync($"localExpOutput:/{filename}{threadnumber}");

            var actualContent   = TestHelper.GetActualOutputFileContent(testsSubpath, nameof(TestSymsSavingAndFetchingDocument), filename);
            var expectedContent = TestHelper.GetExpectedOutputFileContent(testsSubpath, nameof(TestSymsSavingAndFetchingDocument), filename);

            TestHelper.AssertSameObjectWasSerialized(actualContent, expectedContent);
        }
        private async static void addExistingEntity(CdmCorpusDefinition cdmCorpus, string manifestName, CdmManifestDefinition manifestDefinition)
        {
            CdmManifestDefinition manifest = await cdmCorpus.FetchObjectAsync <CdmManifestDefinition>(manifestName + ".manifest.cdm.json");

            if (manifest != null)
            {
                foreach (CdmEntityDeclarationDefinition eDef in manifest.Entities)
                {
                    // Create the entity definition instance
                    var entity = cdmCorpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, eDef.EntityName, false);
                    // Add properties to the entity instance
                    entity.DisplayName = eDef.EntityName;
                    entity.Version     = "1.0.0";
                    entity.Description = eDef.EntityName;
                    //manifestAbstract.Entities.Add(entity.EntityName, $"resolved/{eDef.EntityName}.cdm.json/{eDef.EntityName}");


                    var entSelected = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(eDef.EntityPath, manifest);

                    foreach (CdmTypeAttributeDefinition attribute in entSelected.Attributes)

                    {
                        //var attributes = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, attribute.Name, "hasA", attribute.DataType);
                        entity.Attributes.Add(attribute);
                    }
                    // Create the document which contains the entity
                    var entityDoc = cdmCorpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{eDef.EntityName}.cdm.json", false);
                    // Add an import to the foundations doc so the traits about partitons will resolve nicely
                    entityDoc.Imports.Add(FoundationJsonPath);
                    entityDoc.Definitions.Add(entity);
                    // Add the document to the root of the local documents in the corpus
                    var localRoot = cdmCorpus.Storage.FetchRootFolder("adls");
                    localRoot.Documents.Add(entityDoc, entityDoc.Name);
                    manifestDefinition.Entities.Add(entity);
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Convert to SyMs object from Manifest object.
        /// </summary>
        internal static async Task <SymsManifestContent> ConvertManifestToSyms(CdmManifestDefinition doc, StorageAdapterBase adapter, string path,
                                                                               ResolveOptions resOpt, CopyOptions options)
        {
            DatabaseEntity             databaseEntity     = null;
            bool                       isDeltaSync        = true;
            IList <TableEntity>        existingSymsTables = null;
            IList <RelationshipEntity> existingSymsRelationshipEntities = null;

            try
            {
                databaseEntity = JsonConvert.DeserializeObject <DatabaseEntity>(await adapter.ReadAsync(path));
            }
            catch (Exception e)
            {
                if (e.Message.Contains("NotFound"))
                {
                    isDeltaSync = false;
                }
                else
                {
                    throw;
                }
            }

            if (isDeltaSync)
            {
                var entities = await adapter.ReadAsync($"/{databaseEntity.Name}/{databaseEntity.Name}.manifest.cdm.json/entitydefinition");

                existingSymsTables = JsonConvert.DeserializeObject <SymsTableResponse>(entities).Tables;

                var realtionships = await adapter.ReadAsync($"/{databaseEntity.Name}/{databaseEntity.Name}.manifest.cdm.json/relationships");

                existingSymsRelationshipEntities = JsonConvert.DeserializeObject <SymsRelationshipResponse>(realtionships).Relationships;
            }

            return(await Persistence.Syms.ManifestPersistence.ToDataAsync(doc, resOpt, options, isDeltaSync, existingSymsTables, existingSymsRelationshipEntities));
        }
Пример #11
0
        public async Task TestInvalidJson()
        {
            var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, nameof(TestInvalidJson));

            CdmCorpusDefinition corpus = new CdmCorpusDefinition();

            corpus.SetEventCallback(new EventCallback {
                Invoke = CommonDataModelLoader.ConsoleStatusReport
            }, CdmStatusLevel.Warning);
            corpus.Storage.Mount("local", new LocalAdapter(testInputPath));
            corpus.Storage.DefaultNamespace = "local";

            CdmManifestDefinition invalidManifest = null;

            try
            {
                invalidManifest = await corpus.FetchObjectAsync <CdmManifestDefinition>("local:/invalidManifest.manifest.cdm.json");
            }
            catch (Exception)
            {
                Assert.Fail("Error should not be thrown when input json is invalid.");
            }
            Assert.IsNull(invalidManifest);
        }
Пример #12
0
        public async Task TestReferencedEntityDeclarationResolution()
        {
            var cdmCorpus = new CdmCorpusDefinition();

            cdmCorpus.Storage.Mount("cdm", new LocalAdapter(TestHelper.SchemaDocumentsPath));
            cdmCorpus.Storage.DefaultNamespace = "cdm";

            var manifest = new CdmManifestDefinition(cdmCorpus.Ctx, "manifest");

            manifest.Entities.Add("Account", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account");

            var referencedEntity = new CdmReferencedEntityDeclarationDefinition(cdmCorpus.Ctx, "Address");

            referencedEntity.EntityPath = "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/electronicMedicalRecords.manifest.cdm.json/Address";
            manifest.Entities.Add(referencedEntity);

            cdmCorpus.Storage.FetchRootFolder("cdm").Documents.Add(manifest);

            var resolvedManifest = await manifest.CreateResolvedManifestAsync("resolvedManifest", null);

            Assert.AreEqual(2, resolvedManifest.Entities.Count);
            Assert.AreEqual("core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/resolved/Account.cdm.json/Account", resolvedManifest.Entities[0].EntityPath);
            Assert.AreEqual("cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/electronicMedicalRecords.manifest.cdm.json/Address", resolvedManifest.Entities[1].EntityPath);
        }
Пример #13
0
        public async Task TestSavingInvalidModelJsonName()
        {
            CdmCorpusDefinition corpus = new CdmCorpusDefinition();

            corpus.SetEventCallback(new EventCallback {
                Invoke = CommonDataModelLoader.ConsoleStatusReport
            }, CdmStatusLevel.Warning);
            corpus.Storage.Unmount("cdm");
            corpus.Storage.DefaultNamespace = "local";
            var manifest = new CdmManifestDefinition(corpus.Ctx, "manifest");

            corpus.Storage.FetchRootFolder("local").Documents.Add(manifest);

            ConcurrentDictionary <string, string> allDocs = new ConcurrentDictionary <string, string>();
            var testAdapter = new TestStorageAdapter(allDocs);

            corpus.Storage.SetAdapter("local", testAdapter);

            var newManifestFromModelJsonName = "my.model.json";
            await manifest.SaveAsAsync(newManifestFromModelJsonName, true);

            // TODO: because we can load documents properly now, SaveAsAsync returns false. Will check the value returned from SaveAsAsync() when the problem is solved
            Assert.IsFalse(allDocs.ContainsKey($"/{newManifestFromModelJsonName}"));
        }
Пример #14
0
        public static async Task <CdmManifestDefinition> FromObject(CdmCorpusContext ctx, Model obj, CdmFolderDefinition folder)
        {
            #region Prepare extensionDoc
            List <CdmTraitDefinition> extensionTraitDefList = new List <CdmTraitDefinition>();
            #endregion

            #region Set manifest fields
            CdmManifestDefinition manifest = ctx.Corpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, obj.Name);

            // We need to set up folder path and namespace of a manifest to be able to retrieve that object.
            folder.Documents.Add(manifest);

            if (obj.Imports != null)
            {
                foreach (var element in obj.Imports)
                {
                    manifest.Imports.Add(CdmFolder.ImportPersistence.FromData(ctx, element));
                }
            }

            if (!manifest.Imports.Any((CdmImport importPresent) => importPresent.CorpusPath == "cdm:/foundations.cdm.json"))
            {
                manifest.Imports.Add("cdm:/foundations.cdm.json");
            }

            manifest.Explanation               = obj.Description;
            manifest.LastFileModifiedTime      = obj.ModifiedTime;
            manifest.LastChildFileModifiedTime = obj.LastChildFileModifiedTime;
            manifest.LastFileStatusCheckTime   = obj.LastFileStatusCheckTime;

            if (!string.IsNullOrEmpty(obj.DocumentVersion))
            {
                manifest.DocumentVersion = obj.DocumentVersion;
            }

            if (obj.Application != null)
            {
                var applicationTrait = ctx.Corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "is.managedBy", false);
                applicationTrait.IsFromProperty = true;

                var arg = ctx.Corpus.MakeObject <CdmArgumentDefinition>(CdmObjectType.ArgumentDef, "application");
                arg.Value = obj.Application;
                applicationTrait.Arguments.Add(arg);

                manifest.ExhibitsTraits.Add(applicationTrait);
            }

            if (obj.Version != null)
            {
                var versionTrait = ctx.Corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "is.modelConversion.modelVersion", false);

                var arg = ctx.Corpus.MakeObject <CdmArgumentDefinition>(CdmObjectType.ArgumentDef, "version");
                arg.Value = obj.Version;
                versionTrait.Arguments.Add(arg);

                manifest.ExhibitsTraits.Add(versionTrait);
            }

            if (obj.Culture != null)
            {
                var cultureTrait = ctx.Corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "is.partition.culture", false);
                cultureTrait.IsFromProperty = true;

                var arg = ctx.Corpus.MakeObject <CdmArgumentDefinition>(CdmObjectType.ArgumentDef, "culture");
                arg.Value = obj.Culture;
                cultureTrait.Arguments.Add(arg);

                manifest.ExhibitsTraits.Add(cultureTrait);
            }

            if (obj.IsHidden == true)
            {
                var isHiddenTrait = ctx.Corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "is.hidden", true);
                isHiddenTrait.IsFromProperty = true;
                manifest.ExhibitsTraits.Add(isHiddenTrait);
            }

            var referenceModels = new Dictionary <string, string>();

            if (obj.ReferenceModels != null)
            {
                var referenceModelsTrait = ctx.Corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "is.modelConversion.referenceModelMap", false);

                var arg = ctx.Corpus.MakeObject <CdmArgumentDefinition>(CdmObjectType.ArgumentDef, "referenceModelMap");
                arg.Value = JToken.FromObject(obj.ReferenceModels);
                referenceModelsTrait.Arguments.Add(arg);

                manifest.ExhibitsTraits.Add(referenceModelsTrait);

                foreach (var referenceModel in obj.ReferenceModels)
                {
                    referenceModels.Add(referenceModel.Id, referenceModel.Location);
                }
            }

            var entitySchemaByName = new Dictionary <string, string>();
            if (obj.Entities != null && obj.Entities.Count > 0)
            {
                foreach (var element in obj.Entities)
                {
                    CdmEntityDeclarationDefinition entity = null;

                    if ((string)element["$type"] == "LocalEntity")
                    {
                        entity = await LocalEntityDeclarationPersistence.FromData(ctx, folder, element.ToObject <LocalEntity>(), extensionTraitDefList, manifest);
                    }
                    else if ((string)element["$type"] == "ReferenceEntity")
                    {
                        var referenceEntity = element.ToObject <ReferenceEntity>();
                        if (!referenceModels.ContainsKey(referenceEntity.ModelId))
                        {
                            Logger.Error(nameof(ManifestPersistence), ctx, $"Model Id {referenceEntity.ModelId} from {referenceEntity.Name} not found in referenceModels.");

                            return(null);
                        }
                        entity = await ReferencedEntityDeclarationPersistence.FromData(ctx, referenceEntity, referenceModels[referenceEntity.ModelId]);
                    }
                    else
                    {
                        Logger.Error(nameof(ManifestPersistence), ctx, "There was an error while trying to parse entity type.");
                    }

                    if (entity != null)
                    {
                        manifest.Entities.Add(entity);
                        entitySchemaByName.Add(entity.EntityName, entity.EntityPath);
                    }
                    else
                    {
                        Logger.Error(nameof(ManifestPersistence), ctx, "There was an error while trying to parse entity type.");
                    }
                }
            }

            if (obj.Relationships != null && obj.Relationships.Count > 0)
            {
                foreach (var element in obj.Relationships)
                {
                    var relationship = await RelationshipPersistence.FromData(ctx, element, entitySchemaByName);

                    if (relationship != null)
                    {
                        manifest.Relationships.Add(relationship);
                    }
                    else
                    {
                        Logger.Warning(nameof(ManifestPersistence), ctx, "There was an issue while trying to read relationships from the model.json file.");
                    }
                }
            }

            await Utils.ProcessAnnotationsFromData(ctx, obj, manifest.ExhibitsTraits);

            var localExtensionTraitDefList = new List <CdmTraitDefinition>();
            ExtensionHelper.ProcessExtensionFromJson(ctx, obj, manifest.ExhibitsTraits, extensionTraitDefList, localExtensionTraitDefList);
            #endregion

            #region Use extensionDoc, finalize importDocs

            List <CdmImport> importDocs = await ExtensionHelper.StandardImportDetection(ctx, extensionTraitDefList, localExtensionTraitDefList);

            ExtensionHelper.AddImportDocsToManifest(ctx, importDocs, manifest);

            CreateExtensionDocAndAddToFolderAndImports(ctx, extensionTraitDefList, folder);
            #endregion

            return(manifest);
        }
Пример #15
0
        public async static Task <Model> ToData(CdmManifestDefinition instance, ResolveOptions resOpt, CopyOptions options)
        {
            var result = new Model()
            {
                Name         = instance.ManifestName,
                Description  = instance.Explanation,
                ModifiedTime = instance.LastFileModifiedTime,
                LastChildFileModifiedTime = instance.LastChildFileModifiedTime,
                LastFileStatusCheckTime   = instance.LastFileStatusCheckTime,
                DocumentVersion           = instance.DocumentVersion
            };

            TraitToPropertyMap t2pm = new TraitToPropertyMap(instance);

            CdmTraitReference isHiddenTrait = t2pm.FetchTraitReference("is.hidden");

            if (isHiddenTrait != null)
            {
                result.IsHidden = true;
            }

            CdmTraitReference applicationTrait = t2pm.FetchTraitReference("is.managedBy");

            if (applicationTrait != null)
            {
                result.Application = applicationTrait.Arguments.AllItems[0].Value as string;
            }

            CdmTraitReference versionTrait = t2pm.FetchTraitReference("is.modelConversion.modelVersion");

            if (versionTrait != null)
            {
                result.Version = versionTrait.Arguments.AllItems[0].Value;
            }
            else
            {
                // version property is required. If it doesn't exist set default.
                result.Version = "1.0";
            }

            CdmTraitReference cultureTrait = t2pm.FetchTraitReference("is.partition.culture");

            if (cultureTrait != null)
            {
                result.Culture = cultureTrait.Arguments.AllItems[0].Value as string;
            }

            Dictionary <string, string> referenceEntityLocations = new Dictionary <string, string>();
            Dictionary <string, string> referenceModels          = new Dictionary <string, string>();

            CdmTraitReference referenceModelsTrait = t2pm.FetchTraitReference("is.modelConversion.referenceModelMap");

            if (referenceModelsTrait != null)
            {
                JArray refModels = referenceModelsTrait.Arguments[0].Value as JArray;

                foreach (JObject referenceModel in refModels)
                {
                    var referenceModelId               = referenceModel["id"];
                    var referenceModelIdAsString       = referenceModelId.ToString();
                    var referenceModelLocation         = referenceModel["location"];
                    var referenceModelLocationAsString = referenceModelLocation.ToString();
                    referenceModels.Add(referenceModelIdAsString, referenceModelLocationAsString);
                    referenceEntityLocations.Add(referenceModelLocationAsString, referenceModelIdAsString);
                }
            }

            Utils.ProcessTraitsAndAnnotationsToData(instance.Ctx, result, instance.ExhibitsTraits);

            if (instance.Entities != null && instance.Entities.Count > 0)
            {
                List <Task> promises         = new List <Task>();
                var         obtainedEntities = new ConcurrentBag <JToken>();
                foreach (var entity in instance.Entities)
                {
                    Task createdPromise = Task.Run(async() =>
                    {
                        dynamic element = null;
                        if (entity.ObjectType == CdmObjectType.LocalEntityDeclarationDef)
                        {
                            element = await LocalEntityDeclarationPersistence.ToData(
                                entity as CdmLocalEntityDeclarationDefinition,
                                instance,
                                resOpt,
                                options
                                );
                        }
                        else if (entity.ObjectType == CdmObjectType.ReferencedEntityDeclarationDef)
                        {
                            element = await ReferencedEntityDeclarationPersistence.ToData(
                                entity as CdmReferencedEntityDeclarationDefinition,
                                resOpt,
                                options
                                );

                            var location = instance.Ctx.Corpus.Storage.CorpusPathToAdapterPath(entity.EntityPath);
                            if (string.IsNullOrEmpty(location))
                            {
                                Logger.Error(nameof(ManifestPersistence), instance.Ctx, $"Invalid entity path set in entity {entity.EntityName}");
                                element = null;
                            }

                            if (element is ReferenceEntity referenceEntity)
                            {
                                location = location.Slice(0, location.LastIndexOf("/"));

                                if (referenceEntity.ModelId != null)
                                {
                                    if (referenceModels.TryGetValue(referenceEntity.ModelId, out var savedLocation) && savedLocation != location)
                                    {
                                        Logger.Error(nameof(ManifestPersistence), instance.Ctx, $"Same ModelId pointing to different locations");
                                        element = null;
                                    }
                                    else if (savedLocation == null)
                                    {
                                        referenceModels[referenceEntity.ModelId] = location;
                                        referenceEntityLocations[location]       = referenceEntity.ModelId;
                                    }
                                }
                                else if (referenceEntity.ModelId == null && referenceEntityLocations.ContainsKey(location))
                                {
                                    referenceEntity.ModelId = referenceEntityLocations[location];
                                }
                                else
                                {
                                    referenceEntity.ModelId = Guid.NewGuid().ToString();
                                    referenceModels[referenceEntity.ModelId] = location;
                                    referenceEntityLocations[location]       = referenceEntity.ModelId;
                                }
                            }
                        }

                        if (element != null)
                        {
                            obtainedEntities.Add(JToken.FromObject(element));
                        }
                        else
                        {
                            Logger.Error(nameof(ManifestPersistence), instance.Ctx, $"There was an error while trying to convert {entity.EntityName}'s entity declaration to model json format.");
                        }
                    });
                    try
                    {
                        // TODO: Currently function is synchronous. Remove next line to turn it asynchronous.
                        // Currently some functions called are not thread safe.
                        await createdPromise;
                        promises.Add(createdPromise);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(nameof(ManifestPersistence), instance.Ctx, $"There was an error while trying to convert {entity.EntityName}'s entity declaration to model json format for reason {ex.Message}.");
                    }
                }
                await Task.WhenAll(promises);

                result.Entities = obtainedEntities.ToList();
            }

            if (referenceModels.Count > 0)
            {
                result.ReferenceModels = new List <ReferenceModel>();
                foreach (var referenceModel in referenceModels)
                {
                    result.ReferenceModels.Add(new ReferenceModel()
                    {
                        Id       = referenceModel.Key,
                        Location = referenceModel.Value
                    });
                }
            }

            if (instance.Relationships != null && instance.Relationships.Count > 0)
            {
                result.Relationships = new List <SingleKeyRelationship>();

                foreach (var cdmRelationship in instance.Relationships)
                {
                    var relationship = await RelationshipPersistence.ToData(cdmRelationship, resOpt, options);

                    if (relationship != null)
                    {
                        result.Relationships.Add(relationship);
                    }
                    else
                    {
                        Logger.Error(nameof(ManifestPersistence), instance.Ctx, "There was an error while trying to convert cdm relationship to model.json relationship.");
                    }
                }
            }

            if (instance.Imports != null && instance.Imports.Count > 0)
            {
                result.Imports = new List <Import>();
                foreach (var element in instance.Imports)
                {
                    result.Imports.Add(CdmFolder.ImportPersistence.ToData(element, resOpt, options));
                }
            }

            return(result);
        }
Пример #16
0
        static async Task Main(string[] args)
        {
            // Make a corpus, the corpus is the collection of all documents and folders created or discovered while navigating objects and paths
            var cdmCorpus = new CdmCorpusDefinition();

            Console.WriteLine("Configure storage adapters");

            // Configure storage adapters to point at the target local manifest location and at the fake public standards
            string pathFromExeToExampleRoot = "../../../../../../";

            cdmCorpus.Storage.Mount("local", new LocalAdapter(pathFromExeToExampleRoot + "2-create-manifest"));
            cdmCorpus.Storage.DefaultNamespace = "local"; // local is our default. so any paths that start out navigating without a device tag will assume local

            // Fake cdm, normaly use the github adapter
            // Mount it as the 'cdm' device, not the default so must use "cdm:/folder" to get there
            cdmCorpus.Storage.Mount("cdm", new LocalAdapter(pathFromExeToExampleRoot + "example-public-standards"));

            // Example how to mount to the ADLS.
            // cdmCorpus.Storage.Mount("adls",
            //    new ADLSAdapter(
            // "<ACCOUNT-NAME>.dfs.core.windows.net", // Hostname.
            // "/<FILESYSTEM-NAME>", // Root.
            // "72f988bf-86f1-41af-91ab-2d7cd011db47",  // Tenant ID.
            // "<CLIENT-ID>",  // Client ID.
            // "<CLIENT-SECRET>" // Client secret.
            // ));

            Console.WriteLine("Make placeholder manifest");
            // Make the temp manifest and add it to the root of the local documents in the corpus
            CdmManifestDefinition manifestAbstract = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract");

            // Add each declaration, this example is about medical appointments and care plans
            manifestAbstract.Entities.Add("Account", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account");
            manifestAbstract.Entities.Add("Address", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Address.cdm.json/Address");
            manifestAbstract.Entities.Add("CarePlan", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CarePlan.cdm.json/CarePlan");
            manifestAbstract.Entities.Add("CodeableConcept", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CodeableConcept.cdm.json/CodeableConcept");
            manifestAbstract.Entities.Add("Contact", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Contact.cdm.json/Contact");
            manifestAbstract.Entities.Add("Device", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Device.cdm.json/Device");
            manifestAbstract.Entities.Add("EmrAppointment", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EmrAppointment.cdm.json/EmrAppointment");
            manifestAbstract.Entities.Add("Encounter", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Encounter.cdm.json/Encounter");
            manifestAbstract.Entities.Add("EpisodeOfCare", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EpisodeOfCare.cdm.json/EpisodeOfCare");
            manifestAbstract.Entities.Add("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.
            var localRoot = cdmCorpus.Storage.FetchRootFolder("local");

            localRoot.Documents.Add(manifestAbstract);

            // Create the resolved version of everything in the root folder too
            Console.WriteLine("Resolve the placeholder");
            var manifestResolved = await manifestAbstract.CreateResolvedManifestAsync("default", "");

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            manifestResolved.Imports.Add("cdm:/foundations.cdm.json");

            Console.WriteLine("Save the documents");
            foreach (CdmEntityDeclarationDefinition eDef in manifestResolved.Entities)
            {
                // Get the entity being pointed at
                var localEDef = eDef;
                var entDef    = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(localEDef.EntityPath, manifestResolved);

                // Make a fake partition, just to demo that
                var part = cdmCorpus.MakeObject <CdmDataPartitionDefinition>(CdmObjectType.DataPartitionDef, $"{entDef.EntityName}-data-description");
                localEDef.DataPartitions.Add(part);
                part.Explanation = "not real data, just for demo";

                // Define the location of the partition, relative to the manifest
                var location = $"local:/{entDef.EntityName}/partition-data.csv";
                part.Location = cdmCorpus.Storage.CreateRelativeCorpusPath(location, manifestResolved);

                // Add trait to partition for csv params
                var csvTrait = part.ExhibitsTraits.Add("is.partition.format.CSV", false);
                csvTrait.Arguments.Add("columnHeaders", "true");
                csvTrait.Arguments.Add("delimiter", ",");

                // Get the actual location of the partition file from the corpus
                string partPath = cdmCorpus.Storage.CorpusPathToAdapterPath(location);

                // Make a fake file with nothing but header for columns
                string header = "";
                foreach (CdmTypeAttributeDefinition att in entDef.Attributes)
                {
                    if (header != "")
                    {
                        header += ",";
                    }
                    header += att.Name;
                }

                Directory.CreateDirectory(cdmCorpus.Storage.CorpusPathToAdapterPath($"local:/{ entDef.EntityName}"));
                File.WriteAllText(partPath, header);
            }

            await manifestResolved.SaveAsAsync($"{manifestResolved.ManifestName}.manifest.cdm.json", true);
        }
Пример #17
0
        public async static Task <bool> manifestToSQLMetadata(AdlsContext adlsContext, string manifestName, string localRoot, List <SQLMetadata> metadataList)
        {
            ManifestHandler       manifestHandler = new ManifestHandler(adlsContext, localRoot);
            CdmManifestDefinition manifest        = await manifestHandler.cdmCorpus.FetchObjectAsync <CdmManifestDefinition>(manifestName + ".manifest.cdm.json");

            if (manifest == null)
            {
                Console.WriteLine($"Manifest: {manifestName } at Location {localRoot} is invalid");
                return(false);
            }

            foreach (var submanifest in manifest.SubManifests)
            {
                string subManifestName = submanifest.ManifestName;

                await manifestToSQLMetadata(adlsContext, subManifestName, localRoot + '/' + subManifestName, metadataList);
            }

            foreach (CdmEntityDeclarationDefinition eDef in manifest.Entities)
            {
                string entityName = eDef.EntityName;

                string dataLocation;
                if (eDef.DataPartitionPatterns.Count > 0)
                {
                    var pattern = eDef.DataPartitionPatterns.First();
                    dataLocation = localRoot + "/" + pattern.RootLocation + pattern.GlobPattern;
                }
                else if (eDef.DataPartitions.Count > 0)
                {
                    dataLocation = eDef.DataPartitions[0].Location;
                    string nameSpace = dataLocation.Substring(0, dataLocation.IndexOf(":") + 1);

                    if (nameSpace != "")
                    {
                        dataLocation = dataLocation.Replace(nameSpace, localRoot);
                    }
                    else
                    {
                        if (dataLocation.StartsWith('/') || localRoot.EndsWith('/'))
                        {
                            dataLocation = localRoot + dataLocation;
                        }
                        else
                        {
                            dataLocation = localRoot + "/" + dataLocation;
                        }
                    }
                }
                else
                {
                    dataLocation = $"{localRoot}/{entityName}/*.*";
                }


                string fileName = dataLocation.Substring(dataLocation.LastIndexOf("/") + 1);
                string ext      = fileName.Substring(fileName.LastIndexOf("."));
                dataLocation = dataLocation.Replace(fileName, "*" + ext);

                var entSelected = await manifestHandler.cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(eDef.EntityPath, manifest);

                string columnDef = string.Join(", ", entSelected.Attributes.Select(i => CdmTypeToSQl((CdmTypeAttributeDefinition)i)));;

                metadataList.Add(new SQLMetadata()
                {
                    entityName = entityName, columnDefinition = columnDef, dataLocation = dataLocation
                });
            }
            return(true);
        }
Пример #18
0
        /// <summary>
        /// Get the text version of all the resolved entities.
        /// </summary>
        /// <param name="cdmCorpus"> The CDM corpus. </param>
        /// <param name="directives"> The directives to use while getting the resolved entities. </param>
        /// <param name="manifest"> The manifest to be resolved. </param>
        /// <param name="spew"> The object used to store the text to be returned. </param>
        /// <returns> The text version of the resolved entities. (it's in a form that facilitates debugging) </returns>
        internal static async Task <string> ListAllResolved(CdmCorpusDefinition cdmCorpus, AttributeResolutionDirectiveSet directives, CdmManifestDefinition manifest, StringSpewCatcher spew = null)
        {
            // make sure the corpus has a set of default artifact attributes
            await cdmCorpus.PrepareArtifactAttributesAsync();

            var seen = new HashSet <string>();
            Func <CdmManifestDefinition, Task> seekEntities = null;

            seekEntities = async(CdmManifestDefinition f) =>
            {
                if (f.Entities != null)
                {
                    if (spew != null)
                    {
                        spew.SpewLine(f.FolderPath);
                    }

                    foreach (CdmEntityDeclarationDefinition entity in f.Entities)
                    {
                        string corpusPath;
                        CdmEntityDeclarationDefinition ent = entity;
                        CdmObject currentFile = f;
                        while (ent is CdmReferencedEntityDeclarationDefinition)
                        {
                            corpusPath = cdmCorpus.Storage.CreateAbsoluteCorpusPath(ent.EntityPath, currentFile);
                            ent        = await cdmCorpus.FetchObjectAsync <CdmReferencedEntityDeclarationDefinition>(corpusPath);

                            currentFile = ent;
                        }
                        corpusPath = cdmCorpus.Storage.CreateAbsoluteCorpusPath(((CdmLocalEntityDeclarationDefinition)ent).EntityPath, currentFile);
                        ResolveOptions resOpt = new ResolveOptions()
                        {
                            ImportsLoadStrategy = ImportsLoadStrategy.Load
                        };
                        CdmEntityDefinition newEnt = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(corpusPath, null, resOpt);

                        resOpt.WrtDoc     = newEnt.InDocument;
                        resOpt.Directives = directives;
                        ResolvedEntity resEnt = new ResolvedEntity(resOpt, newEnt);
                        if (spew != null)
                        {
                            resEnt.Spew(resOpt, spew, " ", true);
                        }
                    }
                }
                if (f.SubManifests != null)
                {
                    // folder.SubManifests.ForEach(async f =>
                    foreach (CdmManifestDeclarationDefinition subManifest in f.SubManifests)
                    {
                        string corpusPath = cdmCorpus.Storage.CreateAbsoluteCorpusPath(subManifest.Definition, f);
                        await seekEntities(await cdmCorpus.FetchObjectAsync <CdmManifestDefinition>(corpusPath));
                    }
                }
            };
            await seekEntities(manifest);

            if (spew != null)
            {
                return(spew.GetContent());
            }
            return("");
        }
        public async Task <bool> createManifest(EntityList entityList, bool resolveRef = true)
        {
            bool   manifestCreated = false;
            string manifestName    = entityList.manifestName;

            Console.WriteLine("Make placeholder manifest");
            // Add the temp manifest to the root of the local adapter in the corpus
            var localRoot = cdmCorpus.Storage.FetchRootFolder("adls");

            CdmManifestDefinition manifestAbstract = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract");

            localRoot.Documents.Add(manifestAbstract, "TempAbstract.manifest.cdm.json");

            // Create two entities from scratch, and add some attributes, traits, properties, and relationships in between
            Console.WriteLine("Create net new entities");

            List <EntityDefinition> EntityDefinitions = entityList.entityDefinitions;

            foreach (EntityDefinition entityDefinition in EntityDefinitions)
            {
                string entityName       = entityDefinition.name;
                string entityDesciption = entityDefinition.description;
                // Create the entity definition instance
                var entity = cdmCorpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName, false);
                // Add properties to the entity instance
                entity.DisplayName = entityName;
                entity.Version     = "1.0.0";
                entity.Description = entityDesciption;

                List <dynamic> attributes = entityDefinition.attributes;

                foreach (var a in attributes)
                {
                    // Add type attributes to the entity instance
                    entity.Attributes.Add(sqlToCDMAttribute(cdmCorpus, a));
                }

                // Create the document which contains the entity
                var entityDoc = cdmCorpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false);
                // Add an import to the foundations doc so the traits about partitons will resolve nicely
                entityDoc.Imports.Add(FoundationJsonPath);
                entityDoc.Definitions.Add(entity);
                // Add the document to the root of the local documents in the corpus
                localRoot.Documents.Add(entityDoc, entityDoc.Name);
                manifestAbstract.Entities.Add(entity);
            }

            CdmManifestDefinition manifestResolved = await manifestAbstract.CreateResolvedManifestAsync(manifestName, null);

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            manifestResolved.Imports.Add(FoundationJsonPath);

            foreach (CdmEntityDeclarationDefinition eDef in manifestResolved.Entities)
            {
                // Get the entity being pointed at
                var localEDef = eDef;
                var entDef    = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(localEDef.EntityPath, manifestResolved);

                var entityDefinition = EntityDefinitions.Find(x => x.name.Equals(entDef.EntityName, StringComparison.OrdinalIgnoreCase));

                if (entityDefinition != null)
                {
                    var part = cdmCorpus.MakeObject <CdmDataPartitionDefinition>(CdmObjectType.DataPartitionDef, $"{entDef.EntityName}-data");
                    eDef.DataPartitions.Add(part);
                    part.Explanation = "data files";

                    // We have existing partition files for the custom entities, so we need to make the partition point to the file location
                    part.Location = $"adls:{entityDefinition.dataPartitionLocation}/{entityDefinition.partitionPattern}";

                    if (entityDefinition.partitionPattern.Contains("parquet"))
                    {
                        part.ExhibitsTraits.Add("is.partition.format.parquet", false);
                    }
                    //default is csv
                    else
                    {
                        // Add trait to partition for csv params
                        var csvTrait = part.ExhibitsTraits.Add("is.partition.format.CSV", false);
                        csvTrait.Arguments.Add("columnHeaders", "false");
                        csvTrait.Arguments.Add("delimiter", ",");
                    }
                }
            }
            Console.WriteLine("Save the documents");
            // We can save the documents as manifest.cdm.json format or model.json
            // Save as manifest.cdm.json
            manifestCreated = await manifestResolved.SaveAsAsync($"{manifestName}.manifest.cdm.json", resolveRef);

            // Save as a model.json
            // await manifestResolved.SaveAsAsync("model.json", true);
            return(manifestCreated);
        }
Пример #20
0
        static async Task Main(string[] args)
        {
            // Make a corpus, the corpus is the collection of all documents and folders created or discovered while navigating objects and paths
            var cdmCorpus = new CdmCorpusDefinition();

            // set callback to receive error and warning logs.
            cdmCorpus.SetEventCallback(new EventCallback
            {
                Invoke = (level, message) =>
                {
                    Console.WriteLine(message);
                }
            }, CdmStatusLevel.Warning);

            Console.WriteLine("Configure storage adapters");

            // Configure storage adapters to point at the target local manifest location and at the fake public standards
            string pathFromExeToExampleRoot = "../../../../../../../";
            string sampleEntityName         = "Account";

            // Mount it as a local adapter.
            cdmCorpus.Storage.Mount("local", new LocalAdapter(pathFromExeToExampleRoot + "7-search-partition-pattern/sample-data"));
            cdmCorpus.Storage.DefaultNamespace = "local"; // local is our default. so any paths that start out navigating without a device tag will assume local

            // Fake cdm, normaly use the CDM Standards adapter
            // Mount it as the 'cdm' adapter, not the default so must use "cdm:/folder" to get there
            cdmCorpus.Storage.Mount("cdm", new LocalAdapter(pathFromExeToExampleRoot + "example-public-standards"));

            // Example how to mount to the ADLS.
            // cdmCorpus.Storage.Mount("adls",
            //    new ADLSAdapter(
            // "<ACCOUNT-NAME>.dfs.core.windows.net", // Hostname.
            // "/<FILESYSTEM-NAME>", // Root.
            // "72f988bf-86f1-41af-91ab-2d7cd011db47",  // Tenant ID.
            // "<CLIENT-ID>",  // Client ID.
            // "<CLIENT-SECRET>" // Client secret.
            // ));

            Console.WriteLine("Make placeholder manifest");
            // Make the temp manifest and add it to the root of the local documents in the corpus
            CdmManifestDefinition manifestAbstract = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract");

            // Add the temp manifest to the root of the local documents in the corpus.
            var localRoot = cdmCorpus.Storage.FetchRootFolder("local");

            localRoot.Documents.Add(manifestAbstract, "tempAbstract.manifest.cdm.json");

            // Add an entity named Account from some public standards
            Console.WriteLine("Add an entity named Account from some public standards");
            var accountDeclarationDefinition = manifestAbstract.Entities.Add(sampleEntityName, "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account");

            // Create a data partition pattern
            var dataPartitionPattern = CreatePartitionPatternDefinition(cdmCorpus, "sampleDataPartitionPattern");

            dataPartitionPattern.Explanation = "/ capture 4 digits / capture a word / capture one or more digits after the word cohort but before .csv";
            Console.WriteLine($"    Assign regular expression of the data partition pattern to: {dataPartitionPattern.RegularExpression}");
            Console.WriteLine($"    Assign root location of the data partition pattern to: {dataPartitionPattern.RootLocation}");

            // Add the data partition pattern we just created to the entity data partition pattern collection
            accountDeclarationDefinition.DataPartitionPatterns.Add(dataPartitionPattern);

            // Create incremental partition patterns
            var upsertIncrementalPartitionPattern = CreatePartitionPatternDefinition(cdmCorpus, "UpsertPattern", true, true);

            AddIncrementalPartitionTrait(upsertIncrementalPartitionPattern, CdmIncrementalPartitionType.Upsert);
            Console.WriteLine($"\n    Assign regular expression of the first incremental partition pattern to: {upsertIncrementalPartitionPattern.RegularExpression}");
            Console.WriteLine($"    Assign root location of the first incremental partition pattern to: {upsertIncrementalPartitionPattern.RootLocation}");

            var deleteIncrementalPartitionPattern = CreatePartitionPatternDefinition(cdmCorpus, "DeletePattern", true);

            AddIncrementalPartitionTrait(deleteIncrementalPartitionPattern, CdmIncrementalPartitionType.Delete, "FullDataPattern");
            Console.WriteLine($"\n    Assign regular expression of the second incremental partition pattern to: {deleteIncrementalPartitionPattern.RegularExpression}");
            Console.WriteLine($"    Assign root location of the second incremental partition pattern to: {deleteIncrementalPartitionPattern.RootLocation}");

            // Add the incremental partition patterns we just created to the entity increment partition pattern collection
            accountDeclarationDefinition.IncrementalPartitionPatterns.Add(upsertIncrementalPartitionPattern);
            accountDeclarationDefinition.IncrementalPartitionPatterns.Add(deleteIncrementalPartitionPattern);

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            manifestAbstract.Imports.Add("cdm:/foundations.cdm.json");

            // Calling FileStatusCheckAsync to pick up the all data partition files which names match the data partition pattern,
            // and add them to the entity in the manifest
            await manifestAbstract.FileStatusCheckAsync(PartitionFileStatusCheckType.FullAndIncremental);

            // List all data partition locations.
            Console.WriteLine($"\nlist of all data partition locations for the entity Account matches the data partition pattern:");

            foreach (CdmDataPartitionDefinition dataPartition in accountDeclarationDefinition.DataPartitions)
            {
                Console.WriteLine($"    {dataPartition.Location}");
            }

            // List all incremental partition locations.
            Console.WriteLine($"\nlist of all incremental partition locations for the entity Account matches the incremental partition pattern:");

            foreach (CdmDataPartitionDefinition incrementalPartition in accountDeclarationDefinition.IncrementalPartitions)
            {
                Console.WriteLine($"    {incrementalPartition.Location}");
            }

            Console.WriteLine("Resolve the manifest");
            var manifestResolved = await manifestAbstract.CreateResolvedManifestAsync("default", null);

            await manifestResolved.SaveAsAsync($"{manifestResolved.ManifestName}.manifest.cdm.json", true);

            // You can save the doc as a model.json format as an option
            // await manifestResolved.SaveAsAsync("model.json", true);
        }
Пример #21
0
        public async static Task ListAllResolved(CdmCorpusDefinition cdmCorpus, AttributeResolutionDirectiveSet directives, CdmManifestDefinition manifest, StringSpewCatcher spew = null)
        {
            ISet <string> seen = new HashSet <string>();
            Func <CdmManifestDefinition, Task> seekEntities = null;

            seekEntities = async(CdmManifestDefinition f) =>
            {
                if (f.Entities != null)
                {
                    if (spew != null)
                    {
                        spew.SpewLine(f.FolderPath);
                    }
                    // manifest.Entities.ForEach(async entity =>
                    foreach (CdmEntityDeclarationDefinition entity in f.Entities)
                    {
                        string corpusPath;
                        CdmEntityDeclarationDefinition ent = entity;
                        CdmObject currentFile = f;
                        while (ent is CdmReferencedEntityDeclarationDefinition)
                        {
                            corpusPath = cdmCorpus.Storage.CreateAbsoluteCorpusPath(ent.EntityPath, currentFile);
                            ent        = await cdmCorpus.FetchObjectAsync <CdmReferencedEntityDeclarationDefinition>(corpusPath);

                            currentFile = (CdmObject)ent;
                        }
                        corpusPath = cdmCorpus.Storage.CreateAbsoluteCorpusPath(((CdmLocalEntityDeclarationDefinition)ent).EntityPath, currentFile);
                        var newEnt = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(corpusPath);

                        ResolveOptions resOpt = new ResolveOptions()
                        {
                            WrtDoc = newEnt.InDocument, Directives = directives
                        };
                        ResolvedEntity resEnt = new ResolvedEntity(resOpt, newEnt);
                        if (spew != null)
                        {
                            resEnt.Spew(resOpt, spew, " ", true);
                        }
                    }
                }
                if (f.SubManifests != null)
                {
                    // folder.SubManifests.ForEach(async f =>
                    foreach (CdmManifestDeclarationDefinition subManifest in f.SubManifests)
                    {
                        string corpusPath = cdmCorpus.Storage.CreateAbsoluteCorpusPath(subManifest.Definition, f);
                        await seekEntities(await cdmCorpus.FetchObjectAsync <CdmManifestDefinition>(corpusPath));
                    }
                }
            };
            await seekEntities(manifest);

            if (spew != null)
            {
                File.WriteAllText(@"c:\temp\allResolved.txt", spew.GetContent(), Encoding.UTF8);
            }
        }
Пример #22
0
        /// <summary>
        /// Common test code for these test cases
        /// </summary>
        /// <param name="testName"></param>
        /// <param name="entityName"></param>
        private void TestRun(string testName, string entityName)
        {
            CdmCorpusDefinition corpus  = TestHelper.GetLocalCorpus(testsSubpath, testName);
            string inputFolder          = TestHelper.GetInputFolderPath(testsSubpath, testName);
            string expectedOutputFolder = TestHelper.GetExpectedOutputFolderPath(testsSubpath, testName);
            string actualOutputFolder   = TestHelper.GetActualOutputFolderPath(testsSubpath, testName);

            if (!Directory.Exists(actualOutputFolder))
            {
                Directory.CreateDirectory(actualOutputFolder);
            }

            CdmManifestDefinition manifest = corpus.FetchObjectAsync <CdmManifestDefinition>($"local:/default.manifest.cdm.json").GetAwaiter().GetResult();

            Assert.IsNotNull(manifest);
            CdmEntityDefinition entity = corpus.FetchObjectAsync <CdmEntityDefinition>($"local:/{entityName}.cdm.json/{entityName}", manifest).GetAwaiter().GetResult();

            Assert.IsNotNull(entity);
            CdmEntityDefinition resolvedEntity = ProjectionTestUtils.GetResolvedEntity(corpus, entity, new List <string> {
                "referenceOnly"
            }).GetAwaiter().GetResult();

            AttributeContextUtil.ValidateAttributeContext(corpus, expectedOutputFolder, entityName, resolvedEntity);

            corpus.CalculateEntityGraphAsync(manifest).GetAwaiter().GetResult();
            manifest.PopulateManifestRelationshipsAsync().GetAwaiter().GetResult();
            string actualRelationshipsString = ListRelationships(corpus, entity, actualOutputFolder, entityName);

            string relationshipsFilename = $"REL_{entityName}.txt";

            File.WriteAllText(Path.Combine(actualOutputFolder, relationshipsFilename), actualRelationshipsString);

            string expectedRelationshipsStringFilePath = Path.GetFullPath(Path.Combine(expectedOutputFolder, relationshipsFilename));
            string expectedRelationshipsString         = File.ReadAllText(expectedRelationshipsStringFilePath);

            Assert.AreEqual(expectedRelationshipsString, actualRelationshipsString);

            CdmFolderDefinition outputFolder = corpus.Storage.FetchRootFolder("output");

            outputFolder.Documents.Add(manifest);

            string manifestFileName = $"saved.manifest.cdm.json";

            manifest.SaveAsAsync(manifestFileName, saveReferenced: true).GetAwaiter().GetResult();
            string actualManifestPath = Path.Combine(actualOutputFolder, manifestFileName);

            if (!File.Exists(actualManifestPath))
            {
                Assert.Fail("Unable to save manifest with relationship");
            }
            else
            {
                CdmManifestDefinition savedManifest  = corpus.FetchObjectAsync <CdmManifestDefinition>($"output:/{manifestFileName}").GetAwaiter().GetResult();
                string actualSavedManifestRel        = GetRelationshipStrings(savedManifest.Relationships);
                string manifestRelationshipsFilename = $"MANIFEST_REL_{entityName}.txt";
                File.WriteAllText(Path.Combine(actualOutputFolder, manifestRelationshipsFilename), actualSavedManifestRel);

                string expectedSavedManifestRel = File.ReadAllText(Path.Combine(expectedOutputFolder, manifestRelationshipsFilename));
                Assert.AreEqual(expectedSavedManifestRel, actualSavedManifestRel);
            }
        }
Пример #23
0
        static async Task Main(string[] args)
        {
            // Make a corpus, the corpus is the collection of all documents and folders created or discovered while navigating objects and paths
            var cdmCorpus = new CdmCorpusDefinition();

            Console.WriteLine("Configure storage adapters");

            // Configure storage adapters to point at the target local manifest location and at the fake public standards
            string pathFromExeToExampleRoot = "../../../../../../";
            string sampleEntityName         = "Account";

            // Mount is as a local device.
            cdmCorpus.Storage.Mount("local", new LocalAdapter(pathFromExeToExampleRoot + "7-search-partition-pattern"));
            cdmCorpus.Storage.DefaultNamespace = "local"; // local is our default. so any paths that start out navigating without a device tag will assume local

            // Fake cdm, normaly use the github adapter
            // Mount it as the 'cdm' device, not the default so must use "cdm:/folder" to get there
            cdmCorpus.Storage.Mount("cdm", new LocalAdapter(pathFromExeToExampleRoot + "example-public-standards"));

            // Example how to mount to the ADLS.
            // cdmCorpus.Storage.Mount("adls",
            //    new ADLSAdapter(
            // "<ACCOUNT-NAME>.dfs.core.windows.net", // Hostname.
            // "/<FILESYSTEM-NAME>", // Root.
            // "72f988bf-86f1-41af-91ab-2d7cd011db47",  // Tenant ID.
            // "<CLIENT-ID>",  // Client ID.
            // "<CLIENT-SECRET>" // Client secret.
            // ));

            Console.WriteLine("Make placeholder manifest");
            // make the temp manifest and add it to the root of the local documents in the corpus
            CdmManifestDefinition manifestAbstract = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract");

            // Add the temp manifest to the root of the local documents in the corpus.
            var localRoot = cdmCorpus.Storage.FetchRootFolder("local");

            localRoot.Documents.Add(manifestAbstract, "tempAbstract.manifest.cdm.json");

            // Add an entity named Account from some public standards
            Console.WriteLine("Add an entity named Account from some public standards");
            var personDeclarationDefinition = manifestAbstract.Entities.Add(sampleEntityName, "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account");

            // Create a data partition pattern
            var dataPartitionPattern = cdmCorpus.MakeObject <CdmDataPartitionPatternDefinition>(CdmObjectType.DataPartitionPatternDef, "sampleDataPartitionPattern", false);

            dataPartitionPattern.RootLocation      = "local:dataFiles";
            dataPartitionPattern.RegularExpression = "/(\\d{4})/(\\w+)/cohort(\\d+)\\.csv$";
            Console.WriteLine($"    Assign regular expression of the data partition pattern to: {dataPartitionPattern.RegularExpression}");
            Console.WriteLine($"    Assign root location of the data partition pattern to: {dataPartitionPattern.RootLocation}");
            dataPartitionPattern.Explanation = "/ capture 4 digits / capture a word / capture one or more digits after the word cohort but before .csv";
            dataPartitionPattern.Parameters  = new List <string> {
                "year", "month", "cohortNumber"
            };

            // Add the data partition pattern we just created to the entity data partition pattern collection
            personDeclarationDefinition.DataPartitionPatterns.Add(dataPartitionPattern);

            // Calling FileStatusCheckAsync to pick up the all data partition files which names match the data partition pattern,
            // and add them to the entity in the manifest
            await manifestAbstract.FileStatusCheckAsync();

            // List all data partition locations.
            Console.WriteLine($"\nlist of all data partition locations for the entity Account matches the data partition pattern:");

            foreach (CdmDataPartitionDefinition dataPartition in personDeclarationDefinition.DataPartitions)
            {
                Console.WriteLine($"    {dataPartition.Location}");
            }

            Console.WriteLine("Resolve the manifest");
            var manifestResolved = await manifestAbstract.CreateResolvedManifestAsync("default", null);

            await manifestResolved.SaveAsAsync($"{manifestResolved.ManifestName}.manifest.cdm.json", true);

            // You can save the doc as a model.json format as an option
            // await manifestResolved.SaveAsAsync("model.json", true);
        }
Пример #24
0
        private async Task CreateManifest(CdmCorpusDefinition cdmCorpus)
        {
            Console.WriteLine("Make placeholder manifest");
            // Make the temp manifest and add it to the root of the local documents in the corpus
            CdmManifestDefinition manifestAbstract = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract");

            // Add each declaration, this example is about medical appointments and care plans
            manifestAbstract.Entities.Add("Account", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Account.cdm.json/Account");
            manifestAbstract.Entities.Add("Address", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Address.cdm.json/Address");
            manifestAbstract.Entities.Add("CarePlan", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CarePlan.cdm.json/CarePlan");
            manifestAbstract.Entities.Add("CodeableConcept", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/CodeableConcept.cdm.json/CodeableConcept");
            manifestAbstract.Entities.Add("Contact", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Contact.cdm.json/Contact");
            manifestAbstract.Entities.Add("Device", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Device.cdm.json/Device");
            manifestAbstract.Entities.Add("EmrAppointment", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EmrAppointment.cdm.json/EmrAppointment");
            manifestAbstract.Entities.Add("Encounter", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/Encounter.cdm.json/Encounter");
            manifestAbstract.Entities.Add("EpisodeOfCare", "cdm:/core/applicationCommon/foundationCommon/crmCommon/accelerators/healthCare/electronicMedicalRecords/EpisodeOfCare.cdm.json/EpisodeOfCare");
            manifestAbstract.Entities.Add("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.
            var localRoot = cdmCorpus.Storage.FetchRootFolder("local");

            localRoot.Documents.Add(manifestAbstract);

            // Create the resolved version of everything in the root folder too
            Console.WriteLine("Resolve the placeholder");
            var manifestResolved = await manifestAbstract.CreateResolvedManifestAsync("default", "");

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            manifestResolved.Imports.Add("cdm:/foundations.cdm.json");

            Console.WriteLine("Save the documents");
            foreach (CdmEntityDeclarationDefinition eDef in manifestResolved.Entities)
            {
                // Get the entity being pointed at
                var localEDef = eDef;
                var entDef    = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(localEDef.EntityPath, manifestResolved);

                // Make a fake partition, just to demo that
                var part = cdmCorpus.MakeObject <CdmDataPartitionDefinition>(CdmObjectType.DataPartitionDef, $"{entDef.EntityName}-data-description");
                localEDef.DataPartitions.Add(part);
                part.Explanation = "not real data, just for demo";

                // Define the location of the partition, relative to the manifest
                var location = $"local:/{entDef.EntityName}/partition-data.csv";
                part.Location = cdmCorpus.Storage.CreateRelativeCorpusPath(location, manifestResolved);

                // Add trait to partition for csv params
                var csvTrait = part.ExhibitsTraits.Add("is.partition.format.CSV", false) as CdmTraitReference;
                csvTrait.Arguments.Add("columnHeaders", "true");
                csvTrait.Arguments.Add("delimiter", ",");

                // Get the actual location of the partition file from the corpus
                string partPath = cdmCorpus.Storage.CorpusPathToAdapterPath(location);

                // Make a fake file with nothing but header for columns
                string header = "";
                foreach (CdmTypeAttributeDefinition att in entDef.Attributes)
                {
                    if (header != "")
                    {
                        header += ",";
                    }
                    header += att.Name;
                }

                Directory.CreateDirectory(cdmCorpus.Storage.CorpusPathToAdapterPath($"local:/{entDef.EntityName}"));
                File.WriteAllText(partPath, header);
            }

            await manifestResolved.SaveAsAsync($"{manifestResolved.ManifestName}.manifest.cdm.json", true);
        }
Пример #25
0
        private async Task <CdmEntityDefinition> SaveResolved(CdmCorpusDefinition corpus, CdmManifestDefinition manifest, string testName, CdmEntityDefinition inputEntity, List <string> resolutionOptions)
        {
            HashSet <string> roHashSet = new HashSet <string>();

            for (int i = 0; i < resolutionOptions.Count; i++)
            {
                roHashSet.Add(resolutionOptions[i]);
            }

            string fileNameSuffix = GetResolutionOptionNameSuffix(resolutionOptions);

            string resolvedEntityName = $"Resolved_{inputEntity.EntityName}{fileNameSuffix}.cdm.json";

            ResolveOptions ro = new ResolveOptions(inputEntity.InDocument)
            {
                Directives = new AttributeResolutionDirectiveSet(roHashSet)
            };

            CdmFolderDefinition resolvedFolder = corpus.Storage.FetchRootFolder("output");
            CdmEntityDefinition resolvedEntity = await inputEntity.CreateResolvedEntityAsync(resolvedEntityName, ro, resolvedFolder);

            return(resolvedEntity);
        }
Пример #26
0
        static async Task Main()
        {
            // Make a corpus, the corpus is the collection of all documents and folders created or discovered while navigating objects and paths
            var cdmCorpus = new CdmCorpusDefinition();

            Console.WriteLine("configure storage adapters");

            // Configure storage adapters to point at the target local manifest location and at the fake public standards
            var pathFromExeToExampleRoot = "../../../../../../";


            cdmCorpus.Storage.Mount("local", new LocalAdapter(pathFromExeToExampleRoot + "6-create-net-new-entities"));
            cdmCorpus.Storage.DefaultNamespace = "local"; // local is our default. so any paths that start out navigating without a device tag will assume local

            // Fake cdm, normaly use the github adapter
            // Mount it as the 'cdm' device, not the default so must use "cdm:/folder" to get there
            cdmCorpus.Storage.Mount("cdm", new LocalAdapter(pathFromExeToExampleRoot + "example-public-standards"));

            // Example how to mount to the ADLS.
            // cdmCorpus.Storage.Mount("adls",
            //    new ADLSAdapter(
            // "<ACCOUNT-NAME>.dfs.core.windows.net", // Hostname.
            // "/<FILESYSTEM-NAME>", // Root.
            // "72f988bf-86f1-41af-91ab-2d7cd011db47",  // Tenant ID.
            // "<CLIENT-ID>",  // Client ID.
            // "<CLIENT-SECRET>" // Client secret.
            // ));

            Console.WriteLine("Make placeholder manifest");
            // Make the temp manifest and add it to the root of the local documents in the corpus
            CdmManifestDefinition manifestAbstract = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "tempAbstract");

            // Add the temp manifest to the root of the local documents in the corpus
            var localRoot = cdmCorpus.Storage.FetchRootFolder("local");

            localRoot.Documents.Add(manifestAbstract, "TempAbstract.manifest.cdm.json");

            // Create two entities from scratch, and add some attributes, traits, properties, and relationships in between
            Console.WriteLine("Create net new entities");


            // Create the simplest entity - CustomPerson
            // Create the entity definition instance
            var personEntity = cdmCorpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, CustomPersonEntityName, false);
            // Add type attributes to the entity instance
            var personAttributeId = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"{CustomPersonEntityName}Id", "identifiedBy", "entityId");

            personEntity.Attributes.Add(personAttributeId);
            var personAttributeName = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"{CustomPersonEntityName}Name", "hasA", "string");

            personEntity.Attributes.Add(personAttributeName);
            // Add properties to the entity instance
            personEntity.DisplayName = CustomPersonEntityName;
            personEntity.Version     = "0.0.1";
            personEntity.Description = "This is a custom entity created for the sample.";
            // Create the document which contains the entity
            var personEntityDoc = cdmCorpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{CustomPersonEntityName}.cdm.json", false);

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            personEntityDoc.Imports.Add(FoundationJsonPath);
            personEntityDoc.Definitions.Add(personEntity);
            // Add the document to the root of the local documents in the corpus
            localRoot.Documents.Add(personEntityDoc, personEntityDoc.Name);
            // Add the entity to the manifest
            manifestAbstract.Entities.Add(personEntity);


            // Create an entity - CustomAccount which has a relationship with the entity CustomPerson
            // Create the entity definition instance
            var accountEntity = cdmCorpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, CustomAccountEntityName, false);
            // Add type attributes to the entity instance
            var accountAttributeId = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"{CustomAccountEntityName}Id", "identifiedBy", "entityId");

            accountEntity.Attributes.Add(accountAttributeId);
            var accountAttributeName = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"{CustomAccountEntityName}Name", "hasA", "string");

            accountEntity.Attributes.Add(accountAttributeName);
            // Add properties to the entity instance
            accountEntity.DisplayName = CustomAccountEntityName;
            accountEntity.Version     = "0.0.1";
            accountEntity.Description = "This is a custom entity created for the sample.";
            // In this sample, every account has one person who owns the account
            // the relationship is actually an entity attribute
            var attributeExplanation = "The owner of the account, which is a person.";
            // You can all CreateSimpleAttributeForRelationshipBetweenTwoEntities() instead, but CreateAttributeForRelationshipBetweenTwoEntities() can show
            // more details of how to use resolution guidance to customize your data
            var accountOwnerAttribute = CreateAttributeForRelationshipBetweenTwoEntities(cdmCorpus, CustomPersonEntityName, "accountOwner", attributeExplanation);

            accountEntity.Attributes.Add(accountOwnerAttribute);
            // Create the document which contains the entity
            var accountEntityDoc = cdmCorpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{CustomAccountEntityName}.cdm.json", false);

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            accountEntityDoc.Imports.Add(FoundationJsonPath);
            // the CustomAccount entity has a relationship with the CustomPerson entity, this relationship is defined from its attribute with traits,
            // the import to the entity reference CustomPerson's doc is required
            accountEntityDoc.Imports.Add($"{CustomPersonEntityName}.cdm.json");
            accountEntityDoc.Definitions.Add(accountEntity);
            // Add the document to the root of the local documents in the corpus
            localRoot.Documents.Add(accountEntityDoc, accountEntityDoc.Name);
            // Add the entity to the manifest
            manifestAbstract.Entities.Add(accountEntity);


            // Create an entity which extends "Account" from the standard, it contains everything that "Account" has
            var extendedStandardAccountEntity = cdmCorpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, ExtendedStandardAccount, false);

            // This function with 'true' will make a simple reference to the base
            extendedStandardAccountEntity.ExtendsEntity = cdmCorpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, "Account", true);
            var attrExplanation = "This is a simple custom account for this sample.";
            // Add a relationship from it to the CustomAccount entity, and name the foreign key to SimpleCustomAccount
            // You can all CreateSimpleAttributeForRelationshipBetweenTwoEntities() instead, but CreateAttributeForRelationshipBetweenTwoEntities() can show
            // more details of how to use resolution guidance to customize your data
            var simpleCustomAccountAttribute = CreateAttributeForRelationshipBetweenTwoEntities(cdmCorpus, CustomAccountEntityName, "SimpleCustomAccount", attrExplanation);

            extendedStandardAccountEntity.Attributes.Add(simpleCustomAccountAttribute);
            var extendedStandardAccountntityDoc = cdmCorpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{ExtendedStandardAccount}.cdm.json", false);

            // Add an import to the foundations doc so the traits about partitons will resolve nicely
            extendedStandardAccountntityDoc.Imports.Add(FoundationJsonPath);
            // The ExtendedAccount entity extends from the "Account" entity from standards, the import to the entity Account's doc is required
            // it also has a relationship with the CustomAccount entity, the relationship defined from its from its attribute with traits, the import to the entity reference CustomAccount's doc is required
            extendedStandardAccountntityDoc.Imports.Add($"{SchemaDocsRoot}/Account.cdm.json");
            extendedStandardAccountntityDoc.Imports.Add($"{CustomAccountEntityName}.cdm.json");
            // Add the document to the root of the local documents in the corpus
            localRoot.Documents.Add(extendedStandardAccountntityDoc, extendedStandardAccountntityDoc.Name);
            extendedStandardAccountntityDoc.Definitions.Add(extendedStandardAccountEntity);
            // Add the entity to the manifest
            manifestAbstract.Entities.Add(extendedStandardAccountEntity);


            // Create the resolved version of everything in the root folder too
            Console.WriteLine("Resolve the placeholder");
            var manifestResolved = await manifestAbstract.CreateResolvedManifestAsync("default", null);

            Console.WriteLine("Save the docs");
            foreach (CdmEntityDeclarationDefinition eDef in manifestResolved.Entities)
            {
                // Get the entity being pointed at
                var localEDef = eDef;
                var entDef    = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(localEDef.EntityPath, manifestResolved);

                // Make a fake partition, just to demo that
                var part = cdmCorpus.MakeObject <CdmDataPartitionDefinition>(CdmObjectType.DataPartitionDef, $"{entDef.EntityName}-data-description");
                localEDef.DataPartitions.Add(part);
                part.Explanation = "not real data, just for demo";
                // We have existing partition files for the custom entities, so we need to make the partition point to the file location
                part.Location = $"local:/{entDef.EntityName}/partition-data.csv";
                // Add trait to partition for csv params
                var csvTrait = part.ExhibitsTraits.Add("is.partition.format.CSV", false);
                csvTrait.Arguments.Add("columnHeaders", "true");
                csvTrait.Arguments.Add("delimiter", ",");
            }

            // We can save the docs as manifest.cdm.json format or model.json
            // Save as manifest.cdm.json
            await manifestResolved.SaveAsAsync($"{manifestResolved.ManifestName}.manifest.cdm.json", true);

            // Save as a model.json
            // await manifestResolved.SaveAsAsync("model.json", true);
        }
        public static async Task <LocalEntity> ToData(CdmLocalEntityDeclarationDefinition instance, CdmManifestDefinition manifest, ResolveOptions resOpt, CopyOptions options)
        {
            var localEntity = await DocumentPersistence.ToData(instance.EntityPath, manifest, resOpt, options, instance.Ctx);

            if (localEntity != null)
            {
                var t2pm          = new TraitToPropertyMap(instance);
                var isHiddenTrait = t2pm.FetchTraitReference("is.hidden");

                localEntity.Description = instance.Explanation;
                localEntity.LastChildFileModifiedTime = instance.LastChildFileModifiedTime;
                localEntity.LastFileModifiedTime      = instance.LastFileModifiedTime;
                localEntity.LastFileStatusCheckTime   = instance.LastFileStatusCheckTime;

                if (isHiddenTrait != null)
                {
                    localEntity.IsHidden = true;
                }

                if (t2pm.FetchPropertyValue("cdmSchemas") is List <string> schemas)
                {
                    localEntity.Schemas = schemas;
                }

                if (instance.DataPartitions != null && instance.DataPartitions.Count > 0)
                {
                    localEntity.Partitions = new List <Partition>();

                    foreach (var element in instance.DataPartitions)
                    {
                        var partition = await DataPartitionPersistence.ToData(element, resOpt, options);

                        if (partition != null)
                        {
                            localEntity.Partitions.Add(partition);
                        }
                        else
                        {
                            Logger.Error(nameof(LocalEntityDeclarationPersistence), instance.Ctx, "There was an error while trying to convert cdm data partition to model.json partition.");
                            return(null);
                        }
                    }
                }
            }

            return(localEntity);
        }
Пример #28
0
        public async Task <bool> createManifest(EntityList entityList, bool createModelJson = false)
        {
            bool   manifestCreated = false;
            string manifestName    = entityList.manifestName;
            // Add to root folder.
            var adlsRoot = cdmCorpus.Storage.FetchRootFolder("adls");

            List <EntityDefinition> EntityDefinitions = entityList.entityDefinitions;

            // Read manifest if exists.
            CdmManifestDefinition manifest = await cdmCorpus.FetchObjectAsync <CdmManifestDefinition>(manifestName + ".manifest.cdm.json");

            if (manifest == null)
            {
                // Make the temp manifest and add it to the root of the local documents in the corpus
                manifest = cdmCorpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, manifestName);

                // Add an import to the foundations doc so the traits about partitons will resolve nicely
                manifest.Imports.Add(FoundationJsonPath);

                // Add to root folder.
                adlsRoot.Documents.Add(manifest, $"{manifestName}.manifest.cdm.json");
            }
            else
            {
                foreach (EntityDefinition entityDefinition in EntityDefinitions)
                {
                    foreach (CdmEntityDeclarationDefinition localEntityDefinition in manifest.Entities.ToList())
                    {
                        if (localEntityDefinition.EntityName.Equals(entityDefinition.name, StringComparison.OrdinalIgnoreCase))
                        {
                            manifest.Entities.Remove(currObject: localEntityDefinition);
                        }
                    }
                }
            }

            foreach (EntityDefinition entityDefinition in EntityDefinitions)
            {
                var cdmEntityDefinition = this.CreateCdmEntityDefinition(entityDefinition);
                var cdmEntityDocument   = this.CreateDocumentDefinition(cdmEntityDefinition);
                // Add Imports to the entity document.
                cdmEntityDocument.Imports.Add(FoundationJsonPath);

                // Add the document to the root of the local documents in the corpus.
                adlsRoot.Documents.Add(cdmEntityDocument, cdmEntityDocument.Name);

                // Add the entity to the manifest.
                manifest.Entities.Add(cdmEntityDefinition);

                this.addPartition(manifest, entityDefinition);
            }

            Console.WriteLine("Save the documents");
            // We can save the documents as manifest.cdm.json format or model.json
            // Save as manifest.cdm.json
            manifestCreated = await manifest.SaveAsAsync($"{manifestName}.manifest.cdm.json", true);

            // Save as a model.json
            if (createModelJson)
            {
                await manifest.SaveAsAsync("model.json", true);
            }

            return(manifestCreated);
        }
Пример #29
0
        static async Task ExploreManifest(CdmCorpusDefinition cdmCorpus, string manifestPath)
        {
            Console.WriteLine($"\nLoading manifest {manifestPath} ...");

            CdmManifestDefinition manifest = await cdmCorpus.FetchObjectAsync <CdmManifestDefinition>(manifestPath);

            if (manifest == null)
            {
                Console.WriteLine($"Unable to load manifest {manifestPath}. Please inspect error log for additional details.");
                return;
            }

            // ------------------------------------------------------------------------------------------------------------
            // List all the entities found in the manifest and allow the user to choose which entity to explore.

            while (true)
            {
                int index = 1;

                if (manifest.Entities.Count > 0)
                {
                    Console.WriteLine("List of all entities:");

                    foreach (var entDec in manifest.Entities)
                    {
                        // Print entity declarations.
                        // Assume there are only local entities in this manifest for simplicity.
                        Console.Write("  " + index.ToString().PadRight(3));
                        Console.Write("  " + entDec.EntityName.PadRight(35));
                        Console.WriteLine("  " + entDec.EntityPath);
                        index++;
                    }
                }

                if (manifest.SubManifests.Count > 0)
                {
                    Console.WriteLine("List of all sub-manifests:");

                    foreach (var manifestDecl in manifest.SubManifests)
                    {
                        // Print sub-manifest declarations.
                        Console.Write("  " + index.ToString().PadRight(3));
                        Console.Write("  " + manifestDecl.ManifestName.PadRight(35));
                        Console.WriteLine("  " + manifestDecl.Definition);
                        index++;
                    }
                }

                if (index == 1)
                {
                    Console.Write("No Entities or Sub-manifest found. Press [enter] to exit.");
                    Console.ReadLine();
                    break;
                }

                Console.Write("Enter a number to show details for that Entity or Sub-manifest (press [enter] to exit): ");

                // Get the user's choice.
                string input = Console.ReadLine();
                if (string.IsNullOrEmpty(input))
                {
                    break;
                }

                // Make sure the user's input is a number.
                int num = 0;
                if (!int.TryParse(input, out num))
                {
                    Console.WriteLine("\nEnter a number.");
                    Console.WriteLine();
                    continue;
                }

                // User can select an entry that is a sub-manifest
                if (num > manifest.Entities.Count)
                {
                    int subNum = num - manifest.Entities.Count - 1;
                    // Re-enter this method supplying the absolute path of the submanifest definition (relative to the current manifest)
                    await ExploreManifest(cdmCorpus, cdmCorpus.Storage.CreateAbsoluteCorpusPath(manifest.SubManifests[subNum].Definition, manifest));

                    continue;
                }

                index = 1;
                foreach (var entityDec in manifest.Entities)
                {
                    if (index == num)
                    {
                        Console.WriteLine("Reading the entity schema and resolving with the standard docs, first one may take a second ...");

                        // From the path to the entity, get the actual schema description.
                        // Take the local relative path in this doc and make sure it works.
                        var entSelected = await cdmCorpus.FetchObjectAsync <CdmEntityDefinition>(entityDec.EntityPath, manifest); // gets the entity object from the doc

                        while (true)
                        {
                            // List all the metadata properties of this entity that can be explored.
                            Console.WriteLine($"\nMetadata properties for the entity {entityDec.EntityName}:");
                            Console.WriteLine("  1: Attributes");
                            Console.WriteLine("  2: Traits");
                            Console.WriteLine("  3: Properties");
                            Console.WriteLine("  4: Data partition locations");
                            Console.WriteLine("  5: Relationships");

                            Console.Write("Enter a number to show details for that metadata property (press [enter] to explore other entities): ");

                            // Get the user's choice.
                            input = Console.ReadLine();
                            if (string.IsNullOrEmpty(input))
                            {
                                Console.WriteLine();
                                break;
                            }

                            // Make sure the user's input is a number.
                            int choice = 0;
                            if (int.TryParse(input, out choice))
                            {
                                switch (choice)
                                {
                                // List the entity's attributes.
                                case 1:
                                    ListAttributes(entSelected);
                                    break;

                                // List the entity's traits.
                                case 2:
                                    ListTraits(entSelected);
                                    break;

                                // List the entity's properties.
                                case 3:
                                    ListProperties(entSelected, entityDec);
                                    break;

                                // List the entity's data partition locations.
                                case 4:
                                    ListDataPartitionLocations(cdmCorpus, entityDec);
                                    break;

                                // List the entity's relationships.
                                case 5:
                                    if (manifest.Relationships != null && manifest.Relationships.Count > 0)
                                    {
                                        // The manifest file contains pre-calculated entity relationships, so we can read them directly.
                                        ListRelationshipsFromManifest(manifest, entSelected);
                                    }
                                    else
                                    {
                                        // The manifest file doesn't contain relationships, so we have to compute the relationships first.
                                        await cdmCorpus.CalculateEntityGraphAsync(manifest);

                                        ListRelationships(cdmCorpus, entSelected);
                                    }
                                    break;

                                default:
                                    Console.WriteLine("\nEnter a number between 1-5.");
                                    break;
                                }
                            }
                            else
                            {
                                Console.WriteLine("\nEnter a number.");
                            }
                        }
                    }
                    index++;
                }
            }
        }
Пример #30
0
 /// <summary>
 /// Test that a document is saved using the syms persistence class.
 /// </summary>
 internal async Task TestSymsSaveManifest(CdmManifestDefinition manifest)
 {
     Assert.IsTrue(await manifest.SaveAsAsync($"syms:/{manifest.ManifestName}/{manifest.ManifestName}.manifest.cdm.json"));
 }