예제 #1
0
        /// <summary>
        /// Builds the root entity.
        /// </summary>
        /// <param name="node">The root node.</param>
        /// <param name="context">The context.</param>
        /// <returns>Entity.</returns>
        /// <exception cref="System.Exception">Unknown report node type.</exception>
        internal static Entity BuildReportNode(ReportNode node, FromEntityContext context)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Entity structuredQueryEntity;

            if (node.Is <AggregateReportNode>())
            {
                structuredQueryEntity = BuildAggregateReportNode(node.As <AggregateReportNode>(), context);
            }
            else if (node.Is <RelationshipReportNode>())
            {
                structuredQueryEntity = BuildRelationshipReportNode(node.As <RelationshipReportNode>(), context);
            }
            else if (node.Is <CustomJoinReportNode>( ))
            {
                structuredQueryEntity = BuildCustomJoinReportNode(node.As <CustomJoinReportNode>( ), context);
            }
            else if (node.Is <DerivedTypeReportNode>())
            {
                structuredQueryEntity = BuildDerivedTypeReportNode(node.As <DerivedTypeReportNode>(), context);
            }
            else if (node.Is <ResourceReportNode>())
            {
                structuredQueryEntity = BuildResourceReportNode(node.As <ResourceReportNode>(), context);
            }
            else
            {
                throw new Exception("Unknown report node type. " + node.GetType().Name);
            }
            if (node.RelatedReportNodes != null && node.RelatedReportNodes.Count > 0)
            {
                structuredQueryEntity.RelatedEntities = new List <Entity>(node.RelatedReportNodes.Select(relatedReportNode => BuildReportNode(relatedReportNode, context)).Where(entity => entity != null));
            }
            if (structuredQueryEntity != null)
            {
                // Only valid nodes get placed into the ReportNodeToEntityMap
                // (but ReportNodeMap may contain invalid nodes for historical reasons)
                context.ReportNodeToEntityMap[node.Id] = structuredQueryEntity;
            }
            return(structuredQueryEntity);
        }
        /// <summary>
        /// Populates the analyser type for column.
        /// </summary>
        /// <param name="report">The report.</param>
        /// <param name="entityType">The resource type returned if the analyser refers to a resource expression.</param>
        /// <param name="reportExpression">The report expression.</param>
        /// <param name="reportAnalyserColumn">The report analyser column.</param>
        private static void PopulateAnalyserTypeForColumn(Report report, EntityType entityType, ReportExpression reportExpression, ReportAnalyserColumn reportAnalyserColumn)
        {
            reportAnalyserColumn.AnalyserType = reportAnalyserColumn.Type.GetDisplayName();

            if (reportExpression.Is <StructureViewExpression>())
            {
                reportAnalyserColumn.AnalyserType    = StructureLevelsType.DisplayName;
                reportAnalyserColumn.DefaultOperator = Structured.ConditionType.AnyBelowStructureLevel;
                var expression    = reportExpression.As <StructureViewExpression>();
                var resReportNode = expression.StructureViewExpressionSourceNode.As <ResourceReportNode>();
                var eType         = resReportNode.ResourceReportNodeType;
                reportAnalyserColumn.TypeId = eType.Id;
                return;
            }

            if (!reportExpression.Is <NodeExpression>())
            {
                return;
            }

            NodeExpression nodeExpression = reportExpression.As <NodeExpression>();

            if (!nodeExpression.SourceNode.Is <ResourceReportNode>())
            {
                return;
            }

            bool isNameColumnForType = false;

            if (reportExpression.Is <FieldExpression>())
            {
                var fieldExpression = reportExpression.As <FieldExpression>();
                if (fieldExpression.FieldExpressionField.Alias != "core:name")
                {
                    return;
                }
                long sourceId = fieldExpression.SourceNode != null ? fieldExpression.SourceNode.Id : 0;
                long rootId   = report.RootNode != null ? report.RootNode.Id : 0;
                isNameColumnForType = (sourceId == rootId) && (sourceId != 0);
            }
            reportAnalyserColumn.IsNameColumnForType = isNameColumnForType;

            ResourceReportNode     resourceReportNode     = nodeExpression.SourceNode.As <ResourceReportNode>( );
            RelationshipReportNode relationshipReportNode = nodeExpression.SourceNode.As <RelationshipReportNode>( );

            if (entityType == null)
            {
                // Need to be able accept entityType as an argument, e.g. if it is from a script column
                // But also need to be able to read it from the node, e.g. if it is the root name column. Messed up.
                entityType = resourceReportNode.ResourceReportNodeType;
                if (entityType == null)
                {
                    return;
                }
            }

            ResourceExpression resourceExpression = reportExpression.As <ResourceExpression>();

            // Handle "Type" types
            //if the resource type is "Type", add current parent node type and descendant types' id as filtered entity ids (bug 24859)
            //Update: only the forward relationship is "isOfType", the "type" list will be restricted. (bug 27862)
            if (entityType.Alias == "core:type" &&
                relationshipReportNode?.FollowRelationship?.Alias == "core:isOfType"
                )
            {
                AggregateReportNode parentAggregatedNode     = resourceReportNode.ParentAggregatedNode;
                ReportNode          parentReportNode         = parentAggregatedNode != null ? parentAggregatedNode.GroupedNode : resourceReportNode.ParentReportNode;
                ResourceReportNode  parentResourceReportNode = parentReportNode != null?parentReportNode.As <ResourceReportNode>() : null;

                if (parentResourceReportNode != null && parentResourceReportNode.ResourceReportNodeType != null)
                {
                    reportAnalyserColumn.FilteredEntityIds = PerTenantEntityTypeCache.Instance.GetDescendantsAndSelf(
                        parentResourceReportNode.ResourceReportNodeType.Id).ToArray();
                }
            }

            // Handle "User" and "Person" types
            if (PerTenantEntityTypeCache.Instance.IsDerivedFrom(entityType.Id, "core:person") ||
                PerTenantEntityTypeCache.Instance.IsDerivedFrom(entityType.Id, "core:userAccount"))
            {
                // If this is a relationship or calc then make it as a user inline relationship otherwise a simple user string.
                reportAnalyserColumn.AnalyserType = nodeExpression.SourceNode.Is <FieldExpression>( ) ? "UserString" : "UserInlineRelationship";
                return;
            }

            // Treat the root 'Name' column like a lookup, so we get the 'Any Of', 'Any Except' options.
            if (isNameColumnForType)
            {
                reportAnalyserColumn.AnalyserType = "InlineRelationship";
                reportAnalyserColumn.TypeId       = entityType.Id;
            }
        }