Beispiel #1
0
        public async Task TestResolvedAttributeLimit()
        {
            CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestResolvedAttributeLimit");

            CdmEntityDefinition mainEntity = await corpus.FetchObjectAsync <CdmEntityDefinition>("local:/mainEntity.cdm.json/mainEntity");

            ResolveOptions resOpt = new ResolveOptions {
                WrtDoc = mainEntity.InDocument, Directives = new AttributeResolutionDirectiveSet(new HashSet <string> {
                    "normalized", "referenceOnly"
                })
            };

            // if attribute limit is reached, entity should be null
            resOpt.ResolvedAttributeLimit = 4;
            var resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_zeroAtts", resOpt);

            Assert.IsNull(resEnt);

            // when the attribute limit is set to null, there should not be a limit on the possible number of attributes
            resOpt.ResolvedAttributeLimit = null;
            resOpt.Directives             = new AttributeResolutionDirectiveSet(new HashSet <string> {
                "normalized", "referenceOnly"
            });
            var ras = mainEntity.FetchResolvedAttributes(resOpt);

            resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_normalized_referenceOnly", resOpt);

            // there are 5 total attributes
            Assert.AreEqual(ras.ResolvedAttributeCount, 5);
            Assert.AreEqual(ras.Set.Count, 5);
            Assert.AreEqual(mainEntity.Attributes.Count, 3);
            // there are 2 attributes grouped in an entity attribute
            // and 2 attributes grouped in an attribute group
            Assert.AreEqual(((mainEntity.Attributes[2] as CdmAttributeGroupReference).ExplicitReference as CdmAttributeGroupDefinition).Members.Count, 2);

            // using the default limit number
            resOpt = new ResolveOptions {
                WrtDoc = mainEntity.InDocument, Directives = new AttributeResolutionDirectiveSet(new HashSet <string> {
                    "normalized", "referenceOnly"
                })
            };
            ras    = mainEntity.FetchResolvedAttributes(resOpt);
            resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_normalized_referenceOnly", resOpt);

            // there are 5 total attributes
            Assert.AreEqual(ras.ResolvedAttributeCount, 5);
            Assert.AreEqual(ras.Set.Count, 5);
            Assert.AreEqual(mainEntity.Attributes.Count, 3);
            // there are 2 attributes grouped in an entity attribute
            // and 2 attributes grouped in an attribute group
            Assert.AreEqual(((mainEntity.Attributes[2] as CdmAttributeGroupReference).ExplicitReference as CdmAttributeGroupDefinition).Members.Count, 2);

            resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> {
                "normalized", "structured"
            });
            ras    = mainEntity.FetchResolvedAttributes(resOpt);
            resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_normalized_structured", resOpt);

            // there are 5 total attributes
            Assert.AreEqual(ras.ResolvedAttributeCount, 5);
            // the attribute count is different because one attribute is a group that contains two different attributes
            Assert.AreEqual(ras.Set.Count, 4);
            Assert.AreEqual(mainEntity.Attributes.Count, 3);
            // again there are 2 attributes grouped in an entity attribute
            // and 2 attributes grouped in an attribute group
            Assert.AreEqual(((mainEntity.Attributes[2] as CdmAttributeGroupReference).ExplicitReference as CdmAttributeGroupDefinition).Members.Count, 2);
        }
Beispiel #2
0
        public static dynamic FetchReplacementValue(ResolveOptions resOpt, dynamic oldValue, dynamic newValue, bool wasSet)
        {
            if (oldValue == null)
            {
                return(newValue);
            }

            if (!wasSet)
            {
                // must explicitly set a value to override
                // if a new value is not set, then newValue holds nothing or the default.
                // in this case, if there was already a value in this argument then just keep using it.
                return(oldValue);
            }

            if (oldValue is string)
            {
                return(newValue);
            }
            CdmObject ov = oldValue as CdmObject;
            CdmObject nv = newValue as CdmObject;

            // replace an old table with a new table? actually just mash them together
            if (ov != null && ov.ObjectType == CdmObjectType.EntityRef &&
                nv != null && nv.GetType() != typeof(string) && nv.ObjectType == CdmObjectType.EntityRef)
            {
                var oldEnt = ov.FetchObjectDefinition <CdmConstantEntityDefinition>(resOpt);
                var newEnt = nv.FetchObjectDefinition <CdmConstantEntityDefinition>(resOpt);

                // check that the entities are the same shape
                if (newEnt == null)
                {
                    return(ov);
                }

                // BUG
                CdmEntityDefinition entDefShape = null;
                if (oldEnt == null || ((entDefShape = oldEnt.EntityShape.FetchObjectDefinition <CdmEntityDefinition>(resOpt)) != newEnt.EntityShape.FetchObjectDefinition <CdmEntityDefinition>(resOpt)))
                {
                    return(nv);
                }

                var oldCv = oldEnt.ConstantValues;
                var newCv = newEnt.ConstantValues;
                // rows in old?
                if (oldCv == null || oldCv.Count == 0)
                {
                    return(nv);
                }
                // rows in new?
                if (newCv == null || newCv.Count == 0)
                {
                    return(ov);
                }

                // make a set of rows in the old one and add the new ones. this will union the two
                // find rows in the new one that are not in the old one. slow, but these are small usually
                IDictionary <string, List <string> > unionedRows = new Dictionary <string, List <string> >();

                // see if any of the entity atts are the primary key, meaning, the only thing that causes us to merge dups unique.
                // i know this makes you think about a snake eating its own tail, but fetch the resolved attributes of the constant shape
                int pkAtt = -1;
                if (entDefShape != null)
                {
                    var resOptShape  = new ResolveOptions(entDefShape.InDocument);
                    var resAttsShape = entDefShape.FetchResolvedAttributes(resOptShape);
                    if (resAttsShape != null)
                    {
                        pkAtt = resAttsShape.Set.FindIndex((ra) => ra.ResolvedTraits.Find(resOptShape, "is.identifiedBy") != null);
                    }
                }

                for (int i = 0; i < oldCv.Count; i++)
                {
                    List <string> row = oldCv[i];
                    string        key;
                    // the entity might have a PK, if so, only look at that values as the key
                    if (pkAtt != -1)
                    {
                        key = row[pkAtt];
                    }
                    else
                    {
                        key = row.Aggregate((prev, curr) =>
                        {
                            return($"{(!string.IsNullOrEmpty(prev) ? prev : "")}::{curr}");
                        });
                    }
                    unionedRows[key] = row;
                }

                for (int i = 0; i < newCv.Count; i++)
                {
                    List <string> row = newCv[i];
                    string        key;
                    // the entity might have a PK, if so, only look at that values as the key
                    if (pkAtt != -1)
                    {
                        key = row[pkAtt];
                    }
                    else
                    {
                        key = row.Aggregate((prev, curr) =>
                        {
                            return($"{(!string.IsNullOrEmpty(prev) ? prev : "")}::{curr}");
                        });
                    }
                    unionedRows[key] = row;
                }

                if (unionedRows.Count == oldCv.Count)
                {
                    return(ov);
                }
                List <List <string> > allRows = unionedRows.Values.ToList();

                CdmConstantEntityDefinition replacementEnt = (CdmConstantEntityDefinition)oldEnt.Copy(resOpt);
                replacementEnt.ConstantValues = allRows;
                return(resOpt.WrtDoc.Ctx.Corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, replacementEnt, false));
            }

            return(newValue);
        }