/// <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; } }