bool CopyNeeded(ResolvedTraitSet traits, 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 = traits.ResOpt, ResAttSource = resAtt, ResGuide = resGuide }; if (currentTraitAction.WillAttributeModify(ctx)) { return(true); } } } return(false); }
public static AttributeResolutionGuidance ToData(CdmAttributeResolutionGuidance instance, ResolveOptions resOpt, CopyOptions options) { AttributeResolutionGuidance obj = new AttributeResolutionGuidance { removeAttribute = instance.removeAttribute, imposedDirectives = instance.imposedDirectives, removedDirectives = instance.removedDirectives, addSupportingAttribute = Utils.JsonForm(instance.addSupportingAttribute, resOpt, options), cardinality = instance.cardinality, renameFormat = instance.renameFormat }; if (instance.expansion != null) { obj.expansion = new AttributeResolutionGuidance.Expansion() { startingOrdinal = instance.expansion.startingOrdinal, maximumExpansion = instance.expansion.maximumExpansion, countAttribute = Utils.JsonForm(instance.expansion.countAttribute, resOpt, options) }; } if (instance.entityByReference != null) { obj.entityByReference = new AttributeResolutionGuidance.CdmAttributeResolutionGuidance_EntityByReference() { alwaysIncludeForeignKey = instance.entityByReference.alwaysIncludeForeignKey, referenceOnlyAfterDepth = instance.entityByReference.referenceOnlyAfterDepth, allowReference = instance.entityByReference.allowReference, foreignKeyAttribute = Utils.JsonForm(instance.entityByReference.foreignKeyAttribute, resOpt, options) }; } if (instance.selectsSubAttribute != null) { obj.selectsSubAttribute = new AttributeResolutionGuidance.CdmAttributeResolutionGuidance_SelectsSubAttribute() { selects = instance.selectsSubAttribute.selects, selectedTypeAttribute = Utils.JsonForm(instance.selectsSubAttribute.selectedTypeAttribute, resOpt, options), selectsSomeTakeNames = instance.selectsSubAttribute.selectsSomeTakeNames, selectsSomeAvoidNames = instance.selectsSubAttribute.selectsSomeAvoidNames }; } return(obj); }
public void TestResolutionGuidanceCopy() { var corpus = new CdmCorpusDefinition(); var resolutionGuidance = new CdmAttributeResolutionGuidance(corpus.Ctx) { expansion = new CdmAttributeResolutionGuidance.Expansion(), entityByReference = new CdmAttributeResolutionGuidance.CdmAttributeResolutionGuidance_EntityByReference(), selectsSubAttribute = new CdmAttributeResolutionGuidance.CdmAttributeResolutionGuidance_SelectsSubAttribute(), imposedDirectives = new List <string>(), removedDirectives = new List <string>() }; var resolutionGuidanceCopy = resolutionGuidance.Copy() as CdmAttributeResolutionGuidance; Assert.IsFalse(Object.ReferenceEquals(resolutionGuidance.expansion, resolutionGuidanceCopy.expansion)); Assert.IsFalse(Object.ReferenceEquals(resolutionGuidance.entityByReference, resolutionGuidanceCopy.entityByReference)); Assert.IsFalse(Object.ReferenceEquals(resolutionGuidance.selectsSubAttribute, resolutionGuidanceCopy.selectsSubAttribute)); Assert.IsFalse(Object.ReferenceEquals(resolutionGuidance.imposedDirectives, resolutionGuidanceCopy.imposedDirectives)); Assert.IsFalse(Object.ReferenceEquals(resolutionGuidance.removedDirectives, resolutionGuidanceCopy.removedDirectives)); }
//////////////////////////////////////////////////////////////////////////////////////////////////// // traits that change attributes //////////////////////////////////////////////////////////////////////////////////////////////////// internal ResolvedAttributeSet ApplyTraits(ResolvedTraitSet traits, CdmAttributeResolutionGuidance resGuide, List <AttributeResolutionApplier> actions) { ResolvedAttributeSet rasResult = this; ResolvedAttributeSet rasApplied; if (this.RefCnt > 1 && rasResult.CopyNeeded(traits, resGuide, actions)) { rasResult = rasResult.Copy(); } rasApplied = rasResult.Apply(traits, resGuide, actions); // now we are that rasResult.ResolvedName2resolvedAttribute = rasApplied.ResolvedName2resolvedAttribute; rasResult.BaseTrait2Attributes = null; rasResult.Set = rasApplied.Set; rasResult.Ra2attCtxSet = rasApplied.Ra2attCtxSet; rasResult.AttCtx2ra = rasApplied.AttCtx2ra; return(rasResult); }
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); } } }