Collecta API Visual Basic .Net 3.5 Interface
Option Explicit On

Imports System
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Net
Imports System.Xml
Imports System.IO

Namespace Collecta

    Public Class API

        Private mKey As String
        Public Sub New(ByVal key As String)
            mKey = key
        End Sub

    End Class

    Public Enum ResultFormat As Integer
        ATOM
        JSON
    End Enum

    Public Enum ResultCategory As Integer
        Story ' Typically long form content. These are blog posts and news articles.
        Comment ' Typically short form content. 
        Update ' Status update messages, including Twitter tweets.
        Photo
        Video
    End Enum

    Public Class Query

#Region "Public Properties"

        ''' <summary>
        ''' The query string in the Collecta query language
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>
        ''' Required in query string.
        ''' Implemented as a temporary means; future: offer a more user-friendly means of building the query string.
        ''' </remarks>
        Public Property QueryString() As String
            Get
                Return mQueryString
            End Get
            Set(ByVal value As String)
                mQueryString = value
            End Set
        End Property
        Private mQueryString As String

        ''' <summary>
        ''' Maximum number of results per page in the response.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property MaximumResultCount() As Integer
            Get
                Return mMaximumResultCount
            End Get
            Set(ByVal value As Integer)
                mMaximumResultCount = value
            End Set
        End Property
        Private Const dMaximumResultCount As Integer = 15
        Private mMaximumResultCount As Integer = dMaximumResultCount

        ''' <summary>
        ''' Number of pages back to go for results.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Page() As Integer
            Get
                Return mPage
            End Get
            Set(ByVal value As Integer)
                mPage = value
            End Set
        End Property
        Private mPage As Integer = 0

        ''' <summary>
        ''' When specified, the ID number after which payloads will be returned.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property SinceID() As Integer
            Get
                Return mSinceID
            End Get
            Set(ByVal value As Integer)
                mSinceID = value
            End Set
        End Property
        Private mSinceID As Integer = 0

        ''' api_key - Required. ALL requests to the HTTP API require an API key, please request a key.
        Private mKey As String

        ''' <summary>
        ''' Format of the results returned. 
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>
        ''' Since the XML content is not actually returned to the user, this may appear to be 
        ''' needless. However, this distinction allows the user to choose the format he wants
        ''' to use, and makes it easier to support new return formats in the future.
        ''' </remarks>
        Public Property Format() As ResultFormat
            Get
                Return mFormat
            End Get
            Set(ByVal value As ResultFormat)
                mFormat = value
            End Set
        End Property
        Private mFormat As ResultFormat = ResultFormat.ATOM

        ''' <summary>
        ''' Name of the JavaScript function to support crossdomain JSONp callback. 
        ''' </summary>
        ''' <remarks></remarks>
        Private mCallback As String
        Public Property Callback() As String
            Get
                Return mCallback
            End Get
            Set(ByVal value As String)
                mCallback = value
            End Set
        End Property

#End Region

        Public Sub New(ByVal key As String)
            mKey = key
        End Sub

        Public Function Execute() As List(Of Result)

            Dim list As New List(Of Result)

            Try
                Dim resultDoc As New XmlDocument
                resultDoc.LoadXml(QueryResultContent)

                If resultDoc.DocumentElement IsNot Nothing Then
                    For Each childElement As XmlElement In resultDoc.DocumentElement.GetElementsByTagName("entry")
                        list.Add(New Result(childElement))
                    Next
                End If

            Catch ex As Exception
                Throw New Exception("Error parsing response received from Collecta.", ex)
            End Try

            Return list

        End Function

#Region "Private Methods"

        Private ReadOnly Property QueryURI() As String
            Get
                Dim sb As New System.Text.StringBuilder("http://api.collecta.com/search/?q=")
                sb.Append(mQueryString)
                sb.Append("&api_key=")
                sb.Append(mKey)
                If mMaximumResultCount <> dMaximumResultCount Then
                    sb.Append("&rpp=")
                    sb.Append(mMaximumResultCount)
                End If
                If mPage > 0 Then
                    sb.Append("&page=")
                    sb.Append(mPage)
                End If
                If mSinceID > 0 Then
                    sb.Append("&since_id=")
                    sb.Append(mSinceID)
                End If
                If mFormat = ResultFormat.JSON Then
                    sb.Append("format=json")
                End If
                If mCallback.Length > 0 Then
                    sb.Append("&callback=")
                    sb.Append(mCallback)
                End If
                Return sb.ToString
            End Get
        End Property

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks>Can throw exceptions to caller.</remarks>
        Private ReadOnly Property QueryResultContent() As String
            Get

                Dim contentReceived As String

                Dim request As HttpWebRequest = CType(WebRequest.Create(QueryURI), HttpWebRequest)
                With request
                    .Method = "GET"
                    .MaximumAutomaticRedirections = 4
                    .MaximumResponseHeadersLength = 4
                    .ContentLength = 0
                End With

                Dim response As HttpWebResponse = CType(request.GetResponse, HttpWebResponse)

                Dim receiveStream As Stream = response.GetResponseStream
                Dim reader As StreamReader = New StreamReader(receiveStream, Encoding.UTF8)
                contentReceived = reader.ReadToEnd
                reader.Close()

                response.Close()

                Return contentReceived

            End Get
        End Property

#End Region

    End Class

    Public Class Result

        Private mSummary As String = ""
        Public ReadOnly Property Summary() As String
            Get
                Return mSummary
            End Get
        End Property

        Private mTitle As String = ""
        Public ReadOnly Property Title() As String
            Get
                Return mTitle
            End Get
        End Property

        Private mLink As String
        Public ReadOnly Property Link() As String
            Get
                Return mLink
            End Get
        End Property

        Private mPublishDate As DateTime
        Public ReadOnly Property PublishDate() As DateTime
            Get
                Return mPublishDate
            End Get
        End Property

        Private mUpdateDate As DateTime
        Public ReadOnly Property UpdateDate() As DateTime
            Get
                Return mUpdateDate
            End Get
        End Property

        Private mLanguage As String
        Public ReadOnly Property Language() As String
            Get
                Return mLanguage
            End Get
        End Property

        Private mCategory As ResultCategory
        Public ReadOnly Property Category() As ResultCategory
            Get
                Return mCategory
            End Get
        End Property

        Private mAbstract As String
        Public ReadOnly Property Abstract() As String
            Get
                Return mAbstract
            End Get
        End Property

        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="node">An 'entry' node.</param>
        ''' <remarks></remarks>
        Public Sub New(ByVal node As XmlNode)

            Const cNullInv As String = "Null or invalid node passed to constructor."
            Const cAtomURI As String = "http://www.w3.org/2005/Atom"

            If node Is Nothing Then                Throw New ArgumentException(cNullInv)

            'TODO: Verify that the node is 'entry'.

            If node.Attributes("xmlns") Is Nothing Then Throw New ArgumentException(cNullInv)

            If node.Attributes("xmlns").InnerText = cAtomURI Then ParseAtomNode(node)

        End Sub

        Private Sub ParseAtomNode(ByVal node As XmlNode)

            mSummary = node("summary").InnerText
            mTitle = node("title").InnerText
            mLink = node("link").Attributes("href").InnerText
            mPublishDate = ParseDateString(node("published").InnerText)
            mUpdateDate = ParseDateString(node("updated").InnerText)
            mLanguage = node("Language").InnerText
            Select Case node("Category").InnerText
                Case "story" : mCategory = ResultCategory.Story
                Case "comment" : mCategory = ResultCategory.Comment
                Case "update" : mCategory = ResultCategory.Update
                Case "photo" : mCategory = ResultCategory.Photo
                Case "video" : mCategory = ResultCategory.Video
            End Select
            mAbstract = node("abstract").InnerText

        End Sub

        Private Shared Function ParseDateString(ByVal dateString As String) As DateTime

            Dim regex As New Regex("(?<DayName>[^ ]+) (?<MonthName>[^ ]+) (?<Day>[^ ]{1,2}) (?<Hour>[0-9]{1,2}):(?<Minute>[0-9]{1,2}):(?<Second>[0-9]{1,2}) (?<TimeZone>[+-][0-9]{4}) (?<Year>[0-9]{4})")
            Dim regexMatch As Match = regex.Match(dateString)

            Dim monthName As String = regexMatch.Groups("MonthName").Value
            Dim day As String = regexMatch.Groups("Day").Value
            Dim year As String = regexMatch.Groups("Year").Value
            Dim hour As String = regexMatch.Groups("Hour").Value
            Dim minute As String = regexMatch.Groups("Minute").Value
            Dim second As String = regexMatch.Groups("Second").Value

            Return DateTime.Parse(String.Format("{0} {1} {2} {3}:{4}:{5}", monthName, day, year, hour, minute, second))

        End Function

    End Class

End Namespace
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License