예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        /// <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);
            }
        }
예제 #5
0
 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)
     });
 }
예제 #6
0
        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);
            }
        }
예제 #8
0
 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);
            }
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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));
            }
        }
예제 #17
0
        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);
        }
예제 #19
0
        static async Task Main(string[] args)
        {
            // Make a corpus, the corpus is the collection of all documents and folders created or discovered while navigating objects and paths
            var 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");
        }
예제 #20
0
        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);
        }
예제 #21
0
        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);
        }
예제 #23
0
        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");
        }