/// <summary> /// Create an entity 'TestEntityAttributeProjection' that contains an entity attribute with a projection as a source entity /// </summary> /// <param name="corpus"></param> /// <param name="manifestDefault"></param> /// <param name="localRoot"></param> /// <returns></returns> private CdmEntityDefinition CreateEntityTestEntityAttributeProjection(CdmCorpusDefinition corpus, CdmManifestDefinition manifestDefault, CdmFolderDefinition localRoot) { string entityName = "TestEntityAttributeProjection"; CdmEntityReference inlineProjectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); inlineProjectionEntityRef.ExplicitReference = CreateProjection(corpus); CdmEntityDefinition entityTestEntityAttributeProjection = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName); { string attributeName = "TestAttribute"; CdmEntityAttributeDefinition entityTestEntityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, nameOrRef: attributeName, simpleNameRef: false); entityTestEntityAttribute.Entity = inlineProjectionEntityRef; entityTestEntityAttributeProjection.Attributes.Add(entityTestEntityAttribute); } CdmDocumentDefinition entityTestEntityAttributeProjectionDoc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false); entityTestEntityAttributeProjectionDoc.Imports.Add(FoundationJsonPath); entityTestEntityAttributeProjectionDoc.Imports.Add("TestSource.cdm.json"); entityTestEntityAttributeProjectionDoc.Definitions.Add(entityTestEntityAttributeProjection); localRoot.Documents.Add(entityTestEntityAttributeProjectionDoc, entityTestEntityAttributeProjectionDoc.Name); manifestDefault.Entities.Add(entityTestEntityAttributeProjection); return(entityTestEntityAttributeProjection); }
/// <summary> /// Create an entity attribute /// </summary> /// <param name="entityAttributeName"></param> /// <param name="projectionSourceEntityRef"></param> /// <returns></returns> public CdmEntityAttributeDefinition CreateEntityAttribute(string entityAttributeName, CdmEntityReference projectionSourceEntityRef) { CdmEntityAttributeDefinition entityAttribute = Corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, nameOrRef: entityAttributeName, simpleNameRef: false); entityAttribute.Entity = projectionSourceEntityRef; return(entityAttribute); }
public async Task TestNestedProjUsingObjectModel() { CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestNestedProjUsingObjectModel"); corpus.Storage.Mount("local", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestNestedProjUsingObjectModel"))); 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 ExcludeAttributes operation CdmOperationExcludeAttributes excludeAttrsOp = corpus.MakeObject <CdmOperationExcludeAttributes>(CdmObjectType.OperationExcludeAttributesDef); excludeAttrsOp.ExcludeAttributes.Add("id"); excludeAttrsOp.ExcludeAttributes.Add("date"); projection.Operations.Add(excludeAttrsOp); // Create an entity reference to hold this projection CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef.ExplicitReference = projection; // Create another projection that uses the previous projection as its source CdmProjection projection2 = corpus.MakeObject <CdmProjection>(CdmObjectType.ProjectionDef); projection2.Source = projectionEntityRef; // Create an ExcludeAttributes operation CdmOperationExcludeAttributes excludeAttrsOp2 = corpus.MakeObject <CdmOperationExcludeAttributes>(CdmObjectType.OperationExcludeAttributesDef); excludeAttrsOp2.ExcludeAttributes.Add("value"); projection2.Operations.Add(excludeAttrsOp2); // Create an entity reference to hold this projection CdmEntityReference projectionEntityRef2 = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef2.ExplicitReference = projection2; // Create an entity attribute that contains this projection and add this to the entity CdmEntityAttributeDefinition entityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, "TestEntityAttribute"); entityAttribute.Entity = projectionEntityRef2; 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 ExcludeAttributes operations // Original set of attributes: ["id", "name", "value", "date"] // Excluded attributes: ["id", "date"], ["value"] Assert.AreEqual(1, resolvedEntity.Attributes.Count); Assert.AreEqual("name", (resolvedEntity.Attributes[0] as CdmTypeAttributeDefinition).Name); }
/// <summary> /// Applies the arrayExpansion operation to the entity attribute provided. /// It also takes care of applying a renameAttributes operation and optionally applying a addCountAttribute operation. /// </summary> /// <param name="entityAttr"></param> /// <param name="startOrdinal"></param> /// <param name="endOrdinal"></param> /// <param name="renameFormat"></param> /// <param name="countAttName"></param> static void ApplyArrayExpansion(CdmEntityAttributeDefinition entityAttr, int startOrdinal, int endOrdinal, string renameFormat, string countAttName) { var ctx = entityAttr.Ctx; CdmProjection projection = new CdmProjection(ctx) { Source = entityAttr.Entity, RunSequentially = true, // Link for the Condition property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#condition Condition = "!normalized" }; entityAttr.Entity = new CdmEntityReference(ctx, projection, false); // Link for the ArrayExpansion operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/arrayexpansion var arrExpansionOperation = new CdmOperationArrayExpansion(ctx) { StartOrdinal = startOrdinal, EndOrdinal = endOrdinal }; projection.Operations.Add(arrExpansionOperation); // Link for the RenameAttributes operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/renameattributes // Doing an ArrayExpansion without a RenameAttributes afterwards will result in the expanded attributes being merged in the final resolved entity. // This is because ArrayExpansion does not rename the attributes it expands by default. The expanded attributes end up with the same name and gets merged. // Example: We expand A to A[1], A[2], A[3], but A[1], A[2], A[3] are still named "A". var renameAttrsOperation = new CdmOperationRenameAttributes(ctx) { RenameFormat = renameFormat }; projection.Operations.Add(renameAttrsOperation); if (countAttName != null) { var countAttribute = new CdmTypeAttributeDefinition(ctx, countAttName) { DataType = new CdmDataTypeReference(ctx, "integer", true) }; // Link for the AddCountAttribute operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addcountattribute // It is recommended, but not mandated, to be used with the ArrayExpansion operation to provide an ArrayExpansion a count attribute that // represents the total number of expanded elements. AddCountAttribute can also be used by itself. var addCountAttrOperation = new CdmOperationAddCountAttribute(ctx) { CountAttribute = countAttribute }; projection.Operations.Add(addCountAttrOperation); } }
public static EntityAttribute ToData(CdmEntityAttributeDefinition instance, ResolveOptions resOpt, CopyOptions options) { return(new EntityAttribute { Explanation = instance.Explanation, Name = instance.Name, Entity = Utils.JsonForm(instance.Entity, resOpt, options), Purpose = Utils.JsonForm(instance.Purpose, resOpt, options), AppliedTraits = CopyDataUtils.ListCopyData(resOpt, instance.AppliedTraits, options), ResolutionGuidance = Utils.JsonForm(instance.ResolutionGuidance, resOpt, options) }); }
public async Task TestEAProjOM() { string className = "ProjectionIncludeTest"; string testName = "TestEAProjOM"; string entityName_RGB = "RGB"; List <TypeAttributeParam> attributeParams_RGB = new List <TypeAttributeParam>(); { attributeParams_RGB.Add(new TypeAttributeParam("Red", "string", "hasA")); attributeParams_RGB.Add(new TypeAttributeParam("Green", "string", "hasA")); attributeParams_RGB.Add(new TypeAttributeParam("Blue", "string", "hasA")); attributeParams_RGB.Add(new TypeAttributeParam("IsGrayscale", "boolean", "hasA")); } string entityName_Color = "Color"; List <TypeAttributeParam> attributeParams_Color = new List <TypeAttributeParam>(); { attributeParams_Color.Add(new TypeAttributeParam("ColorName", "string", "identifiedBy")); } List <string> includeAttributeNames = new List <string>() { "Red", "Green", "Blue" }; using (ProjectionOMTestUtil util = new ProjectionOMTestUtil(className, testName)) { CdmEntityDefinition entity_RGB = util.CreateBasicEntity(entityName_RGB, attributeParams_RGB); util.ValidateBasicEntity(entity_RGB, entityName_RGB, attributeParams_RGB); CdmEntityDefinition entity_Color = util.CreateBasicEntity(entityName_Color, attributeParams_Color); util.ValidateBasicEntity(entity_Color, entityName_Color, attributeParams_Color); CdmProjection projection_RGBColor = util.CreateProjection(entity_RGB.EntityName); CdmOperationIncludeAttributes operation_IncludeAttributes = util.CreateOperationInputAttributes(projection_RGBColor, includeAttributeNames); CdmEntityReference projectionEntityRef_RGBColor = util.CreateProjectionInlineEntityReference(projection_RGBColor); CdmEntityAttributeDefinition entityAttribute_RGBColor = util.CreateEntityAttribute("RGBColor", projectionEntityRef_RGBColor); entity_Color.Attributes.Add(entityAttribute_RGBColor); foreach (List <string> resOpts in resOptsCombinations) { await util.GetAndValidateResolvedEntity(entity_Color, resOpts); } await util.DefaultManifest.SaveAsAsync(util.ManifestDocName, saveReferenced : true); } }
/// <summary> /// Applies the arrayExpansion operation to the entity attribute provided. /// It also takes care of applying a renameAttributes operation and optionally applying a addCountAttribute operation. /// </summary> /// <param name="entityAttr"></param> /// <param name="startOrdinal"></param> /// <param name="endOrdinal"></param> /// <param name="renameFormat"></param> /// <param name="countAttName"></param> static void ApplyArrayExpansion(CdmEntityAttributeDefinition entityAttr, int startOrdinal, int endOrdinal, string renameFormat, string countAttName) { var ctx = entityAttr.Ctx; CdmProjection projection = new CdmProjection(ctx) { Source = entityAttr.Entity, RunSequentially = true, // Link for the Condition property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#condition Condition = "!normalized" }; entityAttr.Entity = new CdmEntityReference(ctx, projection, false); // Link for the ArrayExpansion operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/arrayexpansion var arrExpansionOperation = new CdmOperationArrayExpansion(ctx) { StartOrdinal = startOrdinal, EndOrdinal = endOrdinal }; projection.Operations.Add(arrExpansionOperation); // Link for the RenameAttributes operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/renameattributes var renameAttrsOperation = new CdmOperationRenameAttributes(ctx) { RenameFormat = renameFormat }; projection.Operations.Add(renameAttrsOperation); if (countAttName != null) { var countAttribute = new CdmTypeAttributeDefinition(ctx, countAttName) { DataType = new CdmDataTypeReference(ctx, "integer", true) }; // Link for the AddCountAttribute operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addcountattribute var addCountAttrOperation = new CdmOperationAddCountAttribute(ctx) { CountAttribute = countAttribute }; projection.Operations.Add(addCountAttrOperation); } }
public static EntityAttribute ToData(CdmEntityAttributeDefinition instance, ResolveOptions resOpt, CopyOptions options) { return(new EntityAttribute { Explanation = instance.Explanation, Name = instance.Name, IsPolymorphicSource = instance.IsPolymorphicSource, Entity = Utils.JsonForm(instance.Entity, resOpt, options), Purpose = Utils.JsonForm(instance.Purpose, resOpt, options), AppliedTraits = CopyDataUtils.ListCopyData(resOpt, instance.AppliedTraits?.Where(trait => !trait.IsFromProperty), options), ResolutionGuidance = Utils.JsonForm(instance.ResolutionGuidance, resOpt, options), DisplayName = instance.GetProperty("displayName"), Description = instance.GetProperty("description") }); }
/// <summary> /// Applies the replaceAsForeignKey and addAttributeGroup operations to the entity attribute provided. /// </summary> /// <param name="entityAttr"></param> /// <param name="fkAttrName"></param> /// <param name="attrGroupName"></param> static void ApplyDefaultBehavior(CdmEntityAttributeDefinition entityAttr, string fkAttrName, string attrGroupName) { var ctx = entityAttr.Ctx; CdmProjection projection = new CdmProjection(ctx) { // Link for the Source property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#source Source = entityAttr.Entity, // Link for the RunSequentially property documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#run-sequentially RunSequentially = true }; entityAttr.Entity = new CdmEntityReference(ctx, projection, false); if (fkAttrName != null) { var foreignKeyAttr = new CdmTypeAttributeDefinition(ctx, fkAttrName) { DataType = new CdmDataTypeReference(ctx, "entityId", true) }; // Link for the ReplaceAsForeignKey operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/replaceasforeignkey var replaceAsFKOperation = new CdmOperationReplaceAsForeignKey(ctx) { Condition = "referenceOnly", Reference = "addressLine", ReplaceWith = foreignKeyAttr }; projection.Operations.Add(replaceAsFKOperation); } if (attrGroupName != null) { // Link for the AddAttributeGroup operation documentation. // https://docs.microsoft.com/en-us/common-data-model/sdk/projections/addattributegroup var addAttrGroupOperation = new CdmOperationAddAttributeGroup(ctx) { Condition = "structured", AttributeGroupName = attrGroupName }; projection.Operations.Add(addAttrGroupOperation); } }
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); }
public void TestEntityAttributeSource() { CdmCorpusDefinition corpus = new CdmCorpusDefinition(); int errorCount = 0; corpus.SetEventCallback(new EventCallback() { Invoke = (level, message) => { errorCount++; } }, CdmStatusLevel.Error); CdmProjection projection = new CdmProjection(corpus.Ctx); CdmEntityAttributeDefinition _ = new CdmEntityAttributeDefinition(corpus.Ctx, "attribute") { Entity = new CdmEntityReference(corpus.Ctx, projection, false) }; // First case, a projection without source. projection.Validate(); Assert.AreEqual(1, errorCount); errorCount = 0; // Second case, a projection with a nested projection. CdmProjection innerProjection = new CdmProjection(corpus.Ctx); projection.Source = new CdmEntityReference(corpus.Ctx, innerProjection, false); projection.Validate(); innerProjection.Validate(); Assert.AreEqual(1, errorCount); errorCount = 0; // Third case, a projection with an explicit entity definition. innerProjection.Source = new CdmEntityReference(corpus.Ctx, new CdmEntityDefinition(corpus.Ctx, "Entity"), false); projection.Validate(); innerProjection.Validate(); Assert.AreEqual(0, errorCount); // Third case, a projection with a named reference. innerProjection.Source = new CdmEntityReference(corpus.Ctx, "Entity", false); projection.Validate(); innerProjection.Validate(); Assert.AreEqual(0, errorCount); }
public static EntityAttribute ToData(CdmEntityAttributeDefinition instance, ResolveOptions resOpt, CopyOptions options) { EntityAttribute obj = new EntityAttribute { Explanation = instance.Explanation, Name = instance.Name, IsPolymorphicSource = instance.IsPolymorphicSource, Entity = Utils.JsonForm(instance.Entity, resOpt, options), Purpose = Utils.JsonForm(instance.Purpose, resOpt, options), AppliedTraits = CopyDataUtils.ListCopyData(resOpt, instance.AppliedTraits? .Where(trait => trait is CdmTraitGroupReference || !(trait as CdmTraitReference).IsFromProperty), options), ResolutionGuidance = Utils.JsonForm(instance.ResolutionGuidance, resOpt, options), DisplayName = instance.GetProperty("displayName"), Description = instance.GetProperty("description"), Cardinality = Utils.CardinalitySettingsToData(instance.Cardinality) }; return(obj); }
public ProjectionDirective(ResolveOptions resOpt, CdmObjectDefinitionBase owner, CdmObjectReference ownerRef = null) { this.ResOpt = resOpt; // Owner information this.Owner = owner; this.OwnerRef = ownerRef; this.OwnerType = (owner != null) ? owner.ObjectType : CdmObjectType.Error; if (owner?.ObjectType == CdmObjectType.EntityAttributeDef) { // Entity Attribute CdmEntityAttributeDefinition _owner = (CdmEntityAttributeDefinition)owner; this.Cardinality = _owner.Cardinality != null ? _owner.Cardinality : new CardinalitySettings(_owner); this.IsSourcePolymorphic = (_owner.IsPolymorphicSource != null && _owner.IsPolymorphicSource == true); } else { // Entity Def this.Cardinality = null; this.IsSourcePolymorphic = false; } this.IsReferenceOnly = (resOpt.Directives?.Has("referenceOnly") == true); this.IsNormalized = (resOpt.Directives?.Has("normalized") == true); this.IsStructured = (resOpt.Directives?.Has("structured") == true); this.IsVirtual = (resOpt.Directives?.Has("virtual") == true); this.HasNoMaximumDepth = (resOpt.Directives?.Has("noMaxDepth") == true); this.IsArray = (resOpt.Directives?.Has("isArray") == true); if (resOpt.DepthInfo != null) { this.CurrentDepth = (resOpt?.DepthInfo == null) ? 1 : resOpt.DepthInfo.CurrentDepth + 1; resOpt.DepthInfo.CurrentDepth = (int)this.CurrentDepth; } // if noMaxDepth directive the max depth is 32 else defaults to 2 // these depths were arbitrary and were set for the resolution guidance // re-using the same for projections as well this.MaximumDepth = this.HasNoMaximumDepth ? MaxDepthHasNoMax : MaxDepthDefault; }
public async Task TestEntityAttributeProjUsingObjectModel() { string testName = "TestEntityAttributeProjUsingObjectModel"; CdmCorpusDefinition corpus = ProjectionTestUtils.GetCorpus(testName, testsSubpath); 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 AddAttributeGroup operation CdmOperationAddAttributeGroup addAttGroupOp = corpus.MakeObject <CdmOperationAddAttributeGroup>(CdmObjectType.OperationAddAttributeGroupDef); addAttGroupOp.AttributeGroupName = "PersonAttributeGroup"; projection.Operations.Add(addAttGroupOp); // 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 AddAttributeGroup operation // Original set of attributes: ["id", "name", "value", "date"] CdmAttributeGroupDefinition attGroupDefinition = this.ValidateAttributeGroup(resolvedEntity.Attributes, "PersonAttributeGroup"); Assert.AreEqual(4, attGroupDefinition.Members.Count); Assert.AreEqual("id", (attGroupDefinition.Members[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (attGroupDefinition.Members[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (attGroupDefinition.Members[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (attGroupDefinition.Members[3] as CdmTypeAttributeDefinition).Name); }
public async Task TestEntRefNonexistent() { var expectedCodes = new HashSet <CdmLogCode> { CdmLogCode.WarnResolveObjectFailed, CdmLogCode.ErrResolveReferenceFailure }; var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestEntRefNonexistent", expectedCodes: expectedCodes); var folder = corpus.Storage.NamespaceFolders["local"]; var doc = new CdmDocumentDefinition(corpus.Ctx, "someDoc.cdm.json"); folder.Documents.Add(doc); var entity = new CdmEntityDefinition(corpus.Ctx, "someEntity"); var entAtt = new CdmEntityAttributeDefinition(corpus.Ctx, "entityAtt"); entAtt.Entity = new CdmEntityReference(corpus.Ctx, "nonExistingEntity", true); entity.Attributes.Add(entAtt); doc.Definitions.Add(entity); var resolvedEnt = await entity.CreateResolvedEntityAsync("resolvedSomeEntity"); Assert.IsNotNull(resolvedEnt); }
public void TestGetDefaultConditionExpression() { CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestGetDefaultConditionExpression"); corpus.Storage.Mount("local", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestGetDefaultConditionExpression"))); CdmFolderDefinition localRoot = corpus.Storage.FetchRootFolder("local"); CdmManifestDefinition manifestDefault = CreateDefaultManifest(corpus, localRoot); CdmEntityDefinition entityTestSource = CreateEntityTestSource(corpus, manifestDefault, localRoot); // projection for a non entity attribute CdmOperationCollection opColl = new CdmOperationCollection(corpus.Ctx, entityTestSource); { // add 1st FK opColl.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx)); Assert.AreEqual($" (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource)); // add 2nd FK opColl.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx)); Assert.AreEqual($" (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource)); opColl.Clear(); // add AddCount opColl.Add(new CdmOperationAddCountAttribute(corpus.Ctx)); Assert.AreEqual($" (!structured) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource)); // add ArrayExpansion opColl.Add(new CdmOperationArrayExpansion(corpus.Ctx)); Assert.AreEqual($" (!structured) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource)); opColl.Clear(); // add AddSupporting opColl.Add(new CdmOperationAddSupportingAttribute(corpus.Ctx)); Assert.AreEqual($" (true) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource)); } CdmEntityAttributeDefinition entityTestEntityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, nameOrRef: "TestEntityAttribute", simpleNameRef: false); // projection for a non entity attribute CdmOperationCollection opCollEA = new CdmOperationCollection(corpus.Ctx, entityTestEntityAttribute); { // add 1st FK opCollEA.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx)); Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) ) && (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute)); // add 2nd FK opCollEA.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx)); Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) ) && (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute)); opCollEA.Clear(); // add AddCount opCollEA.Add(new CdmOperationAddCountAttribute(corpus.Ctx)); Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) ) && (!structured) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute)); // add ArrayExpansion opCollEA.Add(new CdmOperationArrayExpansion(corpus.Ctx)); Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) ) && (!structured) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute)); opCollEA.Clear(); // add AddSupporting opCollEA.Add(new CdmOperationAddSupportingAttribute(corpus.Ctx)); Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) ) && (true) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute)); } }
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"); // 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); }
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 corpus = new CdmCorpusDefinition(); // set callback to receive error and warning logs. corpus.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 = "../../../../../../"; corpus.Storage.Mount("local", new LocalAdapter(pathFromExeToExampleRoot + "8-logical-manipulation-using-projections/sample-data")); corpus.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' device, not the default so must use "cdm:/folder" to get there corpus.Storage.Mount("cdm", new LocalAdapter(pathFromExeToExampleRoot + "example-public-standards")); Console.WriteLine("Create logical entity definition."); var logicalFolder = await corpus.FetchObjectAsync <CdmFolderDefinition>("local:/"); var logicalDoc = logicalFolder.Documents.Add("Person.cdm.json"); logicalDoc.Imports.Add("Address.cdm.json"); var entity = logicalDoc.Definitions.Add("Person"); // Add "name" data typed attribute. var nameAttr = entity.Attributes.Add("name") as CdmTypeAttributeDefinition; nameAttr.DataType = new CdmDataTypeReference(corpus.Ctx, "string", true); // Add "age" data typed attribute. var ageAttr = entity.Attributes.Add("age") as CdmTypeAttributeDefinition; ageAttr.DataType = new CdmDataTypeReference(corpus.Ctx, "string", true); // Add "address" entity typed attribute. var entityAttr = new CdmEntityAttributeDefinition(corpus.Ctx, "address") { Entity = new CdmEntityReference(corpus.Ctx, "Address", true) }; ApplyArrayExpansion(entityAttr, 1, 3, "{m}{A}{o}", "countAttribute"); ApplyDefaultBehavior(entityAttr, "addressFK", "address"); entity.Attributes.Add(entityAttr); // Add "email" data typed attribute. var emailAttr = entity.Attributes.Add("email") as CdmTypeAttributeDefinition; emailAttr.DataType = new CdmDataTypeReference(corpus.Ctx, "string", true); // Save the logical definition of Person. await entity.InDocument.SaveAsAsync("Person.cdm.json"); Console.WriteLine("Get \"resolved\" folder where the resolved entities will be saved."); var resolvedFolder = await corpus.FetchObjectAsync <CdmFolderDefinition>("local:/resolved/"); var resOpt = new ResolveOptions(entity); // To get more information about directives and their meaning refer to // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#directives-guidance-and-the-resulting-resolved-shapes // We will start by resolving this entity with the "normalized" direcitve. // This directive will be used on this and the next two examples so we can analize the resolved entity // without the array expansion. Console.WriteLine("Resolving logical entity with normalized directive."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized" }); var resNormalizedEntity = await entity.CreateResolvedEntityAsync($"normalized_{entity.EntityName}", resOpt, resolvedFolder); await resNormalizedEntity.InDocument.SaveAsAsync($"{resNormalizedEntity.EntityName}.cdm.json"); // Another common scenario is to resolve an entity using the "referenceOnly" directive. // This directives is used to replace the relationships with a foreign key. Console.WriteLine("Resolving logical entity with referenceOnly directive."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "referenceOnly" }); var resReferenceOnlyEntity = await entity.CreateResolvedEntityAsync($"referenceOnly_{entity.EntityName}", resOpt, resolvedFolder); await resReferenceOnlyEntity.InDocument.SaveAsAsync($"{resReferenceOnlyEntity.EntityName}.cdm.json"); // When dealing with structured data, like Json or parquet, it sometimes necessary to represent the idea that // a property can hold a complex object. The shape of the complex object is defined by the source entity pointed by the // entity attribute and we use the "structured" directive to resolve the entity attribute as an attribute group. Console.WriteLine("Resolving logical entity with structured directive."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "structured" }); var resStructuredEntity = await entity.CreateResolvedEntityAsync($"structured_{entity.EntityName}", resOpt, resolvedFolder); await resStructuredEntity.InDocument.SaveAsAsync($"{resStructuredEntity.EntityName}.cdm.json"); // Now let us remove the "normalized" directive so the array expansion operation can run. Console.WriteLine("Resolving logical entity without directives (array expansion)."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { }); var resArrayEntity = await entity.CreateResolvedEntityAsync($"array_expansion_{entity.EntityName}", resOpt, resolvedFolder); await resArrayEntity.InDocument.SaveAsAsync($"{resArrayEntity.EntityName}.cdm.json"); }
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 ArrayExpansion operation CdmOperationArrayExpansion arrayExpansionOp = corpus.MakeObject <CdmOperationArrayExpansion>(CdmObjectType.OperationArrayExpansionDef); arrayExpansionOp.StartOrdinal = 1; arrayExpansionOp.EndOrdinal = 2; projection.Operations.Add(arrayExpansionOp); // Create an entity reference to hold this projection CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef.ExplicitReference = projection; // Create another projection that does a rename so that we can see the expanded attributes in the final resolved entity CdmProjection projection2 = corpus.MakeObject <CdmProjection>(CdmObjectType.ProjectionDef); projection2.Source = projectionEntityRef; // Create a RenameAttributes operation CdmOperationRenameAttributes renameAttrsOp = corpus.MakeObject <CdmOperationRenameAttributes>(CdmObjectType.OperationRenameAttributesDef); renameAttrsOp.RenameFormat = "{m}{o}"; projection2.Operations.Add(renameAttrsOp); // Create an entity reference to hold this projection CdmEntityReference projectionEntityRef2 = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null); projectionEntityRef2.ExplicitReference = projection2; // Create an entity attribute that contains this projection and add this to the entity CdmEntityAttributeDefinition entityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, "TestEntityAttribute"); entityAttribute.Entity = projectionEntityRef2; 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 projections // Original set of attributes: ["id", "name", "value", "date"] // Expand 1...2, renameFormat = {m}{o} Assert.AreEqual(8, resolvedEntity.Attributes.Count); Assert.AreEqual("id1", (resolvedEntity.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name1", (resolvedEntity.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value1", (resolvedEntity.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date1", (resolvedEntity.Attributes[3] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("id2", (resolvedEntity.Attributes[4] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name2", (resolvedEntity.Attributes[5] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value2", (resolvedEntity.Attributes[6] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date2", (resolvedEntity.Attributes[7] as CdmTypeAttributeDefinition).Name); }
public async Task TestEAProjOM() { string className = "ProjectionCombineTest"; string testName = "TestEAProjOM"; string entityName_Email = "Email"; List <TypeAttributeParam> attributeParams_Email = new List <TypeAttributeParam>(); { attributeParams_Email.Add(new TypeAttributeParam("EmailID", "string", "identifiedBy")); attributeParams_Email.Add(new TypeAttributeParam("Address", "string", "hasA")); attributeParams_Email.Add(new TypeAttributeParam("IsPrimary", "boolean", "hasA")); } string entityName_Phone = "Phone"; List <TypeAttributeParam> attributeParams_Phone = new List <TypeAttributeParam>(); { attributeParams_Phone.Add(new TypeAttributeParam("PhoneID", "string", "identifiedBy")); attributeParams_Phone.Add(new TypeAttributeParam("Number", "string", "hasA")); attributeParams_Phone.Add(new TypeAttributeParam("IsPrimary", "boolean", "hasA")); } string entityName_Social = "Social"; List <TypeAttributeParam> attributeParams_Social = new List <TypeAttributeParam>(); { attributeParams_Social.Add(new TypeAttributeParam("SocialID", "string", "identifiedBy")); attributeParams_Social.Add(new TypeAttributeParam("Account", "string", "hasA")); attributeParams_Social.Add(new TypeAttributeParam("IsPrimary", "boolean", "hasA")); } string entityName_Customer = "Customer"; List <TypeAttributeParam> attributeParams_Customer = new List <TypeAttributeParam>(); { attributeParams_Customer.Add(new TypeAttributeParam("CustomerName", "string", "hasA")); } List <string> selectedAttributes = new List <string>() { "EmailID", "PhoneID", "SocialID" }; using (ProjectionOMTestUtil util = new ProjectionOMTestUtil(className, testName)) { CdmEntityDefinition entity_Email = util.CreateBasicEntity(entityName_Email, attributeParams_Email); util.ValidateBasicEntity(entity_Email, entityName_Email, attributeParams_Email); CdmEntityDefinition entity_Phone = util.CreateBasicEntity(entityName_Phone, attributeParams_Phone); util.ValidateBasicEntity(entity_Phone, entityName_Phone, attributeParams_Phone); CdmEntityDefinition entity_Social = util.CreateBasicEntity(entityName_Social, attributeParams_Social); util.ValidateBasicEntity(entity_Social, entityName_Social, attributeParams_Social); CdmEntityDefinition entity_Customer = util.CreateBasicEntity(entityName_Customer, attributeParams_Customer); util.ValidateBasicEntity(entity_Customer, entityName_Customer, attributeParams_Customer); CdmProjection projection_Customer = util.CreateProjection(entity_Customer.EntityName); CdmTypeAttributeDefinition typeAttribute_MergeInto = util.CreateTypeAttribute("MergeInto", "string", "hasA"); CdmOperationCombineAttributes operation_CombineAttributes = util.CreateOperationCombineAttributes(projection_Customer, selectedAttributes, typeAttribute_MergeInto); CdmEntityReference projectionEntityRef_Customer = util.CreateProjectionInlineEntityReference(projection_Customer); CdmEntityAttributeDefinition entityAttribute_ContactAt = util.CreateEntityAttribute("ContactAt", projectionEntityRef_Customer); entity_Customer.Attributes.Add(entityAttribute_ContactAt); foreach (List <string> resOpts in resOptsCombinations) { await util.GetAndValidateResolvedEntity(entity_Customer, resOpts); } await util.DefaultManifest.SaveAsAsync(util.ManifestDocName, saveReferenced : true); } }
public async Task TestConditionalProjUsingObjectModel() { string testName = "TestConditionalProjUsingObjectModel"; CdmCorpusDefinition corpus = ProjectionTestUtils.GetCorpus(testName, testsSubpath); 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 AddAttributeGroup operation CdmOperationAddAttributeGroup addAttGroupOp = corpus.MakeObject <CdmOperationAddAttributeGroup>(CdmObjectType.OperationAddAttributeGroupDef); addAttGroupOp.AttributeGroupName = "PersonAttributeGroup"; projection.Operations.Add(addAttGroupOp); // 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); // Verify correctness of the resolved attributes after running the AddAttributeGroup operation // 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); // Verify correctness of the resolved attributes after running the AddAttributeGroup operation // Original set of attributes: ["id", "name", "value", "date"] // Condition met, put all attributes in an attribute group CdmAttributeGroupDefinition attGroupDefinition = this.ValidateAttributeGroup(resolvedEntityWithStructured.Attributes, "PersonAttributeGroup"); Assert.AreEqual(4, attGroupDefinition.Members.Count); Assert.AreEqual("id", (attGroupDefinition.Members[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name", (attGroupDefinition.Members[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value", (attGroupDefinition.Members[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date", (attGroupDefinition.Members[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"); }
private async Task LogicalManipulationUsingProjections(CdmCorpusDefinition corpus) { Console.WriteLine("Create logical entity definition."); var logicalFolder = await corpus.FetchObjectAsync <CdmFolderDefinition>("output:/"); var logicalDoc = logicalFolder.Documents.Add("Person.cdm.json"); logicalDoc.Imports.Add("local:/Address.cdm.json"); var entity = logicalDoc.Definitions.Add("Person"); // Add "name" data typed attribute. var nameAttr = entity.Attributes.Add("name") as CdmTypeAttributeDefinition; nameAttr.DataType = new CdmDataTypeReference(corpus.Ctx, "string", true); // Add "age" data typed attribute. var ageAttr = entity.Attributes.Add("age") as CdmTypeAttributeDefinition; ageAttr.DataType = new CdmDataTypeReference(corpus.Ctx, "string", true); // Add "address" entity typed attribute. var entityAttr = new CdmEntityAttributeDefinition(corpus.Ctx, "address") { Entity = new CdmEntityReference(corpus.Ctx, "Address", true) }; ApplyArrayExpansion(entityAttr, 1, 3, "{m}{A}{o}", "countAttribute"); ApplyDefaultBehavior(entityAttr, "addressFK", "address"); entity.Attributes.Add(entityAttr); // Add "email" data typed attribute. var emailAttr = entity.Attributes.Add("email") as CdmTypeAttributeDefinition; emailAttr.DataType = new CdmDataTypeReference(corpus.Ctx, "string", true); // Save the logical definition of Person. await entity.InDocument.SaveAsAsync("Person.cdm.json"); Console.WriteLine("Get \"resolved\" folder where the resolved entities will be saved."); var resolvedFolder = await corpus.FetchObjectAsync <CdmFolderDefinition>("output:/"); var resOpt = new ResolveOptions(entity); // To get more information about directives and their meaning refer to // https://docs.microsoft.com/en-us/common-data-model/sdk/convert-logical-entities-resolved-entities#directives-guidance-and-the-resulting-resolved-shapes // We will start by resolving this entity with the "normalized" direcitve. // This directive will be used on this and the next two examples so we can analize the resolved entity // without the array expansion. Console.WriteLine("Resolving logical entity with normalized directive."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized" }); var resNormalizedEntity = await entity.CreateResolvedEntityAsync($"normalized_{entity.EntityName}", resOpt, resolvedFolder); await resNormalizedEntity.InDocument.SaveAsAsync($"{resNormalizedEntity.EntityName}.cdm.json"); // Another common scenario is to resolve an entity using the "referenceOnly" directive. // This directives is used to replace the relationships with a foreign key. Console.WriteLine("Resolving logical entity with referenceOnly directive."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "referenceOnly" }); var resReferenceOnlyEntity = await entity.CreateResolvedEntityAsync($"referenceOnly_{entity.EntityName}", resOpt, resolvedFolder); await resReferenceOnlyEntity.InDocument.SaveAsAsync($"{resReferenceOnlyEntity.EntityName}.cdm.json"); // When dealing with structured data, like Json or parquet, it sometimes necessary to represent the idea that // a property can hold a complex object. The shape of the complex object is defined by the source entity pointed by the // entity attribute and we use the "structured" directive to resolve the entity attribute as an attribute group. Console.WriteLine("Resolving logical entity with structured directive."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "structured" }); var resStructuredEntity = await entity.CreateResolvedEntityAsync($"structured_{entity.EntityName}", resOpt, resolvedFolder); await resStructuredEntity.InDocument.SaveAsAsync($"{resStructuredEntity.EntityName}.cdm.json"); // Now let us remove the "normalized" directive so the array expansion operation can run. Console.WriteLine("Resolving logical entity without directives (array expansion)."); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { }); var resArrayEntity = await entity.CreateResolvedEntityAsync($"array_expansion_{entity.EntityName}", resOpt, resolvedFolder); await resArrayEntity.InDocument.SaveAsAsync($"{resArrayEntity.EntityName}.cdm.json"); }