/// <summary> /// Gets a <see cref="DataTable"/> representation from data in a tree structure of <see cref="NestedElement"/>s based on a <see cref="CategoryDecompositionHierarchy"/> /// </summary> /// <param name="categoryDecompositionHierarchy"> /// The <see cref="CategoryDecompositionHierarchy"/> used for filtering the considered <see cref="NestedElement"/> items. /// </param> /// <param name="nestedElements"> /// The <see cref="List{NestedElement}"/>s /// </param> /// <param name="excludeMissingParameters"> /// By default all rows are returned by filtering on <see cref="CategoryDecompositionHierarchy"/>. /// In case you only want the rows that indeed contain the wanted <see cref="ParameterValueSet"/>s then set this parameter to true. /// </param> /// <returns> /// The <see cref="DataTable"/>. /// </returns> public DataTable GetTable( CategoryDecompositionHierarchy categoryDecompositionHierarchy, List <NestedElement> nestedElements, bool excludeMissingParameters = false ) { var dataTables = this.CreateNodes(categoryDecompositionHierarchy, nestedElements) .Select(x => x.GetTable(excludeMissingParameters)) .ToList(); if (!dataTables.Any()) { return(null); } var dataTable = dataTables.First(); if (dataTables.Count > 1) { for (var dt = 1; dt < dataTables.Count; dt++) { var mergeTable = dataTables[dt]; dataTable.Merge(mergeTable, false, MissingSchemaAction.Add); } } return(dataTable); }
/// <summary> /// Creates an <see cref="IEnumerable{T}"/> of type <see cref="DataCollectorNode{T}"/> that contains <see cref="DataCollectorNode{T}"/> instances, /// using a <see cref="CategoryDecompositionHierarchy"/> and a <see cref="List{NestedElement}"/> /// </summary> /// <param name="categoryDecompositionHierarchy"> /// The <see cref="CategoryDecompositionHierarchy"/> used for filtering the considered <see cref="NestedElement"/> items. /// </param> /// <param name="nestedElements"> /// The <see cref="List{NestedElement}"/>s /// </param> internal IEnumerable <DataCollectorNode <T> > CreateNodes( CategoryDecompositionHierarchy categoryDecompositionHierarchy, List <NestedElement> nestedElements) { var topElement = nestedElements.First(ne => ne.IsRootElement); return(this.GetDataCollectorNodes(topElement, categoryDecompositionHierarchy, nestedElements, null)); }
/// <summary> /// Initializes a new instance of the <see cref="DataCollectorNode{T}"/> class. /// </summary> /// <param name="categoryDecompositionHierarchy"> /// The <see cref="CategoryDecompositionHierarchy"/> associated with this node's subtree. /// </param> /// <param name="topElement"> /// The <see cref="CDP4Common.EngineeringModelData.NestedElement"/> associated with this node. /// </param> /// <param name="parent"> /// The parent node in the hierarhical tree upon which the data collector is based. /// </param> public DataCollectorNode( CategoryDecompositionHierarchy categoryDecompositionHierarchy, NestedElement topElement, DataCollectorNode <T> parent = null) { this.Initialize(); this.NestedElement = topElement; this.parent = parent; this.InitializeCategoryDecompositionHierarchy(categoryDecompositionHierarchy); }
/// <summary> /// Sets all properties according to data in the related <see cref="CategoryDecompositionHierarchy"/> /// </summary> /// <param name="categoryDecompositionHierarchy"> /// The related <see cref="CategoryDecompositionHierarchy"/> /// </param> private void InitializeCategoryDecompositionHierarchy(CategoryDecompositionHierarchy categoryDecompositionHierarchy) { this.categoryDecompositionHierarchy = categoryDecompositionHierarchy; this.CategoriesInRequiredRdl = categoryDecompositionHierarchy.CategoriesInRequiredRdl; if (categoryDecompositionHierarchy.IsRecursive) { var level = this.CountCategoryRecursionLevel(this.categoryDecompositionHierarchy.Category); this.FieldName = $"{categoryDecompositionHierarchy.FieldName}_{Math.Min(level, categoryDecompositionHierarchy.MaximumRecursiveLevels)}"; } else { this.FieldName = categoryDecompositionHierarchy.FieldName; } }
/// <summary> /// Adds a new level to the <see cref="CategoryDecompositionHierarchy"/>. /// </summary> /// <param name="category"> /// The to-be-added <see cref="Category"/>. /// </param> /// <param name="fieldName"> /// The field name to be used in the result table. /// </param> /// <param name="maximumRecursiveLevels"> /// Maximum level of recursive usages of the same <see cref="Category"/> within a <see cref="NestedElement"/> tree structure /// </param> /// <returns> /// This <see cref="Builder"/> object. /// </returns> private Builder AddlevelImpl(Category category, string fieldName, int maximumRecursiveLevels) { var newCategoryHierarchy = new CategoryDecompositionHierarchy(this.categoriesInRequiredRdl, category, fieldName); newCategoryHierarchy.MaximumRecursiveLevels = maximumRecursiveLevels; if (this.current == null) { this.top = this.current = newCategoryHierarchy; } else { this.current.Child = newCategoryHierarchy; this.current = this.current.Child; } return(this); }
/// <summary> /// Gets the tree of <see cref="DataCollectorNode{T}"/>s. This method can call itself recursively. /// </summary> /// <param name="nestedElement"> /// The <see cref="NestedElement"/> /// </param> /// <param name="categoryDecompositionHierarchy"> /// The <see cref="CategoryDecompositionHierarchy"/> used for filtering the considered <see cref="NestedElement"/> items. /// </param> /// <param name="nestedElements"> /// The <see cref="List{NestedElement}"/>s /// </param> /// <param name="parentNode"> /// The <see cref=" DataCollectorNode{T}"/> that is the parent of new nodes. /// </param> /// <returns> /// An <see cref="IEnumerable{T}"/> of <see cref="DataCollectorNode{T}"/> /// </returns> private IEnumerable <DataCollectorNode <T> > GetDataCollectorNodes(NestedElement nestedElement, CategoryDecompositionHierarchy categoryDecompositionHierarchy, List <NestedElement> nestedElements, DataCollectorNode <T> parentNode) { var resultNodes = new List <DataCollectorNode <T> >(); DataCollectorNode <T> newNode = null; var searchCategory = categoryDecompositionHierarchy; if (categoryDecompositionHierarchy.Child != null && parentNode?.CountCategoryRecursionLevel(categoryDecompositionHierarchy.Category) > 0 && nestedElement.IsMemberOfCategory(categoryDecompositionHierarchy.Child.Category)) { searchCategory = categoryDecompositionHierarchy.Child; newNode = new DataCollectorNode <T>(searchCategory, nestedElement, parentNode); parentNode.Children.Add(newNode); resultNodes.Add(newNode); } else if (nestedElement.IsMemberOfCategory(categoryDecompositionHierarchy.Category)) { newNode = new DataCollectorNode <T>(categoryDecompositionHierarchy, nestedElement, parentNode); parentNode?.Children.Add(newNode); resultNodes.Add(newNode); } else if (!(categoryDecompositionHierarchy.Child?.AllowSkipUnknownCategories ?? true)) { return(resultNodes); } var children = nestedElement.GetChildren(nestedElements).ToList(); foreach (var child in children) { var nodes = this.GetDataCollectorNodes(child, searchCategory, nestedElements, newNode ?? parentNode).ToArray(); if (newNode == null && nodes.Any()) { resultNodes = resultNodes.Concat(nodes).ToList(); } } return(resultNodes); }