Skip to content

Commit

Permalink
Merge branch 'feature/New_aggregation_Concatenate_(#571)' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Cédric L. Charlier committed Jan 6, 2020
2 parents ea21084 + 9ae1862 commit 30e2266
Show file tree
Hide file tree
Showing 43 changed files with 324 additions and 79 deletions.
3 changes: 2 additions & 1 deletion NBi.Core/NBi.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
<HintPath>..\packages\Microsoft.AnalysisServices.AdomdClient.retail.amd64.18.0.2\lib\net45\Microsoft.AnalysisServices.SPClient.Interfaces.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.13.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.13.0\lib\net45\Moq.dll</HintPath>
<HintPath>..\packages\Moq.4.13.1\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="NCalc, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NCalc-Edge.1.5.0\lib\net35\NCalc.dll</HintPath>
Expand Down Expand Up @@ -769,6 +769,7 @@
<Compile Include="Sequence\Transformation\Aggregation\AggregationArgs.cs" />
<Compile Include="Sequence\Transformation\Aggregation\AggregationFactory.cs" />
<Compile Include="Sequence\Transformation\Aggregation\AggregationFunctionType.cs" />
<Compile Include="Sequence\Transformation\Aggregation\Function\Concatenation.cs" />
<Compile Include="Sequence\Transformation\Aggregation\IAggregationStrategy.cs" />
<Compile Include="Sequence\Transformation\Aggregation\Function\BaseAggregation.cs" />
<Compile Include="Sequence\Transformation\Aggregation\IAggregationFunction.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBi.Core.Sequence.Transformation.Aggregation;
using NBi.Core.Scalar.Resolver;
using NBi.Core.Sequence.Transformation.Aggregation;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -10,9 +11,9 @@ namespace NBi.Core.ResultSet.Alteration.Summarization
public class ColumnAggregationArgs : AggregationArgs
{
public IColumnIdentifier Identifier { get; }
public ColumnAggregationArgs(IColumnIdentifier identifier, AggregationFunctionType function, ColumnType columnType)
: base(function, columnType)

public ColumnAggregationArgs(IColumnIdentifier identifier, AggregationFunctionType function, ColumnType columnType, IList<IScalarResolver> parameters)
: base(function, columnType, parameters)
=> (Identifier) = (identifier);
}
}
2 changes: 2 additions & 0 deletions NBi.Core/Scalar/Casting/DateTimeCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,7 @@ public bool IsValid(object value)
catch (Exception)
{ return false; }
}

public bool IsStrictlyValid(object value) => IsValid(value);
}
}
3 changes: 2 additions & 1 deletion NBi.Core/Scalar/Casting/ICaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ namespace NBi.Core.Scalar.Casting
public interface ICaster<T>: ICaster
{
new T Execute(object obj);
bool IsValid(object obj);
}

public interface ICaster
{
object Execute(object obj);
bool IsValid(object obj);
bool IsStrictlyValid(object obj);
}
}
1 change: 1 addition & 0 deletions NBi.Core/Scalar/Casting/ImplicitCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ class ImplicitCaster : ICaster<object>
object ICaster.Execute(object value) => Execute(value);

public bool IsValid(object value) => true;
public bool IsStrictlyValid(object value) => true;
}
}
12 changes: 11 additions & 1 deletion NBi.Core/Scalar/Casting/TextCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,18 @@ public string Execute(object value)

object ICaster.Execute(object value) => Execute(value);

public bool IsValid(object value)
public bool IsValid(object value) => true;
public bool IsStrictlyValid(object value)
{
if (value == null)
return false;

if (value == DBNull.Value)
return false;

if (value is string && ((string) value) == "(null)")
return false;

return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBi.Core.ResultSet;
using NBi.Core.Scalar.Resolver;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -11,9 +12,10 @@ public class AggregationArgs
{
public ColumnType ColumnType { get; }
public AggregationFunctionType Function { get; }
public IList<IScalarResolver> Parameters { get; } = new List<IScalarResolver>();
public IList<IAggregationStrategy> Strategies { get; } = new List<IAggregationStrategy>();

public AggregationArgs(AggregationFunctionType function, ColumnType columnType)
=> (ColumnType, Function) = (columnType, function);
public AggregationArgs(AggregationFunctionType function, ColumnType columnType, IList<IScalarResolver> parameters)
=> (ColumnType, Function, Parameters) = (columnType, function, parameters ?? new List<IScalarResolver>());
}
}
19 changes: 14 additions & 5 deletions NBi.Core/Sequence/Transformation/Aggregation/AggregationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,32 @@
using NBi.Core.Sequence.Transformation.Aggregation.Strategy;
using NBi.Core.Sequence.Transformation.Aggregation.Function;
using System.Reflection;
using NBi.Core.Scalar.Resolver;

namespace NBi.Core.Sequence.Transformation.Aggregation
{
public class AggregationFactory
{
public Aggregation Instantiate(ColumnType columnType, AggregationFunctionType function, IAggregationStrategy[] strategies)
public Aggregation Instantiate(ColumnType columnType, AggregationFunctionType function, IScalarResolver[] parameters, IAggregationStrategy[] strategies)
{
var missingValue = (IMissingValueStrategy)(strategies.SingleOrDefault(x => x is IMissingValueStrategy) ?? new DropStrategy());
var emptySeries = (IEmptySeriesStrategy)(strategies.SingleOrDefault(x => x is IEmptySeriesStrategy) ?? new ReturnDefaultStrategy(0));
var missingValue = (IMissingValueStrategy)(strategies.SingleOrDefault(x => x is IMissingValueStrategy) ?? new DropStrategy(columnType));
var emptySeries = (IEmptySeriesStrategy)(strategies.SingleOrDefault(x => x is IEmptySeriesStrategy) ?? new ReturnDefaultStrategy(columnType));

var @namespace = $"{this.GetType().Namespace}.Function.";
var typeName = $"{Enum.GetName(typeof(AggregationFunctionType), function)}{Enum.GetName(typeof(ColumnType), columnType)}";
var type = GetType().Assembly.GetType($"{@namespace}{typeName}", false, true) ?? throw new ArgumentException($"No aggregation named '{typeName}' has been found in the namespace '{@namespace}'.");
return new Aggregation((IAggregationFunction)(type.GetConstructor(Type.EmptyTypes).Invoke(new object[] { })), missingValue, emptySeries);

if ((parameters?.Count() ?? 0) == 0)
return new Aggregation((IAggregationFunction)(type.GetConstructor(Type.EmptyTypes).Invoke(Array.Empty<object>())), missingValue, emptySeries);
else
{
var ctor = type.GetConstructors().Where(x => x.IsPublic && (x.GetParameters().Count() == parameters.Count())).FirstOrDefault()
?? throw new ArgumentException($"No public constructor for the aggregation '{function}' expecting {parameters.Count()} parameters.");
return new Aggregation((IAggregationFunction)ctor.Invoke(parameters), missingValue, emptySeries);
}
}

public Aggregation Instantiate(AggregationArgs args)
=> Instantiate(args.ColumnType, args.Function, args.Strategies.ToArray());
=> Instantiate(args.ColumnType, args.Function, args.Parameters.ToArray(), args.Strategies.ToArray());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public enum AggregationFunctionType
Sum,
Max,
Min,
Concatenation,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace NBi.Core.Sequence.Transformation.Aggregation.Function
{
abstract class Average<T> : BaseNumericAggregation<T>
abstract class Average<T> : BaseAggregation<T>
{
public Average(ICaster<T> caster) : base(caster)
{ }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

namespace NBi.Core.Sequence.Transformation.Aggregation.Function
{
abstract class BaseNumericAggregation<T> : IAggregationFunction
abstract class BaseAggregation<T> : IAggregationFunction
{
protected ICaster<T> Caster { get; }

public BaseNumericAggregation(ICaster<T> caster) => Caster = caster;
public BaseAggregation(ICaster<T> caster) => Caster = caster;

public object Execute(IEnumerable<object> values)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Deedle;
using NBi.Core.Scalar.Casting;
using NBi.Core.Scalar.Resolver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NBi.Core.Sequence.Transformation.Aggregation.Function
{
abstract class Concatenation<T> : BaseAggregation<T>
{
protected IScalarResolver<string> Separator { get; }
public Concatenation(ICaster<T> caster, IScalarResolver<string> separator) : base(caster)
=> Separator = separator;

protected override T Execute(Series<int, T> series)
=> Caster.Execute(string.Join(Separator.Execute(), series.Values.ToArray()));
}

class ConcatenationText : Concatenation<string>
{
public ConcatenationText(IScalarResolver<string> separator) : base(new TextCaster(), separator)
{ }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace NBi.Core.Sequence.Transformation.Aggregation.Function
{
abstract class Max<T> : BaseNumericAggregation<T>
abstract class Max<T> : BaseAggregation<T>
{
public Max(ICaster<T> caster) : base(caster)
{ }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace NBi.Core.Sequence.Transformation.Aggregation.Function
{
abstract class Min<T> : BaseNumericAggregation<T>
abstract class Min<T> : BaseAggregation<T>
{
public Min(ICaster<T> caster) : base(caster)
{ }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace NBi.Core.Sequence.Transformation.Aggregation.Function
{
abstract class Sum<T> : BaseNumericAggregation<T>
abstract class Sum<T> : BaseAggregation<T>
{
public Sum(ICaster<T> caster) : base(caster)
{ }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBi.Core.Scalar.Casting;
using NBi.Core.ResultSet;
using NBi.Core.Scalar.Casting;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,10 +10,15 @@ namespace NBi.Core.Sequence.Transformation.Aggregation.Strategy
{
public class DropStrategy : IMissingValueStrategy
{
private ColumnType ColumnType { get; }

public DropStrategy(ColumnType columnType)
=> ColumnType = columnType;

public IEnumerable<object> Execute(IEnumerable<object> values)
{
var caster = new NumericCaster();
return values.Where(x => caster.IsValid(x)).Select(x => caster.Execute(x)).Cast<object>();
var caster = new CasterFactory().Instantiate(ColumnType);
return values.Where(x => caster.IsValid(x) && x!=null).Select(x => caster.Execute(x)).Cast<object>();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBi.Core.Scalar.Casting;
using NBi.Core.ResultSet;
using NBi.Core.Scalar.Casting;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,10 +10,15 @@ namespace NBi.Core.Sequence.Transformation.Aggregation.Strategy
{
public class FailureMissingValueStrategy : IMissingValueStrategy
{
private ColumnType ColumnType { get; }

public FailureMissingValueStrategy(ColumnType columnType)
=> ColumnType = columnType;

public IEnumerable<object> Execute(IEnumerable<object> values)
{
var caster = new NumericCaster();
if (values.All(x => caster.IsStrictlyValid(x)))
var caster = new CasterFactory().Instantiate(ColumnType);
if (values.All(x => ((NumericCaster)caster).IsStrictlyValid(x)))
return values.Select(x => caster.Execute(x)).Cast<object>();
else
throw new ArgumentException();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using NBi.Core.Sequence.Transformation.Aggregation;
using NBi.Core.ResultSet;
using NBi.Core.Scalar.Casting;
using NBi.Core.Sequence.Transformation.Aggregation;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBi.Core.Scalar.Casting;
using NBi.Core.ResultSet;
using NBi.Core.Scalar.Casting;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,13 +10,16 @@ namespace NBi.Core.Sequence.Transformation.Aggregation.Strategy
{
public class ReplaceByDefaultStrategy : IMissingValueStrategy
{
private decimal DefaultValue { get; }
private object DefaultValue { get; }

public ReplaceByDefaultStrategy(decimal defaultValue) => DefaultValue = defaultValue;
private ColumnType ColumnType { get; }

public ReplaceByDefaultStrategy(ColumnType columnType, object defaultValue)
=> (ColumnType, DefaultValue) = (columnType, defaultValue);

public IEnumerable<object> Execute(IEnumerable<object> values)
{
var caster = new NumericCaster();
var caster = new CasterFactory().Instantiate(ColumnType);
return values.Select(x => caster.IsStrictlyValid(x) ? caster.Execute(x) : DefaultValue).Cast<object>();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using NBi.Core.ResultSet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -12,6 +13,18 @@ class ReturnDefaultStrategy : IEmptySeriesStrategy

public ReturnDefaultStrategy(object defaultValue) => DefaultValue = defaultValue;

internal static ReturnDefaultStrategy Instantiate(ColumnType columnType)
{
switch (columnType)
{
case ColumnType.Text: return new ReturnDefaultStrategy(string.Empty);
case ColumnType.Numeric: return new ReturnDefaultStrategy(0);
case ColumnType.DateTime: return new ReturnDefaultStrategy(new DateTime(1900, 1, 1));
case ColumnType.Boolean: return new ReturnDefaultStrategy(false);
default: throw new ArgumentOutOfRangeException();
}
}

public object Execute() => DefaultValue;
}
}
2 changes: 1 addition & 1 deletion NBi.Core/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<package id="FSharp.Core" version="4.7.0" targetFramework="net461" />
<package id="FuzzyString" version="1.0.0" targetFramework="net461" />
<package id="Microsoft.AnalysisServices.AdomdClient.retail.amd64" version="18.0.2" targetFramework="net461" />
<package id="Moq" version="4.13.0" targetFramework="net461" />
<package id="Moq" version="4.13.1" targetFramework="net461" />
<package id="NCalc-Edge" version="1.5.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net461" />
<package id="Ninject" version="3.3.4" targetFramework="net461" />
Expand Down
5 changes: 4 additions & 1 deletion NBi.NUnit/Builder/Helper/ResultSetSystemHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,16 @@ private Alter InstantiateTransform(TransformXml transformXml)

private Alter InstantiateSummarize(SummarizeXml summarizeXml)
{
var scalarHelper = new ScalarHelper(ServiceLocator, null);

var factory = new SummarizationFactory();
var aggregations = new List<ColumnAggregationArgs>()
{
new ColumnAggregationArgs(
summarizeXml.Aggregation.Identifier,
summarizeXml.Aggregation.Function,
summarizeXml.Aggregation.ColumnType
summarizeXml.Aggregation.ColumnType,
summarizeXml.Aggregation.Parameters.Select(x => scalarHelper.InstantiateResolver(summarizeXml.Aggregation.ColumnType, x)).ToList()
)
};
var groupBys = summarizeXml.GroupBy?.Columns?.Cast<IColumnDefinitionLight>() ?? new List<IColumnDefinitionLight>();
Expand Down
6 changes: 5 additions & 1 deletion NBi.Testing.Core/NBi.Testing.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<HintPath>..\packages\Microsoft.AnalysisServices.AdomdClient.retail.amd64.18.0.2\lib\net45\Microsoft.AnalysisServices.SPClient.Interfaces.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.13.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.13.0\lib\net45\Moq.dll</HintPath>
<HintPath>..\packages\Moq.4.13.1\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="NCalc, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NCalc-Edge.1.5.0\lib\net35\NCalc.dll</HintPath>
Expand All @@ -74,6 +74,9 @@
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
Expand Down Expand Up @@ -249,6 +252,7 @@
<Compile Include="Sequence\Transformation\Aggregation\Numeric\MeanTest.cs" />
<Compile Include="Sequence\Transformation\Aggregation\Numeric\MinTest.cs" />
<Compile Include="Sequence\Transformation\Aggregation\Numeric\SumTest.cs" />
<Compile Include="Sequence\Transformation\Aggregation\Text\ConcatenateTest.cs" />
<Compile Include="Sequence\Transformation\Strategy\DropStrategyTest.cs" />
<Compile Include="Sequence\Transformation\Strategy\FailureEmptySeriesStrategyTest.cs" />
<Compile Include="Sequence\Transformation\Strategy\FailureMissingValueStrategyTest.cs" />
Expand Down
Loading

0 comments on commit 30e2266

Please sign in to comment.