Esempio n. 1
0
        internal override ResolvedAttributeSetBuilder ConstructResolvedAttributes(ResolveOptions resOpt, CdmAttributeContext under = null)
        {
            // find and cache the complete set of attributes
            // attributes definitions originate from and then get modified by subsequent re-defintions from (in this order):
            // the datatype used as an attribute, traits applied to that datatype,
            // the purpose of the attribute, dynamic traits applied to the attribute.
            ResolvedAttributeSetBuilder rasb = new ResolvedAttributeSetBuilder();

            rasb.ResolvedAttributeSet.AttributeContext = under;

            // add this attribute to the set
            // make a new one and apply dynamic traits
            ResolvedAttribute newAtt = new ResolvedAttribute(resOpt, this, this.Name, under as CdmAttributeContext);

            rasb.OwnOne(newAtt);

            ResolvedTraitSet rts = this.FetchResolvedTraits(resOpt);
            // this context object holds all of the info about what needs to happen to resolve these attribute
            // make a copy and add defaults if missing
            CdmAttributeResolutionGuidance resGuideWithDefault;

            if (this.ResolutionGuidance != null)
            {
                resGuideWithDefault = (CdmAttributeResolutionGuidance)this.ResolutionGuidance.Copy(resOpt);
            }
            else
            {
                resGuideWithDefault = new CdmAttributeResolutionGuidance(this.Ctx);
            }

            // renameFormat is not currently supported for type attributes
            resGuideWithDefault.renameFormat = null;

            resGuideWithDefault.UpdateAttributeDefaults(null, this);
            AttributeResolutionContext arc = new AttributeResolutionContext(resOpt, resGuideWithDefault, rts);

            // TODO: remove the resolution guidance if projection is being used
            // from the traits of the datatype, purpose and applied here, see if new attributes get generated
            rasb.ApplyTraits(arc);
            rasb.GenerateApplierAttributes(arc, false); // false = don't apply these traits to added things
            // this may have added symbols to the dependencies, so merge them
            resOpt.SymbolRefSet.Merge(arc.ResOpt.SymbolRefSet);

            if (this.Projection != null)
            {
                ProjectionDirective projDirective = new ProjectionDirective(resOpt, this);
                ProjectionContext   projCtx       = this.Projection.ConstructProjectionContext(projDirective, under, rasb.ResolvedAttributeSet);

                ResolvedAttributeSet ras = this.Projection.ExtractResolvedAttributes(projCtx, under);
                rasb.ResolvedAttributeSet = ras;
            }

            return(rasb);
        }
Esempio n. 2
0
        internal override ResolvedAttributeSetBuilder ConstructResolvedAttributes(ResolveOptions resOpt, CdmAttributeContext under = null)
        {
            ResolvedAttributeSetBuilder rasb     = new ResolvedAttributeSetBuilder();
            CdmAttributeContext         allUnder = under;

            if (under != null)
            {
                AttributeContextParameters acpAttGrp = new AttributeContextParameters
                {
                    under         = under,
                    type          = CdmAttributeContextType.AttributeGroup,
                    Name          = this.GetName(),
                    Regarding     = this,
                    IncludeTraits = false
                };
                under = rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpAttGrp);
            }

            if (this.Members != null)
            {
                for (int i = 0; i < this.Members.Count; i++)
                {
                    CdmObjectBase att = this.Members[i] as CdmObjectBase;
                    AttributeContextParameters acpAtt = null;
                    if (under != null)
                    {
                        acpAtt = new AttributeContextParameters
                        {
                            under         = under,
                            type          = CdmAttributeContextType.AttributeDefinition,
                            Name          = att.FetchObjectDefinitionName(),
                            Regarding     = att,
                            IncludeTraits = false
                        };
                    }

                    ResolvedAttributeSet rasFromAtt = att.FetchResolvedAttributes(resOpt, acpAtt);
                    // before we just merge, need to handle the case of 'attribute restatement' AKA an entity with an attribute having the same name as an attribute
                    // from a base entity. thing might come out with different names, if they do, then any attributes owned by a similar named attribute before
                    // that didn't just pop out of that same named attribute now need to go away.
                    // mark any attributes formerly from this named attribute that don't show again as orphans
                    rasb.ResolvedAttributeSet.MarkOrphansForRemoval((att as CdmAttributeItem).FetchObjectDefinitionName(), rasFromAtt);
                    // now merge
                    rasb.MergeAttributes(rasFromAtt);
                }
            }
            rasb.ResolvedAttributeSet.AttributeContext = allUnder; // context must be the one expected from the caller's pov.

            // things that need to go away
            rasb.RemoveRequestedAtts();
            return(rasb);
        }
Esempio n. 3
0
        virtual internal ResolvedAttributeSetBuilder FetchObjectFromCache(ResolveOptions resOpt, AttributeContextParameters acpInContext)
        {
            const string   kind     = "rasb";
            ResolveContext ctx      = this.Ctx as ResolveContext;
            string         cacheTag = ctx.Corpus.CreateDefinitionCacheTag(resOpt, this, kind, acpInContext != null ? "ctx" : "");

            ResolvedAttributeSetBuilder rasbCache = null;

            if (cacheTag != null)
            {
                ctx.AttributeCache.TryGetValue(cacheTag, out rasbCache);
            }

            return(rasbCache);
        }
        internal override ResolvedAttributeSetBuilder ConstructResolvedAttributes(ResolveOptions resOpt, CdmAttributeContext under = null)
        {
            ResolvedAttributeSetBuilder rasb = new ResolvedAttributeSetBuilder();

            if (under != null)
            {
                AttributeContextParameters acpAttGrp = new AttributeContextParameters
                {
                    under         = under,
                    type          = CdmAttributeContextType.AttributeGroup,
                    Name          = this.GetName(),
                    Regarding     = this,
                    IncludeTraits = false
                };
                under = rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpAttGrp);
            }

            if (this.Members != null)
            {
                for (int i = 0; i < this.Members.Count; i++)
                {
                    dynamic                    att      = this.Members.AllItems[i];
                    CdmAttributeContext        attUnder = under;
                    AttributeContextParameters acpAtt   = null;
                    if (under != null)
                    {
                        acpAtt = new AttributeContextParameters
                        {
                            under         = under,
                            type          = CdmAttributeContextType.AttributeDefinition,
                            Name          = att.FetchObjectDefinitionName(),
                            Regarding     = att,
                            IncludeTraits = false
                        };
                    }
                    rasb.MergeAttributes(att.FetchResolvedAttributes(resOpt, acpAtt));
                }
            }
            rasb.ResolvedAttributeSet.AttributeContext = under;

            // things that need to go away
            rasb.RemoveRequestedAtts();
            return(rasb);
        }
Esempio n. 5
0
        internal override ResolvedAttributeSetBuilder ConstructResolvedAttributes(ResolveOptions resOpt, CdmAttributeContext under = null)
        {
            // find and cache the complete set of attributes
            // attributes definitions originate from and then get modified by subsequent re-definitions from (in this order):
            // an extended entity, traits applied to extended entity, exhibited traits of main entity, the (datatype or entity) used as an attribute, traits applied to that datatype or entity,
            // the relationsip of the attribute, the attribute definition itself and included attribute groups, dynamic traits applied to the attribute.
            this.Rasb = new ResolvedAttributeSetBuilder();
            this.Rasb.ResolvedAttributeSet.AttributeContext = under;

            if (this.ExtendsEntity != null)
            {
                CdmObjectReference         extRef          = this.ExtendsEntityRef;
                CdmAttributeContext        extendsRefUnder = null;
                AttributeContextParameters acpExtEnt       = null;

                if (under != null)
                {
                    AttributeContextParameters acpExt = new AttributeContextParameters
                    {
                        under         = under,
                        type          = CdmAttributeContextType.EntityReferenceExtends,
                        Name          = "extends",
                        Regarding     = null,
                        IncludeTraits = false
                    };
                    extendsRefUnder = this.Rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpExt);
                }

                if (extRef.ExplicitReference != null && extRef.FetchObjectDefinition <CdmObjectDefinition>(resOpt).ObjectType == CdmObjectType.ProjectionDef)
                {
                    // A Projection

                    CdmObjectDefinition extRefObjDef = extRef.FetchObjectDefinition <CdmObjectDefinition>(resOpt);
                    if (extendsRefUnder != null)
                    {
                        acpExtEnt = new AttributeContextParameters
                        {
                            under         = extendsRefUnder,
                            type          = CdmAttributeContextType.Projection,
                            Name          = extRefObjDef.GetName(),
                            Regarding     = extRef,
                            IncludeTraits = false
                        };
                    }

                    ProjectionDirective projDirective = new ProjectionDirective(resOpt, this, ownerRef: extRef);
                    CdmProjection       projDef       = (CdmProjection)extRefObjDef;
                    ProjectionContext   projCtx       = projDef.ConstructProjectionContext(projDirective, extendsRefUnder);

                    this.Rasb.ResolvedAttributeSet = projDef.ExtractResolvedAttributes(projCtx);
                }
                else
                {
                    // An Entity Reference

                    if (extendsRefUnder != null)
                    {
                        // usually the extended entity is a reference to a name.
                        // it is allowed however to just define the entity inline.
                        acpExtEnt = new AttributeContextParameters
                        {
                            under         = extendsRefUnder,
                            type          = CdmAttributeContextType.Entity,
                            Name          = extRef.NamedReference ?? extRef.ExplicitReference.GetName(),
                            Regarding     = extRef,
                            IncludeTraits = false
                        };
                    }

                    // save moniker, extended entity may attach a different moniker that we do not
                    // want to pass along to getting this entities attributes
                    string oldMoniker = resOpt.FromMoniker;

                    this.Rasb.MergeAttributes((this.ExtendsEntityRef as CdmObjectReferenceBase).FetchResolvedAttributes(resOpt, acpExtEnt));

                    if (!resOpt.CheckAttributeCount(this.Rasb.ResolvedAttributeSet.ResolvedAttributeCount))
                    {
                        Logger.Error(nameof(CdmEntityDefinition), this.Ctx, $"Maximum number of resolved attributes reached for the entity: {this.EntityName}.");
                        return(null);
                    }

                    if (this.ExtendsEntityResolutionGuidance != null)
                    {
                        // some guidance was given on how to integrate the base attributes into the set. apply that guidance
                        ResolvedTraitSet rtsBase = this.FetchResolvedTraits(resOpt);

                        // this context object holds all of the info about what needs to happen to resolve these attributes.
                        // make a copy and set defaults if needed
                        CdmAttributeResolutionGuidance resGuide = (CdmAttributeResolutionGuidance)this.ExtendsEntityResolutionGuidance.Copy(resOpt);
                        resGuide.UpdateAttributeDefaults(resGuide.FetchObjectDefinitionName());
                        // holds all the info needed by the resolver code
                        AttributeResolutionContext arc = new AttributeResolutionContext(resOpt, resGuide, rtsBase);

                        this.Rasb.GenerateApplierAttributes(arc, false); // true = apply the prepared traits to new atts
                    }

                    // reset to the old moniker
                    resOpt.FromMoniker = oldMoniker;
                }
            }

            this.Rasb.MarkInherited();
            this.Rasb.ResolvedAttributeSet.AttributeContext = under;

            if (this.Attributes != null)
            {
                int l = this.Attributes.Count;
                for (int i = 0; i < l; i++)
                {
                    dynamic                    att      = this.Attributes.AllItems[i];
                    CdmAttributeContext        attUnder = under;
                    AttributeContextParameters acpAtt   = null;
                    if (under != null)
                    {
                        acpAtt = new AttributeContextParameters
                        {
                            under         = under,
                            type          = CdmAttributeContextType.AttributeDefinition,
                            Name          = att.FetchObjectDefinitionName(),
                            Regarding     = att,
                            IncludeTraits = false
                        };
                    }
                    this.Rasb.MergeAttributes(att.FetchResolvedAttributes(resOpt, acpAtt));

                    if (!resOpt.CheckAttributeCount(this.Rasb.ResolvedAttributeSet.ResolvedAttributeCount))
                    {
                        Logger.Error(nameof(CdmEntityDefinition), this.Ctx, $"Maximum number of resolved attributes reached for the entity: {this.EntityName}.");
                        return(null);
                    }
                }
            }
            this.Rasb.MarkOrder();
            this.Rasb.ResolvedAttributeSet.AttributeContext = under;

            // things that need to go away
            this.Rasb.RemoveRequestedAtts();

            return(this.Rasb);
        }
        internal override ResolvedAttributeSetBuilder ConstructResolvedAttributes(ResolveOptions resOpt, CdmAttributeContext under = null)
        {
            // find and cache the complete set of attributes
            // attributes definitions originate from and then get modified by subsequent re-defintions from (in this order):
            // the entity used as an attribute, traits applied to that entity,
            // the purpose of the attribute, any traits applied to the attribute.
            ResolvedAttributeSetBuilder rasb = new ResolvedAttributeSetBuilder();
            CdmEntityReference ctxEnt = this.Entity as CdmEntityReference;
            CdmAttributeContext underAtt = (CdmAttributeContext)under;
            AttributeContextParameters acpEnt = null;
            if (underAtt != null)
            {
                // make a context for this attreibute that holds the attributes that come up from the entity
                acpEnt = new AttributeContextParameters
                {
                    under = underAtt,
                    type = CdmAttributeContextType.Entity,
                    Name = ctxEnt.FetchObjectDefinitionName(),
                    Regarding = ctxEnt,
                    IncludeTraits = true
                };
            }

            ResolvedTraitSet rtsThisAtt = this.FetchResolvedTraits(resOpt);

            // this context object holds all of the info about what needs to happen to resolve these attributes.
            // make a copy and add defaults if missing
            CdmAttributeResolutionGuidance resGuideWithDefault;
            if (this.ResolutionGuidance != null)
                resGuideWithDefault = (CdmAttributeResolutionGuidance)this.ResolutionGuidance.Copy(resOpt);
            else
                resGuideWithDefault = new CdmAttributeResolutionGuidance(this.Ctx);
            resGuideWithDefault.UpdateAttributeDefaults(this.Name);

            AttributeResolutionContext arc = new AttributeResolutionContext(resOpt, resGuideWithDefault, rtsThisAtt);

            // complete cheating but is faster.
            // this purpose will remove all of the attributes that get collected here, so dumb and slow to go get them
            RelationshipInfo relInfo = this.GetRelationshipInfo(arc.ResOpt, arc);
            if (relInfo.IsByRef)
            {
                // make the entity context that a real recursion would have give us
                if (under != null)
                    under = rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpEnt);
                // if selecting from one of many attributes, then make a context for each one
                if (under != null && relInfo.SelectsOne)
                {
                    // the right way to do this is to get a resolved entity from the embedded entity and then 
                    // look through the attribute context hierarchy for non-nested entityReferenceAsAttribute nodes
                    // that seems like a disaster waiting to happen given endless looping, etc.
                    // for now, just insist that only the top level entity attributes declared in the ref entity will work
                    CdmEntityDefinition entPickFrom = (this.Entity as CdmEntityReference).FetchObjectDefinition<CdmEntityDefinition>(resOpt) as CdmEntityDefinition;
                    CdmCollection<CdmAttributeItem> attsPick = entPickFrom?.GetAttributeDefinitions();
                    if (entPickFrom != null && attsPick != null)
                    {
                        for (int i = 0; i < attsPick.Count; i++)
                        {
                            if (attsPick.AllItems[i].ObjectType == CdmObjectType.EntityAttributeDef)
                            {
                                // a table within a table. as expected with a selectsOne attribute
                                // since this is by ref, we won't get the atts from the table, but we do need the traits that hold the key
                                // these are the same contexts that would get created if we recursed
                                // first this attribute
                                AttributeContextParameters acpEntAtt = new AttributeContextParameters
                                {
                                    under = under,
                                    type = CdmAttributeContextType.AttributeDefinition,
                                    Name = attsPick.AllItems[i].FetchObjectDefinitionName(),
                                    Regarding = attsPick.AllItems[i],
                                    IncludeTraits = true
                                };
                                CdmAttributeContext pickUnder = rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpEntAtt);
                                CdmEntityReference pickEnt = (attsPick.AllItems[i] as CdmEntityAttributeDefinition).Entity as CdmEntityReference;
                                AttributeContextParameters acpEntAttEnt = new AttributeContextParameters
                                {
                                    under = pickUnder,
                                    type = CdmAttributeContextType.Entity,
                                    Name = pickEnt.FetchObjectDefinitionName(),
                                    Regarding = pickEnt,
                                    IncludeTraits = true
                                };
                                rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpEntAttEnt);
                            }
                        }
                    }
                }

                // if we got here because of the max depth, need to impose the directives to make the trait work as expected
                if (relInfo.MaxDepthExceeded)
                {
                    if (arc.ResOpt.Directives == null)
                        arc.ResOpt.Directives = new AttributeResolutionDirectiveSet();
                    arc.ResOpt.Directives.Add("referenceOnly");
                }
            }
            else
            {
                ResolveOptions resLink = CopyResolveOptions(resOpt);
                resLink.SymbolRefSet = resOpt.SymbolRefSet;
                resLink.RelationshipDepth = relInfo.NextDepth;
                rasb.MergeAttributes((this.Entity as CdmEntityReference).FetchResolvedAttributes(resLink, acpEnt));
            }

            // from the traits of purpose and applied here, see if new attributes get generated
            rasb.ResolvedAttributeSet.AttributeContext = underAtt;
            rasb.ApplyTraits(arc);
            rasb.GenerateApplierAttributes(arc, true); // true = apply the prepared traits to new atts
            // this may have added symbols to the dependencies, so merge them
            resOpt.SymbolRefSet.Merge(arc.ResOpt.SymbolRefSet);

            // use the traits for linked entity identifiers to record the actual foreign key links
            if (rasb.ResolvedAttributeSet?.Set != null && relInfo.IsByRef)
            {
                foreach (var att in rasb.ResolvedAttributeSet.Set)
                {
                    var reqdTrait = att.ResolvedTraits.Find(resOpt, "is.linkedEntity.identifier");
                    if (reqdTrait == null)
                    {
                        continue;
                    }

                    if (reqdTrait.ParameterValues == null || reqdTrait.ParameterValues.Length == 0)
                    {
                        Logger.Warning(nameof(CdmEntityAttributeDefinition), this.Ctx as ResolveContext, "is.linkedEntity.identifier does not support arguments");
                        continue;
                    }

                    var entReferences = new List<string>();
                    var attReferences = new List<string>();
                    Action<CdmEntityReference, string> addEntityReference = (CdmEntityReference entRef, string nameSpace) =>
                        {
                            var entDef = entRef.FetchObjectDefinition<CdmEntityDefinition>(resOpt);
                            var identifyingTrait = entRef.FetchResolvedTraits(resOpt).Find(resOpt, "is.identifiedBy");
                            if (identifyingTrait != null && entDef != null)
                            {
                                var attRef = identifyingTrait.ParameterValues.FetchParameterValueByName("attribute").Value;
                                string attNamePath = ((CdmObjectReferenceBase)attRef).NamedReference;
                                string attName = attNamePath.Split('/').Last();                                // path should be absolute and without a namespace
                                string relativeEntPath = Ctx.Corpus.Storage.CreateAbsoluteCorpusPath(entDef.AtCorpusPath, entDef.InDocument);
                                if (relativeEntPath.StartsWith($"{nameSpace}:"))
                                {
                                    relativeEntPath = relativeEntPath.Substring(nameSpace.Length + 1);
                                }
                                entReferences.Add(relativeEntPath);
                                attReferences.Add(attName);
                            }
                        };
                    if (relInfo.SelectsOne)
                    {
                        var entPickFrom = (this.Entity as CdmEntityReference).FetchObjectDefinition<CdmEntityDefinition>(resOpt) as CdmEntityDefinition;
                        var attsPick = entPickFrom?.GetAttributeDefinitions()?.Cast<CdmObject>().ToList();
                        if (entPickFrom != null && attsPick != null)
                        {
                            for (int i = 0; i < attsPick.Count; i++)
                            {
                                if (attsPick[i].ObjectType == CdmObjectType.EntityAttributeDef)
                                {
                                    var entAtt = attsPick[i] as CdmEntityAttributeDefinition;
                                    addEntityReference(entAtt.Entity, this.InDocument.Namespace);
                                }
                            }
                        }
                    }
                    else
                    {
                        addEntityReference(this.Entity, this.InDocument.Namespace);
                    }

                    var constantEntity = this.Ctx.Corpus.MakeObject<CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef);
                    constantEntity.EntityShape = this.Ctx.Corpus.MakeRef<CdmEntityReference>(CdmObjectType.EntityRef, "entityGroupSet", true);
                    constantEntity.ConstantValues = entReferences.Select((entRef, idx) => new List<string> { entRef, attReferences[idx] }).ToList();
                    var traitParam = this.Ctx.Corpus.MakeRef<CdmEntityReference>(CdmObjectType.EntityRef, constantEntity, false);
                    reqdTrait.ParameterValues.SetParameterValue(resOpt, "entityReferences", traitParam);
                }
            }

            // a 'structured' directive wants to keep all entity attributes together in a group
            if (arc.ResOpt.Directives?.Has("structured") == true)
            {
                ResolvedAttribute raSub = new ResolvedAttribute(rtsThisAtt.ResOpt, rasb.ResolvedAttributeSet, this.Name, (CdmAttributeContext)rasb.ResolvedAttributeSet.AttributeContext);
                if (relInfo.IsArray)
                {
                    // put a resolved trait on this att group, yuck, hope I never need to do this again and then need to make a function for this
                    CdmTraitReference tr = this.Ctx.Corpus.MakeObject<CdmTraitReference>(CdmObjectType.TraitRef, "is.linkedEntity.array", true);
                    var t = tr.FetchObjectDefinition<CdmTraitDefinition>(resOpt);
                    ResolvedTrait rt = new ResolvedTrait(t, null, new List<dynamic>(), new List<bool>());
                    raSub.ResolvedTraits = raSub.ResolvedTraits.Merge(rt, true);
                }
                rasb = new ResolvedAttributeSetBuilder();
                rasb.OwnOne(raSub);
            }

            return rasb;
        }
Esempio n. 7
0
        internal override ResolvedAttributeSetBuilder ConstructResolvedAttributes(ResolveOptions resOpt, CdmAttributeContext under = null)
        {
            // find and cache the complete set of attributes
            // attributes definitions originate from and then get modified by subsequent re-definitions from (in this order):
            // an extended entity, traits applied to extended entity, exhibited traits of main entity, the (datatype or entity) used as an attribute, traits applied to that datatype or entity,
            // the relationsip of the attribute, the attribute definition itself and included attribute groups, dynamic traits applied to the attribute.
            this.Rasb = new ResolvedAttributeSetBuilder();
            this.Rasb.ResolvedAttributeSet.AttributeContext = under;

            if (this.ExtendsEntity != null)
            {
                CdmObjectReference         extRef          = this.ExtendsEntityRef;
                CdmAttributeContext        extendsRefUnder = null;
                AttributeContextParameters acpExtEnt       = null;
                if (under != null)
                {
                    AttributeContextParameters acpExt = new AttributeContextParameters
                    {
                        under         = under,
                        type          = CdmAttributeContextType.EntityReferenceExtends,
                        Name          = "extends",
                        Regarding     = null,
                        IncludeTraits = false
                    };
                    extendsRefUnder = this.Rasb.ResolvedAttributeSet.CreateAttributeContext(resOpt, acpExt);
                    acpExtEnt       = new AttributeContextParameters
                    {
                        under         = extendsRefUnder,
                        type          = CdmAttributeContextType.Entity,
                        Name          = extRef.NamedReference,
                        Regarding     = extRef,
                        IncludeTraits = false
                    };
                }
                // save moniker, extended entity may attach a different moniker that we do not
                // want to pass along to getting this entities attributes
                string oldMoniker = resOpt.FromMoniker;

                this.Rasb.MergeAttributes((this.ExtendsEntityRef as CdmObjectReferenceBase).FetchResolvedAttributes(resOpt, acpExtEnt));

                if (this.ExtendsEntityResolutionGuidance != null)
                {
                    // some guidance was given on how to integrate the base attributes into the set. apply that guidance
                    ResolvedTraitSet rtsBase = this.FetchResolvedTraits(resOpt);

                    // this context object holds all of the info about what needs to happen to resolve these attributes.
                    // make a copy and set defaults if needed
                    CdmAttributeResolutionGuidance resGuide = (CdmAttributeResolutionGuidance)this.ExtendsEntityResolutionGuidance.Copy(resOpt);
                    resGuide.UpdateAttributeDefaults(resGuide.FetchObjectDefinitionName());
                    // holds all the info needed by the resolver code
                    AttributeResolutionContext arc = new AttributeResolutionContext(resOpt, resGuide, rtsBase);

                    this.Rasb.GenerateApplierAttributes(arc, false); // true = apply the prepared traits to new atts
                }

                // reset to the old moniker
                resOpt.FromMoniker = oldMoniker;
            }

            this.Rasb.MarkInherited();
            this.Rasb.ResolvedAttributeSet.AttributeContext = under;

            if (this.Attributes != null)
            {
                int l = this.Attributes.Count;
                for (int i = 0; i < l; i++)
                {
                    dynamic                    att      = this.Attributes.AllItems[i];
                    CdmAttributeContext        attUnder = under;
                    AttributeContextParameters acpAtt   = null;
                    if (under != null)
                    {
                        acpAtt = new AttributeContextParameters
                        {
                            under         = under,
                            type          = CdmAttributeContextType.AttributeDefinition,
                            Name          = att.FetchObjectDefinitionName(),
                            Regarding     = att,
                            IncludeTraits = false
                        };
                    }
                    this.Rasb.MergeAttributes(att.FetchResolvedAttributes(resOpt, acpAtt));
                }
            }
            this.Rasb.MarkOrder();
            this.Rasb.ResolvedAttributeSet.AttributeContext = under;

            // things that need to go away
            this.Rasb.RemoveRequestedAtts();

            return(this.Rasb);
        }
Esempio n. 8
0
        internal ResolvedAttributeSet FetchResolvedAttributes(ResolveOptions resOpt = null, AttributeContextParameters acpInContext = null)
        {
            bool wasPreviouslyResolving = this.Ctx.Corpus.isCurrentlyResolving;

            this.Ctx.Corpus.isCurrentlyResolving = true;
            if (resOpt == null)
            {
                resOpt = new ResolveOptions(this, this.Ctx.Corpus.DefaultResolutionDirectives);
            }

            bool inCircularReference    = false;
            bool wasInCircularReference = resOpt.InCircularReference;

            if (this is CdmEntityDefinition entity)
            {
                inCircularReference = resOpt.CurrentlyResolvingEntities.Contains(entity);
                resOpt.CurrentlyResolvingEntities.Add(entity);
                resOpt.InCircularReference = inCircularReference;

                // uncomment this line as a test to turn off allowing cycles
                //if (inCircularReference)
                //{
                //    return new ResolvedAttributeSet();
                //}
            }

            int currentDepth = resOpt.DepthInfo.CurrentDepth;

            const string   kind = "rasb";
            ResolveContext ctx  = this.Ctx as ResolveContext;
            ResolvedAttributeSetBuilder rasbResult = null;
            ResolvedAttributeSetBuilder rasbCache  = this.FetchObjectFromCache(resOpt, acpInContext);
            CdmAttributeContext         underCtx;

            // store the previous document set, we will need to add it with
            // children found from the constructResolvedTraits call
            SymbolSet currDocRefSet = resOpt.SymbolRefSet;

            if (currDocRefSet == null)
            {
                currDocRefSet = new SymbolSet();
            }
            resOpt.SymbolRefSet = new SymbolSet();

            // if using the cache passes the maxDepth, we cannot use it
            if (rasbCache != null && resOpt.DepthInfo.CurrentDepth + rasbCache.ResolvedAttributeSet.DepthTraveled > resOpt.DepthInfo.MaxDepth)
            {
                rasbCache = null;
            }

            if (rasbCache == null)
            {
                // a new context node is needed for these attributes,
                // this tree will go into the cache, so we hang it off a placeholder parent
                // when it is used from the cache (or now), then this placeholder parent is ignored and the things under it are
                // put into the 'receiving' tree
                underCtx = CdmAttributeContext.GetUnderContextForCacheContext(resOpt, this.Ctx, acpInContext);

                rasbCache = this.ConstructResolvedAttributes(resOpt, underCtx);

                if (rasbCache != null)
                {
                    // register set of possible docs
                    CdmObjectDefinition oDef = this.FetchObjectDefinition <CdmObjectDefinitionBase>(resOpt);
                    if (oDef != null)
                    {
                        ctx.Corpus.RegisterDefinitionReferenceSymbols(oDef, kind, resOpt.SymbolRefSet);

                        if (this.ObjectType == CdmObjectType.EntityDef)
                        {
                            // if we just got attributes for an entity, take the time now to clean up this cached tree and prune out
                            // things that don't help explain where the final set of attributes came from
                            if (underCtx != null)
                            {
                                var scopesForAttributes = new HashSet <CdmAttributeContext>();
                                underCtx.CollectContextFromAtts(rasbCache.ResolvedAttributeSet, scopesForAttributes); // the context node for every final attribute
                                if (!underCtx.PruneToScope(scopesForAttributes))
                                {
                                    return(null);
                                }
                            }
                        }

                        // get the new cache tag now that we have the list of docs
                        string cacheTag = ctx.Corpus.CreateDefinitionCacheTag(resOpt, this, kind, acpInContext != null ? "ctx" : null);

                        // save this as the cached version
                        if (!string.IsNullOrWhiteSpace(cacheTag))
                        {
                            ctx.AttributeCache[cacheTag] = rasbCache;
                        }
                    }
                    // get the 'underCtx' of the attribute set from the acp that is wired into
                    // the target tree
                    underCtx = rasbCache.ResolvedAttributeSet.AttributeContext?.GetUnderContextFromCacheContext(resOpt, acpInContext);
                }
            }
            else
            {
                // get the 'underCtx' of the attribute set from the cache. The one stored there was build with a different
                // acp and is wired into the fake placeholder. so now build a new underCtx wired into the output tree but with
                // copies of all cached children
                underCtx = rasbCache.ResolvedAttributeSet.AttributeContext?.GetUnderContextFromCacheContext(resOpt, acpInContext);
                //underCtx.ValidateLineage(resOpt); // debugging
            }

            if (rasbCache != null)
            {
                // either just built something or got from cache
                // either way, same deal: copy resolved attributes and copy the context tree associated with it
                // 1. deep copy the resolved att set (may have groups) and leave the attCtx pointers set to the old tree
                // 2. deep copy the tree.

                // 1. deep copy the resolved att set (may have groups) and leave the attCtx pointers set to the old tree
                rasbResult = new ResolvedAttributeSetBuilder
                {
                    ResolvedAttributeSet = rasbCache.ResolvedAttributeSet.Copy()
                };

                // 2. deep copy the tree and map the context references.
                if (underCtx != null) // null context? means there is no tree, probably 0 attributes came out
                {
                    if (!underCtx.AssociateTreeCopyWithAttributes(resOpt, rasbResult.ResolvedAttributeSet))
                    {
                        return(null);
                    }
                }
            }

            if (this is CdmEntityAttributeDefinition)
            {
                // current depth should now be set to this entity attribute level
                resOpt.DepthInfo.CurrentDepth = currentDepth;
                // now at the top of the chain where max depth does not influence the cache
                if (currentDepth == 0)
                {
                    resOpt.DepthInfo.MaxDepthExceeded = false;
                }
            }

            if (!inCircularReference && this.ObjectType == CdmObjectType.EntityDef)
            {
                // should be removed from the root level only
                // if it is in a circular reference keep it there
                resOpt.CurrentlyResolvingEntities.Remove(this as CdmEntityDefinition);
            }
            resOpt.InCircularReference = wasInCircularReference;

            // merge child document set with current
            currDocRefSet.Merge(resOpt.SymbolRefSet);
            resOpt.SymbolRefSet = currDocRefSet;

            this.Ctx.Corpus.isCurrentlyResolving = wasPreviouslyResolving;

            return(rasbResult?.ResolvedAttributeSet);
        }
Esempio n. 9
0
        internal ResolvedAttributeSet FetchResolvedAttributes(ResolveOptions resOpt = null, AttributeContextParameters acpInContext = null)
        {
            bool wasPreviouslyResolving = this.Ctx.Corpus.isCurrentlyResolving;

            this.Ctx.Corpus.isCurrentlyResolving = true;
            if (resOpt == null)
            {
                resOpt = new ResolveOptions(this, this.Ctx.Corpus.DefaultResolutionDirectives);
            }


            const string   kind = "rasb";
            ResolveContext ctx  = this.Ctx as ResolveContext;
            ResolvedAttributeSetBuilder rasbResult = null;
            // keep track of the context node that the results of this call would like to use as the parent
            CdmAttributeContext         parentCtxForResult = null;
            ResolvedAttributeSetBuilder rasbCache          = this.FetchObjectFromCache(resOpt, acpInContext);
            CdmAttributeContext         underCtx           = null;

            if (acpInContext != null)
            {
                parentCtxForResult = acpInContext.under;
            }

            // store the previous document set, we will need to add it with
            // children found from the constructResolvedTraits call
            SymbolSet currDocRefSet = resOpt.SymbolRefSet;

            if (currDocRefSet == null)
            {
                currDocRefSet = new SymbolSet();
            }
            resOpt.SymbolRefSet = new SymbolSet();

            // if using the cache passes the maxDepth, we cannot use it
            if (rasbCache != null && resOpt.DepthInfo != null && resOpt.DepthInfo.CurrentDepth + rasbCache.ResolvedAttributeSet.DepthTraveled > resOpt.DepthInfo.MaxDepth)
            {
                rasbCache = null;
            }

            if (rasbCache == null)
            {
                if (this.resolvingAttributes)
                {
                    // re-entered this attribute through some kind of self or looping reference.
                    this.Ctx.Corpus.isCurrentlyResolving = wasPreviouslyResolving;
                    //return new ResolvedAttributeSet();  // uncomment this line as a test to turn off allowing cycles
                    resOpt.InCircularReference = true;
                    this.circularReference     = true;
                }
                this.resolvingAttributes = true;

                // a new context node is needed for these attributes,
                // this tree will go into the cache, so we hang it off a placeholder parent
                // when it is used from the cache (or now), then this placeholder parent is ignored and the things under it are
                // put into the 'receiving' tree
                underCtx = CdmAttributeContext.GetUnderContextForCacheContext(resOpt, this.Ctx, acpInContext);

                rasbCache = this.ConstructResolvedAttributes(resOpt, underCtx);

                this.resolvingAttributes = false;

                if (rasbCache != null)
                {
                    // register set of possible docs
                    CdmObjectDefinition oDef = this.FetchObjectDefinition <CdmObjectDefinitionBase>(resOpt);
                    if (oDef != null)
                    {
                        ctx.Corpus.RegisterDefinitionReferenceSymbols(oDef, kind, resOpt.SymbolRefSet);

                        // get the new cache tag now that we have the list of docs
                        string cacheTag = ctx.Corpus.CreateDefinitionCacheTag(resOpt, this, kind, acpInContext != null ? "ctx" : null);

                        // save this as the cached version
                        if (!string.IsNullOrWhiteSpace(cacheTag))
                        {
                            ctx.Cache[cacheTag] = rasbCache;
                        }
                    }
                    // get the 'underCtx' of the attribute set from the acp that is wired into
                    // the target tree
                    underCtx = (rasbCache as ResolvedAttributeSetBuilder).ResolvedAttributeSet.AttributeContext?.GetUnderContextFromCacheContext(resOpt, acpInContext);
                }

                if (this.circularReference)
                {
                    resOpt.InCircularReference = false;
                }
            }
            else
            {
                // get the 'underCtx' of the attribute set from the cache. The one stored there was build with a different
                // acp and is wired into the fake placeholder. so now build a new underCtx wired into the output tree but with
                // copies of all cached children
                underCtx = (rasbCache as ResolvedAttributeSetBuilder).ResolvedAttributeSet.AttributeContext?.GetUnderContextFromCacheContext(resOpt, acpInContext);
                //underCtx.ValidateLineage(resOpt); // debugging
            }

            if (rasbCache != null)
            {
                // either just built something or got from cache
                // either way, same deal: copy resolved attributes and copy the context tree associated with it
                // 1. deep copy the resolved att set (may have groups) and leave the attCtx pointers set to the old tree
                // 2. deep copy the tree.

                // 1. deep copy the resolved att set (may have groups) and leave the attCtx pointers set to the old tree
                rasbResult = new ResolvedAttributeSetBuilder();
                rasbResult.ResolvedAttributeSet = (rasbCache as ResolvedAttributeSetBuilder).ResolvedAttributeSet.Copy();

                // 2. deep copy the tree and map the context references.
                if (underCtx != null) // null context? means there is no tree, probably 0 attributes came out
                {
                    if (underCtx.AssociateTreeCopyWithAttributes(resOpt, rasbResult.ResolvedAttributeSet) == false)
                    {
                        return(null);
                    }
                }
            }

            DepthInfo currDepthInfo = resOpt.DepthInfo;

            if (this is CdmEntityAttributeDefinition && currDepthInfo != null)
            {
                // if we hit the maxDepth, we are now going back up
                currDepthInfo.CurrentDepth--;
                // now at the top of the chain where max depth does not influence the cache
                if (currDepthInfo.CurrentDepth <= 0)
                {
                    resOpt.DepthInfo = null;
                }
            }

            // merge child document set with current
            currDocRefSet.Merge(resOpt.SymbolRefSet);
            resOpt.SymbolRefSet = currDocRefSet;

            this.Ctx.Corpus.isCurrentlyResolving = wasPreviouslyResolving;
            return(rasbResult?.ResolvedAttributeSet);
        }