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); } }
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); }
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); }
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); }
internal void MergeTraits(ResolvedTraitSet rtsNew) { if (rtsNew != null) { if (this.ResolvedTraitSet == null) { this.ResolvedTraitSet = new ResolvedTraitSet(rtsNew.ResOpt); } this.ResolvedTraitSet = this.ResolvedTraitSet.MergeSet(rtsNew); } }
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); }
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); }
/// <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); } } }
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); }
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); }
//////////////////////////////////////////////////////////////////////////////////////////////////// // 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); }
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); }
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); }
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); } } }
public void SetTraitParameterValue(ResolveOptions resOpt, CdmTraitDefinition toTrait, string paramName, dynamic value) { this.ResolvedTraitSet = this.ResolvedTraitSet.SetTraitParameterValue(resOpt, toTrait, paramName, value); }
public void OwnOne(ResolvedTrait rt, ResolveOptions resOpt) { this.ResolvedTraitSet = new ResolvedTraitSet(resOpt); this.ResolvedTraitSet.Merge(rt, false); }
internal void TakeReference(ResolvedTraitSet rtsNew) { this.ResolvedTraitSet = rtsNew; }
public void Clear() { this.ResolvedTraitSet = null; }
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); }
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); }
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); }