Skip to content

Commit

Permalink
Merge pull request #42 from jdunkerley/streaming
Browse files Browse the repository at this point in the history
IOutputHelper interface and factory
  • Loading branch information
jdunkerley authored Oct 11, 2016
2 parents 4c5dc12 + 90bc05d commit 3ab3d2c
Show file tree
Hide file tree
Showing 21 changed files with 199 additions and 71 deletions.
3 changes: 3 additions & 0 deletions AlteryxAddIns.Framework/AlteryxAddIns.Framework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Compile Include="ConfigWithIncomingConnection.cs" />
<Compile Include="ConnectionState.cs" />
<Compile Include="Factories\InputPropertyFactory.cs" />
<Compile Include="Factories\OutputHelperFactory.cs" />
<Compile Include="Factories\RecordCopierFactory.cs" />
<Compile Include="FieldBaseHelpers.cs" />
<Compile Include="FieldDescription.cs" />
Expand All @@ -83,6 +84,7 @@
<Compile Include="ConfigWindows\InputFieldTypeConverter.cs" />
<Compile Include="InputProperty.cs" />
<Compile Include="Interfaces\IInputPropertyFactory.cs" />
<Compile Include="Interfaces\IOutputHelperFactory.cs" />
<Compile Include="Interfaces\IRecordCopier.cs" />
<Compile Include="Interfaces\IRecordCopierFactory.cs" />
<Compile Include="Interfaces\ProgressUpdatedEventArgs.cs" />
Expand All @@ -91,6 +93,7 @@
<Compile Include="Interfaces\RecordPushedEventHandler.cs" />
<Compile Include="Interfaces\SuccessEventArgs.cs" />
<Compile Include="Interfaces\SuccessEventHandler.cs" />
<Compile Include="Interfaces\IOutputHelper.cs" />
<Compile Include="OutputHelper.cs" />
<Compile Include="OutputType.cs" />
<Compile Include="OutputTypeHelpers.cs" />
Expand Down
15 changes: 12 additions & 3 deletions AlteryxAddIns.Framework/BaseEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace JDunkerley.AlteryxAddIns.Framework
public abstract class BaseEngine<TConfig> : AlteryxRecordInfoNet.INetPlugin, IBaseEngine
where TConfig : new()
{
private readonly IOutputHelperFactory _outputHelperFactory;

private readonly Dictionary<string, PropertyInfo> _inputs;
private readonly Dictionary<string, PropertyInfo> _outputs;

Expand All @@ -26,13 +28,20 @@ public abstract class BaseEngine<TConfig> : AlteryxRecordInfoNet.INetPlugin, IBa
/// Initializes a new instance of the <see cref="BaseEngine{T}"/> class.
/// </summary>
/// <param name="recordCopierFactory">Factory to create copiers</param>
protected BaseEngine(IRecordCopierFactory recordCopierFactory)
/// <param name="outputHelperFactory">Factory to create output helpers</param>
protected BaseEngine(IRecordCopierFactory recordCopierFactory, IOutputHelperFactory outputHelperFactory)
{
this.RecordCopierFactory = recordCopierFactory;
this._outputHelperFactory = outputHelperFactory;

var type = this.GetType();
this._inputs = type.GetProperties<AlteryxRecordInfoNet.IIncomingConnectionInterface>();
this._outputs = type.GetProperties<OutputHelper>();
this._outputs = type.GetProperties<IOutputHelper>();

if (this._outputHelperFactory == null && this._outputs.Count > 0)
{
throw new ArgumentNullException(nameof(outputHelperFactory), "Tool has an output but no factory has been provided.");
}
}

/// <summary>
Expand Down Expand Up @@ -88,7 +97,7 @@ public void PI_Init(int nToolId, AlteryxRecordInfoNet.EngineInterface engineInte

foreach (var kvp in this._outputs)
{
kvp.Value.SetValue(this, new OutputHelper(this, kvp.Key), null);
kvp.Value.SetValue(this, this._outputHelperFactory.CreateOutputHelper(this, kvp.Key), null);
}

this.OnInitCalled();
Expand Down
1 change: 1 addition & 0 deletions AlteryxAddIns.Framework/BaseTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/// <seealso cref="AlteryxGuiToolkit.Plugins.IPlugin" />
public abstract class BaseTool<TConfig, TEngine>
where TConfig : new()
where TEngine : AlteryxRecordInfoNet.INetPlugin
{
private readonly Lazy<Image> _icon;

Expand Down
Binary file modified AlteryxAddIns.Framework/BaseTool.pdn
Binary file not shown.
19 changes: 19 additions & 0 deletions AlteryxAddIns.Framework/Factories/OutputHelperFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace JDunkerley.AlteryxAddIns.Framework.Factories
{
using Interfaces;

/// <summary>
/// Factory For Creating <see cref="IOutputHelper"/> objects.
/// </summary>
public class OutputHelperFactory : IOutputHelperFactory
{
/// <summary>
/// Creates a new instance of an <see cref="IOutputHelper"/>
/// </summary>
/// <param name="hostEngine">The host engine.</param>
/// <param name="connectionName">Name of the outgoing connection.</param>
/// <returns>A configured instance of an <see cref="IOutputHelper"/></returns>
public IOutputHelper CreateOutputHelper(IBaseEngine hostEngine, string connectionName)
=> new OutputHelper(hostEngine, connectionName);
}
}
57 changes: 57 additions & 0 deletions AlteryxAddIns.Framework/Interfaces/IOutputHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
namespace JDunkerley.AlteryxAddIns.Framework.Interfaces
{
using System.Xml;
using AlteryxRecordInfoNet;

/// <summary>
/// Interface Defining An Output Helper
/// </summary>
public interface IOutputHelper
{
/// <summary>
/// Gets a reusable <see cref="Record"/> object
/// </summary>
Record Record { get; }

/// <summary>
/// Gets the <see cref="RecordInfo"/> describing the Output records
/// </summary>
RecordInfo RecordInfo { get; }

/// <summary>
/// Given a fieldName, gets the <see cref="FieldBase"/> for it
/// </summary>
/// <param name="fieldName">Name of field</param>
/// <returns><see cref="FieldBase"/> representing the field</returns>
FieldBase this[string fieldName] { get; }

/// <summary>
/// Initializes the output stream.
/// </summary>
/// <param name="recordInfo">RecordInfo defining the fields and outputs of the connection.</param>
/// <param name="sortConfig">Sort configuration to pass onto Alteryx.</param>
/// <param name="oldConfig">XML configuration of the tool.</param>
void Init(RecordInfo recordInfo, XmlElement sortConfig = null, XmlElement oldConfig = null);

/// <summary>
/// Pushes a record to Alteryx to hand onto over tools.
/// </summary>
/// <param name="record">Record object to push to the stream.</param>
/// <param name="close">Value indicating whether to close the connection after pushing the record.</param>
/// <param name="updateCountMod">How often to update Row Count and Data</param>
void Push(Record record, bool close = false, ulong updateCountMod = 250);

/// <summary>
/// Update The Progress Of A Connection
/// </summary>
/// <param name="percentage">Percentage Progress from 0.0 to 1.0</param>
/// <param name="setToolProgress">Set Tool Progress As Well</param>
void UpdateProgress(double percentage, bool setToolProgress = false);

/// <summary>
/// Tell Alteryx We Are Finished
/// </summary>
/// <param name="executionComplete">Tell Alteryx Tool Execution Is Complete</param>
void Close(bool executionComplete = false);
}
}
16 changes: 16 additions & 0 deletions AlteryxAddIns.Framework/Interfaces/IOutputHelperFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace JDunkerley.AlteryxAddIns.Framework.Interfaces
{
/// <summary>
/// Interface to decouple the construction of <see cref="IOutputHelper"/> objects from <see cref="BaseEngine{TConfig}"/>.
/// </summary>
public interface IOutputHelperFactory
{
/// <summary>
/// Creates a new instance of an <see cref="IOutputHelper"/>
/// </summary>
/// <param name="hostEngine">The host engine.</param>
/// <param name="connectionName">Name of the outgoing connection.</param>
/// <returns>A configured instance of an <see cref="IOutputHelper"/></returns>
IOutputHelper CreateOutputHelper(IBaseEngine hostEngine, string connectionName);
}
}
2 changes: 1 addition & 1 deletion AlteryxAddIns.Framework/Interfaces/IRecordCopierFactory.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace JDunkerley.AlteryxAddIns.Framework.Interfaces
{
/// <summary>
/// Interface to decouple the construction of <see cref="IRecordCopier"/> objects from the engines.
/// Interface to decouple the construction of <see cref="IRecordCopier"/> objects from <see cref="BaseEngine{TConfig}"/>.
/// </summary>
public interface IRecordCopierFactory
{
Expand Down
12 changes: 4 additions & 8 deletions AlteryxAddIns.Framework/OutputHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ namespace JDunkerley.AlteryxAddIns.Framework

using AlteryxRecordInfoNet;

using Interfaces;

/// <summary>
/// Output Helper Class
/// </summary>
public sealed class OutputHelper : IDisposable
internal sealed class OutputHelper : IDisposable, IOutputHelper
{
private readonly IBaseEngine _hostEngine;

Expand Down Expand Up @@ -70,7 +72,7 @@ public void AddConnection(OutgoingConnection connection)
public void Init(RecordInfo recordInfo, XmlElement sortConfig = null, XmlElement oldConfig = null)
{
this.RecordInfo = recordInfo;
this._lazyRecord = new Lazy<Record>(this.CreateRecord);
this._lazyRecord = new Lazy<Record>(() => this.RecordInfo?.CreateRecord());

this._recordCount = 0;
this._recordLength = 0;
Expand All @@ -79,12 +81,6 @@ public void Init(RecordInfo recordInfo, XmlElement sortConfig = null, XmlElement
this._hostEngine.Engine.OutputMessage(this._hostEngine.NToolId, MessageStatus.STATUS_Info, $"Init called back on {this._connectionName}");
}

/// <summary>
/// Create A New Record (Can be reused)
/// </summary>
/// <returns>An empty record based off the RecordInfo.</returns>
public Record CreateRecord() => this.RecordInfo?.CreateRecord();

/// <summary>
/// Pushes a record to Alteryx to hand onto over tools.
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions AlteryxAddIns.Roslyn/AlteryxAddIns.Roslyn.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Install.bat" />
<None Include="InstallRelease.bat">
<None Include="Install.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="InstallRelease.bat" />
<None Include="packages.config" />
<None Include="Uninstall.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand All @@ -135,8 +135,8 @@
<PropertyGroup>
<PostBuildEvent>rmdir "$(SolutionDir)\Release\Roslyn" /s /q
mkdir "$(SolutionDir)\Release\Roslyn"
copy "$(TargetDir)\*.dll" "$(SolutionDir)\Release\Roslyn\"
copy "$(TargetDir)\InstallRelease.bat" "$(SolutionDir)\Release\RoslynInstall.bat"
copy "$(ProjectDir)\*.dll" "$(SolutionDir)\Release\Roslyn\"
copy "$(ProjectDir)\InstallRelease.bat" "$(SolutionDir)\Release\RoslynInstall.bat"
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
17 changes: 14 additions & 3 deletions AlteryxAddIns.Roslyn/RoslynInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

using Framework;
using Framework.Attributes;
using Framework.Interfaces;

using JDunkerley.AlteryxAddIns.Framework.Factories;

public class RoslynInput :
BaseTool<RoslynInput.Config, RoslynInput.Engine>, IPlugin
Expand Down Expand Up @@ -62,16 +65,24 @@ public class Engine : BaseEngine<Config>
/// Constructor for Alteryx Engine
/// </summary>
public Engine()
: base(null)
: this(new OutputHelperFactory())
{
}

/// <summary>
/// Create An Engine for unit testing.
/// </summary>
/// <param name="outputHelperFactory">Factory to create output helpers</param>
internal Engine(IOutputHelperFactory outputHelperFactory)
: base(null, outputHelperFactory)
{
}

/// <summary>
/// Gets or sets the output.
/// </summary>
[CharLabel('O')]
public OutputHelper Output { get; set; }
public IOutputHelper Output { get; set; }

/// <summary>
/// Called only if you have no Input Connections
Expand Down Expand Up @@ -104,7 +115,7 @@ public override bool PI_PushAllRecords(long nRecordLimit)
}

var data = this._result.Execute.DynamicInvoke();
var recordOut = this.Output.CreateRecord();
var recordOut = this.Output.Record;

var asString = data as string;
var asEnum = asString != null ? new[] { asString } : (data as IEnumerable) ?? new[] { data };
Expand Down
12 changes: 4 additions & 8 deletions AlteryxAddIns/AlteryxAddIns.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,9 @@
<None Include="Install.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="InstallRelease.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="InstallRelease.bat" />
<None Include="packages.config" />
<None Include="Uninstall.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Uninstall.bat" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AlteryxAddIns.Framework\AlteryxAddIns.Framework.csproj">
Expand All @@ -117,8 +113,8 @@
<PostBuildEvent>rmdir "$(SolutionDir)\Release\AddIns" /s /q
mkdir "$(SolutionDir)\Release\AddIns"
copy "$(TargetDir)\*.dll" "$(SolutionDir)\Release\AddIns\"
copy "$(TargetDir)\InstallRelease.bat" "$(SolutionDir)\Release\Install.bat"
copy "$(TargetDir)\UnInstall.bat" "$(SolutionDir)\Release\"
copy "$(ProjectDir)\InstallRelease.bat" "$(SolutionDir)\Release\Install.bat"
copy "$(ProjectDir)\UnInstall.bat" "$(SolutionDir)\Release\"
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
11 changes: 6 additions & 5 deletions AlteryxAddIns/CircuitBreaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,18 @@ public class Engine : BaseEngine<Config>
/// Constructor For Alteryx
/// </summary>
public Engine()
: this(new RecordCopierFactory(), new InputPropertyFactory())
: this(new RecordCopierFactory(), new InputPropertyFactory(), new OutputHelperFactory())
{
}

/// <summary>
/// Create An Engine
/// Create An Engine for unit testing.
/// </summary>
/// <param name="recordCopierFactory">Factory to create copiers</param>
/// <param name="inputPropertyFactory">Factory to create input properties</param>
internal Engine(IRecordCopierFactory recordCopierFactory, IInputPropertyFactory inputPropertyFactory)
: base(recordCopierFactory)
/// <param name="outputHelperFactory">Factory to create output helpers</param>
internal Engine(IRecordCopierFactory recordCopierFactory, IInputPropertyFactory inputPropertyFactory, IOutputHelperFactory outputHelperFactory)
: base(recordCopierFactory, outputHelperFactory)
{
// Handle Breaker Connection
this.Breaker = inputPropertyFactory.Build(recordCopierFactory, this.ShowDebugMessages);
Expand All @@ -74,7 +75,7 @@ internal Engine(IRecordCopierFactory recordCopierFactory, IInputPropertyFactory
public IInputProperty Input { get; }

[CharLabel('O')]
public OutputHelper Output { get; set; }
public IOutputHelper Output { get; set; }

private void BreakerOnRecordPushed(object sender, RecordPushedEventArgs args)
{
Expand Down
18 changes: 15 additions & 3 deletions AlteryxAddIns/DateTimeInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using Framework;
using Framework.Attributes;
using Framework.ConfigWindows;
using Framework.Interfaces;

using JDunkerley.AlteryxAddIns.Framework.Factories;

/// <summary>
/// Simple Date Time Input Control
Expand Down Expand Up @@ -62,15 +65,24 @@ public class Engine : BaseEngine<Config>
/// Constructor for Alteryx Engine
/// </summary>
public Engine()
: base(null)
: this(new OutputHelperFactory())
{
}

/// <summary>
/// Create An Engine for unit testing.
/// </summary>
/// <param name="outputHelperFactory">Factory to create output helpers</param>
internal Engine(IOutputHelperFactory outputHelperFactory)
: base(null, outputHelperFactory)
{
}

/// <summary>
/// Gets or sets the output.
/// </summary>
[CharLabel('O')]
public OutputHelper Output { get; set; }
public IOutputHelper Output { get; set; }

/// <summary>
/// Called only if you have no Input Connections
Expand Down Expand Up @@ -131,7 +143,7 @@ public override bool PI_PushAllRecords(long nRecordLimit)
break;
}

var recordOut = this.Output.CreateRecord();
var recordOut = this.Output.Record;
this.Output[this.ConfigObject.OutputFieldName]?
.SetFromString(recordOut, dateOutput.ToString(this.ConfigObject.OutputType == OutputType.Time ? "HH:mm:ss" : "yyyy-MM-dd HH:mm:ss"));
this.Output.Push(recordOut);
Expand Down
Loading

0 comments on commit 3ab3d2c

Please sign in to comment.