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));
     }
 }
예제 #2
0
        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));
     }
 }
예제 #4
0
        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);
        }
예제 #5
0
        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("");
        }
예제 #6
0
        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;
     }
 }
예제 #9
0
        /// <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;
     }
 }
예제 #11
0
        /// <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;
     }
 }
예제 #14
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);
        }
예제 #15
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);
        }
예제 #16
0
        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);
        }
예제 #17
0
        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);
        }
예제 #18
0
        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);
        }
예제 #19
0
        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);
        }
예제 #20
0
        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);
        }
예제 #21
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);
        }
        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);
            }
        }
예제 #23
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);
        }
예제 #24
0
        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;
                }
            }
        }
예제 #25
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);
        }