/// <summary> /// Locates all items in the given collection of facts that match the current element. /// </summary> /// <param name="ItemElement"> /// The element describing the items to be found. /// </param> /// <param name="FactList"> /// The collection of items that should be searched. /// </param> /// <returns> /// A collection of items that match the current element. If no items match, /// a non-null List will still be returned, but the list will be empty. /// </returns> /// <remarks> /// This method should most likely be moved into a class which wraps <see cref="Item"/> /// collections with a value-added wrapper class. /// </remarks> private List <Item> LocateItems(Element ItemElement, FactCollection FactList) { var ItemList = new List <Item>(); if (ItemElement != null) { foreach (Fact CurrentFact in FactList) { if ((CurrentFact is Item) == true) { var CurrentItem = CurrentFact as Item; if (CurrentItem.SchemaElement.Equals(ItemElement) == true) { ItemList.Add(CurrentItem); } } else if ((CurrentFact is Tuple) == true) { var currentTuple = CurrentFact as Tuple; var tupleList = LocateItems(ItemElement, currentTuple.Facts); ItemList.AddRange(tupleList); } } } return(ItemList); }
internal Tuple(XbrlFragment ParentFragment, INode TupleNode) : base(ParentFragment, TupleNode) { this.Facts = new FactCollection(); foreach (INode CurrentChild in TupleNode.ChildNodes) { var CurrentFact = Fact.Create(ParentFragment, CurrentChild); if (CurrentFact != null) { this.Facts.Add(CurrentFact); } } }
internal PresentableFactTree(XbrlSchema schema, FactCollection facts) { TopLevelNodes = new List <PresentableFactTreeNode>(); var presentationLinkbase = schema.PresentationLinkbase; foreach (var presentationLink in presentationLinkbase.PresentationLinks) { var unorderedPresentationArcs = presentationLink.PresentationArcs; var orderedPresentationArcs = unorderedPresentationArcs.OrderBy(o => o.Order).ToList(); var newTreeNode = new PresentableFactTreeNode(); TopLevelNodes.Add(newTreeNode); foreach (var orderedPresentationArc in orderedPresentationArcs) { // Set the tree node's node fact, if it is not already set. // // This code is making an assumption that each arc in the link is set up with // the same "from" locator, so locating the "from" fact only needs to be done // if it is not already set. If it is already set, the code assumes that it // was set from a previous arc and doesn't not need to be set again (presumably // with the same information it would get this time if it did all of the work // again). // // If the locator references an abstract element, then there will be no fact // and the value will remain null. if (newTreeNode.NodeFact == null) { var fromLocator = GetLocator(orderedPresentationArc.From, presentationLink); newTreeNode.PresentationLinkbaseLocator = fromLocator; newTreeNode.NodeLabel = GetLabel(schema, fromLocator); var fromElement = GetElement(schema, fromLocator.HrefResourceId); if (fromElement.IsAbstract == false) { var fromFact = facts.GetFactByName(fromElement.Name); newTreeNode.NodeFact = fromFact; } } var toLocator = GetLocator(orderedPresentationArc.To, presentationLink); var newChildTreeNode = new PresentableFactTreeNode(); newTreeNode.ChildNodes.Add(newChildTreeNode); newTreeNode.NodeLabel = GetLabel(schema, toLocator); newChildTreeNode.PresentationLinkbaseLocator = toLocator; var toElement = GetElement(schema, toLocator.HrefResourceId); if (toElement.IsAbstract == false) { var toFact = facts.GetFactByName(toElement.Name); newChildTreeNode.NodeFact = toFact; } } } }
/// <summary> /// Locates an item in a list of facts. /// </summary> /// <param name="ItemElement"> /// A schema element defining the item to be found. /// </param> /// <param name="FactList"> /// The collection of items that should be searched. /// </param> /// <returns> /// A reference to the first item that matches the given element, or null if no matching item is found. /// </returns> /// <remarks> /// This method should most likely be moved into a class which wraps <see cref="Item"/> /// collections with a value-added wrapper class. /// </remarks> private Item LocateItem(Element ItemElement, FactCollection FactList) { if (ItemElement == null) { return(null); } foreach (Fact CurrentFact in FactList) { var CurrentItem = CurrentFact as Item; if (CurrentItem != null) { if (CurrentItem.SchemaElement.Equals(ItemElement) == true) { return(CurrentItem); } } } return(null); }
/// <summary> /// Validates a given summation concept. /// </summary> /// <param name="CurrentCalculationLink"> /// The calculation link that defines the given summation concept. /// </param> /// <param name="CurrentSummationConcept"> /// The summation concept to be validated. /// </param> /// <param name="FactList"> /// The collection of items that should be searched when looking for summation or contributing items. /// </param> private void ValidateSummationConcept(CalculationLink CurrentCalculationLink, SummationConcept CurrentSummationConcept, FactCollection FactList) { Element SummationConceptElement = LocateElement(CurrentSummationConcept.SummationConceptLocator); Item SummationConceptItem = LocateItem(SummationConceptElement, FactList); // If the summation concept item doesn't exist, then there is no calculation // to perform. if (SummationConceptItem == null) { return; } // If the summation concept item has a "nil" value, then there is no calculation // to perform. if (SummationConceptItem.NilSpecified == true) { return; } double SummationConceptRoundedValue = SummationConceptItem.RoundedValue; double ContributingConceptRoundedValueTotal = 0; var ContributingConceptItemsFound = false; foreach (Locator CurrentLocator in CurrentSummationConcept.ContributingConceptLocators) { // Some decisions need to be made before the code can actually add the value of the // contributing concept to the total that the code is keeping. var IncludeContributingConceptItemInCalculation = true; // Find the calculation arc for the given calculation link. CalculationArc ContributingConceptCalculationArc = CurrentCalculationLink.GetCalculationArc(CurrentLocator); if (ContributingConceptCalculationArc == null) { IncludeContributingConceptItemInCalculation = false; } // Find the elemement for the given locator. Element ContributingConceptElement = LocateElement(CurrentLocator); if (ContributingConceptElement == null) { IncludeContributingConceptItemInCalculation = false; } // Find all items for the given element. If there is more than one, and at least // one of them is not p-equals with at least one of the other ones, then // the entire calculation validation is forfeit, according to test 397.12 in // the XBRL-CONF-CR3-2007-03-05 conformance suite. var AllMatchingItems = LocateItems(ContributingConceptElement, FactList); if (AllItemsNotPEquals(AllMatchingItems) == false) { return; } // Find the item for the given element. if (AllMatchingItems.Count == 0) { IncludeContributingConceptItemInCalculation = false; } else { foreach (var ContributingConceptItem in AllMatchingItems) { // Ensure that the contributing concept item is context-equals // with the summation item. if (IncludeContributingConceptItemInCalculation == true) { if (SummationConceptItem.ContextEquals(ContributingConceptItem) == false) { IncludeContributingConceptItemInCalculation = false; } } // Ensure that the contributing concept item is unit-equals // with the summation item. if (IncludeContributingConceptItemInCalculation == true) { if (SummationConceptItem.UnitEquals(ContributingConceptItem) == false) { IncludeContributingConceptItemInCalculation = false; } } // Ensure that the contributing concept item does not have a nil value. if (IncludeContributingConceptItemInCalculation == true) { if (ContributingConceptItem.NilSpecified == true) { IncludeContributingConceptItemInCalculation = false; } } // If the code is still interested in including the contributing concept item // in the calculation, then get its rounded value and add it to the total. if (IncludeContributingConceptItemInCalculation == true) { ContributingConceptItemsFound = true; double ContributingConceptRoundedValue = ContributingConceptItem.RoundedValue; if (ContributingConceptCalculationArc.Weight != (decimal)(1.0)) { ContributingConceptRoundedValue = ContributingConceptRoundedValue * (double)(ContributingConceptCalculationArc.Weight); } ContributingConceptRoundedValueTotal += ContributingConceptRoundedValue; } } } } if (ContributingConceptItemsFound == true) { ContributingConceptRoundedValueTotal = SummationConceptItem.Round(ContributingConceptRoundedValueTotal); if (SummationConceptRoundedValue != ContributingConceptRoundedValueTotal) { StringBuilder MessageBuilder = new StringBuilder(); string StringFormat = AssemblyResources.GetName("SummationConceptError"); MessageBuilder.AppendFormat(StringFormat, SummationConceptItem.Name, SummationConceptRoundedValue, ContributingConceptRoundedValueTotal); ValidatedFragment.AddValidationError(new SummationConceptValidationError(CurrentSummationConcept, MessageBuilder.ToString())); return; } } }