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) { }
}
///
/// Represents a collection of CalcDependency objects.
///
public class CalcDependencyCollection : List
{
///
/// Returns collection of calc dependencies that the object identified by the params references (directly or indirectly).
///
/// Type of the object to look up dependencies.
/// Name of the object to look up dependencies.
///
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);
}
}
}
///
/// Returns collection of M dependency objects that hold references to the object identified by the param values (directly or chained).
///
/// Type of the object to look up dependencies.
/// Name of the object to look up dependencies.
///
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);
}
}
}
///
/// Find an object in the collection by name.
///
///
/// CalcDependency object if found. Null if not found.
public CalcDependency FindByName(string name)
{
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectName == name)
{
return calcDependency;
}
}
return null;
}
///
/// A Boolean specifying whether the collection contains object by name.
///
///
/// True if the object is found, or False if it's not found.
public bool ContainsName(string name)
{
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectName == name)
{
return true;
}
}
return false;
}
///
/// Removes an object from the collection by its name.
///
///
/// True if the object was removed, or False if was not found.
public bool Remove(string name)
{
foreach (CalcDependency calcDependency in this)
{
if (calcDependency.ObjectName == name)
{
this.Remove(calcDependency);
return true;
}
}
return false;
}
}
}