Пример #1
0
        /// <summary>
        /// A function to construct projection context and populate the resolved attribute set that ExtractResolvedAttributes method can then extract
        /// This function is the entry point for projection resolution.
        /// This function is expected to do the following 3 things:
        /// - Create an condition expression tree & default if appropriate
        /// - Create and initialize Projection Context
        /// - Process operations
        /// </summary>
        /// <param name="projDirective"></param>
        /// <param name="attrCtx"></param>
        /// <returns></returns>
        internal ProjectionContext ConstructProjectionContext(ProjectionDirective projDirective, CdmAttributeContext attrCtx)
        {
            ProjectionContext projContext = null;

            if (string.IsNullOrWhiteSpace(this.Condition))
            {
                // if no condition is provided, get default condition and persist
                this.Condition = ConditionExpression.GetDefaultConditionExpression(this.Operations, this.Owner);
            }
            // create an expression tree based on the condition
            ExpressionTree tree = new ExpressionTree();

            this.ConditionExpressionTreeRoot = tree.ConstructExpressionTree(this.Condition);
            if (this.ConditionExpressionTreeRoot == null)
            {
                Logger.Info(nameof(CdmProjection), this.Ctx, $"Optional expression missing. Implicit expression will automatically apply.", nameof(ConstructProjectionContext));
            }

            if (attrCtx != null)
            {
                // Add projection to context tree
                AttributeContextParameters acpProj = new AttributeContextParameters
                {
                    under         = attrCtx,
                    type          = CdmAttributeContextType.Projection,
                    Name          = this.FetchObjectDefinitionName(),
                    Regarding     = projDirective.OwnerRef,
                    IncludeTraits = false
                };
                CdmAttributeContext acProj = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpProj);

                AttributeContextParameters acpSource = new AttributeContextParameters
                {
                    under         = acProj,
                    type          = CdmAttributeContextType.Source,
                    Name          = "source",
                    Regarding     = null,
                    IncludeTraits = false
                };
                CdmAttributeContext acSource = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpSource);

                if (this.Source.FetchObjectDefinition <CdmObjectDefinition>(projDirective.ResOpt).ObjectType == CdmObjectType.ProjectionDef)
                {
                    // A Projection

                    projContext = ((CdmProjection)this.Source.ExplicitReference).ConstructProjectionContext(projDirective, acSource);
                }
                else
                {
                    // An Entity Reference

                    AttributeContextParameters acpSourceProjection = new AttributeContextParameters
                    {
                        under         = acSource,
                        type          = CdmAttributeContextType.Entity,
                        Name          = this.Source.NamedReference ?? this.Source.ExplicitReference.GetName(),
                        Regarding     = this.Source,
                        IncludeTraits = false
                    };
                    ResolvedAttributeSet ras = this.Source.FetchResolvedAttributes(projDirective.ResOpt, acpSourceProjection);

                    // Initialize the projection context

                    CdmCorpusContext ctx = (projDirective.Owner?.Ctx);

                    ProjectionAttributeStateSet pasSet = null;

                    // if polymorphic keep original source as previous state
                    Dictionary <string, List <ProjectionAttributeState> > polySourceSet = null;
                    if (projDirective.IsSourcePolymorphic)
                    {
                        polySourceSet = ProjectionResolutionCommonUtil.GetPolymorphicSourceSet(projDirective, ctx, this.Source, acpSourceProjection);
                    }

                    // now initialize projection attribute state
                    pasSet = ProjectionResolutionCommonUtil.InitializeProjectionAttributeStateSet(
                        projDirective,
                        ctx,
                        ras,
                        isSourcePolymorphic: projDirective.IsSourcePolymorphic,
                        polymorphicSet: polySourceSet);

                    projContext = new ProjectionContext(projDirective, ras.AttributeContext)
                    {
                        CurrentAttributeStateSet = pasSet
                    };
                }

                bool isConditionValid = false;
                if (this.ConditionExpressionTreeRoot != null)
                {
                    InputValues input = new InputValues()
                    {
                        noMaxDepth = projDirective.HasNoMaximumDepth,
                        isArray    = projDirective.IsArray,

                        referenceOnly = projDirective.IsReferenceOnly,
                        normalized    = projDirective.IsNormalized,
                        structured    = projDirective.IsStructured,

                        nextDepth = ++projDirective.CurrentDepth,
                        maxDepth  = projDirective.MaximumDepth,

                        minCardinality = projDirective.Cardinality?._MinimumNumber,
                        maxCardinality = projDirective.Cardinality?._MaximumNumber
                    };

                    isConditionValid = ExpressionTree.EvaluateExpressionTree(this.ConditionExpressionTreeRoot, input);
                }

                if (isConditionValid && this.Operations != null && this.Operations.Count > 0)
                {
                    // Just in case new operations were added programmatically, reindex operations
                    for (int i = 0; i < this.Operations.Count; i++)
                    {
                        this.Operations[i].Index = i + 1;
                    }

                    // Operation

                    AttributeContextParameters acpGenAttrSet = new AttributeContextParameters
                    {
                        under = attrCtx,
                        type  = CdmAttributeContextType.GeneratedSet,
                        Name  = "_generatedAttributeSet"
                    };
                    CdmAttributeContext acGenAttrSet = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpGenAttrSet);

                    AttributeContextParameters acpGenAttrRound0 = new AttributeContextParameters
                    {
                        under = acGenAttrSet,
                        type  = CdmAttributeContextType.GeneratedRound,
                        Name  = "_generatedAttributeRound0"
                    };
                    CdmAttributeContext acGenAttrRound0 = CdmAttributeContext.CreateChildUnder(projDirective.ResOpt, acpGenAttrRound0);

                    // Start with an empty list for each projection
                    ProjectionAttributeStateSet pasOperations = new ProjectionAttributeStateSet(projContext.CurrentAttributeStateSet.Ctx);
                    foreach (CdmOperationBase operation in this.Operations)
                    {
                        // Evaluate projections and apply to empty state
                        ProjectionAttributeStateSet newPasOperations = operation.AppendProjectionAttributeState(projContext, pasOperations, acGenAttrRound0);

                        // If the operations fails or it is not implemented the projection cannot be evaluated so keep previous valid state.
                        if (newPasOperations != null)
                        {
                            pasOperations = newPasOperations;
                        }
                    }

                    // Finally update the current state to the projection context
                    projContext.CurrentAttributeStateSet = pasOperations;
                }
                else
                {
                    // Pass Through - no operations to process
                }
            }

            return(projContext);
        }
Пример #2
0
        public void TestGetDefaultConditionExpression()
        {
            CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestGetDefaultConditionExpression");

            corpus.Storage.Mount("local", new LocalAdapter(TestHelper.GetActualOutputFolderPath(testsSubpath, "TestGetDefaultConditionExpression")));
            CdmFolderDefinition   localRoot       = corpus.Storage.FetchRootFolder("local");
            CdmManifestDefinition manifestDefault = CreateDefaultManifest(corpus, localRoot);

            CdmEntityDefinition entityTestSource = CreateEntityTestSource(corpus, manifestDefault, localRoot);

            // projection for a non entity attribute
            CdmOperationCollection opColl = new CdmOperationCollection(corpus.Ctx, entityTestSource);
            {
                // add 1st FK
                opColl.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx));
                Assert.AreEqual($" (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource));

                // add 2nd FK
                opColl.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx));
                Assert.AreEqual($" (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource));

                opColl.Clear();

                // add AddCount
                opColl.Add(new CdmOperationAddCountAttribute(corpus.Ctx));
                Assert.AreEqual($" (!structured) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource));

                // add ArrayExpansion
                opColl.Add(new CdmOperationArrayExpansion(corpus.Ctx));
                Assert.AreEqual($" (!structured) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource));

                opColl.Clear();

                // add AddSupporting
                opColl.Add(new CdmOperationAddSupportingAttribute(corpus.Ctx));
                Assert.AreEqual($" (true) ", ConditionExpression.GetDefaultConditionExpression(opColl, owner: entityTestSource));
            }

            CdmEntityAttributeDefinition entityTestEntityAttribute = corpus.MakeObject <CdmEntityAttributeDefinition>(CdmObjectType.EntityAttributeDef, nameOrRef: "TestEntityAttribute", simpleNameRef: false);

            // projection for a non entity attribute
            CdmOperationCollection opCollEA = new CdmOperationCollection(corpus.Ctx, entityTestEntityAttribute);
            {
                // add 1st FK
                opCollEA.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx));
                Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) )  &&  (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute));

                // add 2nd FK
                opCollEA.Add(new CdmOperationReplaceAsForeignKey(corpus.Ctx));
                Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) )  &&  (referenceOnly || noMaxDepth || (depth > maxDepth)) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute));

                opCollEA.Clear();

                // add AddCount
                opCollEA.Add(new CdmOperationAddCountAttribute(corpus.Ctx));
                Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) )  &&  (!structured) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute));

                // add ArrayExpansion
                opCollEA.Add(new CdmOperationArrayExpansion(corpus.Ctx));
                Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) )  &&  (!structured) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute));

                opCollEA.Clear();

                // add AddSupporting
                opCollEA.Add(new CdmOperationAddSupportingAttribute(corpus.Ctx));
                Assert.AreEqual($" ( (!normalized) || (cardinality.maximum <= 1) )  &&  (true) ", ConditionExpression.GetDefaultConditionExpression(opCollEA, owner: entityTestEntityAttribute));
            }
        }