/// <summary> /// Create a constant entity that contains the source mapping to a foreign key. /// e.g. /// an fk created to entity "Customer" based on the "customerName", would add a parameter to the "is.linkedEntity.identifier" trait as follows: /// [ /// "/Customer.cdm.json/Customer", /// "customerName" /// ] /// In the case of polymorphic source, there will be a collection of such entries. /// </summary> /// <param name="projDir"></param> /// <param name="corpus"></param> /// <param name="refFoundList"></param> /// <returns></returns> internal static CdmEntityReference CreateForeignKeyLinkedEntityIdentifierTraitParameter(ProjectionDirective projDir, CdmCorpusDefinition corpus, List <ProjectionAttributeState> refFoundList) { CdmEntityReference traitParamEntRef = null; List <Tuple <string, string> > entRefAndAttrNameList = new List <Tuple <string, string> >(); foreach (ProjectionAttributeState refFound in refFoundList) { ResolvedAttribute resAttr = refFound.CurrentResolvedAttribute; if (resAttr.Owner == null) { var atCorpusPath = resAttr.Target is CdmObjectBase target ? target.AtCorpusPath : resAttr.ResolvedName; Logger.Warning(corpus.Ctx, TAG, nameof(CreateForeignKeyLinkedEntityIdentifierTraitParameter), atCorpusPath, CdmLogCode.WarnProjCreateForeignKeyTraits, resAttr.ResolvedName); } else if (resAttr.Target.ObjectType == CdmObjectType.TypeAttributeDef || resAttr.Target.ObjectType == CdmObjectType.EntityAttributeDef) { // find the linked entity var owner = resAttr.Owner; // find where the projection is defined var projectionDoc = projDir.Owner?.InDocument; if (owner?.ObjectType == CdmObjectType.EntityDef && projectionDoc != null) { CdmEntityDefinition entDef = owner.FetchObjectDefinition <CdmEntityDefinition>(projDir.ResOpt); if (entDef != null) { // should contain relative path without the namespace string relativeEntPath = entDef.Ctx.Corpus.Storage.CreateRelativeCorpusPath(entDef.AtCorpusPath, projectionDoc); entRefAndAttrNameList.Add(new Tuple <string, string>(relativeEntPath, resAttr.ResolvedName)); } } } } if (entRefAndAttrNameList.Count > 0) { CdmConstantEntityDefinition constantEntity = corpus.MakeObject <CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef); constantEntity.EntityShape = corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, "entitySet", true); string originalSourceEntityAttributeName = projDir.OriginalSourceEntityAttributeName; if (originalSourceEntityAttributeName == null) { originalSourceEntityAttributeName = ""; } constantEntity.ConstantValues = entRefAndAttrNameList.Select((entAndAttrName) => new List <string> { entAndAttrName.Item1, entAndAttrName.Item2, $"{originalSourceEntityAttributeName}_{entAndAttrName.Item1.Substring(entAndAttrName.Item1.LastIndexOf("/") + 1)}" }).ToList(); traitParamEntRef = corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, constantEntity, false); } return(traitParamEntRef); }
public void TestModelJsonToDataTypeAttribute() { CdmCorpusDefinition corpus = new CdmCorpusDefinition(); corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning); corpus.Storage.Mount("local", new LocalAdapter("C:\\Root\\Path")); corpus.Storage.DefaultNamespace = "local"; var cdmTypeAttributeDefinition = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "TestSavingTraitAttribute", false); List <string> englishConstantsList = new List <string>() { "en", "Some description in English language" }; List <string> serbianConstantsList = new List <string>() { "sr", "Opis na srpskom jeziku" }; List <string> chineseConstantsList = new List <string>() { "cn", "一些中文描述" }; List <List <string> > listOfConstLists = new List <List <string> > { englishConstantsList, serbianConstantsList, chineseConstantsList }; var constEntDef = corpus.MakeObject <CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef, "localizedDescriptions", false); constEntDef.ConstantValues = listOfConstLists; constEntDef.EntityShape = corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, "localizedTable", true); var traitReference2 = corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, "is.localized.describedAs", false); traitReference2.Arguments.Add("localizedDisplayText", corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, constEntDef, true)); cdmTypeAttributeDefinition.AppliedTraits.Add(traitReference2); var result = PersistenceLayer.ToData <CdmTypeAttributeDefinition, Task <Attribute> >(cdmTypeAttributeDefinition, null, null, PersistenceLayer.ModelJson).Result; Assert.IsNotNull(result.Traits); var argument = result.Traits[0].ToObject <TraitReferenceDefinition>().Arguments[0].ToObject <Argument>(); List <List <string> > constantValues = argument.Value.ToObject <EntityReferenceDefinition>().EntityReference.ToObject <ConstantEntity>().ConstantValues; Assert.AreEqual("en", constantValues[0][0]); Assert.AreEqual("Some description in English language", constantValues[0][1]); Assert.AreEqual("sr", constantValues[1][0]); Assert.AreEqual("Opis na srpskom jeziku", constantValues[1][1]); Assert.AreEqual("cn", constantValues[2][0]); Assert.AreEqual("一些中文描述", constantValues[2][1]); }
/// <summary> /// Create an type attribute definition instance with provided purpose. /// </summary> /// <param name="cdmCorpus"> The CDM corpus. </param> /// <param name="attributeName"> The directives to use while getting the resolved entities. </param> /// <param name="purpose"> The manifest to be resolved. </param> /// <returns> The instance of type attribute definition. </returns> private static CdmTypeAttributeDefinition CreateEntityAttributeWithPurpose(CdmCorpusDefinition cdmCorpus, string attributeName, string purpose) { var entityAttribute = cdmCorpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, attributeName, false); entityAttribute.Purpose = cdmCorpus.MakeRef <CdmPurposeReference>(CdmObjectType.PurposeRef, purpose, true); return(entityAttribute); }
/// <summary> /// Create a relationship linking by creating an eneity attribute definition instance with a trait. /// This allows you to add a resolution guidance to customize your data. /// </summary> /// <param name="cdmCorpus"> The CDM corpus. </param> /// <param name="associatedEntityName"> The name of the associated entity. </param> /// <param name="foreignKeyName"> The name of the foreign key. </param> /// <param name="attributeExplanation"> The explanation of the attribute.</param> /// <returns> The instatnce of entity attribute definition. </returns> private static CdmEntityAttributeDefinition CreateAttributeForRelationshipBetweenTwoEntities( CdmCorpusDefinition cdmCorpus, string associatedEntityName, string foreignKeyName, string attributeExplanation) { // Define a relationship by creating an entity attribute var entityAttributeDef = cdmCorpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, foreignKeyName); entityAttributeDef.Explanation = attributeExplanation; // Creating an entity reference for the associated entity CdmEntityReference associatedEntityRef = cdmCorpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, associatedEntityName, false); // Creating a "is.identifiedBy" trait for entity reference CdmTraitReference traitReference = cdmCorpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, "is.identifiedBy", false); traitReference.Arguments.Add(null, $"{associatedEntityName}/(resolvedAttributes)/{associatedEntityName}Id"); // Add the trait to the attribute's entity reference associatedEntityRef.AppliedTraits.Add(traitReference); entityAttributeDef.Entity = associatedEntityRef; // Add resolution guidance var attributeResolution = cdmCorpus.MakeObject <CdmAttributeResolutionGuidance>(CdmObjectType.AttributeResolutionGuidanceDef); attributeResolution.entityByReference = attributeResolution.makeEntityByReference(); attributeResolution.entityByReference.allowReference = true; attributeResolution.renameFormat = "{m}"; var entityAttribute = CreateEntityAttributeWithPurposeAndDataType(cdmCorpus, $"{foreignKeyName}Id", "identifiedBy", "entityId"); attributeResolution.entityByReference.foreignKeyAttribute = entityAttribute as CdmTypeAttributeDefinition; entityAttributeDef.ResolutionGuidance = attributeResolution; return(entityAttributeDef); }
public async Task TestWithNesting() { CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestEventList"); corpus.SetEventCallback(eventCallback, CdmStatusLevel.Warning, DummyCorrelationId); var manifest = corpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "dummy"); // Test resolving a manifest (added to a folder) with an entity in it, this should collect messages from // CreateResolvedManifestAsync and CreateResolvedEntityAsync functions corpus.Storage.FetchRootFolder("local").Documents.Add(manifest); var entity1 = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, "MyEntity1"); var someAttrib1 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "someAttrib1", false); someAttrib1.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "entityId", true); entity1.Attributes.Add(someAttrib1); var entity1Doc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, "MyEntity1.cdm.json"); entity1Doc.Definitions.Add(entity1); corpus.Storage.FetchRootFolder("local").Documents.Add(entity1Doc); manifest.Entities.Add(entity1); await manifest.CreateResolvedManifestAsync("new dummy 2", null); TestBasicLogsState(corpus); TestHelper.AssertCdmLogCodeEquality(corpus, CdmLogCode.ErrResolveReferenceFailure); // Keep for debugging //corpus.Ctx.Events.ForEach(logEntry => { // logEntry.ToList().ForEach(logEntryPair => Console.WriteLine($"{logEntryPair.Key}={logEntryPair.Value}")); // Console.WriteLine(); //}); }
/// <summary> /// Create an type attribute definition instance with provided data type. /// </summary> /// <param name="cdmCorpus"> The CDM corpus. </param> /// <param name="attributeName"> The directives to use while getting the resolved entities. </param> /// <param name="purpose"> The manifest to be resolved. </param> /// <param name="dataType"> The data type.</param> /// <returns> The instance of type attribute definition. </returns> private static CdmTypeAttributeDefinition CreateEntityAttributeWithPurposeAndDataType(CdmCorpusDefinition cdmCorpus, string attributeName, string purpose, string dataType) { var entityAttribute = CreateEntityAttributeWithPurpose(cdmCorpus, attributeName, purpose); entityAttribute.DataType = cdmCorpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, dataType, true); return(entityAttribute); }
static CdmTypeAttributeDefinition sqlToCDMAttribute(CdmCorpusDefinition cdmCorpus, dynamic columnAttribute) { CdmTypeAttributeDefinition entityAttribute; string name = System.Convert.ToString(columnAttribute.name); string dataType = System.Convert.ToString(columnAttribute.dataType); if (System.Convert.ToInt32(columnAttribute.IsPrimaryKey) == 1) { entityAttribute = CreateEntityAttributeWithPurpose(cdmCorpus, name, "identifiedBy"); } else { entityAttribute = CreateEntityAttributeWithPurpose(cdmCorpus, name, "hasA"); } string cdmType = sqlToCDMDataType(dataType); entityAttribute.DataType = cdmCorpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, cdmType, true); if (cdmType.ToLower().Equals("string")) { if (UseCollat) { string collation = $"Collate {DefaultCollation}"; if (columnAttribute.collation != null) { collation = $"Collate {System.Convert.ToString(columnAttribute.collation)}"; } entityAttribute.Explanation = collation; } int maximumLenght = DefaultMaxLength; if (columnAttribute.maximumLength != null) { maximumLenght = System.Convert.ToInt32(columnAttribute.maximumLength); } entityAttribute.MaximumLength = maximumLenght; } if (cdmType.ToLower().Equals("decimal")) { int precision = DefaultPrecison, scale = DefaultScale; if (columnAttribute.precision != null && columnAttribute.scale != null) { precision = System.Convert.ToInt32(columnAttribute.precision); scale = System.Convert.ToInt32(columnAttribute.scale); } entityAttribute.Explanation = $"({precision},{scale})"; } return(entityAttribute); }
/// <summary> /// Create an purpose reference instance which points to `meaningOfRelationshipVerbPhrases` which is defined in public standards. /// </summary> /// <param name="cdmCorpus"> The CDM corpus. </param> /// <returns> The instance of purpose reference. </returns> private static CdmPurposeReference CreateRelationshipMeanings(CdmCorpusDefinition cdmCorpus, string customMessage) { // The purpose "meaningOfRelationshipVerbPhrases" is from /samples/example-public-standards/foundations.cdm.json // With the use of this purpose, two additional traits ("means.relationship.verbPhrase" and "means.relationship.inverseVerbPhrase") will be added by default // as they are attached to the purpose definition. CdmPurposeReference purposeRef = cdmCorpus.MakeRef <CdmPurposeReference>(CdmObjectType.PurposeRef, "meaningOfRelationshipVerbPhrases", false); // You can add your own argument to the additional traits // The trait "means.relationship.verbPhrase" is also from /samples/example-public-standards/foundations.cdm.json // This trait states that the data type it requires is an entity "localizedTable", which allow you to define phrases in different languages CdmTraitReference forwardPurposeTraitReference = cdmCorpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, "means.relationship.verbPhrase", false); List <List <string> > forwardDescriptions = new List <List <string> > { new List <string>() { "en", $"{customMessage} - Forwards" }, new List <string>() { "cn", "正向" } }; var forwardConstEntDef = cdmCorpus.MakeObject <CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef, null, false); forwardConstEntDef.ConstantValues = forwardDescriptions; // The entity "localizedTable" is from /samples/example-public-standards/foundations.cdm.json forwardConstEntDef.EntityShape = cdmCorpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, "localizedTable", true); forwardPurposeTraitReference.Arguments.Add(null, cdmCorpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, forwardConstEntDef, true)); purposeRef.AppliedTraits.Add(forwardPurposeTraitReference); // You can also use the same way above to decorate the second trait "means.relationship.inverseVerbPhrase" // it is also available in /samples/example-public-standards/foundations.cdm.json return(purposeRef); }
/// <summary> /// Creates a source entity for a projection /// </summary> public static CdmEntityDefinition CreateSourceEntity(CdmCorpusDefinition corpus, CdmFolderDefinition localRoot) { string entityName = "SourceEntity"; CdmEntityDefinition entity = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName); string attributeName1 = "id"; CdmTypeAttributeDefinition attribute1 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, attributeName1); attribute1.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "string", true); entity.Attributes.Add(attribute1); string attributeName2 = "name"; CdmTypeAttributeDefinition attribute2 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, attributeName2); attribute2.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "string", true); entity.Attributes.Add(attribute2); string attributeName3 = "value"; CdmTypeAttributeDefinition attribute3 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, attributeName3); attribute3.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "integer", true); entity.Attributes.Add(attribute3); string attributeName4 = "date"; CdmTypeAttributeDefinition attribute4 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, attributeName4); attribute4.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "date", true); entity.Attributes.Add(attribute4); CdmDocumentDefinition entityDoc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false); entityDoc.Imports.Add(foundationJsonPath); entityDoc.Definitions.Add(entity); localRoot.Documents.Add(entityDoc, entityDoc.Name); return(entity); }
public async Task TestEntityAttributeProjUsingObjectModel() { CdmCorpusDefinition corpus = ProjectionTestUtils.GetLocalCorpus(testsSubpath, "TestEntityAttributeProjUsingObjectModel"); corpus.Storage.Mount("local", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestEntityAttributeProjUsingObjectModel"))); CdmFolderDefinition localRoot = corpus.Storage.FetchRootFolder("local"); // Create an entity CdmEntityDefinition entity = ProjectionTestUtils.CreateEntity(corpus, localRoot); // Create a projection CdmProjection projection = ProjectionTestUtils.CreateProjection(corpus, localRoot); // Create an AddTypeAttribute operation CdmOperationAddTypeAttribute addTypeAttrOp = corpus.MakeObject <CdmOperationAddTypeAttribute>(CdmObjectType.OperationAddTypeAttributeDef); addTypeAttrOp.TypeAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "testType"); addTypeAttrOp.TypeAttribute.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "entityName", true); projection.Operations.Add(addTypeAttrOp); // Create an entity reference to hold this projection CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef.ExplicitReference = projection; // Create an entity attribute that contains this projection and add this to the entity CdmEntityAttributeDefinition entityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, "TestEntityAttribute"); entityAttribute.Entity = projectionEntityRef; entity.Attributes.Add(entityAttribute); // Resolve the entity CdmEntityDefinition resolvedEntity = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", null, localRoot); // Verify correctness of the resolved attributes after running the AddTypeAttribute operation // Original set of attributes: ["id", "name", "value", "date"] // Type attribute: "testType" Assert.AreEqual(5, resolvedEntity.Attributes.Count); Assert.AreEqual("id", (resolvedEntity.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (resolvedEntity.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (resolvedEntity.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (resolvedEntity.Attributes[3] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("testType", (resolvedEntity.Attributes[4] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("is.linkedEntity.name", resolvedEntity.Attributes[4].AppliedTraits[4].NamedReference); }
/// <summary> /// Call CreateResolvedManifestAsync function to resolve a manifest with one entity, /// and get the logs of the function and all other internally called functions /// </summary> private async Task CallResolveManifestWithAnEntity(CdmCorpusDefinition corpus) { var manifest = corpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "dummy"); corpus.Storage.FetchRootFolder("local").Documents.Add(manifest, "default.manifest.cdm.json"); var entity1 = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, "MyEntity"); var someAttrib1 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "MyAttribute", false); someAttrib1.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "entityId", true); entity1.Attributes.Add(someAttrib1); var entity1Doc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, "MyEntity.cdm.json"); entity1Doc.Definitions.Add(entity1); corpus.Storage.FetchRootFolder("local").Documents.Add(entity1Doc); manifest.Entities.Add(entity1); await manifest.CreateResolvedManifestAsync("new dummy", null); }
public async Task TestWithNesting() { CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestEventList"); corpus.SetEventCallback(eventCallback, CdmStatusLevel.Warning, DummyCorrelationId); var manifest = corpus.MakeObject <CdmManifestDefinition>(CdmObjectType.ManifestDef, "dummy"); // Test resolving a manifest (added to a folder) with an entity in it, this should collect messages from // CreateResolvedManifestAsync and CreateResolvedEntityAsync functions corpus.Storage.FetchRootFolder("local").Documents.Add(manifest); var entity1 = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, "MyEntity1"); var someAttrib1 = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "someAttrib1", false); someAttrib1.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "entityId", true); entity1.Attributes.Add(someAttrib1); var entity1Doc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, "MyEntity1.cdm.json"); entity1Doc.Definitions.Add(entity1); corpus.Storage.FetchRootFolder("local").Documents.Add(entity1Doc); manifest.Entities.Add(entity1); await manifest.CreateResolvedManifestAsync("new dummy 2", null); Assert.IsFalse(corpus.Ctx.Events.IsRecording, "Recording should be disabled at the end of API call"); Assert.IsTrue(corpus.Ctx.Events.Count > 0, "There should have been at least one event recorded"); // We check that there first event recorded was an error from the nested function Assert.IsTrue(corpus.Ctx.Events[0]["level"] == "Error", "The first recorded event level should have been 'Error'"); Assert.IsTrue(corpus.Ctx.Events[0]["message"] == "Unable to resolve the reference 'entityId' to a known object", "The first recorded event message should have specified that 'entityId' was not resolved"); Assert.IsTrue(corpus.Ctx.Events[0]["correlationId"] == DummyCorrelationId, "The recorded event should have had a correlationId key with the dummy value"); // Keep for debugging //corpus.Ctx.Events.ForEach(logEntry => { // logEntry.ToList().ForEach(logEntryPair => Console.WriteLine($"{logEntryPair.Key}={logEntryPair.Value}")); // Console.WriteLine(); //}); }
/// <summary> /// Create a relationship linking with an attribute an eneity attribute definition instance without a trait. /// </summary> /// <param name="cdmCorpus"> The CDM corpus. </param> /// <param name="associatedEntityName"> The name of . </param> /// <param name="foreignKeyName"> The name of the foreign key. </param> /// <param name="attributeExplanation"> The explanation of the attribute.</param> /// <returns> The instatnce of entity attribute definition. </returns> private static CdmEntityAttributeDefinition CreateSimpleAttributeForRelationshipBetweenTwoEntities( CdmCorpusDefinition cdmCorpus, string associatedEntityName, string foreignKeyName, string attributeExplanation) { // Define a relationship by creating an entity attribute var entityAttributeDef = cdmCorpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, foreignKeyName); entityAttributeDef.Explanation = attributeExplanation; // Creating an entity reference for the associated entity - simple name reference entityAttributeDef.Entity = cdmCorpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, associatedEntityName, true); // Add resolution guidance - enable reference var attributeResolution = cdmCorpus.MakeObject <CdmAttributeResolutionGuidance>(CdmObjectType.AttributeResolutionGuidanceDef); attributeResolution.entityByReference = attributeResolution.makeEntityByReference(); attributeResolution.entityByReference.allowReference = true; entityAttributeDef.ResolutionGuidance = attributeResolution; return(entityAttributeDef); }
public async Task TestConditionalProjUsingObjectModel() { CdmCorpusDefinition corpus = ProjectionTestUtils.GetLocalCorpus(testsSubpath, "TestConditionalProjUsingObjectModel"); corpus.Storage.Mount("local", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestConditionalProjUsingObjectModel"))); CdmFolderDefinition localRoot = corpus.Storage.FetchRootFolder("local"); // Create an entity CdmEntityDefinition entity = ProjectionTestUtils.CreateEntity(corpus, localRoot); // Create a projection with a condition that states the operation should only execute when the resolution directive is 'referenceOnly' CdmProjection projection = ProjectionTestUtils.CreateProjection(corpus, localRoot); projection.Condition = "referenceOnly==true"; // Create an AddTypeAttribute operation CdmOperationAddTypeAttribute addTypeAttrOp = corpus.MakeObject <CdmOperationAddTypeAttribute>(CdmObjectType.OperationAddTypeAttributeDef); addTypeAttrOp.TypeAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "testType"); addTypeAttrOp.TypeAttribute.DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "entityName", true); projection.Operations.Add(addTypeAttrOp); // Create an entity reference to hold this projection CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef.ExplicitReference = projection; // Create an entity attribute that contains this projection and add this to the entity CdmEntityAttributeDefinition entityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, "TestEntityAttribute"); entityAttribute.Entity = projectionEntityRef; entity.Attributes.Add(entityAttribute); // Create resolution options with the 'referenceOnly' directive ResolveOptions resOpt = new ResolveOptions(entity.InDocument); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "referenceOnly" }); // Resolve the entity with 'referenceOnly' CdmEntityDefinition resolvedEntityWithReferenceOnly = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", resOpt, localRoot); // Verify correctness of the resolved attributes after running the AddTypeAttribute operation // Original set of attributes: ["id", "name", "value", "date"] // Type attribute: "testType" Assert.AreEqual(5, resolvedEntityWithReferenceOnly.Attributes.Count); Assert.AreEqual("id", (resolvedEntityWithReferenceOnly.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (resolvedEntityWithReferenceOnly.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (resolvedEntityWithReferenceOnly.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (resolvedEntityWithReferenceOnly.Attributes[3] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("testType", (resolvedEntityWithReferenceOnly.Attributes[4] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("is.linkedEntity.name", resolvedEntityWithReferenceOnly.Attributes[4].AppliedTraits[4].NamedReference); // Now resolve the entity with the 'structured' directive resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "structured" }); CdmEntityDefinition resolvedEntityWithStructured = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", resOpt, localRoot); // Verify correctness of the resolved attributes after running the AddTypeAttribute operation // Original set of attributes: ["id", "name", "value", "date"] // No Type attribute added, condition was false Assert.AreEqual(4, resolvedEntityWithStructured.Attributes.Count); Assert.AreEqual("id", (resolvedEntityWithStructured.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (resolvedEntityWithStructured.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (resolvedEntityWithStructured.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (resolvedEntityWithStructured.Attributes[3] as CdmTypeAttributeDefinition).Name); }
public async Task TestConditionalProjUsingObjectModel() { string testName = nameof(TestConditionalProjUsingObjectModel); CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, testName); CdmFolderDefinition localRoot = corpus.Storage.FetchRootFolder("local"); corpus.Storage.Mount("traitGroup", new LocalAdapter(traitGroupFilePath)); // Create an entity. CdmEntityDefinition entity = ProjectionTestUtils.CreateEntity(corpus, localRoot); entity.InDocument.Imports.Add("traitGroup:/TraitGroup.cdm.json"); // Create a projection with a condition that states the operation should only execute when the resolution directive is 'structured'. CdmProjection projection = ProjectionTestUtils.CreateProjection(corpus, localRoot); projection.Condition = "structured==true"; projection.RunSequentially = true; // Create an AlterTraits operation CdmOperationAlterTraits alterTraitsOp_1 = corpus.MakeObject <CdmOperationAlterTraits>(CdmObjectType.OperationAlterTraitsDef); alterTraitsOp_1.TraitsToAdd = new CdmCollection <CdmTraitReferenceBase>(corpus.Ctx, alterTraitsOp_1, CdmObjectType.TraitRef); alterTraitsOp_1.TraitsToAdd.Add(corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "means.TraitG100", true)); alterTraitsOp_1.TraitsToAdd.Add(corpus.MakeRef <CdmTraitGroupReference>(CdmObjectType.TraitGroupRef, "JobTitleBase", true)); alterTraitsOp_1.TraitsToRemove = new CdmCollection <CdmTraitReferenceBase>(corpus.Ctx, alterTraitsOp_1, CdmObjectType.TraitRef); alterTraitsOp_1.TraitsToRemove.Add(corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "means.TraitG300", true)); projection.Operations.Add(alterTraitsOp_1); CdmOperationAlterTraits alterTraitsOp_2 = corpus.MakeObject <CdmOperationAlterTraits>(CdmObjectType.OperationAlterTraitsDef); var traitG4 = corpus.MakeRef <CdmTraitReference>(CdmObjectType.TraitRef, "means.TraitG4", true); traitG4.Arguments.Add("precision", "5"); traitG4.Arguments.Add("scale", "15"); alterTraitsOp_2.TraitsToAdd = new CdmCollection <CdmTraitReferenceBase>(corpus.Ctx, alterTraitsOp_2, CdmObjectType.TraitRef); alterTraitsOp_2.TraitsToAdd.Add(traitG4); alterTraitsOp_2.ApplyTo = new List <string>() { "name" }; projection.Operations.Add(alterTraitsOp_2); // Create an entity reference to hold this projection. CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef.ExplicitReference = projection; // Create an entity attribute that contains this projection and add this to the entity. CdmEntityAttributeDefinition entityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, "TestEntityAttribute"); entityAttribute.Entity = projectionEntityRef; entity.Attributes.Add(entityAttribute); // Create resolution options with the 'referenceOnly' directive. ResolveOptions resOpt = new ResolveOptions(entity.InDocument) { Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "referenceOnly" }) }; CdmEntityDefinition resolvedEntityWithReferenceOnly = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", resOpt, localRoot); // Original set of attributes: ["name", "age", "address", "phoneNumber", "email"] // Condition not met, no traits are added Assert.AreEqual(4, resolvedEntityWithReferenceOnly.Attributes.Count); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithReferenceOnly.Attributes[0], "id", doesNotExist: true); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithReferenceOnly.Attributes[1], "name", doesNotExist: true); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithReferenceOnly.Attributes[2], "value", doesNotExist: true); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithReferenceOnly.Attributes[3], "date", doesNotExist: true); CdmEntityDefinition resolvedEntityWithStructured = await ProjectionTestUtils.GetResolvedEntity(corpus, entity, new List <string> { "structured" }); // Original set of attributes: ["name", "age", "address", "phoneNumber", "email"] // Condition met, new traits are added Assert.AreEqual(4, resolvedEntityWithStructured.Attributes.Count); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithStructured.Attributes[0], "id"); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithStructured.Attributes[1], "name", true); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithStructured.Attributes[2], "value"); ValidateTrait((CdmTypeAttributeDefinition)resolvedEntityWithStructured.Attributes[3], "date"); }
public async Task TestConditionalProjUsingObjectModel() { string testName = nameof(TestConditionalProjUsingObjectModel); CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, testName); CdmFolderDefinition localRoot = corpus.Storage.FetchRootFolder("local"); // Create an entity. CdmEntityDefinition entity = ProjectionTestUtils.CreateEntity(corpus, localRoot); // Create a projection with a condition that states the operation should only execute when the resolution directive is 'structured'. CdmProjection projection = ProjectionTestUtils.CreateProjection(corpus, localRoot); projection.Condition = "structured==true"; // Create an AddArtifactAttribute operation CdmOperationAddArtifactAttribute addArtifactAttributeOp = corpus.MakeObject <CdmOperationAddArtifactAttribute>(CdmObjectType.OperationAddArtifactAttributeDef); addArtifactAttributeOp.NewAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "newName"); ((CdmTypeAttributeDefinition)addArtifactAttributeOp.NewAttribute).DataType = corpus.MakeRef <CdmDataTypeReference>(CdmObjectType.DataTypeRef, "string", true); projection.Operations.Add(addArtifactAttributeOp); // Create an entity reference to hold this projection. CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef.ExplicitReference = projection; // Create an entity attribute that contains this projection and add this to the entity. CdmEntityAttributeDefinition entityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, "TestEntityAttribute"); entityAttribute.Entity = projectionEntityRef; entity.Attributes.Add(entityAttribute); // Create resolution options with the 'referenceOnly' directive. ResolveOptions resOpt = new ResolveOptions(entity.InDocument) { Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "referenceOnly" }) }; // Resolve the entity with 'referenceOnly' CdmEntityDefinition resolvedEntityWithReferenceOnly = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", resOpt, localRoot); // Original set of attributes: ["id", "name", "value", "date"] // Condition not met, keep attributes in flat list Assert.AreEqual(4, resolvedEntityWithReferenceOnly.Attributes.Count); Assert.AreEqual("id", (resolvedEntityWithReferenceOnly.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (resolvedEntityWithReferenceOnly.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (resolvedEntityWithReferenceOnly.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (resolvedEntityWithReferenceOnly.Attributes[3] as CdmTypeAttributeDefinition).Name); // Now resolve the entity with the 'structured' directive resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "structured" }); CdmEntityDefinition resolvedEntityWithStructured = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", resOpt, localRoot); // Original set of attributes: ["id", "name", "value", "date"] // Condition met, keep attributes in flat list and add the new attribute "newName" all attributes at the end Assert.AreEqual(5, resolvedEntityWithStructured.Attributes.Count); Assert.AreEqual("id", (resolvedEntityWithStructured.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (resolvedEntityWithStructured.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (resolvedEntityWithStructured.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (resolvedEntityWithStructured.Attributes[3] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("newName", (resolvedEntityWithStructured.Attributes[4] as CdmTypeAttributeDefinition).Name); }