public void ApplyTraits(AttributeResolutionContext arc) { if (this.ResolvedAttributeSet != null && arc != null && arc.TraitsToApply != null) { this.TakeReference(ResolvedAttributeSet.ApplyTraits(arc.TraitsToApply, arc.ResOpt, arc.ResGuide, arc.ActionsModify)); } }
public ResolvedAttributeSet Copy() { ResolvedAttributeSet copy = new ResolvedAttributeSet(); copy.AttributeContext = this.AttributeContext; int l = this.Set.Count; // save the mappings to overwrite // maps from merge may not be correct IDictionary <ResolvedAttribute, HashSet <CdmAttributeContext> > newRa2attCtxSet = new Dictionary <ResolvedAttribute, HashSet <CdmAttributeContext> >(); IDictionary <CdmAttributeContext, ResolvedAttribute> newAttCtx2ra = new Dictionary <CdmAttributeContext, ResolvedAttribute>(); for (int i = 0; i < l; i++) { ResolvedAttribute sourceRa = this.Set[i]; ResolvedAttribute copyRa = sourceRa.Copy(); this.CopyAttCtxMappingsInto(newRa2attCtxSet, newAttCtx2ra, sourceRa, copyRa); copy.Merge(copyRa); } // reset mappings to the correct one copy.Ra2attCtxSet = newRa2attCtxSet; copy.AttCtx2ra = newAttCtx2ra; return(copy); }
internal void MergeAttributes(ResolvedAttributeSet rasNew) { if (rasNew != null) { this.TakeReference(this.ResolvedAttributeSet.MergeSet(rasNew)); } }
public ResolvedAttributeSet MergeSet(ResolvedAttributeSet toMerge) { ResolvedAttributeSet rasResult = this; if (toMerge != null) { foreach (ResolvedAttribute ra in toMerge.Set) { // don't pass in the context here ResolvedAttributeSet rasMerged = rasResult.Merge(ra); if (rasMerged != rasResult) { rasResult = rasMerged; } // get the attribute from the merged set, attributes that were already present were merged, not replaced rasResult.ResolvedName2resolvedAttribute.TryGetValue(ra.ResolvedName, out ResolvedAttribute currentRa); } // merge the ownership map. if (toMerge.AttributeOwnershipMap != null) { if (this.AttributeOwnershipMap == null) { this.AttributeOwnershipMap = new Dictionary <string, HashSet <string> >(); } foreach (var newPair in toMerge.AttributeOwnershipMap) { // always take the new one as the right list, not sure if the constructor for dictionary uses this logic or fails this.AttributeOwnershipMap[newPair.Key] = newPair.Value; } } } return(rasResult); }
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); for (int r = 0; r < entValues.Count; r++) { List <string> rowData = entValues[r]; IDictionary <string, string> row = new SortedDictionary <string, string>(); 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(""); }
public ResolvedAttributeSet Copy() { ResolvedAttributeSet copy = new ResolvedAttributeSet(); copy.AttributeContext = this.AttributeContext; int l = this.Set.Count; // save the mappings to overwrite // maps from merge may not be correct IDictionary <ResolvedAttribute, HashSet <CdmAttributeContext> > newRa2attCtxSet = new Dictionary <ResolvedAttribute, HashSet <CdmAttributeContext> >(); IDictionary <CdmAttributeContext, ResolvedAttribute> newAttCtx2ra = new Dictionary <CdmAttributeContext, ResolvedAttribute>(); 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); }
/// <summary> /// Function to initialize the input projection attribute state Set for a projection /// </summary> /// <param name="projDir"></param> /// <param name="ctx"></param> /// <param name="orgSrcRAS"></param> /// <param name="isSourcePolymorphic"></param> /// <param name="polymorphicSet"></param> /// <returns></returns> internal static ProjectionAttributeStateSet InitializeProjectionAttributeStateSet( ProjectionDirective projDir, CdmCorpusContext ctx, ResolvedAttributeSet orgSrcRAS, bool isSourcePolymorphic = false, Dictionary <string, List <ProjectionAttributeState> > polymorphicSet = null) { ProjectionAttributeStateSet set = new ProjectionAttributeStateSet(ctx); foreach (ResolvedAttribute resAttr in orgSrcRAS.Set) { List <ProjectionAttributeState> prevSet = null; if (isSourcePolymorphic && polymorphicSet != null) { List <ProjectionAttributeState> polyList = null; polymorphicSet.TryGetValue(resAttr.ResolvedName, out polyList); prevSet = polyList; } ProjectionAttributeState projAttrState = new ProjectionAttributeState(ctx) { CurrentResolvedAttribute = resAttr, PreviousStateList = prevSet }; set.Add(projAttrState); } return(set); }
public void RemoveRequestedAtts() { if (this.ResolvedAttributeSet != null) { Marker marker = new Marker { CountIndex = 0, MarkIndex = this.InheritedMark }; this.TakeReference(ResolvedAttributeSet.RemoveRequestedAtts(marker)); this.InheritedMark = marker.MarkIndex; } }
/// <summary> /// If a source is tagged as polymorphic source, get the list of original source /// </summary> /// <param name="projDir"></param> /// <param name="ctx"></param> /// <param name="source"></param> /// <param name="attrCtxParam"></param> /// <returns></returns> internal static Dictionary <string, List <ProjectionAttributeState> > GetPolymorphicSourceSet( ProjectionDirective projDir, CdmCorpusContext ctx, CdmEntityReference source, ResolvedAttributeSet rasSource) { Dictionary <string, List <ProjectionAttributeState> > polySources = new Dictionary <string, List <ProjectionAttributeState> >(); // TODO (sukanyas): when projection based polymorphic source is made available - the following line will have to be changed // for now assuming non-projections based polymorphic source CdmEntityDefinition sourceDef = source.FetchObjectDefinition <CdmEntityDefinition>(projDir.ResOpt); foreach (CdmAttributeItem attr in sourceDef.Attributes) { if (attr.ObjectType == CdmObjectType.EntityAttributeDef) { // the attribute context for this entity typed attribute was already created by the `FetchResolvedAttributes` that happens before this function call. // we are only interested in linking the attributes to the entity that they came from and the attribute context nodes should not be taken into account. // create this dummy attribute context so the resolution code works properly and discard it after. AttributeContextParameters attrCtxParam = new AttributeContextParameters { Regarding = attr, type = CdmAttributeContextType.PassThrough, under = new CdmAttributeContext(ctx, "discard") }; ResolvedAttributeSet raSet = ((CdmEntityAttributeDefinition)attr).FetchResolvedAttributes(projDir.ResOpt, attrCtxParam); foreach (ResolvedAttribute resAttr in raSet.Set) { // we got a null ctx because null was passed in to fetch, but the nodes are in the parent's tree // so steal them based on name var resAttSrc = rasSource.Get(resAttr.ResolvedName); if (resAttSrc != null) { resAttr.AttCtx = resAttSrc.AttCtx; } ProjectionAttributeState projAttrState = new ProjectionAttributeState(ctx) { CurrentResolvedAttribute = resAttr, PreviousStateList = null }; // the key doesn't exist, initialize with an empty list first if (!polySources.ContainsKey(resAttr.ResolvedName)) { polySources[resAttr.ResolvedName] = new List <ProjectionAttributeState>(); } polySources[resAttr.ResolvedName].Add(projAttrState); } } } return(polySources); }
internal void MergeAttributes(ResolvedAttributeSet rasNew) { if (rasNew != null) { this.TakeReference(this.ResolvedAttributeSet.MergeSet(rasNew)); } if (rasNew.DepthTraveled > this.ResolvedAttributeSet.DepthTraveled) { this.ResolvedAttributeSet.DepthTraveled = rasNew.DepthTraveled; } }
/// <summary> /// If a source is tagged as polymorphic source, get the list of original source /// </summary> /// <param name="projDir"></param> /// <param name="ctx"></param> /// <param name="source"></param> /// <param name="attrCtxParam"></param> /// <returns></returns> internal static Dictionary <string, List <ProjectionAttributeState> > GetPolymorphicSourceSet( ProjectionDirective projDir, CdmCorpusContext ctx, CdmEntityReference source, ResolvedAttributeSet rasSource, AttributeContextParameters attrCtxParam) { Dictionary <string, List <ProjectionAttributeState> > polySources = new Dictionary <string, List <ProjectionAttributeState> >(); // TODO (sukanyas): when projection based polymorphic source is made available - the following line will have to be changed // for now assuming non-projections based polymorphic source CdmEntityDefinition sourceDef = source.FetchObjectDefinition <CdmEntityDefinition>(projDir.ResOpt); foreach (CdmAttributeItem attr in sourceDef.Attributes) { if (attr.ObjectType == CdmObjectType.EntityAttributeDef) { ResolvedAttributeSet raSet = ((CdmEntityAttributeDefinition)attr).FetchResolvedAttributes(projDir.ResOpt, null); foreach (ResolvedAttribute resAttr in raSet.Set) { // we got a null ctx because null was passed in to fetch, but the nodes are in the parent's tree // so steal them based on name var resAttSrc = rasSource.Get(resAttr.ResolvedName); if (resAttSrc != null) { resAttr.AttCtx = resAttSrc.AttCtx; } ProjectionAttributeState projAttrState = new ProjectionAttributeState(ctx) { CurrentResolvedAttribute = resAttr, PreviousStateList = null }; // the key already exists, just add to the existing list if (polySources.ContainsKey(resAttr.ResolvedName)) { List <ProjectionAttributeState> exisitingSet = polySources[resAttr.ResolvedName]; exisitingSet.Add(projAttrState); polySources[resAttr.ResolvedName] = exisitingSet; } else { List <ProjectionAttributeState> pasList = new List <ProjectionAttributeState>(); pasList.Add(projAttrState); polySources.Add(resAttr.ResolvedName, pasList); } } } } return(polySources); }
internal ResolvedAttributeSet GiveReference() { ResolvedAttributeSet rasRef = this.ResolvedAttributeSet; if (this.ResolvedAttributeSet != null) { this.ResolvedAttributeSet.Release(); if (this.ResolvedAttributeSet.RefCnt == 0) { this.ResolvedAttributeSet = null; } } return(rasRef); }
internal void TakeReference(ResolvedAttributeSet rasNew) { if (this.ResolvedAttributeSet != rasNew) { if (rasNew != null) { rasNew.AddRef(); } if (this.ResolvedAttributeSet != null) { this.ResolvedAttributeSet.Release(); } this.ResolvedAttributeSet = rasNew; } }
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); }
public ResolvedAttributeSet MergeSet(ResolvedAttributeSet toMerge) { ResolvedAttributeSet rasResult = this; if (toMerge != null) { int l = toMerge.Set.Count; for (int i = 0; i < l; i++) { // don't pass in the context here ResolvedAttributeSet rasMerged = rasResult.Merge(toMerge.Set[i]); if (rasMerged != rasResult) { rasResult = rasMerged; } // copy context here toMerge.CopyAttCtxMappingsInto(rasResult.Ra2attCtxSet, rasResult.AttCtx2ra, toMerge.Set[i]); } } return(rasResult); }
public ResolvedAttributeSet MergeSet(ResolvedAttributeSet toMerge) { ResolvedAttributeSet rasResult = this; if (toMerge != null) { foreach (ResolvedAttribute ra in toMerge.Set) { // don't pass in the context here ResolvedAttributeSet rasMerged = rasResult.Merge(ra); if (rasMerged != rasResult) { rasResult = rasMerged; } // get the attribute from the merged set, attributes that were already present were merged, not replaced rasResult.ResolvedName2resolvedAttribute.TryGetValue(ra.ResolvedName, out ResolvedAttribute currentRa); // copy context here toMerge.CopyAttCtxMappingsInto(rasResult.Ra2attCtxSet, rasResult.AttCtx2ra, ra, currentRa); } } return(rasResult); }
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); }
public ResolvedAttributeSet FetchAttributesWithTraits(ResolveOptions resOpt, dynamic queryFor) { // put the input into a standard form List <TraitParamSpec> query = new List <TraitParamSpec>(); if (queryFor.GetType() == typeof(List <TraitParamSpec>)) { int l = queryFor.length; for (int i = 0; i < l; i++) { dynamic q = queryFor[i]; if (q is string) { query.Add(new TraitParamSpec { TraitBaseName = q, Parameters = new Dictionary <string, string>() }); } else { query.Add(q); } } } else { if (queryFor is string) { query.Add(new TraitParamSpec { TraitBaseName = queryFor, Parameters = new Dictionary <string, string>() }); } else { query.Add(queryFor); } } // if the map isn't in place, make one now. assumption is that this is called as part of a usage pattern where it will get called again. if (this.BaseTrait2Attributes == null) { this.BaseTrait2Attributes = new Dictionary <string, HashSet <ResolvedAttribute> >(); int l = this.Set.Count; for (int i = 0; i < l; i++) { // create a map from the name of every trait found in this whole set of attributes to the attributes that have the trait (included base classes of traits) var resAtt = this.Set[i]; ISet <string> traitNames = resAtt.ResolvedTraits.CollectTraitNames(); foreach (string tName in traitNames) { if (!this.BaseTrait2Attributes.ContainsKey(tName)) { this.BaseTrait2Attributes.Add(tName, new HashSet <ResolvedAttribute>()); } this.BaseTrait2Attributes[tName].Add(resAtt); } } } // for every trait in the query, get the set of attributes. // intersect these sets to get the final answer HashSet <ResolvedAttribute> finalSet = null; for (int i = 0; i < query.Count; i++) { var q = query[i]; if (this.BaseTrait2Attributes.ContainsKey(q.TraitBaseName)) { var subSet = this.BaseTrait2Attributes[q.TraitBaseName]; if (q.Parameters?.Count > 0) { // need to check param values, so copy the subset to something we can modify HashSet <ResolvedAttribute> filteredSubSet = new HashSet <ResolvedAttribute>(); foreach (var ra in subSet) { ParameterValueSet pvals = ra.ResolvedTraits.Find(resOpt, q.TraitBaseName).ParameterValues; // compare to all query params int lParams = q.Parameters.Count; int iParam = 0; for (iParam = 0; iParam < lParams; iParam++) { var param = q.Parameters.ElementAt(iParam); var pv = pvals.FetchParameterValueByName(param.Key); if (pv == null || pv.FetchValueString(resOpt) != param.Value) { break; } } // stop early means no match if (iParam == lParams) { filteredSubSet.Add(ra); } } subSet = filteredSubSet; } if (subSet != null && subSet.Count > 0) { // got some. either use as starting point for answer or intersect this in if (finalSet == null) { finalSet = subSet; } else { var intersection = new HashSet <ResolvedAttribute>(); // intersect the two foreach (var ra in finalSet) { if (subSet.Contains(ra)) { intersection.Add(ra); } } finalSet = intersection; } } } } // collect the final set into a resolvedAttributeSet if (finalSet != null && finalSet.Count > 0) { ResolvedAttributeSet rasResult = new ResolvedAttributeSet(); foreach (ResolvedAttribute ra in finalSet) { rasResult.Merge(ra); } return(rasResult); } return(null); }
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); }
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); }
public void GenerateApplierAttributes(AttributeResolutionContext arc, bool applyTraitsToNew) { if (arc == null || arc.ApplierCaps == null) { return; } if (this.ResolvedAttributeSet == null) { this.TakeReference(new ResolvedAttributeSet()); } // make sure all of the 'source' attributes know about this context List <ResolvedAttribute> set = this.ResolvedAttributeSet.Set; if (set != null) { int l = set.Count; for (int i = 0; i < l; i++) { set[i].Arc = arc; } // the resolution guidance may be asking for a one time 'take' or avoid of attributes from the source // this also can re-order the attributes // if (arc.ResGuide != null && arc.ResGuide.selectsSubAttribute != null && arc.ResGuide.selectsSubAttribute.selects == "some" && (arc.ResGuide.selectsSubAttribute.selectsSomeTakeNames != null || arc.ResGuide.selectsSubAttribute.selectsSomeAvoidNames != null)) { // we will make a new resolved attribute set from the 'take' list List <ResolvedAttribute> takeSet = new List <ResolvedAttribute>(); List <string> selectsSomeTakeNames = arc.ResGuide.selectsSubAttribute.selectsSomeTakeNames; List <string> selectsSomeAvoidNames = arc.ResGuide.selectsSubAttribute.selectsSomeAvoidNames; if (selectsSomeTakeNames != null && selectsSomeAvoidNames == null) { // make an index that goes from name to insertion order Dictionary <string, int> inverted = new Dictionary <string, int>(); for (int iOrder = 0; iOrder < l; iOrder++) { inverted.Add(set[iOrder].ResolvedName, iOrder); } for (int iTake = 0; iTake < selectsSomeTakeNames.Count; iTake++) { // if in the original set of attributes, take it in the new order int iOriginalOrder; if (inverted.TryGetValue(selectsSomeTakeNames[iTake], out iOriginalOrder)) { takeSet.Add(set[iOriginalOrder]); } } } if (selectsSomeAvoidNames != null) { // make a quick look up of avoid names HashSet <string> avoid = new HashSet <string>(); foreach (string avoidName in selectsSomeAvoidNames) { avoid.Add(avoidName); } for (int iAtt = 0; iAtt < l; iAtt++) { // only take the ones not in avoid the list given if (!avoid.Contains(set[iAtt].ResolvedName)) { takeSet.Add(set[iAtt]); } } } // replace the guts of the resolvedAttributeSet with this this.ResolvedAttributeSet.AlterSetOrderAndScope(takeSet); } } // get the new atts and then add them one at a time into this set List <ResolvedAttribute> newAtts = GetApplierGeneratedAttributes(arc, true, applyTraitsToNew); if (newAtts != null) { ResolvedAttributeSet ras = this.ResolvedAttributeSet; for (int i = 0; i < newAtts.Count; i++) { ras = ras.Merge(newAtts[i]); } this.TakeReference(ras); } }
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 void MarkOrphansForRemoval(string ownerName, ResolvedAttributeSet rasNewOnes) { if (this.AttributeOwnershipMap == null) { return; } if (!this.AttributeOwnershipMap.ContainsKey(ownerName)) { return; } var lastSet = this.AttributeOwnershipMap[ownerName]; // make a list of all atts from last time with this owner, remove the ones that show up now var thoseNotRepeated = new HashSet <string>(lastSet); // of course, if none show up, all must go if (rasNewOnes != null && rasNewOnes.Set != null && rasNewOnes.Set.Count > 0) { foreach (var newOne in rasNewOnes.Set) { if (lastSet.Contains(newOne.ResolvedName)) { // congrats, you are not doomed thoseNotRepeated.Remove(newOne.ResolvedName); } } } // anyone left must be marked for remove var fixedArcs = new HashSet <AttributeResolutionContext>(); // to avoid checking if we need to fix the same thing many times foreach (string toRemove in thoseNotRepeated) { var raDoomed = this.ResolvedName2resolvedAttribute[toRemove]; if (raDoomed.Arc != null) { // to remove these, need to have our special remover thing in the set of actions if (!fixedArcs.Contains(raDoomed.Arc)) { fixedArcs.Add(raDoomed.Arc); // not again if (raDoomed.Arc.ApplierCaps.CanRemove == true) { // don't add more than once. if (!raDoomed.Arc.ActionsRemove.Contains(PrimitiveAppliers.isRemovedInternal)) { raDoomed.Arc.ActionsRemove.Add(PrimitiveAppliers.isRemovedInternal); } } else { raDoomed.Arc.ActionsRemove.Add(PrimitiveAppliers.isRemovedInternal); raDoomed.Arc.ApplierCaps.CanRemove = true; } } // mark the att in the state if (raDoomed.ApplierState == null) { raDoomed.ApplierState = new ApplierState(); } raDoomed.ApplierState.Flex_remove = true; } } }
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); }