Exemplo n.º 1
0
 public void ReplaceTraitParameterValue(ResolveOptions resOpt, string toTrait, string paramName, dynamic valueWhen, dynamic valueNew)
 {
     if (this.ResolvedTraitSet != null)
     {
         this.ResolvedTraitSet = this.ResolvedTraitSet.ReplaceTraitParameterValue(resOpt, toTrait, paramName, valueWhen, valueNew);
     }
 }
Exemplo n.º 2
0
        public ResolvedTraitSet ReplaceTraitParameterValue(ResolveOptions resOpt, string toTrait, string paramName, dynamic valueWhen, dynamic valueNew)
        {
            ResolvedTraitSet traitSetResult = this as ResolvedTraitSet;

            for (int i = 0; i < traitSetResult.Set.Count; i++)
            {
                ResolvedTrait rt = traitSetResult.Set[i];
                if (rt?.Trait.IsDerivedFrom(toTrait, resOpt) == true)
                {
                    if (rt.ParameterValues != null)
                    {
                        ParameterCollection pc = rt.ParameterValues.PC;
                        List <dynamic>      av = rt.ParameterValues.Values;
                        int idx = pc.FetchParameterIndex(paramName);
                        if (idx >= 0 && Equals(av[idx], valueWhen))
                        {
                            // copy the set and make a deep copy of the trait being set
                            traitSetResult = this.ShallowCopyWithException(rt.Trait);
                            // assume these are all still true for this copy
                            rt      = traitSetResult.Set[i];
                            av      = rt.ParameterValues.Values;
                            av[idx] = ParameterValue.FetchReplacementValue(resOpt, av[idx], valueNew, true);
                            break;
                        }
                    }
                }
            }
            return(traitSetResult);
        }
Exemplo n.º 3
0
        bool CopyNeeded(ResolvedTraitSet traits, ResolveOptions resOpt, CdmAttributeResolutionGuidance resGuide, List <AttributeResolutionApplier> actions)
        {
            if (actions == null || actions.Count == 0)
            {
                return(false);
            }

            // for every attribute in the set, detect if a merge of traits will alter the traits. if so, need to copy the attribute set to avoid overwrite
            int l = this.Set.Count;

            for (int i = 0; i < l; i++)
            {
                ResolvedAttribute resAtt = this.Set[i];
                foreach (var currentTraitAction in actions)
                {
                    ApplierContext ctx = new ApplierContext {
                        ResOpt = resOpt, ResAttSource = resAtt, ResGuide = resGuide
                    };
                    if (currentTraitAction.WillAttributeModify(ctx))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemplo n.º 4
0
        public ResolvedTraitSet SetTraitParameterValue(ResolveOptions resOpt, CdmTraitDefinition toTrait, string paramName, dynamic value)
        {
            ResolvedTraitSet altered = this.ShallowCopyWithException(toTrait);

            altered.Get(toTrait).ParameterValues.SetParameterValue(this.ResOpt, paramName, value);
            return(altered);
        }
Exemplo n.º 5
0
 internal void MergeTraits(ResolvedTraitSet rtsNew)
 {
     if (rtsNew != null)
     {
         if (this.ResolvedTraitSet == null)
         {
             this.ResolvedTraitSet = new ResolvedTraitSet(rtsNew.ResOpt);
         }
         this.ResolvedTraitSet = this.ResolvedTraitSet.MergeSet(rtsNew);
     }
 }
Exemplo n.º 6
0
        public ResolvedTraitSet SetTraitParameterValue(ResolveOptions resOpt, CdmTraitDefinition toTrait, string paramName, dynamic value)
        {
            ResolvedTraitSet altered = this.ShallowCopyWithException(toTrait);
            var currTrait            = altered.Get(toTrait)?.ParameterValues;

            if (currTrait != null)
            {
                currTrait.SetParameterValue(this.ResOpt, paramName, value);
            }
            return(altered);
        }
Exemplo n.º 7
0
        public ResolvedTraitSet DeepCopy()
        {
            ResolvedTraitSet copy = new ResolvedTraitSet(this.ResOpt);

            for (int i = 0; i < this.Set.Count; i++)
            {
                ResolvedTrait rt = this.Set[i].Copy();
                copy.Set.Add(rt);
                copy.LookupByTrait.Add(rt.Trait, rt);
            }
            copy.HasElevated = this.HasElevated;
            return(copy);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Apply a set of resolved traits to this resolved attribute set.
 /// </summary>
 /// <param name="traits"></param>
 internal void ApplyTraits(ResolvedTraitSet traits)
 {
     foreach (var resAtt in this.Set)
     {
         if (resAtt.Target is ResolvedAttributeSet resAttSet)
         {
             resAttSet.ApplyTraits(traits);
         }
         else
         {
             resAtt.ResolvedTraits = resAtt.ResolvedTraits.MergeSet(traits);
         }
     }
 }
Exemplo n.º 9
0
        internal ResolvedAttributeSet Merge(ResolvedAttribute toMerge, CdmAttributeContext attCtx = null)
        {
            ResolvedAttributeSet rasResult = this;

            if (toMerge != null)
            {
                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];
                    }
                    existing.Target = toMerge.Target; // replace with newest version
                    existing.Arc    = toMerge.Arc;

                    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);
                }
                this.BaseTrait2Attributes = null;
            }
            return(rasResult);
        }
Exemplo n.º 10
0
        public ResolvedTraitSet ShallowCopy()
        {
            ResolvedTraitSet copy = new ResolvedTraitSet(this.ResOpt);

            if (this.Set != null)
            {
                int l = this.Set.Count;
                for (int i = 0; i < l; i++)
                {
                    ResolvedTrait rt = this.Set[i];
                    copy.Set.Add(rt);
                    copy.LookupByTrait.Add(rt.Trait, rt);
                }
            }

            copy.HasElevated = this.HasElevated;
            return(copy);
        }
Exemplo n.º 11
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        //  traits that change attributes
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        internal ResolvedAttributeSet ApplyTraits(ResolvedTraitSet traits, ResolveOptions resOpt, CdmAttributeResolutionGuidance resGuide, List <AttributeResolutionApplier> actions)
        {
            ResolvedAttributeSet rasResult = this;
            ResolvedAttributeSet rasApplied;

            if (this.RefCnt > 1 && rasResult.CopyNeeded(traits, resOpt, resGuide, actions))
            {
                rasResult = rasResult.Copy();
            }
            rasApplied = rasResult.Apply(traits, resOpt, resGuide, actions);

            // now we are that
            rasResult.ResolvedName2resolvedAttribute = rasApplied.ResolvedName2resolvedAttribute;
            rasResult.BaseTrait2Attributes           = null;
            rasResult.Set = rasApplied.Set;

            return(rasResult);
        }
Exemplo n.º 12
0
        public ResolvedTraitSet ShallowCopyWithException(CdmTraitDefinition just)
        {
            ResolvedTraitSet copy = new ResolvedTraitSet(this.ResOpt);
            int l = this.Set.Count;

            for (int i = 0; i < l; i++)
            {
                ResolvedTrait rt = this.Set[i];
                if (rt.Trait == just)
                {
                    rt = rt.Copy();
                }
                copy.Set.Add(rt);
                copy.LookupByTrait.Add(rt.Trait, rt);
            }

            copy.HasElevated = this.HasElevated;
            return(copy);
        }
Exemplo n.º 13
0
        public ResolvedTraitSet MergeSet(ResolvedTraitSet toMerge, bool elevatedOnly = false)
        {
            bool             copyOnWrite    = true;
            ResolvedTraitSet traitSetResult = this;

            if (toMerge != null)
            {
                int l = toMerge.Set.Count;
                for (int i = 0; i < l; i++)
                {
                    ResolvedTrait rt = toMerge.Set[i];
                    if (!elevatedOnly || rt.Trait.Elevated == true)
                    {
                        ResolvedTraitSet traitSetMerge = traitSetResult.Merge(rt, copyOnWrite);
                        if (traitSetMerge != traitSetResult)
                        {
                            traitSetResult = traitSetMerge;
                            copyOnWrite    = false;
                        }
                    }
                }
            }
            return(traitSetResult);
        }
Exemplo n.º 14
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);
        }
        internal AttributeResolutionContext(ResolveOptions resOpt, CdmAttributeResolutionGuidance resGuide, ResolvedTraitSet traits)
        {
            // collect a set of appliers for all traits
            this.TraitsToApply = traits;
            this.ResGuide      = resGuide;
            this.ResOpt        = resOpt;

            this.ActionsModify       = new List <AttributeResolutionApplier>();
            this.ActionsGroupAdd     = new List <AttributeResolutionApplier>();
            this.ActionsRoundAdd     = new List <AttributeResolutionApplier>();
            this.ActionsAttributeAdd = new List <AttributeResolutionApplier>();
            this.ActionsRemove       = new List <AttributeResolutionApplier>();
            this.ApplierCaps         = null;

            this.ResOpt = resOpt.Copy();

            if (resGuide != null)
            {
                if (this.ApplierCaps == null)
                {
                    this.ApplierCaps = new AttributeResolutionApplierCapabilities()
                    {
                        CanAlterDirectives = false,
                        CanCreateContext   = false,
                        CanRemove          = false,
                        CanAttributeModify = false,
                        CanGroupAdd        = false,
                        CanRoundAdd        = false,
                        CanAttributeAdd    = false
                    }
                }
                ;
                Func <AttributeResolutionApplier, bool> addApplier = (AttributeResolutionApplier apl) =>
                {
                    // Collect the code that will perform the right action.
                    // Associate with the resolved trait and get the priority
                    if (apl.WillAttributeModify != null && apl.DoAttributeModify != null)
                    {
                        this.ActionsModify.Add(apl);
                        this.ApplierCaps.CanAttributeModify = true;
                    }
                    if (apl.WillAttributeAdd != null && apl.DoAttributeAdd != null)
                    {
                        this.ActionsAttributeAdd.Add(apl);
                        this.ApplierCaps.CanAttributeAdd = true;
                    }
                    if (apl.WillGroupAdd != null && apl.DoGroupAdd != null)
                    {
                        this.ActionsGroupAdd.Add(apl);
                        this.ApplierCaps.CanGroupAdd = true;
                    }
                    if (apl.WillRoundAdd != null && apl.DoRoundAdd != null)
                    {
                        this.ActionsRoundAdd.Add(apl);
                        this.ApplierCaps.CanRoundAdd = true;
                    }
                    if (apl.WillAlterDirectives != null && apl.DoAlterDirectives != null)
                    {
                        this.ApplierCaps.CanAlterDirectives = true;
                        apl.DoAlterDirectives(this.ResOpt, resGuide);
                    }
                    if (apl.WillCreateContext != null && apl.DoCreateContext != null)
                    {
                        this.ApplierCaps.CanCreateContext = true;
                    }
                    if (apl.WillRemove != null)
                    {
                        this.ActionsRemove.Add(apl);
                        this.ApplierCaps.CanRemove = true;
                    }
                    return(true);
                };

                if (resGuide.removeAttribute == true)
                {
                    addApplier(PrimitiveAppliers.isRemoved);
                }
                if (resGuide.imposedDirectives != null)
                {
                    addApplier(PrimitiveAppliers.doesImposeDirectives);
                }
                if (resGuide.removedDirectives != null)
                {
                    addApplier(PrimitiveAppliers.doesRemoveDirectives);
                }
                if (resGuide.addSupportingAttribute != null)
                {
                    addApplier(PrimitiveAppliers.doesAddSupportingAttribute);
                }
                if (resGuide.renameFormat != null)
                {
                    addApplier(PrimitiveAppliers.doesDisambiguateNames);
                }
                if (resGuide.cardinality == "many")
                {
                    addApplier(PrimitiveAppliers.doesExplainArray);
                }
                if (resGuide.entityByReference != null)
                {
                    addApplier(PrimitiveAppliers.doesReferenceEntityVia);
                }

                if (resGuide.selectsSubAttribute != null && resGuide.selectsSubAttribute.selects == "one")
                {
                    addApplier(PrimitiveAppliers.doesSelectAttributes);
                }

                // sorted by priority
                this.ActionsModify.Sort((l, r) => l.Priority - r.Priority);
                this.ActionsGroupAdd.Sort((l, r) => l.Priority - r.Priority);
                this.ActionsRoundAdd.Sort((l, r) => l.Priority - r.Priority);
                this.ActionsAttributeAdd.Sort((l, r) => l.Priority - r.Priority);
            }
        }
    }
Exemplo n.º 16
0
 public void SetTraitParameterValue(ResolveOptions resOpt, CdmTraitDefinition toTrait, string paramName, dynamic value)
 {
     this.ResolvedTraitSet = this.ResolvedTraitSet.SetTraitParameterValue(resOpt, toTrait, paramName, value);
 }
Exemplo n.º 17
0
 public void OwnOne(ResolvedTrait rt, ResolveOptions resOpt)
 {
     this.ResolvedTraitSet = new ResolvedTraitSet(resOpt);
     this.ResolvedTraitSet.Merge(rt, false);
 }
Exemplo n.º 18
0
 internal void TakeReference(ResolvedTraitSet rtsNew)
 {
     this.ResolvedTraitSet = rtsNew;
 }
Exemplo n.º 19
0
 public void Clear()
 {
     this.ResolvedTraitSet = null;
 }
Exemplo n.º 20
0
        public ResolvedTraitSet Merge(ResolvedTrait toMerge, bool copyOnWrite)
        {
            ResolvedTraitSet traitSetResult = this;
            var            trait            = toMerge.Trait;
            List <dynamic> av     = null;
            List <bool>    wasSet = null;

            if (toMerge.ParameterValues != null)
            {
                av     = toMerge.ParameterValues.Values;
                wasSet = toMerge.ParameterValues.WasSet;
            }

            if (this.HasElevated != true)
            {
                this.HasElevated = trait.Elevated;
            }

            if (traitSetResult.LookupByTrait.ContainsKey(trait))
            {
                ResolvedTrait  rtOld = traitSetResult.LookupByTrait[trait];
                List <dynamic> avOld = null;
                if (rtOld.ParameterValues != null)
                {
                    avOld = rtOld.ParameterValues.Values;
                }
                if (av != null && avOld != null)
                {
                    // the new values take precedence
                    for (int i = 0; i < av.Count; i++)
                    {
                        if (avOld[i]?.GetType() == typeof(JValue))
                        {
                            avOld[i] = (string)avOld[i];
                        }
                        try
                        {
                            if (av[i] != avOld[i])
                            {
                                if (copyOnWrite)
                                {
                                    traitSetResult = traitSetResult.ShallowCopyWithException(trait);
                                    rtOld          = traitSetResult.LookupByTrait[trait];
                                    avOld          = rtOld.ParameterValues.Values;
                                    copyOnWrite    = false;
                                }
                                avOld[i] = ParameterValue.FetchReplacementValue(this.ResOpt, avOld[i], av[i], wasSet[i]);
                            }
                        }
                        catch
                        {
                        }
                    }
                }
            }
            else
            {
                if (copyOnWrite)
                {
                    traitSetResult = traitSetResult.ShallowCopy();
                }
                toMerge = toMerge.Copy();
                traitSetResult.Set.Add(toMerge);
                traitSetResult.LookupByTrait.Add(trait, toMerge);
            }

            return(traitSetResult);
        }
Exemplo n.º 21
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);
        }
Exemplo n.º 22
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;

                    // Replace old context mappings with mappings to new attribute
                    rasResult.RemoveCachedAttributeContext(existing.AttCtx);
                    rasResult.CacheAttributeContext(attCtx, existing);

                    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);
        }