/// <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);
        }
Пример #2
0
        public ProjectionContext(ProjectionDirective projDirective, CdmAttributeContext attrCtx)
        {
            this.ProjectionDirective = projDirective;

            this.CurrentAttributeContext = attrCtx;

            this.CurrentAttributeStateSet = new ProjectionAttributeStateSet(projDirective?.Owner?.Ctx);
        }
Пример #3
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);
        }
Пример #4
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);
        }
        /// <summary>
        /// Create a constant entity that contains the source mapping to a foreign key.
        /// e.g.
        /// an fk created to entity "Customer" based on the "customerName", would add a parameter to the "is.linkedEntity.identifier" trait as follows:
        ///   [
        ///     "/Customer.cdm.json/Customer",
        ///     "customerName"
        ///   ]
        /// In the case of polymorphic source, there will be a collection of such entries.
        /// </summary>
        /// <param name="corpus"></param>
        /// <param name="foundResAttrList"></param>
        /// <returns></returns>
        internal static CdmEntityReference CreateForeignKeyLinkedEntityIdentifierTraitParameter(ProjectionDirective projDir, CdmCorpusDefinition corpus, List <ProjectionAttributeState> refFoundList)
        {
            CdmEntityReference traitParamEntRef = null;

            List <Tuple <string, string> > entRefAndAttrNameList = new List <Tuple <string, string> >();

            foreach (ProjectionAttributeState refFound in refFoundList)
            {
                ResolvedAttribute resAttr = refFound.CurrentResolvedAttribute;

                if (resAttr?.Target?.Owner != null &&
                    (resAttr.Target.ObjectType == CdmObjectType.TypeAttributeDef || resAttr.Target.ObjectType == CdmObjectType.EntityAttributeDef))
                {
                    var owner = resAttr.Target.Owner;

                    while (owner != null && owner.ObjectType != CdmObjectType.EntityDef)
                    {
                        owner = owner.Owner;
                    }

                    if (owner != null && owner.ObjectType == CdmObjectType.EntityDef)
                    {
                        CdmEntityDefinition entDef = owner.FetchObjectDefinition <CdmEntityDefinition>(projDir.ResOpt);
                        if (entDef != null)
                        {
                            // should contain relative path without the namespace
                            string relativeEntPath = entDef.Ctx.Corpus.Storage.CreateRelativeCorpusPath(entDef.AtCorpusPath, entDef.InDocument);
                            entRefAndAttrNameList.Add(new Tuple <string, string>(relativeEntPath, resAttr.ResolvedName));
                        }
                    }
                }
            }

            if (entRefAndAttrNameList.Count > 0)
            {
                CdmConstantEntityDefinition constantEntity = corpus.MakeObject <CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef);
                constantEntity.EntityShape = corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, "entityGroupSet", true);
                string originalSourceEntityAttributeName = projDir.OriginalSourceEntityAttributeName;
                if (originalSourceEntityAttributeName == null)
                {
                    originalSourceEntityAttributeName = "";
                }

                constantEntity.ConstantValues = entRefAndAttrNameList.Select((entAndAttrName) => new List <string> {
                    entAndAttrName.Item1, entAndAttrName.Item2, $"{originalSourceEntityAttributeName}_{entAndAttrName.Item1.Substring(entAndAttrName.Item1.LastIndexOf("/") + 1)}"
                }).ToList();

                traitParamEntRef = corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, constantEntity, false);
            }

            return(traitParamEntRef);
        }