Example #1
0
        public async Task TestEntityProjUsingObjectModel()
        {
            string testName               = "TestEntityProjUsingObjectModel";
            CdmCorpusDefinition corpus    = ProjectionTestUtils.GetLocalCorpus(testsSubpath, testName);
            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;

            // Set the entity's ExtendEntity to be the projection
            entity.ExtendsEntity = projectionEntityRef;

            // 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);
        }
Example #2
0
        public async Task TestEntityProjUsingObjectModel()
        {
            CdmCorpusDefinition corpus = TestHelper.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 ExcludeAttributes operation
            CdmOperationExcludeAttributes excludeAttrsOp = corpus.MakeObject <CdmOperationExcludeAttributes>(CdmObjectType.OperationExcludeAttributesDef);

            excludeAttrsOp.ExcludeAttributes.Add("name");
            excludeAttrsOp.ExcludeAttributes.Add("value");
            projection.Operations.Add(excludeAttrsOp);

            // Create an entity reference to hold this projection
            CdmEntityReference projectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null);

            projectionEntityRef.ExplicitReference = projection;

            // Set the entity's ExtendEntity to be the projection
            entity.ExtendsEntity = projectionEntityRef;

            // 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 operation
            // Original set of attributes: ["id", "name", "value", "date"]
            // Excluded attributes: ["name", "value"]
            Assert.AreEqual(2, resolvedEntity.Attributes.Count);
            Assert.AreEqual("id", (resolvedEntity.Attributes[0] as CdmTypeAttributeDefinition).Name);
            Assert.AreEqual("date", (resolvedEntity.Attributes[1] as CdmTypeAttributeDefinition).Name);
        }
Example #3
0
        public void TestCdmCollectionChangeMakesDocumentDirty()
        {
            var manifest   = CdmCollectionHelperFunctions.GenerateManifest();
            var collection = new CdmCollection <CdmEntityReference>(manifest.Ctx, manifest, Enums.CdmObjectType.EntityRef);

            manifest.IsDirty = false;
            collection.Add(new CdmEntityReference(manifest.Ctx, "name", false));
            Assert.IsTrue(manifest.IsDirty);
            manifest.IsDirty = false;
            collection.Add("theName");
            Assert.IsTrue(manifest.IsDirty);
            var entity     = new CdmEntityReference(manifest.Ctx, "otherEntity", false);
            var entityList = new List <CdmEntityReference>()
            {
                entity
            };

            manifest.IsDirty = false;
            collection.AddRange(entityList);
            Assert.IsTrue(manifest.IsDirty);
            manifest.IsDirty = false;
            var entity2 = new CdmEntityReference(manifest.Ctx, "otherEntity2", false);

            collection.Insert(0, entity2);
            Assert.IsTrue(manifest.IsDirty);

            manifest.IsDirty = false;
            collection.Remove(entity);
            Assert.IsTrue(manifest.IsDirty);

            manifest.IsDirty = false;
            collection.RemoveAt(0);
            Assert.IsTrue(manifest.IsDirty);

            manifest.IsDirty = false;
            collection.Clear();
            Assert.IsTrue(manifest.IsDirty);
        }
Example #4
0
        /// <summary>
        /// Create an entity 'TestEntityNestedProjection' that extends from a projection
        /// </summary>
        /// <param name="corpus"></param>
        /// <param name="manifestDefault"></param>
        /// <param name="localRoot"></param>
        /// <returns></returns>
        private CdmEntityDefinition CreateEntityTestEntityNestedProjection(CdmCorpusDefinition corpus, CdmManifestDefinition manifestDefault, CdmFolderDefinition localRoot)
        {
            string entityName = "TestEntityNestedProjection";

            CdmEntityReference inlineProjectionEntityRef = corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null);

            inlineProjectionEntityRef.ExplicitReference = CreateNestedProjection(corpus);


            CdmEntityDefinition entityTestEntityNestedProjection = corpus.MakeObject <CdmEntityDefinition>(CdmObjectType.EntityDef, entityName);

            entityTestEntityNestedProjection.ExtendsEntity = inlineProjectionEntityRef;

            CdmDocumentDefinition entityTestEntityNestedProjectionDoc = corpus.MakeObject <CdmDocumentDefinition>(CdmObjectType.DocumentDef, $"{entityName}.cdm.json", false);

            entityTestEntityNestedProjectionDoc.Imports.Add(FoundationJsonPath);
            entityTestEntityNestedProjectionDoc.Imports.Add("TestSource.cdm.json");
            entityTestEntityNestedProjectionDoc.Definitions.Add(entityTestEntityNestedProjection);

            localRoot.Documents.Add(entityTestEntityNestedProjectionDoc, entityTestEntityNestedProjectionDoc.Name);
            manifestDefault.Entities.Add(entityTestEntityNestedProjection);

            return(entityTestEntityNestedProjection);
        }
        /// <summary>
        /// Create a relationship linking by creating an entity attribute definition instance with a trait.
        /// This allows you to add a resolution guidance to customize your data.
        /// </summary>
        /// <param name="cdmCorpus"> The CDM corpus. </param>
        /// <param name="associatedEntityName"> The name of the associated entity. </param>
        /// <param name="foreignKeyName"> The name of the foreign key. </param>
        /// <param name="attributeExplanation"> The explanation of the attribute.</param>
        /// <returns> The instatnce of entity attribute definition. </returns>
        private static CdmEntityAttributeDefinition CreateEntityAttributeForRelationshipBetweenTwoEntities(
            CdmCorpusDefinition cdmCorpus,
            string associatedEntityName,
            string foreignKeyName,
            string attributeExplanation)
        {
            // Define a relationship by creating an entity attribute
            var entityAttributeDef = cdmCorpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, foreignKeyName);

            entityAttributeDef.Explanation = attributeExplanation;
            // Creating an entity reference for the associated entity
            CdmEntityReference associatedEntityRef = cdmCorpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, associatedEntityName, false);

            // Creating a "is.identifiedBy" trait for entity reference
            CdmTraitReference traitReference = cdmCorpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, "is.identifiedBy", false);

            traitReference.Arguments.Add(null, $"{associatedEntityName}/(resolvedAttributes)/{associatedEntityName}Id");

            // Add the trait to the attribute's entity reference
            associatedEntityRef.AppliedTraits.Add(traitReference);
            entityAttributeDef.Entity  = associatedEntityRef;
            entityAttributeDef.Purpose = CreateRelationshipMeanings(cdmCorpus, "Non-simple resolution guidance sample");

            // Add resolution guidance
            var attributeResolution = cdmCorpus.MakeObject <CdmAttributeResolutionGuidance>(CdmObjectType.AttributeResolutionGuidanceDef);

            attributeResolution.entityByReference = attributeResolution.makeEntityByReference();
            attributeResolution.entityByReference.allowReference = true;
            attributeResolution.renameFormat = "{m}";
            var entityAttribute = CreateTypeAttributeWithPurposeAndDataType(cdmCorpus, $"{foreignKeyName}Id", "identifiedBy", "entityId");

            attributeResolution.entityByReference.foreignKeyAttribute = entityAttribute as CdmTypeAttributeDefinition;
            entityAttributeDef.ResolutionGuidance = attributeResolution;

            return(entityAttributeDef);
        }
Example #6
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);
        }
 public static dynamic ToData(CdmEntityReference instance, ResolveOptions resOpt, CopyOptions options)
 {
     return(CdmObjectRefPersistence.ToData(instance, resOpt, options));
 }
        public static CdmEntityAttributeDefinition FromData(CdmCorpusContext ctx, JToken obj)
        {
            var entityAttribute = ctx.Corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, (string)obj["name"]);

            entityAttribute.Description = Utils.PropertyFromDataToString(obj["description"]);
            entityAttribute.DisplayName = Utils.PropertyFromDataToString(obj["displayName"]);
            entityAttribute.Explanation = Utils.PropertyFromDataToString(obj["explanation"]);

            if (obj["cardinality"] != null)
            {
                string minCardinality = null;
                if (obj["cardinality"]["minimum"] != null)
                {
                    minCardinality = (string)obj["cardinality"]["minimum"];
                }

                string maxCardinality = null;
                if (obj["cardinality"]["maximum"] != null)
                {
                    maxCardinality = (string)obj["cardinality"]["maximum"];
                }

                if (string.IsNullOrWhiteSpace(minCardinality) || string.IsNullOrWhiteSpace(maxCardinality))
                {
                    Logger.Error((ResolveContext)ctx, Tag, nameof(FromData), null, CdmLogCode.ErrPersistCardinalityPropMissing);
                }

                if (!CardinalitySettings.IsMinimumValid(minCardinality))
                {
                    Logger.Error((ResolveContext)ctx, Tag, nameof(FromData), null, CdmLogCode.ErrPersistInvalidMinCardinality, minCardinality);
                }

                if (!CardinalitySettings.IsMaximumValid(maxCardinality))
                {
                    Logger.Error((ResolveContext)ctx, Tag, nameof(FromData), null, CdmLogCode.ErrPersistInvalidMaxCardinality, maxCardinality);
                }

                if (!string.IsNullOrWhiteSpace(minCardinality) &&
                    !string.IsNullOrWhiteSpace(maxCardinality) &&
                    CardinalitySettings.IsMinimumValid(minCardinality) &&
                    CardinalitySettings.IsMinimumValid(maxCardinality))
                {
                    entityAttribute.Cardinality = new CardinalitySettings(entityAttribute)
                    {
                        Minimum = minCardinality,
                        Maximum = maxCardinality
                    };
                }
            }

            entityAttribute.IsPolymorphicSource = (bool?)obj["isPolymorphicSource"];

            bool isProjection = obj["entity"] != null &&
                                !(obj["entity"] is JValue) &&
                                obj["entity"]["source"] != null;

            if (isProjection)
            {
                CdmEntityReference inlineEntityRef = ctx.Corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null);
                inlineEntityRef.ExplicitReference = ProjectionPersistence.FromData(ctx, obj["entity"]);
                entityAttribute.Entity            = inlineEntityRef;
            }
            else
            {
                entityAttribute.Entity = EntityReferencePersistence.FromData(ctx, obj["entity"]);
            }

            entityAttribute.Purpose = PurposeReferencePersistence.FromData(ctx, obj["purpose"]);
            Utils.AddListToCdmCollection(entityAttribute.AppliedTraits, Utils.CreateTraitReferenceList(ctx, obj["appliedTraits"]));
            // ignore resolution guidance if the entity is a projection
            if (obj["resolutionGuidance"] != null && isProjection)
            {
                Logger.Error((ResolveContext)ctx, Tag, nameof(FromData), null, CdmLogCode.ErrPersistEntityAttrUnsupported, entityAttribute.Name);
            }
            else
            {
                entityAttribute.ResolutionGuidance = AttributeResolutionGuidancePersistence.FromData(ctx, obj["resolutionGuidance"]);
            }
            return(entityAttribute);
        }
Example #9
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);
        }
Example #11
0
        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);
        }
Example #12
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");
        }
Example #13
0
        public string FetchValueString(ResolveOptions resOpt)
        {
            if (this.Value == null)
            {
                return("");
            }

            if (this.Value is string || this.Value is JValue)
            {
                return((string)this.Value);
            }
            if (Value is CdmObject value)
            {
                CdmObjectDefinition def = value.FetchObjectDefinition <CdmObjectDefinition>(resOpt);
                if (value.ObjectType == CdmObjectType.EntityRef && def?.ObjectType == CdmObjectType.ConstantEntityDef)
                {
                    CdmEntityReference    entShape  = (def as CdmConstantEntityDefinition).EntityShape;
                    List <List <string> > entValues = (def as CdmConstantEntityDefinition).ConstantValues;
                    if (entValues == null || entValues?.Count == 0)
                    {
                        return("");
                    }
                    List <IDictionary <string, string> > rows = new List <IDictionary <string, string> >();
                    ResolvedAttributeSet shapeAtts            = entShape.FetchResolvedAttributes(resOpt);
                    if (shapeAtts != null && shapeAtts.Set != null && shapeAtts.Set.Count > 0)
                    {
                        for (int r = 0; r < entValues.Count; r++)
                        {
                            List <string> rowData            = entValues[r];
                            IDictionary <string, string> row = new SortedDictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                            if (rowData?.Count > 0)
                            {
                                for (int c = 0; c < rowData.Count; c++)
                                {
                                    string            tvalue = rowData[c];
                                    ResolvedAttribute colAtt = shapeAtts.Set[c];
                                    if (colAtt != null)
                                    {
                                        row.Add(colAtt.ResolvedName, tvalue);
                                    }
                                }
                                rows.Add(row);
                            }
                        }
                    }
                    return(JsonConvert.SerializeObject(rows, Formatting.None, new JsonSerializerSettings {
                        NullValueHandling = NullValueHandling.Ignore, ContractResolver = new CamelCasePropertyNamesContractResolver()
                    }));
                }
                dynamic data = value.CopyData(resOpt, new CopyOptions {
                    StringRefs = false
                });
                if (data is string)
                {
                    return((string)data);
                }

                return(JsonConvert.SerializeObject(data, Formatting.None, new JsonSerializerSettings {
                    NullValueHandling = NullValueHandling.Ignore, ContractResolver = new CamelCasePropertyNamesContractResolver()
                }));
            }
            return("");
        }
Example #14
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 = new List <string>()
            {
                "id", "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 = new List <string>()
            {
                "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);
        }
Example #15
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);
        }
        public static CdmEntityAttributeDefinition FromData(CdmCorpusContext ctx, JToken obj)
        {
            var entityAttribute = ctx.Corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, (string)obj["name"]);

            entityAttribute.Description = Utils.PropertyFromDataToString(obj["description"]);
            entityAttribute.DisplayName = Utils.PropertyFromDataToString(obj["displayName"]);
            entityAttribute.Explanation = Utils.PropertyFromDataToString(obj["explanation"]);

            if (obj["cardinality"] != null)
            {
                string minCardinality = null;
                if (obj["cardinality"]["minimum"] != null)
                {
                    minCardinality = (string)obj["cardinality"]["minimum"];
                }

                string maxCardinality = null;
                if (obj["cardinality"]["maximum"] != null)
                {
                    maxCardinality = (string)obj["cardinality"]["maximum"];
                }

                if (string.IsNullOrWhiteSpace(minCardinality) || string.IsNullOrWhiteSpace(maxCardinality))
                {
                    Logger.Error(nameof(EntityAttributePersistence), ctx, $"Both minimum and maximum are required for the Cardinality property.", nameof(FromData));
                }

                if (!CardinalitySettings.IsMinimumValid(minCardinality))
                {
                    Logger.Error(nameof(EntityAttributePersistence), ctx, $"Invalid minimum cardinality {minCardinality}.", nameof(FromData));
                }

                if (!CardinalitySettings.IsMaximumValid(maxCardinality))
                {
                    Logger.Error(nameof(EntityAttributePersistence), ctx, $"Invalid maximum cardinality {maxCardinality}.", nameof(FromData));
                }

                if (!string.IsNullOrWhiteSpace(minCardinality) &&
                    !string.IsNullOrWhiteSpace(maxCardinality) &&
                    CardinalitySettings.IsMinimumValid(minCardinality) &&
                    CardinalitySettings.IsMinimumValid(maxCardinality))
                {
                    entityAttribute.Cardinality = new CardinalitySettings(entityAttribute)
                    {
                        Minimum = minCardinality,
                        Maximum = maxCardinality
                    };
                }
            }

            entityAttribute.IsPolymorphicSource = (bool?)obj["isPolymorphicSource"];

            bool isProjection = obj["entity"] != null &&
                                !(obj["entity"] is JValue) &&
                                obj["entity"]["source"] != null;

            if (isProjection)
            {
                CdmProjection projection = ProjectionPersistence.FromData(ctx, obj["entity"]);
                projection.Owner = entityAttribute;

                CdmEntityReference inlineEntityRef = ctx.Corpus.MakeObject <CdmEntityReference>(CdmObjectType.EntityRef, null);
                inlineEntityRef.ExplicitReference = projection;
                entityAttribute.Entity            = inlineEntityRef;
            }
            else
            {
                entityAttribute.Entity = EntityReferencePersistence.FromData(ctx, obj["entity"]);
            }

            entityAttribute.Purpose = PurposeReferencePersistence.FromData(ctx, obj["purpose"]);
            Utils.AddListToCdmCollection(entityAttribute.AppliedTraits, Utils.CreateTraitReferenceList(ctx, obj["appliedTraits"]));
            // ignore resolution guidance if the entity is a projection
            if (obj["resolutionGuidance"] != null && isProjection)
            {
                Logger.Error(nameof(EntityAttributePersistence), ctx, $"The EntityAttribute {entityAttribute.Name} is projection based. Resolution guidance is not supported with a projection.");
            }
            else
            {
                entityAttribute.ResolutionGuidance = AttributeResolutionGuidancePersistence.FromData(ctx, obj["resolutionGuidance"]);
            }
            return(entityAttribute);
        }
Example #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);
        }