private void WriteConceptMember(IPresenterWriter presenterWriter, ConceptMember conceptMember, Axis verticalAxis, IList <Member> horizontalAxisMembers, FactSet facts) { var hypercubeAxis = conceptMember.HypercubeAxis; if (hypercubeAxis != null) { if (horizontalAxisMembers.Count != 1) { throw new InvalidOperationException($"Hypercubes require a single period, but the hypercube '{conceptMember.Label}' has {horizontalAxisMembers.Count} periods."); } // It is crucial to include related aspects to keep beginning/end of period // facts in the fact set. var periodSlicedFactSet = facts.Slice(horizontalAxisMembers.Single(), includeRelatedAspects: true); var reducedFactSet = periodSlicedFactSet.Reduce(hypercubeAxis); if (!reducedFactSet.FactModels.Any()) { // No fact in this hypercube axis: nothing to show. // This should not happen since the concept axis got reduced already. return; } var verticalChildAxis = verticalAxis.CreateChildAxis(conceptMember); // Clear the hypercube axis to signal consumption and avoid infinite loop. conceptMember.HypercubeAxis = null; WriteTable(presenterWriter, verticalChildAxis, hypercubeAxis, reducedFactSet); return; } var verticallySlicedFactSet = facts.Slice(conceptMember, false); var cellFacts = new Dictionary <Member, FactModel>(); foreach (var horizontalAxisMember in horizontalAxisMembers) { // It is crucial to include related aspects to keep beginning/end of period // facts in the fact set. var horizontallySlicedFactSet = verticallySlicedFactSet.Slice(horizontalAxisMember, true); var cellFact = horizontallySlicedFactSet.GetCellFact(); cellFacts[horizontalAxisMember] = cellFact; } presenterWriter.WriteConcept(conceptMember, cellFacts); foreach (var childMember in conceptMember.Children.Cast <ConceptMember>()) { WriteConceptMember(presenterWriter, childMember, verticalAxis, horizontalAxisMembers, facts); } }
private ConceptMember TraversePresentationNetwork(LocatorNode node, Uri preferredLabelRole, ISet <XName> hypercubeDimensionNames) { var concept = node.Item; var aspect = new ConceptAspect(concept.Name); var member = new ConceptMember(aspect) { Item = concept, PreferredLabelRole = preferredLabelRole, Label = concept.FindLabel(preferredLabelRole), HypercubeDimensionNames = hypercubeDimensionNames }; var outgoingArcs = node.GetOrderedOutgoingHierarchicalArcs <PresentationArc>(); var attachedHypercube = GetAttachedHypercube(node); if (attachedHypercube != null) { if (outgoingArcs.Count != 1) { throw new InvalidOperationException($"The hypercube {attachedHypercube.HypercubeItem.Name} has {outgoingArcs.Count} line items children, but exactly one is expected."); } var outgoingArc = outgoingArcs.Single(); // We are replicating and adding the line items tree for each axis, including the respective dimension name to each concept member. foreach (var hypercubeAxis in attachedHypercube.Axes) { var childHypercubeDimensionNames = new HashSet <XName>(hypercubeDimensionNames) { hypercubeAxis.Dimension.Name }; var child = TraversePresentationNetwork(outgoingArc.ToLocator, outgoingArc.PreferredLabelRole, childHypercubeDimensionNames); child.HypercubeAxis = hypercubeAxis; member.AddChild(child); } } else { foreach (var outgoingArc in outgoingArcs) { var child = TraversePresentationNetwork(outgoingArc.ToLocator, outgoingArc.PreferredLabelRole, hypercubeDimensionNames); member.AddChild(child); } } return(member); }