Example #1
0
        /// Returns a map from parameter names to the final argument values for a trait reference.
        /// Values come (in this order) from base trait defaults, then default overrides on inheritence,
        /// then values supplied on this reference.
        public Dictionary <string, dynamic> FetchFinalArgumentValues(ResolveOptions resOpt)
        {
            Dictionary <string, dynamic> finalArgs = new Dictionary <string, dynamic>();
            // get resolved traits does all the work, just clean up the answers
            ResolvedTraitSet rts = this.FetchResolvedTraits(resOpt);

            if (rts == null)
            {
                return(null);
            }
            // there is only one resolved trait
            ResolvedTrait rt = rts.First;

            if (rt.ParameterValues != null && rt.ParameterValues.Length > 0)
            {
                int l = rt.ParameterValues.Length;
                for (int i = 0; i < l; i++)
                {
                    var     p    = rt.ParameterValues.FetchParameterAtIndex(i);
                    dynamic v    = rt.ParameterValues.FetchValue(i);
                    string  name = p.Name;
                    if (name == null)
                    {
                        name = i.ToString();
                    }
                    finalArgs.Add(name, v);
                }
            }

            return(finalArgs);
        }
Example #2
0
        private static ProjectionAttributeStateSet CreateNewProjectionAttributeStateSet(
            ProjectionContext projCtx,
            ProjectionAttributeStateSet projOutputSet,
            ResolvedAttribute newResAttrFK,
            string refAttrName)
        {
            List <ProjectionAttributeState> pasList = ProjectionResolutionCommonUtil.GetLeafList(projCtx, refAttrName);

            if (pasList != null)
            {
                // update the new foreign key resolved attribute with trait param with reference details
                ResolvedTrait reqdTrait = newResAttrFK.ResolvedTraits.Find(projCtx.ProjectionDirective.ResOpt, "is.linkedEntity.identifier");
                if (reqdTrait != null)
                {
                    CdmEntityReference traitParamEntRef = ProjectionResolutionCommonUtil.CreateForeignKeyLinkedEntityIdentifierTraitParameter(projCtx.ProjectionDirective, projOutputSet.Ctx.Corpus, pasList);
                    reqdTrait.ParameterValues.SetParameterValue(projCtx.ProjectionDirective.ResOpt, "entityReferences", traitParamEntRef);
                }

                // Create new output projection attribute state set for FK and add prevPas as previous state set
                ProjectionAttributeState newProjAttrStateFK = new ProjectionAttributeState(projOutputSet.Ctx)
                {
                    CurrentResolvedAttribute = newResAttrFK,
                    PreviousStateList        = pasList
                };

                projOutputSet.Add(newProjAttrStateFK);
            }
            else
            {
                // Log error & return projOutputSet without any change
                Logger.Error(TAG, projOutputSet.Ctx, $"Unable to locate state for reference attribute \"{refAttrName}\".", nameof(CreateNewProjectionAttributeStateSet));
            }

            return(projOutputSet);
        }
Example #3
0
        /// Returns a map from parameter names to the final argument values for a trait reference.
        /// Values come (in this order) from base trait defaults, then default overrides on inheritence,
        /// then values supplied on this reference.
        public Dictionary <string, dynamic> FetchFinalArgumentValues(ResolveOptions resOpt)
        {
            Dictionary <string, dynamic> finalArgs = new Dictionary <string, dynamic>();
            // get resolved traits does all the work, just clean up the answers
            ResolvedTraitSet rts = this.FetchResolvedTraits(resOpt);

            if (rts == null || rts.Size != 1)
            {
                // well didn't get the traits. maybe imports are missing or maybe things are just not defined yet.
                // this function will try to fake up some answers then from the arguments that are set on this reference only
                if (this.Arguments != null && this.Arguments.Count > 0)
                {
                    int unNamedCount = 0;
                    foreach (var arg in this.Arguments)
                    {
                        // if no arg name given, use the position in the list.
                        string argName = arg.Name;
                        if (string.IsNullOrWhiteSpace(argName))
                        {
                            argName = unNamedCount.ToString();
                        }
                        finalArgs.Add(argName, arg.Value);
                        unNamedCount++;
                    }
                    return(finalArgs);
                }
                return(null);
            }
            // there is only one resolved trait
            ResolvedTrait rt = rts.First;

            if (rt?.ParameterValues != null && rt.ParameterValues.Length > 0)
            {
                int l = rt.ParameterValues.Length;
                for (int i = 0; i < l; i++)
                {
                    var     p    = rt.ParameterValues.FetchParameterAtIndex(i);
                    dynamic v    = rt.ParameterValues.FetchValue(i);
                    string  name = p.Name;
                    if (name == null)
                    {
                        name = i.ToString();
                    }
                    finalArgs.Add(name, v);
                }
            }

            return(finalArgs);
        }
        private static ProjectionAttributeStateSet CreateNewProjectionAttributeStateSet(
            ProjectionContext projCtx,
            ProjectionAttributeStateSet projOutputSet,
            ResolvedAttribute newResAttrFK,
            string refAttrName)
        {
            List <ProjectionAttributeState> pasList = ProjectionResolutionCommonUtil.GetLeafList(projCtx, refAttrName);
            string sourceEntity = projCtx.ProjectionDirective.OriginalSourceAttributeName;

            if (sourceEntity == null)
            {
                Logger.Warning(projOutputSet.Ctx, Tag, nameof(CreateNewProjectionAttributeStateSet), null, CdmLogCode.WarnProjFKWithoutSourceEntity, refAttrName);
            }

            if (pasList != null)
            {
                // update the new foreign key resolved attribute with trait param with reference details
                ResolvedTrait reqdTrait = newResAttrFK.ResolvedTraits.Find(projCtx.ProjectionDirective.ResOpt, "is.linkedEntity.identifier");
                if (reqdTrait != null && sourceEntity != null)
                {
                    CdmEntityReference traitParamEntRef = ProjectionResolutionCommonUtil.CreateForeignKeyLinkedEntityIdentifierTraitParameter(projCtx.ProjectionDirective, projOutputSet.Ctx.Corpus, pasList);
                    reqdTrait.ParameterValues.SetParameterValue(projCtx.ProjectionDirective.ResOpt, "entityReferences", traitParamEntRef);
                }

                // Create new output projection attribute state set for FK and add prevPas as previous state set
                ProjectionAttributeState newProjAttrStateFK = new ProjectionAttributeState(projOutputSet.Ctx)
                {
                    CurrentResolvedAttribute = newResAttrFK,
                    PreviousStateList        = pasList
                };

                projOutputSet.Add(newProjAttrStateFK);
            }
            else
            {
                // Log error & return projOutputSet without any change
                Logger.Error(projOutputSet.Ctx, Tag, nameof(CreateNewProjectionAttributeStateSet), null, CdmLogCode.ErrProjRefAttrStateFailure, refAttrName);
            }

            return(projOutputSet);
        }
        internal override ResolvedTraitSet FetchResolvedTraits(ResolveOptions resOpt = null)
        {
            if (resOpt == null)
            {
                resOpt = new ResolveOptions(this, this.Ctx.Corpus.DefaultResolutionDirectives);
            }

            const string   kind = "rtsb";
            ResolveContext ctx  = this.Ctx as ResolveContext;
            // this may happen 0, 1 or 2 times. so make it fast
            CdmTraitDefinition baseTrait  = null;
            ResolvedTraitSet   baseRts    = null;
            List <dynamic>     baseValues = null;

            System.Action GetBaseInfo = () =>
            {
                if (this.ExtendsTrait != null)
                {
                    baseTrait = this.ExtendsTrait.FetchObjectDefinition <CdmTraitDefinition>(resOpt);
                    if (baseTrait != null)
                    {
                        baseRts = this.ExtendsTrait.FetchResolvedTraits(resOpt);
                        if (baseRts?.Size == 1)
                        {
                            ParameterValueSet basePv = baseRts.Get(baseTrait)?.ParameterValues;
                            if (basePv != null)
                            {
                                baseValues = basePv.Values;
                            }
                        }
                    }
                }
            };

            // see if one is already cached
            // if this trait has parameters, then the base trait found through the reference might be a different reference
            // because trait references are unique per argument value set. so use the base as a part of the cache tag
            // since it is expensive to figure out the extra tag, cache that too!
            if (this.BaseIsKnownToHaveParameters == null)
            {
                GetBaseInfo();
                // is a cache tag needed? then make one
                this.BaseIsKnownToHaveParameters = false;
                if (baseValues?.Count > 0)
                {
                    this.BaseIsKnownToHaveParameters = true;
                }
            }
            string cacheTagExtra = "";

            if (this.BaseIsKnownToHaveParameters == true)
            {
                cacheTagExtra = this.ExtendsTrait.Id.ToString();
            }

            string  cacheTag         = ctx.Corpus.CreateDefinitionCacheTag(resOpt, this, kind, cacheTagExtra);
            dynamic rtsResultDynamic = null;

            if (cacheTag != null)
            {
                ctx.Cache.TryGetValue(cacheTag, out rtsResultDynamic);
            }
            ResolvedTraitSet rtsResult = rtsResultDynamic as ResolvedTraitSet;

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

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

            // if not, then make one and save it
            if (rtsResult == null)
            {
                GetBaseInfo();
                if (baseTrait != null)
                {
                    // get the resolution of the base class and use the values as a starting point for this trait's values
                    if (!this.HasSetFlags)
                    {
                        // inherit these flags
                        if (this.Elevated == null)
                        {
                            this.Elevated = baseTrait.Elevated;
                        }
                        if (this.Ugly == null)
                        {
                            this.Ugly = baseTrait.Ugly;
                        }
                        if (this.AssociatedProperties == null)
                        {
                            this.AssociatedProperties = baseTrait.AssociatedProperties;
                        }
                    }
                }
                this.HasSetFlags = true;
                ParameterCollection pc     = this.FetchAllParameters(resOpt);
                List <dynamic>      av     = new List <dynamic>();
                List <bool>         wasSet = new List <bool>();
                this.ThisIsKnownToHaveParameters = pc.Sequence.Count > 0;
                for (int i = 0; i < pc.Sequence.Count; i++)
                {
                    // either use the default value or (higher precidence) the value taken from the base reference
                    dynamic value     = (pc.Sequence[i] as CdmParameterDefinition).DefaultValue;
                    dynamic baseValue = null;
                    if (baseValues != null && i < baseValues.Count)
                    {
                        baseValue = baseValues[i];
                        if (baseValue != null)
                        {
                            value = baseValue;
                        }
                    }
                    av.Add(value);
                    wasSet.Add(false);
                }

                // save it
                ResolvedTrait resTrait = new ResolvedTrait(this, pc, av, wasSet);
                rtsResult = new ResolvedTraitSet(resOpt);
                rtsResult.Merge(resTrait, false);

                // register set of possible symbols
                ctx.Corpus.RegisterDefinitionReferenceSymbols(this.FetchObjectDefinition <CdmObjectDefinitionBase>(resOpt), kind, resOpt.SymbolRefSet);
                // get the new cache tag now that we have the list of docs
                cacheTag = ctx.Corpus.CreateDefinitionCacheTag(resOpt, this, kind, cacheTagExtra);
                if (!string.IsNullOrWhiteSpace(cacheTag))
                {
                    ctx.Cache[cacheTag] = rtsResult;
                }
            }
            else
            {
                // cache found
                // get the SymbolSet for this cached object
                string key = CdmCorpusDefinition.CreateCacheKeyFromObject(this, kind);
                ((CdmCorpusDefinition)ctx.Corpus).DefinitionReferenceSymbols.TryGetValue(key, out SymbolSet tempSymbolRefSet);
                resOpt.SymbolRefSet = tempSymbolRefSet;
            }
            // merge child document set with current
            currSymbolRefSet.Merge(resOpt.SymbolRefSet);
            resOpt.SymbolRefSet = currSymbolRefSet;

            return(rtsResult);
        }
        internal static CdmTraitReference ResolvedTraitToTraitRef(ResolveOptions resOpt, ResolvedTrait rt)
        {
            CdmTraitReference traitRef = null;

            if (rt.ParameterValues != null && rt.ParameterValues.Length > 0)
            {
                traitRef = rt.Trait.Ctx.Corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, rt.TraitName, false);
                int l = rt.ParameterValues.Length;
                if (l == 1)
                {
                    // just one argument, use the shortcut syntax
                    dynamic val = rt.ParameterValues.Values[0];
                    if (val != null)
                    {
                        traitRef.Arguments.Add(null, val);
                    }
                }
                else
                {
                    for (int i = 0; i < l; i++)
                    {
                        CdmParameterDefinition param = rt.ParameterValues.FetchParameterAtIndex(i);
                        dynamic val = rt.ParameterValues.Values[i];
                        if (val != null)
                        {
                            traitRef.Arguments.Add(param.Name, val);
                        }
                    }
                }
            }
            else
            {
                traitRef = rt.Trait.Ctx.Corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, rt.TraitName, true);
            }
            if (resOpt.SaveResolutionsOnCopy)
            {
                // used to localize references between documents
                traitRef.ExplicitReference = rt.Trait as CdmTraitDefinition;
                traitRef.InDocument        = (rt.Trait as CdmTraitDefinition).InDocument;
            }
            // always make it a property when you can, however the dataFormat traits should be left alone
            if (rt.Trait.AssociatedProperties != null && !rt.Trait.IsDerivedFrom("is.dataFormat", resOpt))
            {
                traitRef.IsFromProperty = true;
            }
            return(traitRef);
        }
        // the only thing we need this code for is testing!!!
        public override ResolvedEntityReferenceSet FetchResolvedEntityReferences(ResolveOptions resOpt = null)
        {
            if (resOpt == null)
            {
                resOpt = new ResolveOptions(this);
            }

            ResolvedTraitSet rtsThisAtt = this.FetchResolvedTraits(resOpt);
            CdmAttributeResolutionGuidance resGuide = (CdmAttributeResolutionGuidance)this.ResolutionGuidance;

            // this context object holds all of the info about what needs to happen to resolve these attributes
            AttributeResolutionContext arc = new AttributeResolutionContext(resOpt, resGuide, rtsThisAtt);

            RelationshipInfo relInfo = this.GetRelationshipInfo(resOpt, arc);
            if (relInfo.IsByRef && !relInfo.IsArray)
            {
                {
                    // only place this is used, so logic here instead of encapsulated. 
                    // make a set and the one ref it will hold
                    ResolvedEntityReferenceSet rers = new ResolvedEntityReferenceSet(resOpt);
                    ResolvedEntityReference rer = new ResolvedEntityReference();
                    // referencing attribute(s) come from this attribute
                    rer.Referencing.ResolvedAttributeSetBuilder.MergeAttributes(this.FetchResolvedAttributes(resOpt, null));
                    Func<CdmEntityReference, ResolvedEntityReferenceSide> resolveSide = entRef =>
                    {
                        ResolvedEntityReferenceSide sideOther = new ResolvedEntityReferenceSide(null, null);
                        if (entRef != null)
                        {
                            // reference to the other entity, hard part is the attribue name.
                            // by convention, this is held in a trait that identifies the key
                            sideOther.Entity = entRef.FetchObjectDefinition<CdmEntityDefinition>(resOpt);
                            if (sideOther.Entity != null)
                            {
                                CdmAttribute otherAttribute;
                                ResolveOptions otherOpts = new ResolveOptions { WrtDoc = resOpt.WrtDoc, Directives = resOpt.Directives };
                                ResolvedTrait t = entRef.FetchResolvedTraits(otherOpts).Find(otherOpts, "is.identifiedBy");
                                if (t?.ParameterValues?.Length > 0)
                                {
                                    dynamic otherRef = (t.ParameterValues.FetchParameterValueByName("attribute").Value);
                                    if (typeof(CdmObject).IsAssignableFrom(otherRef?.GetType()))
                                    {
                                        otherAttribute = (otherRef as CdmObject).FetchObjectDefinition<CdmObjectDefinition>(otherOpts) as CdmAttribute;
                                        if (otherAttribute != null)
                                        {
                                            sideOther.ResolvedAttributeSetBuilder.OwnOne(sideOther.Entity.FetchResolvedAttributes(otherOpts).Get(otherAttribute.GetName()).Copy());
                                        }
                                    }
                                }
                            }
                        }

                        return sideOther;
                    };

                    // either several or one entity
                    // for now, a sub for the 'select one' idea
                    if ((this.Entity as CdmEntityReference).ExplicitReference != null)
                    {
                        CdmEntityDefinition entPickFrom = (this.Entity as CdmEntityReference).FetchObjectDefinition<CdmEntityDefinition>(resOpt);
                        CdmCollection<CdmAttributeItem> attsPick = entPickFrom.GetAttributeDefinitions();
                        if (attsPick != null && attsPick != null)
                        {
                            for (int i = 0; i < attsPick.Count; i++)
                            {
                                if (attsPick.AllItems[i].ObjectType == CdmObjectType.EntityAttributeDef)
                                {
                                    CdmEntityReference er = (attsPick.AllItems[i] as CdmEntityAttributeDefinition).Entity;
                                    rer.Referenced.Add(resolveSide(er));
                                }
                            }
                        }
                    }
                    else
                    {
                        rer.Referenced.Add(resolveSide(this.Entity as CdmEntityReference));
                    }

                    rers.Set.Add(rer);
                    return rers;
                }
            }
            return null;
        }
        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;
        }
Example #9
0
        internal static CdmTraitReference ResolvedTraitToTraitRef(ResolveOptions resOpt, ResolvedTrait rt)
        {
            CdmTraitReference traitRef = null;

            if (rt.ParameterValues != null && rt.ParameterValues.Length > 0)
            {
                traitRef = rt.Trait.Ctx.Corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, rt.TraitName, false);
                int l = rt.ParameterValues.Length;
                if (l == 1)
                {
                    // just one argument, use the shortcut syntax
                    dynamic val = ProtectParameterValues(resOpt, rt.ParameterValues.Values[0]);
                    if (val != null)
                    {
                        traitRef.Arguments.Add(null, val);
                    }
                }
                else
                {
                    for (int i = 0; i < l; i++)
                    {
                        CdmParameterDefinition param = rt.ParameterValues.FetchParameterAtIndex(i);
                        dynamic val = ProtectParameterValues(resOpt, rt.ParameterValues.Values[i]);
                        if (val != null)
                        {
                            traitRef.Arguments.Add(param.Name, val);
                        }
                    }
                }
            }
            else
            {
                traitRef = rt.Trait.Ctx.Corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, rt.TraitName, true);
            }
            if (resOpt.SaveResolutionsOnCopy)
            {
                // used to localize references between documents
                traitRef.ExplicitReference = rt.Trait;
                traitRef.InDocument        = rt.Trait.InDocument;
            }
            // always make it a property when you can, however the dataFormat traits should be left alone
            // also the wellKnown is the first constrained list that uses the datatype to hold the table instead of the default value property.
            // so until we figure out how to move the enums away from default value, show that trait too
            if (rt.Trait.AssociatedProperties != null && !rt.Trait.IsDerivedFrom("is.dataFormat", resOpt) && !(rt.Trait.TraitName == "is.constrainedList.wellKnown"))
            {
                traitRef.IsFromProperty = true;
            }
            return(traitRef);
        }
Example #10
0
        internal static CdmTraitReference ResolvedTraitToTraitRef(ResolveOptions resOpt, ResolvedTrait rt)
        {
            CdmTraitReference traitRef = null;

            if (rt.ParameterValues != null && rt.ParameterValues.Length > 0)
            {
                traitRef = rt.Trait.Ctx.Corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, rt.TraitName, false);
                int l = rt.ParameterValues.Length;
                if (l == 1)
                {
                    // just one argument, use the shortcut syntax
                    dynamic val = rt.ParameterValues.Values[0];
                    if (val != null)
                    {
                        traitRef.Arguments.Add(null, val);
                    }
                }
                else
                {
                    for (int i = 0; i < l; i++)
                    {
                        CdmParameterDefinition param = rt.ParameterValues.FetchParameterAtIndex(i);
                        dynamic val = rt.ParameterValues.Values[i];
                        if (val != null)
                        {
                            traitRef.Arguments.Add(param.Name, val);
                        }
                    }
                }
            }
            else
            {
                traitRef = rt.Trait.Ctx.Corpus.MakeObject <CdmTraitReference>(CdmObjectType.TraitRef, rt.TraitName, true);
            }
            if (resOpt.SaveResolutionsOnCopy)
            {
                // used to localize references between documents
                traitRef.ExplicitReference = rt.Trait as CdmTraitDefinition;
                traitRef.DocCreatedIn      = (rt.Trait as CdmTraitDefinition).DocCreatedIn;
            }
            return(traitRef);
        }