private void WriteTabularConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts) { var tableContext = _activeTables.Peek(); if (tableContext.Table == null) { tableContext.Table = AddTable(tableContext); } var conceptRow = tableContext.Table.InsertRow(); var placeholder = string.Format(Placeholders.CellConceptLevel, conceptMember.Depth); AddCellParagraph(conceptRow.Cells.First(), placeholder, GetMemberText(conceptMember)); var iColumn = 1; foreach (var member in tableContext.LinearisedHorizontalAxis) { var cell = conceptRow.Cells[iColumn]; var fact = facts[member]; if (fact != null) { AddCellFact(cell, fact, conceptMember); } iColumn += 1; } }
private void WriteTextBlockConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts) { // To start a new table after the text block. FinishActiveTable(); // Concept var conceptPlaceholder = string.Format(Placeholders.TextblockConceptLevel, conceptMember.Depth); AddTextblockParagraph(conceptPlaceholder, GetMemberText(conceptMember)); var occupiedMembers = facts.Where(item => item.Value != null).ToList(); if (!occupiedMembers.Any()) { return; } // Fact var factValue = occupiedMembers.Count > 1 ? $"Found {occupiedMembers.Count} facts for this text block, but there should be at most one." : occupiedMembers.First().Value.Fact.Value; var factPlaceholder = string.Format(Placeholders.TextblockFactLevel, conceptMember.Depth); AddTextblockParagraph(factPlaceholder, factValue); }
private void WriteTextBlockConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts) { // To create a new table after the text block. var tableContext = _activeTables.Peek(); tableContext.Table = null; var xConceptH2 = CreateMemberElement(conceptMember, HtmlXNames.H2); _xActiveNetwork.Add(xConceptH2); var occupiedMembers = facts.Where(item => item.Value != null).ToList(); if (!occupiedMembers.Any()) { return; } var xValueDiv = new XElement(HtmlXNames.Div); xValueDiv.AddClass(InlineXbrlClassNames.Fact); xValueDiv.AddClass(string.Format(InlineXbrlClassNames.Level, conceptMember.Depth)); _xActiveNetwork.Add(xValueDiv); if (occupiedMembers.Count > 1) { xValueDiv.Add($"Found {occupiedMembers.Count} facts for this text block, but there should be at most one."); return; } var singleFact = occupiedMembers.First().Value; xValueDiv.Add(CreateFactElement(singleFact, conceptMember)); }
private void WriteTabularConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts) { var tableContext = _activeTables.Peek(); if (tableContext.Table == null) { tableContext.Table = CreateHtmlTable(tableContext); } var xBodyTr = new XElement(HtmlXNames.Tr); var xLabelTd = new XElement(HtmlXNames.Td, CreateMemberElement(conceptMember, HtmlXNames.Div)); xBodyTr.Add(xLabelTd); foreach (var member in tableContext.LinearisedHorizontalAxis) { var xValueTd = new XElement(HtmlXNames.Td); var fact = facts[member]; if (fact != null) { xValueTd.Add(CreateFactElement(fact, conceptMember)); } xBodyTr.Add(xValueTd); } var xTBody = tableContext.Table.Element(HtmlXNames.Tbody); xTBody.Add(xBodyTr); }
private Paragraph AddNonFractionCellFact(Cell cell, Fact fact, ConceptMember conceptMember) { var item = conceptMember.Item; var accountingValue = fact.GetAccountingValue(item.BalanceType); var scaledValue = accountingValue / Math.Pow(10, _settings.Scale); var displayValue = LabelRoles.Negatives.Contains(conceptMember.PreferredLabelRole) ? -scaledValue : scaledValue; var formattedAbsoluteValue = Math.Abs(displayValue).ToString("N", _settings.Culture); var displayText = displayValue < 0 ? $"({formattedAbsoluteValue})" : formattedAbsoluteValue; var placeholder = displayValue < 0 ? Placeholders.CellFactMonetaryNegative : Placeholders.CellFactMonetaryPositive; return(AddCellParagraph(cell, placeholder, displayText)); }
public override void WriteConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts) { var concept = conceptMember.Item; var isTextBlock = concept.DataType == DataTypeRegistry.TextBlock; var requiresTable = concept.IsAbstract || !isTextBlock; if (requiresTable) { WriteTabularConcept(conceptMember, facts); } else { WriteTextBlockConcept(conceptMember, facts); } }
private Paragraph AddCellFact(Cell cell, FactModel factModel, ConceptMember conceptMember) { var item = conceptMember.Item; if (item.DataType == DataTypeRegistry.Monetary) { return(AddNonFractionCellFact(cell, factModel.Fact, conceptMember)); } if (DataTypeRegistry.Textual.Contains(item.DataType)) { return(AddTextualCellFact(cell, factModel.Fact)); } return(null); }
private void CreateNonFractionFactElement(XElement element, Fact fact, ConceptMember conceptMember) { var item = conceptMember.Item; element.AddClass(InlineXbrlClassNames.NonFractionFact); // Values in iXBRL are always absolute and a sign attribute is used to express a negative fact value. // This is for two reasons: // 1. There are several ways negative amounts can be rendered, e.g. leading dash, brackets, colour-coded. // 2. With negated labels, the sign of the fact value is the opposite of what is displayed. var accountingValue = fact.GetAccountingValue(item.BalanceType); var scaledAbsoluteValue = Math.Abs(accountingValue) / Math.Pow(10, _settings.Scale); var formattedValue = scaledAbsoluteValue.ToString("N", _settings.Culture); var isAccoutingValueNegative = accountingValue < 0; var decimals = _settings.Culture.NumberFormat.NumberDecimalDigits; var xNonFraction = new XElement(Namespaces.Ix + "nonFraction"); xNonFraction.SetAttributeValue("name", item.Name.ToColonSeparated(_xHtml)); xNonFraction.SetAttributeValue("contextRef", fact.GetContextId(_xHtml)); xNonFraction.SetAttributeValue("unitRef", fact.Unit.Id); xNonFraction.SetAttributeValue("scale", _settings.Scale); xNonFraction.SetAttributeValue("decimals", decimals); xNonFraction.SetAttributeValue("format", $"ixt:{_numberFormat}"); if (isAccoutingValueNegative) { xNonFraction.SetAttributeValue("sign", "-"); } xNonFraction.Value = formattedValue; element.Add(xNonFraction); var isDisplayNegative = LabelRoles.Negatives.Contains(conceptMember.PreferredLabelRole) ? !isAccoutingValueNegative : isAccoutingValueNegative; element.AddClass(isDisplayNegative ? InlineXbrlClassNames.NegativeFact : InlineXbrlClassNames.PositiveFact); if (isDisplayNegative) { element.AddFirst("("); element.Add(")"); } }
private XElement CreateFactElement(FactModel factModel, ConceptMember conceptMember) { var item = conceptMember.Item; var xSpan = new XElement(HtmlXNames.Span); xSpan.AddClass(InlineXbrlClassNames.Fact); if (item.DataType == DataTypeRegistry.Monetary) { CreateNonFractionFactElement(xSpan, factModel.Fact, conceptMember); } else if (DataTypeRegistry.Textual.Contains(item.DataType)) { CreateTextualFactElement(xSpan, factModel.Fact, item); } return(xSpan); }
public abstract void WriteConcept(ConceptMember conceptMember, IDictionary <Member, FactModel> facts);
private void OnMemberRead(ITokenReader iTokenReader, IConceptInfo conceptInfo, ConceptMember conceptMember, ValueOrError <object> valueOrError) { // have we reached a new keyword after target pos? if so, prevent further member parsing if (result.NextKeywordToken != null) { return; } var tokenReader = (TokenReader)iTokenReader; if (tokenReader.PositionInTokenList <= 0 || lastTokenBeforeTarget == null) { return; } var conceptType = conceptInfo.GetType(); var lastTokenRead = result.Tokens[tokenReader.PositionInTokenList - 1]; // track last tokens/members parsed before or at target if (lastTokenRead.PositionInDslScript <= lastTokenBeforeTarget.PositionInDslScript && !valueOrError.IsError) { result.LastTokenParsed[conceptType] = lastTokenRead; result.LastMemberReadAttempt[conceptType] = conceptMember; } // we are interested in those concepts whose member parsing stops at or after target position if (lastTokenRead.PositionInDslScript >= lastTokenBeforeTarget.PositionInDslScript && !result.ActiveConceptValidTypes.Contains(conceptType)) { result.ActiveConceptValidTypes.Add(conceptType); } }
public static int IndexOfParameter(Type conceptInfoType, ConceptMember member) { var members = GetParameters(conceptInfoType); return(members.IndexOf(member)); }
public static string ConceptMemberDescription(ConceptMember conceptMember) { return($"{conceptMember.Name}: {conceptMember.ValueType.Name}"); }