Example #1
0
        public ResolvedAttributeSet Copy()
        {
            ResolvedAttributeSet copy = new ResolvedAttributeSet();

            copy.AttributeContext = this.AttributeContext;
            int l = this.Set.Count;

            for (int i = 0; i < l; i++)
            {
                ResolvedAttribute sourceRa = this.Set[i];
                ResolvedAttribute copyRa   = sourceRa.Copy();
                copy.Merge(copyRa);
            }

            // copy the ownership map. new map will point at old att lists, but we never update these lists, only make new ones, so all is well
            if (this.AttributeOwnershipMap != null)
            {
                copy.AttributeOwnershipMap = new Dictionary <string, HashSet <string> >(this.AttributeOwnershipMap);
            }
            copy.DepthTraveled = this.DepthTraveled;

            return(copy);
        }
Example #2
0
        public ResolvedAttribute Copy()
        {
            ResolveOptions    resOpt = this.ResolvedTraits.ResOpt; // use the options from the traits
            ResolvedAttribute copy   = new ResolvedAttribute(resOpt, this.Target, this._resolvedName, this.AttCtx)
            {
                ResolvedName           = this.ResolvedName,
                ResolvedAttributeCount = this.ResolvedAttributeCount,
                ResolvedTraits         = this.ResolvedTraits.ShallowCopy(),
                InsertOrder            = this.InsertOrder,
                Arc = this.Arc
            };

            if (copy.Target is ResolvedAttributeSet)
            {
                // deep copy when set contains sets. this copies the resolved att set and the context, etc.
                copy.Target = copy.Target.Copy();
            }

            if (ApplierState != null)
            {
                copy.ApplierState = ApplierState.Copy();
            }
            return(copy);
        }
Example #3
0
        internal ResolvedAttributeSet Merge(ResolvedAttribute toMerge, CdmAttributeContext attCtx = null)
        {
            ResolvedAttributeSet rasResult = this;

            if (toMerge != null)
            {
                // if there is already a resolve attribute present, remove it before adding the new attribute
                if (rasResult.ResolvedName2resolvedAttribute.ContainsKey(toMerge.ResolvedName))
                {
                    ResolvedAttribute existing = rasResult.ResolvedName2resolvedAttribute[toMerge.ResolvedName];
                    if (this.RefCnt > 1 && existing.Target != toMerge.Target)
                    {
                        rasResult = rasResult.Copy(); // copy on write
                        existing  = rasResult.ResolvedName2resolvedAttribute[toMerge.ResolvedName];
                    }
                    else
                    {
                        rasResult = this;
                    }

                    if (existing.Target is CdmAttribute)
                    {
                        rasResult.ResolvedAttributeCount -= existing.Target.AttributeCount;
                    }
                    else if (existing.Target is ResolvedAttributeSet)
                    {
                        rasResult.ResolvedAttributeCount -= existing.Target.ResolvedAttributeCount;
                    }

                    if (toMerge.Target is CdmAttribute)
                    {
                        rasResult.ResolvedAttributeCount += toMerge.Target.AttributeCount;
                    }
                    else if (toMerge.Target is ResolvedAttributeSet)
                    {
                        rasResult.ResolvedAttributeCount += toMerge.Target.ResolvedAttributeCount;
                    }

                    existing.Target = toMerge.Target; // replace with newest version
                    existing.Arc    = toMerge.Arc;

                    // remove old context mappings with mappings to new attribute
                    rasResult.RemoveCachedAttributeContext(existing.AttCtx);

                    ResolvedTraitSet rtsMerge = existing.ResolvedTraits.MergeSet(toMerge.ResolvedTraits); // newest one may replace
                    if (rtsMerge != existing.ResolvedTraits)
                    {
                        rasResult = rasResult.Copy(); // copy on write
                        existing  = rasResult.ResolvedName2resolvedAttribute[toMerge.ResolvedName];
                        existing.ResolvedTraits = rtsMerge;
                    }
                }
                else
                {
                    if (this.RefCnt > 1)
                    {
                        rasResult = rasResult.Copy(); // copy on write
                    }
                    if (rasResult == null)
                    {
                        rasResult = this;
                    }
                    rasResult.ResolvedName2resolvedAttribute.Add(toMerge.ResolvedName, toMerge);
                    // don't use the attCtx on the actual attribute, that's only for doing appliers
                    if (attCtx != null)
                    {
                        rasResult.CacheAttributeContext(attCtx, toMerge);
                    }
                    //toMerge.InsertOrder = rasResult.Set.Count;
                    rasResult.Set.Add(toMerge);
                    rasResult.ResolvedAttributeCount += toMerge.ResolvedAttributeCount;
                }
                this.BaseTrait2Attributes = null;
            }
            return(rasResult);
        }
Example #4
0
        public ResolvedAttributeSet RemoveRequestedAtts(Marker marker)
        {
            int countIndex = marker.CountIndex;
            int markIndex  = marker.MarkIndex;

            // for every attribute in the set run any attribute removers on the traits they have
            ResolvedAttributeSet appliedAttSet = new ResolvedAttributeSet();
            int l = this.Set.Count;

            for (int iAtt = 0; iAtt < l; iAtt++)
            {
                ResolvedAttribute resAtt = this.Set[iAtt];
                // possible for another set to be in this set
                ResolvedAttributeSet subSet = resAtt.Target as ResolvedAttributeSet;
                if (subSet?.Set != null)
                {
                    // well, that happened. so now we go around again on this same function and get rid of things from this group
                    marker.CountIndex = countIndex;
                    marker.MarkIndex  = markIndex;
                    ResolvedAttributeSet newSubSet = subSet.RemoveRequestedAtts(marker);
                    countIndex = marker.CountIndex;
                    markIndex  = marker.MarkIndex;
                    // replace the set with the new one that came back
                    resAtt.Target = newSubSet;
                    // if everything went away, then remove this group
                    if (newSubSet?.Set == null || newSubSet.Set.Count == 0)
                    {
                        resAtt = null;
                    }
                    else
                    {
                        // don't count this as an attribute (later)
                        countIndex--;
                    }
                }
                else
                {
                    // this is a good time to make the resolved names final
                    resAtt.previousResolvedName = resAtt.ResolvedName;
                    if (resAtt.Arc != null && resAtt.Arc.ApplierCaps != null && resAtt.Arc.ApplierCaps.CanRemove)
                    {
                        foreach (AttributeResolutionApplier apl in resAtt.Arc.ActionsRemove)
                        {
                            // this should look like the applier context when the att was created
                            ApplierContext ctx = new ApplierContext()
                            {
                                ResOpt = resAtt.Arc.ResOpt, ResAttSource = resAtt, ResGuide = resAtt.Arc.ResGuide
                            };
                            if (apl.WillRemove(ctx))
                            {
                                resAtt = null;
                                break;
                            }
                        }
                    }
                }
                if (resAtt != null)
                {
                    // attribute remains
                    // are we building a new set?
                    if (appliedAttSet != null)
                    {
                        this.CopyAttCtxMappingsInto(appliedAttSet.Ra2attCtxSet, appliedAttSet.AttCtx2ra, resAtt);
                        appliedAttSet.Merge(resAtt);
                    }
                    countIndex++;
                }
                else
                {
                    // remove the att
                    // if this is the first removed attribute, then make a copy of the set now
                    // after this point, the rest of the loop logic keeps the copy going as needed
                    if (appliedAttSet == null)
                    {
                        appliedAttSet = new ResolvedAttributeSet();
                        for (int iCopy = 0; iCopy < iAtt; iCopy++)
                        {
                            this.CopyAttCtxMappingsInto(appliedAttSet.Ra2attCtxSet, appliedAttSet.AttCtx2ra, this.Set[iCopy]);
                            appliedAttSet.Merge(this.Set[iCopy]);
                        }
                    }
                    // track deletes under the mark (move the mark up)
                    if (countIndex < markIndex)
                    {
                        markIndex--;
                    }
                }
            }

            marker.CountIndex = countIndex;
            marker.MarkIndex  = markIndex;

            // now we are that (or a copy)
            ResolvedAttributeSet rasResult = this;

            if (appliedAttSet != null && appliedAttSet.Size != rasResult.Size)
            {
                rasResult = appliedAttSet;
                rasResult.BaseTrait2Attributes = null;
                rasResult.AttributeContext     = this.AttributeContext;
            }

            return(rasResult);
        }
Example #5
0
        ResolvedAttributeSet Apply(ResolvedTraitSet traits, ResolveOptions resOpt, CdmAttributeResolutionGuidance resGuide, List <AttributeResolutionApplier> actions)
        {
            if (traits == null && actions.Count == 0)
            {
                // nothing can change
                return(this);
            }

            // for every attribute in the set run any attribute appliers
            ResolvedAttributeSet appliedAttSet = new ResolvedAttributeSet();
            int l = this.Set.Count;

            appliedAttSet.AttributeContext = this.AttributeContext;

            // check to see if we need to make a copy of the attributes
            // do this when building an attribute context and when we will modify the attributes (beyond traits)
            // see if any of the appliers want to modify
            bool makingCopy = false;

            if (l > 0 && appliedAttSet.AttributeContext != null && actions != null && actions.Count > 0)
            {
                ResolvedAttribute resAttTest = this.Set[0];
                foreach (AttributeResolutionApplier traitAction in actions)
                {
                    ApplierContext ctx = new ApplierContext {
                        ResOpt = resOpt, ResAttSource = resAttTest, ResGuide = resGuide
                    };
                    if (traitAction.WillAttributeModify(ctx) == true)
                    {
                        makingCopy = true;
                        break;
                    }
                }
            }

            if (makingCopy)
            {
                // fake up a generation round for these copies that are about to happen
                AttributeContextParameters acp = new AttributeContextParameters
                {
                    under = appliedAttSet.AttributeContext,
                    type  = Enums.CdmAttributeContextType.GeneratedSet,
                    Name  = "_generatedAttributeSet"
                };
                appliedAttSet.AttributeContext = CdmAttributeContext.CreateChildUnder(traits.ResOpt, acp);
                acp = new AttributeContextParameters
                {
                    under = appliedAttSet.AttributeContext,
                    type  = Enums.CdmAttributeContextType.GeneratedRound,
                    Name  = "_generatedAttributeRound0"
                };
                appliedAttSet.AttributeContext = CdmAttributeContext.CreateChildUnder(traits.ResOpt, acp);
            }
            for (int i = 0; i < l; i++)
            {
                ResolvedAttribute   resAtt        = this.Set[i];
                CdmAttributeContext attCtxToMerge = null;
                if (resAtt.Target is ResolvedAttributeSet subSet)
                {
                    if (makingCopy)
                    {
                        resAtt = resAtt.Copy();
                        // making a copy of a subset (att group) also bring along the context tree for that whole group
                        attCtxToMerge = resAtt.AttCtx;
                    }
                    // the set contains another set. process those
                    resAtt.Target = subSet.Apply(traits, resOpt, resGuide, actions);
                }
                else
                {
                    ResolvedTraitSet rtsMerge = resAtt.ResolvedTraits.MergeSet(traits);
                    resAtt.ResolvedTraits = rtsMerge;
                    if (actions != null)
                    {
                        foreach (AttributeResolutionApplier traitAction in actions)
                        {
                            ApplierContext ctx = new ApplierContext {
                                ResOpt = traits.ResOpt, ResAttSource = resAtt, ResGuide = resGuide
                            };
                            if (traitAction.WillAttributeModify(ctx) == true)
                            {
                                // make a context for this new copy
                                if (makingCopy)
                                {
                                    AttributeContextParameters acp = new AttributeContextParameters
                                    {
                                        under     = appliedAttSet.AttributeContext,
                                        type      = Enums.CdmAttributeContextType.AttributeDefinition,
                                        Name      = resAtt.ResolvedName,
                                        Regarding = resAtt.Target
                                    };
                                    ctx.AttCtx    = CdmAttributeContext.CreateChildUnder(traits.ResOpt, acp);
                                    attCtxToMerge = ctx.AttCtx as CdmAttributeContext;
                                }

                                // make a copy of the resolved att
                                if (makingCopy)
                                {
                                    resAtt = resAtt.Copy();
                                }

                                ctx.ResAttSource = resAtt;
                                // modify it
                                traitAction.DoAttributeModify(ctx);
                            }
                        }
                    }
                }
                appliedAttSet.Merge(resAtt, attCtxToMerge);
            }

            appliedAttSet.AttributeContext = this.AttributeContext;

            if (!makingCopy)
            {
                // didn't copy the attributes or make any new context, so just take the old ones
                appliedAttSet.Ra2attCtxSet = this.Ra2attCtxSet;
                appliedAttSet.AttCtx2ra    = this.AttCtx2ra;
            }

            return(appliedAttSet);
        }
Example #6
0
 internal void CopyAttCtxMappingsInto(IDictionary <ResolvedAttribute, HashSet <CdmAttributeContext> > ra2attCtxSet, IDictionary <CdmAttributeContext, ResolvedAttribute> attCtx2ra, ResolvedAttribute sourceRa, ResolvedAttribute newRa = null)
 {
     if (this.Ra2attCtxSet.Count > 0)
     {
         if (newRa == null)
         {
             newRa = sourceRa;
         }
         // get the set of attribute contexts for the old resolved attribute
         this.Ra2attCtxSet.TryGetValue(sourceRa, out HashSet <CdmAttributeContext> attCtxSet);
         if (attCtxSet != null)
         {
             // map the new resolved attribute to the old context set
             if (ra2attCtxSet.ContainsKey(newRa))
             {
                 var currentSet = ra2attCtxSet[newRa];
                 currentSet.UnionWith(attCtxSet);
             }
             else
             {
                 ra2attCtxSet.Add(newRa, attCtxSet);
             }
             // map the old contexts to the new resolved attribute
             if (attCtxSet.Count > 0)
             {
                 foreach (CdmAttributeContext attCtx in attCtxSet)
                 {
                     attCtx2ra[attCtx] = newRa;
                 }
             }
         }
     }
 }
Example #7
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 #8
0
        internal ResolvedAttributeSet Merge(ResolvedAttribute toMerge)
        {
            ResolvedAttributeSet rasResult = this;

            if (toMerge != null)
            {
                // if there is already a resolve attribute present, remove it before adding the new attribute
                if (rasResult.ResolvedName2resolvedAttribute.ContainsKey(toMerge.ResolvedName))
                {
                    ResolvedAttribute existing = rasResult.ResolvedName2resolvedAttribute[toMerge.ResolvedName];
                    if (existing != toMerge)
                    {
                        if (this.RefCnt > 1 && existing.Target != toMerge.Target)
                        {
                            rasResult = rasResult.Copy(); // copy on write
                            existing  = rasResult.ResolvedName2resolvedAttribute[toMerge.ResolvedName];
                        }
                        else
                        {
                            rasResult = this;
                        }

                        if (existing.Target is CdmAttribute)
                        {
                            rasResult.ResolvedAttributeCount -= existing.Target.AttributeCount;
                        }
                        else if (existing.Target is ResolvedAttributeSet)
                        {
                            rasResult.ResolvedAttributeCount -= existing.Target.ResolvedAttributeCount;
                        }

                        if (toMerge.Target is CdmAttribute)
                        {
                            rasResult.ResolvedAttributeCount += toMerge.Target.AttributeCount;
                        }
                        else if (toMerge.Target is ResolvedAttributeSet)
                        {
                            rasResult.ResolvedAttributeCount += toMerge.Target.ResolvedAttributeCount;
                        }

                        existing.Target = toMerge.Target; // replace with newest version
                        existing.Arc    = toMerge.Arc;

                        // merge a new ra into one with the same name, so make a lineage
                        // the existing attCtx becomes the new lineage. but the old one needs to stay too... so you get both. it came from both places.
                        // we need ONE place where this RA can point, so that will be the most recent place with a fixed lineage
                        // A->C1->C0 gets merged with A'->C2->C3 that turns into A->C2->[(c3), (C1->C0)]. in the more simple case this is just A->C2->C1
                        if (toMerge.AttCtx != null)
                        {
                            if (existing.AttCtx != null)
                            {
                                toMerge.AttCtx.AddLineage(existing.AttCtx);
                            }
                            existing.AttCtx = toMerge.AttCtx;
                        }

                        ResolvedTraitSet rtsMerge = existing.ResolvedTraits.MergeSet(toMerge.ResolvedTraits); // newest one may replace
                        if (rtsMerge != existing.ResolvedTraits)
                        {
                            rasResult = rasResult.Copy(); // copy on write
                            existing  = rasResult.ResolvedName2resolvedAttribute[toMerge.ResolvedName];
                            existing.ResolvedTraits = rtsMerge;
                        }
                    }
                }
                else
                {
                    if (this.RefCnt > 1)
                    {
                        rasResult = rasResult.Copy(); // copy on write
                    }
                    if (rasResult == null)
                    {
                        rasResult = this;
                    }
                    rasResult.ResolvedName2resolvedAttribute.Add(toMerge.ResolvedName, toMerge);
                    //toMerge.InsertOrder = rasResult.Set.Count;
                    rasResult.Set.Add(toMerge);
                    rasResult.ResolvedAttributeCount += toMerge.ResolvedAttributeCount;
                }
                this.BaseTrait2Attributes = null;
            }
            return(rasResult);
        }