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