Analysis-Services/AlmToolkit/BismNormalizer/TabularCompare/TabularMetadata/CalcDependencyCollection.cs
2023-09-28 08:08:39 -07:00

146 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
namespace BismNormalizer.TabularCompare.TabularMetadata
{
[Serializable]
public class CalcDependenciesInfiniteRecursionException : Exception
{
public CalcDependenciesInfiniteRecursionException() { }
public CalcDependenciesInfiniteRecursionException(string message)
: base(message) { }
public CalcDependenciesInfiniteRecursionException(string message, Exception inner)
: base(message, inner) { }
}
/// <summary>
/// Represents a collection of CalcDependency objects.
/// </summary>
public class CalcDependencyCollection : List<CalcDependency>
{
/// <summary>
/// Returns collection of calc dependencies that the object identified by the params references (directly or indirectly).
/// </summary>
/// <param name="objectType">Type of the object to look up dependencies.</param>
/// <param name="objectName">Name of the object to look up dependencies.</param>
/// <returns></returns>
public CalcDependencyCollection DependenciesReferenceFrom(CalcDependencyObjectType objectType, string tableName, string objectName)
{
CalcDependencyCollection returnVal = new CalcDependencyCollection();
recursionCounter = 0;
try
{
LookUpDependenciesReferenceFrom(objectType, tableName, objectName, returnVal);
}
catch (CalcDependenciesInfiniteRecursionException)
{ //Some M is not parsable
}
return returnVal;
}
private const int RecursionCounterMax = 1000;
static int recursionCounter = 0;
private void LookUpDependenciesReferenceFrom(CalcDependencyObjectType objectType, string tableName, string objectName, CalcDependencyCollection returnVal)
{
recursionCounter++;
if (recursionCounter >= RecursionCounterMax)
{
Exception infRecursion = new CalcDependenciesInfiniteRecursionException($"Calc dependencies infinite recursion detected for type \"{objectType}\", table \"{tableName}\", name \"{objectName}\".");
//Telemetry.TrackException(infRecursion);
throw infRecursion;
}
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectType == objectType && calcDependency.TableName == tableName && calcDependency.ObjectName == objectName)
{
LookUpDependenciesReferenceFrom(calcDependency.ReferencedObjectType, calcDependency.ReferencedTableName, calcDependency.ReferencedObjectName, returnVal);
returnVal.Add(calcDependency);
}
}
}
/// <summary>
/// Returns collection of M dependency objects that hold references to the object identified by the param values (directly or chained).
/// </summary>
/// <param name="objectType">Type of the object to look up dependencies.</param>
/// <param name="objectName">Name of the object to look up dependencies.</param>
/// <returns></returns>
public CalcDependencyCollection DependenciesReferenceTo(CalcDependencyObjectType referencedObjectType, string referencedObjectName, string referencedTableName)
{
CalcDependencyCollection returnVal = new CalcDependencyCollection();
LookUpDependenciesReferenceTo(referencedObjectType, referencedObjectName, referencedTableName, returnVal);
return returnVal;
}
private void LookUpDependenciesReferenceTo(CalcDependencyObjectType referencedObjectType, string referencedObjectName, string referencedTableName, CalcDependencyCollection returnVal)
{
foreach (CalcDependency calcDependency in this)
{
if (
(calcDependency.ReferencedObjectType == referencedObjectType && referencedObjectType != CalcDependencyObjectType.Partition && calcDependency.ReferencedObjectName == referencedObjectName) ||
(calcDependency.ReferencedObjectType == referencedObjectType && referencedObjectType == CalcDependencyObjectType.Partition && calcDependency.ReferencedTableName == referencedTableName) //References to table-partition expressions are by table name, not partition name
)
{
LookUpDependenciesReferenceTo(calcDependency.ObjectType, calcDependency.ObjectName, calcDependency.TableName, returnVal);
returnVal.Add(calcDependency);
}
}
}
/// <summary>
/// Find an object in the collection by name.
/// </summary>
/// <param name="name"></param>
/// <returns>CalcDependency object if found. Null if not found.</returns>
public CalcDependency FindByName(string name)
{
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectName == name)
{
return calcDependency;
}
}
return null;
}
/// <summary>
/// A Boolean specifying whether the collection contains object by name.
/// </summary>
/// <param name="name"></param>
/// <returns>True if the object is found, or False if it's not found.</returns>
public bool ContainsName(string name)
{
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectName == name)
{
return true;
}
}
return false;
}
/// <summary>
/// Removes an object from the collection by its name.
/// </summary>
/// <param name="name"></param>
/// <returns>True if the object was removed, or False if was not found.</returns>
public bool Remove(string name)
{
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectName == name)
{
this.Remove(calcDependency);
return true;
}
}
return false;
}
}
}