public static CdmOperationArrayExpansion FromData(CdmCorpusContext ctx, JToken obj) { if (obj == null) { return(null); } CdmOperationArrayExpansion arrayExpansionOp = ctx.Corpus.MakeObject <CdmOperationArrayExpansion>(CdmObjectType.OperationArrayExpansionDef); if (obj["$type"] != null && !StringUtils.EqualsWithIgnoreCase(obj["$type"].ToString(), OperationTypeConvertor.OperationTypeToString(CdmOperationType.ArrayExpansion))) { Logger.Error(nameof(OperationArrayExpansionPersistence), ctx, $"$type {(string)obj["$type"]} is invalid for this operation."); } else { arrayExpansionOp.Type = CdmOperationType.ArrayExpansion; } if (obj["explanation"] != null) { arrayExpansionOp.Explanation = (string)obj["explanation"]; } arrayExpansionOp.StartOrdinal = (int?)obj["startOrdinal"]; arrayExpansionOp.EndOrdinal = (int?)obj["endOrdinal"]; return(arrayExpansionOp); }
public async Task TestEntityProjUsingObjectModel() { CdmCorpusDefinition corpus = ProjectionTestUtils.GetLocalCorpus(testsSubpath, "TestEntityProjUsingObjectModel"); corpus.Storage.Mount("local", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestEntityProjUsingObjectModel"))); 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; // Set the entity's ExtendEntity to be the projection entity.ExtendsEntity = projectionEntityRef2; // 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); }
/// <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 OperationArrayExpansion ToData(CdmOperationArrayExpansion instance, ResolveOptions resOpt, CopyOptions options) { if (instance == null) { return(null); } OperationArrayExpansion obj = OperationBasePersistence.ToData <OperationArrayExpansion>(instance, resOpt, options); obj.StartOrdinal = instance.StartOrdinal; obj.EndOrdinal = instance.EndOrdinal; return(obj); }
public static CdmOperationArrayExpansion FromData(CdmCorpusContext ctx, JToken obj) { if (obj == null) { return(null); } CdmOperationArrayExpansion arrayExpansionOp = OperationBasePersistence.FromData <CdmOperationArrayExpansion>(ctx, CdmObjectType.OperationArrayExpansionDef, obj); arrayExpansionOp.StartOrdinal = (int?)obj["startOrdinal"]; arrayExpansionOp.EndOrdinal = (int?)obj["endOrdinal"]; return(arrayExpansionOp); }
/// <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 OperationArrayExpansion ToData(CdmOperationArrayExpansion instance, ResolveOptions resOpt, CopyOptions options) { if (instance == null) { return(null); } return(new OperationArrayExpansion { Type = OperationTypeConvertor.OperationTypeToString(CdmOperationType.ArrayExpansion), Explanation = instance.Explanation, StartOrdinal = instance.StartOrdinal, EndOrdinal = instance.EndOrdinal }); }
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 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); // 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 projections // Original set of attributes: ["id", "name", "value", "date"] // Expand 1...2, renameFormat = {m}{o} Assert.AreEqual(8, resolvedEntityWithReferenceOnly.Attributes.Count); Assert.AreEqual("id1", (resolvedEntityWithReferenceOnly.Attributes[0] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name1", (resolvedEntityWithReferenceOnly.Attributes[1] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value1", (resolvedEntityWithReferenceOnly.Attributes[2] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date1", (resolvedEntityWithReferenceOnly.Attributes[3] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("id2", (resolvedEntityWithReferenceOnly.Attributes[4] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("name2", (resolvedEntityWithReferenceOnly.Attributes[5] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("value2", (resolvedEntityWithReferenceOnly.Attributes[6] as CdmTypeAttributeDefinition).Name); Assert.AreEqual("date2", (resolvedEntityWithReferenceOnly.Attributes[7] as CdmTypeAttributeDefinition).Name); // Now resolve the entity with the default directives resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { }); CdmEntityDefinition resolvedEntityWithStructured = await entity.CreateResolvedEntityAsync($"Resolved_{entity.EntityName}.cdm.json", resOpt, 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(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 static CdmProjection FromData(CdmCorpusContext ctx, JToken obj) { if (obj == null) { return(null); } CdmProjection projection = ctx.Corpus.MakeObject <CdmProjection>(CdmObjectType.ProjectionDef); CdmEntityReference source = EntityReferencePersistence.FromData(ctx, obj["source"]); if (obj["explanation"] != null) { projection.Explanation = (string)obj["explanation"]; } projection.Condition = obj["condition"]?.ToString(); projection.RunSequentially = (bool?)obj["runSequentially"]; if (obj["operations"] != null) { List <JObject> operationJsons = obj["operations"]?.ToObject <List <JObject> >(); foreach (JObject operationJson in operationJsons) { string type = (string)operationJson["$type"]; switch (type) { case "addCountAttribute": CdmOperationAddCountAttribute addCountAttributeOp = OperationAddCountAttributePersistence.FromData(ctx, operationJson); projection.Operations.Add(addCountAttributeOp); break; case "addSupportingAttribute": CdmOperationAddSupportingAttribute addSupportingAttributeOp = OperationAddSupportingAttributePersistence.FromData(ctx, operationJson); projection.Operations.Add(addSupportingAttributeOp); break; case "addTypeAttribute": CdmOperationAddTypeAttribute addTypeAttributeOp = OperationAddTypeAttributePersistence.FromData(ctx, operationJson); projection.Operations.Add(addTypeAttributeOp); break; case "excludeAttributes": CdmOperationExcludeAttributes excludeAttributesOp = OperationExcludeAttributesPersistence.FromData(ctx, operationJson); projection.Operations.Add(excludeAttributesOp); break; case "arrayExpansion": CdmOperationArrayExpansion arrayExpansionOp = OperationArrayExpansionPersistence.FromData(ctx, operationJson); projection.Operations.Add(arrayExpansionOp); break; case "combineAttributes": CdmOperationCombineAttributes combineAttributesOp = OperationCombineAttributesPersistence.FromData(ctx, operationJson); projection.Operations.Add(combineAttributesOp); break; case "renameAttributes": CdmOperationRenameAttributes renameAttributesOp = OperationRenameAttributesPersistence.FromData(ctx, operationJson); projection.Operations.Add(renameAttributesOp); break; case "replaceAsForeignKey": CdmOperationReplaceAsForeignKey replaceAsForeignKeyOp = OperationReplaceAsForeignKeyPersistence.FromData(ctx, operationJson); projection.Operations.Add(replaceAsForeignKeyOp); break; case "includeAttributes": CdmOperationIncludeAttributes includeAttributesOp = OperationIncludeAttributesPersistence.FromData(ctx, operationJson); projection.Operations.Add(includeAttributesOp); break; case "addAttributeGroup": CdmOperationAddAttributeGroup addAttributeGroupOp = OperationAddAttributeGroupPersistence.FromData(ctx, operationJson); projection.Operations.Add(addAttributeGroupOp); break; default: Logger.Error(nameof(ProjectionPersistence), ctx, $"Invalid operation type '{type}'.", nameof(FromData)); break; } } } projection.Source = source; return(projection); }
/// <summary> /// Create a projection object with operations /// </summary> /// <param name="corpus"></param> /// <returns></returns> private CdmProjection CreateProjectionWithOperationCollection(CdmCorpusDefinition corpus, CdmObject owner) { CdmProjection projection = corpus.MakeObject <CdmProjection>(CdmObjectType.ProjectionDef); { projection.Source = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, "TestSource", simpleNameRef: true); } { // AddCountAttribute Operation CdmOperationAddCountAttribute addCountAttributeOp = new CdmOperationAddCountAttribute(corpus.Ctx) { CountAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef) }; projection.Operations.Add(addCountAttributeOp); // AddSupportingAttribute Operation CdmOperationAddSupportingAttribute addSupportingAttributesOp = new CdmOperationAddSupportingAttribute(corpus.Ctx) { SupportingAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef) }; projection.Operations.Add(addSupportingAttributesOp); // AddTypeAttribute Operation CdmOperationAddTypeAttribute addTypeAttributeOp = new CdmOperationAddTypeAttribute(corpus.Ctx) { TypeAttribute = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef) }; projection.Operations.Add(addTypeAttributeOp); // ExcludeAttributes Operation CdmOperationExcludeAttributes excludeAttributesOp = new CdmOperationExcludeAttributes(corpus.Ctx) { ExcludeAttributes = new List <string>() }; excludeAttributesOp.ExcludeAttributes.Add("testAttribute1"); projection.Operations.Add(excludeAttributesOp); // ArrayExpansion Operation CdmOperationArrayExpansion arrayExpansionOp = new CdmOperationArrayExpansion(corpus.Ctx) { StartOrdinal = 0, EndOrdinal = 1 }; projection.Operations.Add(arrayExpansionOp); // CombineAttributes Operation CdmOperationCombineAttributes combineAttributesOp = new CdmOperationCombineAttributes(corpus.Ctx) { Take = new List <string>(), MergeInto = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef) }; combineAttributesOp.Take.Add("testAttribute1"); projection.Operations.Add(combineAttributesOp); // RenameAttributes Operation CdmOperationRenameAttributes renameAttributesOp = new CdmOperationRenameAttributes(corpus.Ctx) { RenameFormat = "{m}" }; projection.Operations.Add(renameAttributesOp); // ReplaceAsForeignKey Operation CdmOperationReplaceAsForeignKey replaceAsForeignKeyOp = new CdmOperationReplaceAsForeignKey(corpus.Ctx) { Reference = "testAttribute1", ReplaceWith = corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "testForeignKey", simpleNameRef: false) }; projection.Operations.Add(replaceAsForeignKeyOp); // IncludeAttributes Operation CdmOperationIncludeAttributes includeAttributesOp = new CdmOperationIncludeAttributes(corpus.Ctx) { IncludeAttributes = new List <string>() }; includeAttributesOp.IncludeAttributes.Add("testAttribute1"); projection.Operations.Add(includeAttributesOp); } return(projection); }