diff --git a/Siphon/Monitors/DataMonitor.vb b/Siphon/Monitors/DataMonitor.vb
new file mode 100644
index 0000000..05dfa34
--- /dev/null
+++ b/Siphon/Monitors/DataMonitor.vb
@@ -0,0 +1,84 @@
+Imports System.Timers
+
+'''
+''' Base class for all DataMonitor based classes.
+'''
+'''
+Public MustInherit Class DataMonitor
+ Implements IDataMonitor
+
+ Private _disposed As Boolean = False
+ Private _processor As IDataProcessor = Nothing
+ Private _schedule As IMonitorSchedule = Nothing
+ Private _timer As System.Timers.Timer
+
+ Public Sub New(ByVal processor As IDataProcessor, ByVal schedule As IMonitorSchedule)
+ Me.Processor = processor
+ Me.Schedule = schedule
+ End Sub
+
+ Public Overridable Property Processor() As IDataProcessor Implements IDataMonitor.Processor
+ Get
+ Return _processor
+ End Get
+ Set(ByVal value As IDataProcessor)
+ _processor = value
+ End Set
+ End Property
+
+ Public Overridable Sub Start() Implements IDataMonitor.Start
+ Timer.Start()
+ End Sub
+
+ Public Overridable Sub [Stop]() Implements IDataMonitor.Stop
+ Timer.Stop()
+ End Sub
+
+ '''
+ ''' Returns the internal timer used for the current monitor.
+ '''
+ '''
+ ''' Timer
+ '''
+ Protected Overridable ReadOnly Property Timer() As Timer
+ Get
+ If _timer Is Nothing Then
+ _timer = New Timer
+ _timer.AutoReset = False
+ End If
+
+ Return _timer
+ End Get
+ End Property
+
+ '''
+ ''' Gets/sets the schedule for the current monitor instance.
+ '''
+ '''
+ ''' IMonitorSchedule
+ '''
+ Public Overridable Property Schedule() As IMonitorSchedule Implements IDataMonitor.Schedule
+ Get
+ Return _schedule
+ End Get
+ Set(ByVal value As IMonitorSchedule)
+ _schedule = value
+ End Set
+ End Property
+
+ Protected Overridable Sub Dispose(ByVal disposing As Boolean)
+ If Not _disposed Then
+ If disposing Then
+
+ End If
+ End If
+
+ _disposed = True
+ End Sub
+
+ Public Sub Dispose() Implements IDisposable.Dispose
+ Dispose(True)
+ GC.SuppressFinalize(Me)
+ End Sub
+
+End Class
diff --git a/Siphon/Monitors/IDataMonitor.vb b/Siphon/Monitors/IDataMonitor.vb
new file mode 100644
index 0000000..43cf51f
--- /dev/null
+++ b/Siphon/Monitors/IDataMonitor.vb
@@ -0,0 +1,35 @@
+'''
+''' Interface that defines a data monitoring instance.
+'''
+'''
+Public Interface IDataMonitor
+ Inherits IDisposable
+
+ '''
+ ''' Starts the data monitoring instance.
+ '''
+ '''
+ Sub Start()
+
+ '''
+ ''' Stops the data monitoring instance.
+ '''
+ '''
+ Sub [Stop]()
+
+ '''
+ ''' Gets/sets the data processor to use when new data is found.
+ '''
+ '''
+ ''' IDataProcessor
+ '''
+ Property Processor() As IDataProcessor
+
+ '''
+ ''' Gets/sets the data monitor schedule to be used.
+ '''
+ '''
+ ''' IMonitorSchedule
+ '''
+ Property Schedule() As IMonitorSchedule
+End Interface
diff --git a/Siphon/Monitors/IDirectoryMonitor.vb b/Siphon/Monitors/IDirectoryMonitor.vb
new file mode 100644
index 0000000..c5ca37c
--- /dev/null
+++ b/Siphon/Monitors/IDirectoryMonitor.vb
@@ -0,0 +1,23 @@
+'''
+''' Interface that defines a directory monitoring instance.
+'''
+'''
+Public Interface IDirectoryMonitor
+ Inherits IDataMonitor
+
+ '''
+ ''' Gets/sets the file name filter to apply to the directorys contents
+ '''
+ '''
+ ''' String
+ ''' The default should be *, or all files.
+ Property Filter() As String
+
+ '''
+ ''' Gets/sets the full path of the directory to monitor.
+ '''
+ '''
+ '''
+ ''' The path should take either a local system path or a file uri.
+ Property Path() As String
+End Interface
diff --git a/Siphon/My Project/AssemblyInfo.vb b/Siphon/My Project/AssemblyInfo.vb
index a249f8a..239786e 100644
--- a/Siphon/My Project/AssemblyInfo.vb
+++ b/Siphon/My Project/AssemblyInfo.vb
@@ -1,6 +1,7 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
+Imports log4net
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
@@ -14,6 +15,7 @@ Imports System.Runtime.InteropServices
+
diff --git a/Siphon/Processors/IDataProcessor.vb b/Siphon/Processors/IDataProcessor.vb
new file mode 100644
index 0000000..9fe8fc6
--- /dev/null
+++ b/Siphon/Processors/IDataProcessor.vb
@@ -0,0 +1,8 @@
+'''
+''' Interface that defines a data processor instance.
+'''
+'''
+Public Interface IDataProcessor
+ Inherits IDisposable
+
+End Interface
diff --git a/Siphon/Schedules/DailySchedule.vb b/Siphon/Schedules/DailySchedule.vb
new file mode 100644
index 0000000..22bebc6
--- /dev/null
+++ b/Siphon/Schedules/DailySchedule.vb
@@ -0,0 +1,66 @@
+Imports log4net
+
+'''
+''' Class for schedules based on times of day.
+'''
+'''
+Public Class DailySchedule
+ Inherits MonitorSchedule
+
+ Private Shared ReadOnly Log As ILog = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod.DeclaringType)
+ Private _times() As TimeSpan = {}
+
+ '''
+ ''' Creates a new daily schedule instance.
+ '''
+ ''' TimePan. An array of times to run the events each day.
+ '''
+ Public Sub New(ByVal ParamArray times() As TimeSpan)
+ Me.Times = times
+ End Sub
+
+ '''
+ ''' Gets/sets the times of day for the events.
+ '''
+ '''
+ ''' TimeSpan
+ '''
+ Public Overridable Property Times() As TimeSpan()
+ Get
+ Return _times
+ End Get
+ Set(ByVal value() As TimeSpan)
+ _times = value
+ End Set
+ End Property
+
+ '''
+ ''' Gets the next schedule event after the given start date/time.
+ '''
+ ''' DateTime. The schedules start date/time.
+ '''
+ ''' DateTime
+ '''
+ Public Overloads Overrides ReadOnly Property NextEvent(ByVal start As DateTime) As DateTime
+ Get
+ Array.Sort(Me.Times)
+
+ Dim max As New TimeSpan(0, 23, 59, 59, 999)
+
+ For Each tp As TimeSpan In Me.Times
+ If tp > max Then
+ Log.WarnFormat("Skipping TimeSpan greater than 24 hours {0}", tp)
+ Else
+ If tp >= start.TimeOfDay Then
+ Return New DateTime(start.Year, start.Month, start.Day, tp.Hours, tp.Minutes, tp.Seconds)
+ End If
+ End If
+ Next
+
+ Dim tomorow As DateTime = start.AddDays(1)
+ Dim time As TimeSpan = Me.Times(0)
+
+ Return New DateTime(tomorow.Year, tomorow.Month, tomorow.Day, time.Hours, time.Minutes, time.Seconds)
+ End Get
+ End Property
+End Class
diff --git a/Siphon/Schedules/IMonitorSchedule.vb b/Siphon/Schedules/IMonitorSchedule.vb
new file mode 100644
index 0000000..3592980
--- /dev/null
+++ b/Siphon/Schedules/IMonitorSchedule.vb
@@ -0,0 +1,16 @@
+'''
+''' Interface that defines a monitoring schedule.
+'''
+'''
+Public Interface IMonitorSchedule
+ Inherits IDisposable
+
+ '''
+ ''' Gets the next schedule event after the given start date/time.
+ '''
+ ''' DateTime. The schedules start date/time.
+ '''
+ ''' DateTime
+ '''
+ ReadOnly Property NextEvent(ByVal start As DateTime) As DateTime
+End Interface
diff --git a/Siphon/Schedules/IntervalSchedule.vb b/Siphon/Schedules/IntervalSchedule.vb
new file mode 100644
index 0000000..241bb9b
--- /dev/null
+++ b/Siphon/Schedules/IntervalSchedule.vb
@@ -0,0 +1,54 @@
+'''
+''' Class for schedules based on time intervals.
+'''
+'''
+Public Class IntervalSchedule
+ Inherits MonitorSchedule
+
+ Private _interval As New TimeSpan(0, 1, 0)
+
+ '''
+ ''' Creates a new interval schedule instance.
+ '''
+ '''
+ Public Sub New()
+
+ End Sub
+
+ '''
+ ''' Creates a new interval schedule instance.
+ '''
+ ''' TimeSpan. The interval to wait between schedule events.
+ '''
+ Public Sub New(ByVal interval As TimeSpan)
+ Me.Interval = interval
+ End Sub
+
+ '''
+ ''' Gets/sets the interval to wait between schedule events.
+ '''
+ '''
+ ''' TimeSpan
+ '''
+ Public Overridable Property Interval() As TimeSpan
+ Get
+ Return _interval
+ End Get
+ Set(ByVal value As TimeSpan)
+ _interval = value
+ End Set
+ End Property
+
+ '''
+ ''' Gets the next schedule event after the given start date/time.
+ '''
+ ''' DateTime. The schedules start date/time.
+ '''
+ ''' DateTime
+ '''
+ Public Overrides ReadOnly Property NextEvent(ByVal start As DateTime) As DateTime
+ Get
+ Return start.Add(Me.Interval)
+ End Get
+ End Property
+End Class
diff --git a/Siphon/Schedules/MonitorSchedule.vb b/Siphon/Schedules/MonitorSchedule.vb
new file mode 100644
index 0000000..136d67d
--- /dev/null
+++ b/Siphon/Schedules/MonitorSchedule.vb
@@ -0,0 +1,42 @@
+'''
+''' Base class for monitoring schedules.
+'''
+'''
+Public MustInherit Class MonitorSchedule
+ Implements IMonitorSchedule
+
+ Private _disposed As Boolean = False
+
+ '''
+ ''' Gets the next schedule event after the given start date/time.
+ '''
+ ''' DateTime. The schedules start date/time.
+ '''
+ ''' DateTime
+ '''
+ Public MustOverride ReadOnly Property NextEvent(ByVal start As DateTime) As DateTime Implements IMonitorSchedule.NextEvent
+
+ '''
+ ''' Disposes the current schedule instance.
+ '''
+ ''' Boolean. True if we're disposing.
+ '''
+ Protected Overridable Sub Dispose(ByVal disposing As Boolean)
+ If Not _disposed Then
+ If disposing Then
+
+ End If
+ End If
+
+ _disposed = True
+ End Sub
+
+ '''
+ ''' Disposes the current schedule instance.
+ '''
+ '''
+ Public Sub Dispose() Implements IDisposable.Dispose
+ Dispose(True)
+ GC.SuppressFinalize(Me)
+ End Sub
+End Class
diff --git a/Siphon/Siphon.vbproj b/Siphon/Siphon.vbproj
index 06df139..5118e3e 100644
--- a/Siphon/Siphon.vbproj
+++ b/Siphon/Siphon.vbproj
@@ -53,6 +53,12 @@
+
+
+
+
+
+
True
@@ -68,6 +74,8 @@
Settings.settings
True
+
+
diff --git a/SiphonTests/MonitorTests.vb b/SiphonTests/MonitorTests.vb
new file mode 100644
index 0000000..481e630
--- /dev/null
+++ b/SiphonTests/MonitorTests.vb
@@ -0,0 +1,10 @@
+Imports NUnit.Framework
+
+Public Class MonitorTests
+
+ _
+ Public Sub DirectoryMonitor()
+
+ End Sub
+
+End Class
diff --git a/SiphonTests/My Project/AssemblyInfo.vb b/SiphonTests/My Project/AssemblyInfo.vb
index b8031f3..ba940f3 100644
--- a/SiphonTests/My Project/AssemblyInfo.vb
+++ b/SiphonTests/My Project/AssemblyInfo.vb
@@ -1,6 +1,7 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
+Imports log4net
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
@@ -14,6 +15,7 @@ Imports System.Runtime.InteropServices
+
diff --git a/SiphonTests/ScheduleTests.vb b/SiphonTests/ScheduleTests.vb
new file mode 100644
index 0000000..2b15048
--- /dev/null
+++ b/SiphonTests/ScheduleTests.vb
@@ -0,0 +1,84 @@
+Imports NUnit.Framework
+Imports ChrisLaco.Siphon
+
+ _
+Public Class ScheduleTests
+
+ _
+ Public Sub TestFixtureSetupUp()
+ log4net.Config.XmlConfigurator.Configure()
+ End Sub
+
+#Region "Interval Schedule Tests"
+
+ _
+ Public Sub IntervalScheduleDefault()
+ Using schedule As IMonitorSchedule = New IntervalSchedule
+ Dim dt As DateTime = DateTime.Now
+ Dim ndt As DateTime = schedule.NextEvent(dt)
+ Dim ts As TimeSpan = (ndt - dt)
+
+ Assert.Greater(ndt, dt, "Next event is greater than now")
+ Assert.AreEqual(1, ts.Minutes, "Default span of 1 minute")
+ End Using
+ End Sub
+
+ _
+ Public Sub IntervalSchedule()
+ Using schedule As IMonitorSchedule = New IntervalSchedule(New TimeSpan(1, 2, 3))
+ Dim dt As DateTime = DateTime.Now
+ Dim ndt As DateTime = schedule.NextEvent(dt)
+ Dim ts As TimeSpan = (ndt - dt)
+
+ Assert.Greater(ndt, dt, "Next event is greater than now")
+ Assert.AreEqual(1, ts.Hours, "1 hours in interval")
+ Assert.AreEqual(2, ts.Minutes, "2 minutes in interval")
+ Assert.AreEqual(3, ts.Seconds, "3 seconds in interval")
+ End Using
+ End Sub
+
+#End Region
+
+#Region "Hourly Schedule Tests"
+
+ _
+ Public Sub DailySchedule()
+ Using schedule As IMonitorSchedule = New DailySchedule(New TimeSpan(4, 0, 0), New TimeSpan(2, 5, 0, 0), New TimeSpan(12, 30, 25), New TimeSpan(14, 0, 0))
+ Dim start As DateTime
+ Dim ndt As DateTime
+
+ start = DateTime.Parse("1/1/2001 1:00 AM")
+ ndt = schedule.NextEvent(start)
+ Assert.AreEqual(4, ndt.Hour, "Got hour 4")
+ Assert.AreEqual(start.Date, ndt.Date, "Got same date")
+
+ start = DateTime.Parse("1/1/2001 4:00 AM")
+ ndt = schedule.NextEvent(start)
+ Assert.AreEqual(4, ndt.Hour, "Got hour 4")
+ Assert.AreEqual(start.Date, ndt.Date, "Got same date")
+
+ start = DateTime.Parse("1/1/2001 4:10 AM")
+ ndt = schedule.NextEvent(start)
+ Assert.AreEqual(12, ndt.Hour, "Got hour 12")
+ Assert.AreEqual(start.Date, ndt.Date, "Got same date")
+
+ start = DateTime.Parse("1/1/2001 12:30 PM")
+ ndt = schedule.NextEvent(start)
+ Assert.AreEqual(12, ndt.Hour, "Got hour 12")
+ Assert.AreEqual(start.Date, ndt.Date, "Got same date")
+
+ start = DateTime.Parse("1/1/2001 12:30:45 PM")
+ ndt = schedule.NextEvent(start)
+ Assert.AreEqual(14, ndt.Hour, "Got hour 14")
+ Assert.AreEqual(start.Date, ndt.Date, "Got same date")
+
+ start = DateTime.Parse("1/1/2001 15:00 PM")
+ ndt = schedule.NextEvent(start)
+ Assert.AreEqual(4, ndt.Hour, "Got hour 4")
+ Assert.AreEqual(start.AddDays(1).Date, ndt.Date, "Got next day")
+ End Using
+ End Sub
+
+#End Region
+
+End Class
diff --git a/SiphonTests/SiphonTests.vbproj b/SiphonTests/SiphonTests.vbproj
index 42e0496..2ce9a66 100644
--- a/SiphonTests/SiphonTests.vbproj
+++ b/SiphonTests/SiphonTests.vbproj
@@ -40,6 +40,10 @@
False
bin\log4net.dll
+
+ False
+ ..\..\..\..\..\Program Files\TestDriven.NET 2.0\NUnit\2.4\nunit.framework.dll
+
@@ -53,6 +57,7 @@
+
True
@@ -68,6 +73,7 @@
Settings.settings
True
+
@@ -78,6 +84,7 @@
+
MyApplicationCodeGenerator
Application.Designer.vb