wf_createVCAds.xml

Build 1501 on 14/Nov/2017  This topic last edited on: 24/Oct/2016, at 13:07

<!-- Miles33/Tera DP -->

<!-- Back4 Workflow to import lineage and job ads from Gemstone and publish them to VirtualCMS.

 

It uses input XML files generated by the "Generic Exporter" containing 

either <ad> records or <jobAd> records. It will then call, for each ad 

for which a section exists in VirtualCMS, the VC API to create the content 

and another one to publish it immediately.

 

Parameters:

  VCWebsiteUrl: VirtualCMS website (root. Like http://setup.virtualcms.it/henley-standard)

  JobsSectionId: Id of the "Jobs" section on VirtualCMS

  VCAuthCodeKey: authCode for this customer. To be obtained from VirtualCom

 

The Workflow contains a XML which maps the codes of the Gemstone classifications 

to the section ids on VirtualCMS. This is the variable ClassificationMap. To create 

this XML, please follow the instructions in the documentation.

-->

<codeWorkflow xmlns="http://www.teradp.com/schemas/GN4/1/WFRes.xsd">

  <References>

    <Reference>Newtonsoft.Json.dll</Reference>

    <Reference>System.Web.dll</Reference>

  </References>

  <Imports>

    <Import>System.Web</Import>

    <Import>System.Net</Import>

    <Import>System.Text</Import>

    <Import>System.Security.Cryptography</Import>

    <Import>Newtonsoft.Json</Import>

    <Import>Newtonsoft.Json.Linq</Import>

  </Imports>

  <Members><![CDATA[

Dim ClassificationMap As XElement =

    <root>

      <!--classification short_name="PLet" long_name="Property to Let" vcId="572"/>

      <classification short_name="GRAD" long_name="Graduate"/>

      <classification short_name="Marr" long_name="Marriage"/>

      <classification short_name="CV" long_name="Charity &amp; Voluntary Work"/>

      <classification short_name="TT" long_name="Trusted Trades"/>

      <classification short_name="HS" long_name="Health &amp; Safety"/>

      <classification short_name="Gal" long_name="Galleries"/>

      <classification short_name="HHR" long_name="Hospitality, Hotel &amp; Restaurant"/>

      <classification short_name="MDay" long_name="Mothers Day"/>

      <classification short_name="Thank" long_name="Thanks"/>

      <classification short_name="DLS" long_name="Defence, Law, Security"/>

      <classification short_name="MServ" long_name="Miscellaneous Services" vcId="564"/>

      <classification short_name="HL" long_name="Henley Life"/>

      <classification short_name="ROP" long_name="Run of Paper"/>

      <classification short_name="Carp" long_name="Carpets &amp; Curtains" vcId="544"/>

      <classification short_name="TD" long_name="The Directory"/>

      <classification short_name="ACS" long_name="Art. Culture, Sports"/>

      <classification short_name="OG" long_name="Oil &amp; Gas"/>

      <classification short_name="NYNY" long_name="New Year New You"/>

      <classification short_name="Wdine" long_name="Wine &amp; Dine"/>

      <classification short_name="MIL" long_name="Military"/>

      <classification short_name="SA" long_name="Secretarial &amp; Administration"/>

      <classification short_name="Art" long_name="Art Galleries"/>

      <classification short_name="Lost" long_name="Lost &amp; Found" vcId="562"/>

      <classification short_name="Cloth" long_name="Clothing &amp; Footware" vcId="547"/>

      <classification short_name="PUR" long_name="Purchasing"/>

      <classification short_name="TC" long_name="Telecommunications"/>

      <classification short_name="TY" long_name="Treat Yourself"/>

      <classification short_name="CSCC" long_name="Customer Service, Call Centre"/>

      <classification short_name="CON" long_name="Consultancy"/>

      <classification short_name="MARK" long_name="Marketing"/>

      <classification short_name="Accr" long_name="Accommodation/Rooms" vcId="539"/>

      <classification short_name="LEG" long_name="Legal"/>

      <classification short_name="Auto" long_name="Automotive"/>

      <classification short_name="Want" long_name="Wanted" vcId="581"/>

      <classification short_name="TV" long_name="TV &amp; Audio" vcId="578"/>

      <classification short_name="Birth" long_name="Births"/>

      <classification short_name="Music" long_name="Musical Eqiupment" vcId="568"/>

      <classification short_name="SITS" long_name="Situations Vacant" vcId="575"/>

      <classification short_name="Sport" long_name="Sport"/>

      <classification short_name="SGM" long_name="Service Guide"/>

      <classification short_name="QCare" long_name="Quality Caring"/>

      <classification short_name="Car" long_name="Cars and Vans for Sale" vcId="545"/>

      <classification short_name="MAN" long_name="Manufacturing"/>

      <classification short_name="Goods" long_name="General Household Goods" vcId="556"/>

      <classification short_name="HHG" long_name="Henley House &amp; Garden"/>

      <classification short_name="PS" long_name="Public Sector"/>

      <classification short_name="Rev" long_name="Review of the Year"/>

      <classification short_name="Mot" long_name="Motors"/>

      <classification short_name="RFash" long_name="Regatta Fashion"/>

      <classification short_name="Hbeau" long_name="Health &amp; Beauty" vcId="557"/>

      <classification short_name="MED" long_name="Media"/>

      <classification short_name="HS" long_name="Health Services"/>

      <classification short_name="SS" long_name="Social Services"/>

      <classification short_name="TM" long_name="Town Map"/>

      <classification short_name="SALES" long_name="Sales"/>

      <classification short_name="Jewel" long_name="Jewellery &amp; Gifts" vcId="560"/>

      <classification short_name="Trade" long_name="Local Trades &amp; Services"/>

      <classification short_name="Greet" long_name="Greetings"/>

      <classification short_name="MBike" long_name="Motobikes" vcId="567"/>

      <classification short_name="FA" long_name="Finance &amp; Accounting"/>

      <classification short_name="AFG" long_name="Agriculture, Forestry, Gardening"/>

      <classification short_name="RET" long_name="Retail"/>

      <classification short_name="Off" long_name="Official Notices"/>

      <classification short_name="Local" long_name="Keep it Local"/>

      <classification short_name="ATT" long_name="Attractions"/>

      <classification short_name="VG" long_name="Visitor Guide ROP"/>

      <classification short_name="Weds" long_name="Weddings"/>

      <classification short_name="SOA" long_name="Summer Out &amp; About"/>

      <classification short_name="NHome" long_name="New Homes"/>

      <classification short_name="Death" long_name="Deaths"/>

      <classification short_name="FDay" long_name="Fathers Day"/>

      <classification short_name="PUB" long_name="Publishing"/>

      <classification short_name="Home" long_name="Home Improvement" vcId="559"/>

      <classification short_name="SE" long_name="Self Employed"/>

      <classification short_name="ROS" long_name="Run of Site"/>

      <classification short_name="WON" long_name="Whats On"/>

      <classification short_name="TEL" long_name="Telecom"/>

      <classification short_name="XTV" long_name="Christmas TV"/>

      <classification short_name="Leaf" long_name="Leaflets"/>

      <classification short_name="DIS" long_name="Distribution"/>

      <classification short_name="Cycle" long_name="Cycles &amp; Sports" vcId="548"/>

      <classification short_name="Jobs" long_name="Jobs"/>

      <classification short_name="CS" long_name="Customer Service"/>

      <classification short_name="" long_name="Online Announcements"/>

      <classification short_name="ES" long_name="Engineering and Science"/>

      <classification short_name="HEAL" long_name="Health"/>

      <classification short_name="Inmem" long_name="In Memoriam"/>

      <classification short_name="BF" long_name="Banking &amp; Finance"/>

      <classification short_name="Bus" long_name="Business" vcId="542"/>

      <classification short_name="CLEAN" long_name="Cleaning"/>

      <classification short_name="East" long_name="Easter Out &amp; About"/>

      <classification short_name="River" long_name="Messing About on the River"/>

      <classification short_name="Stabl" long_name="Stable Talk"/>

      <classification short_name="IN" long_name="Insurance"/>

      <classification short_name="TD" long_name="Transport &amp; Distribution"/>

      <classification short_name="SWant" long_name="Situations Wanted" vcId="576"/>

      <classification short_name="TRAV" long_name="Travel"/>

      <classification short_name="ELEC" long_name="Electronics"/>

      <classification short_name="RD" long_name="Research and Development"/>

      <classification short_name="Train" long_name="Training &amp; Tuition" vcId="577"/>

      <classification short_name="ME" long_name="Management &amp; Executive"/>

      <classification short_name="Gard" long_name="Garden Furniture &amp; Equipment" vcId="555"/>

      <classification short_name="EA" long_name="Estate Agents"/>

      <classification short_name="ACC" long_name="Accounting"/>

      <classification short_name="TRAIN" long_name="Training"/>

      <classification short_name="Hols" long_name="Holidays" vcId="558"/>

      <classification short_name="MMess" long_name="Mothers Day Messages"/>

      <classification short_name="Regat" long_name="Regatta Supplement"/>

      <classification short_name="Mob" long_name="Mobility" vcId="565"/>

      <classification short_name="CON" long_name="Construction"/>

      <classification short_name="DEF" long_name="Defence"/>

      <classification short_name="EC" long_name="Education &amp; Childcare"/>

      <classification short_name="PCBH" long_name="Personal Care, Beauty, Hairdressing"/>

      <classification short_name="PS" long_name="Personal" vcId="569"/>

      <classification short_name="Moth" long_name="Mother &amp; Baby" vcId="566"/>

      <classification short_name="BP" long_name="Business Promotion"/>

      <classification short_name="XFest" long_name="Christmas Festival"/>

      <classification short_name="HS" long_name="Henley Show"/>

      <classification short_name="FServ" long_name="Funeral Services"/>

      <classification short_name="EDU" long_name="Education"/>

      <classification short_name="FClas" long_name="First Class"/>

      <classification short_name="Dom" long_name="Domestic Appliances" vcId="549"/>

      <classification short_name="CIT" long_name="Computing/IT"/>

      <classification short_name="BBAT" long_name="Bumps, Babies &amp; Toddlers"/>

      <classification short_name="SVD" long_name="Situations Vac Display"/>

      <classification short_name="VMess" long_name="Valentines Message"/>

      <classification short_name="FGO" long_name="Feeling Good"/>

      <classification short_name="HAGS" long_name="Homes &amp; Gardens"/>

      <classification short_name="BI" long_name="Banking &amp; Investments"/>

      <classification short_name="VServ" long_name="Vehicle Services" vcId="579"/>

      <classification short_name="HOUS" long_name="Housing"/>

      <classification short_name="PO" long_name="Production &amp; Operations"/>

      <classification short_name="Barg" long_name="Bargains Under 50" vcId="541"/>

      <classification short_name="BC" long_name="Building &amp; Construction"/>

      <classification short_name="River" long_name="River" vcId="574"/>

      <classification short_name="Cvan" long_name="Caravans" vcId="543"/>

      <classification short_name="ENG" long_name="Engineering"/>

      <classification short_name="ADV" long_name="Advertorial"/>

      <classification short_name="RW" long_name="Retail and Wholesale"/>

      <classification short_name="PSale" long_name="Property for Sale" vcId="571"/>

      <classification short_name="PGG" long_name="Christmas Greetings - Pubs &amp; Restaurants"/>

      <classification short_name="SC" long_name="Scientific"/>

      <classification short_name="CVWan" long_name="Cars and Vans Wanted" vcId="580"/>

      <classification short_name="ES" long_name="Energy Sector (Oil/Gas/Electricity)"/>

      <classification short_name="Event" long_name="Events" vcId="550"/>

      <classification short_name="Rewin" long_name="Rewind Supplement"/>

      <classification short_name="Acc" long_name="Accommodation"/>

      <classification short_name="LLS" long_name="Law and Legal Services"/>

      <classification short_name="CHU" long_name="Churches"/>

      <classification short_name="Creat" long_name="Creature Comforts"/>

      <classification short_name="MSale" long_name="Miscellaneous Sales" vcId="563"/>

      <classification short_name="EU" long_name="Energy &amp; Utilities"/>

      <classification short_name="Farm" long_name="Farm &amp; Garden" vcId="552"/>

      <classification short_name="Val" long_name="Valentines Day"/>

      <classification short_name="REC" long_name="Recruitment"/>

      <classification short_name="AN" long_name="Anniversaries"/>

      <classification short_name="Regat" long_name="Regatta/Festival" vcId="573"/>

      <classification short_name="TGG" long_name="Christmas Greetings - Trade"/>

      <classification short_name="Engag" long_name="Engagement"/>

      <classification short_name="Gdoor" long_name="Garage Doors" vcId="554"/>

      <classification short_name="SE" long_name="Senior Executive"/>

      <classification short_name="Tserv" long_name="Thanksgiving Service"/>

      <classification short_name="CNP" long_name="Charity, Non Profit"/>

      <classification short_name="Ant" long_name="Antiques &amp; Collectables" vcId="540"/>

      <classification short_name="TCH" long_name="Travel, Catering &amp; Hospitality"/>

      <classification short_name="HR" long_name="Human Resources"/>

      <classification short_name="AV" long_name="Aviation"/>

      <classification short_name="AFS" long_name="Articles For Sale"/>

      <classification short_name="IT" long_name="Information Technology"/>

      <classification short_name="Pets" long_name="Pets &amp; Livestock" vcId="570"/>

      <classification short_name="SS" long_name="Shops &amp; Services"/>

      <classification short_name="HFest" long_name="Henley Festival"/>

      <classification short_name="OA" long_name="Office/Administration"/>

      <classification short_name="TS" long_name="Trade/Services"/>

      <classification short_name="Furn" long_name="Furniture" vcId="553"/>

      <classification short_name="PTE" long_name="Places to Eat"/>

      <classification short_name="Xmas" long_name="Christmas"/>

      <classification short_name="Fun" long_name="Fun things to do this Summer"/>

      <classification short_name="Logs" long_name="Logs &amp; Solid Fuel" vcId="561"/>

      <classification short_name="LT" long_name="Logistics &amp; Transport"/>

      <classification short_name="Child" long_name="Childcare" vcId="546"/-->

    </root>

 

  Function LoadPar(ByVal sParName As String, Optional ByVal sDefaultVar As String = Nothing) As String

    Dim sRet As String = Context.ParValue(sParName)

 

    If String.IsNullOrEmpty(sRet) Then

      If IsNothing(sDefaultVar) Then

        Utils.LogError("Parameter '" & sParName & "' missing! Cannot proceed!")

      Else

        sRet = sDefaultVar

        Utils.LogMessage("Parameter '" & sParName & "' missing or empty. Using default value '" & sDefaultVar & "'.", TeraDP.GN4.Workflow.LogEntry.LogCode.Warning)

      End If

    End If

    Return sRet

  End Function

 

  Shared Function GetMd5Hash(ByVal md5Hash As MD5, ByVal input As String) As String

 

    ' Convert the input string to a byte array and compute the hash.

    Dim data As Byte() = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input))

 

    ' Create a new Stringbuilder to collect the bytes

    ' and create a string.

    Dim sBuilder As New StringBuilder()

 

    ' Loop through each byte of the hashed data 

    ' and format each one as a hexadecimal string.

    Dim i As Integer

    For i = 0 To data.Length - 1

      sBuilder.Append(data(i).ToString("x2"))

    Next i

 

    ' Return the hexadecimal string.

    Return sBuilder.ToString()

 

  End Function 'GetMd5Hash

 

  Function CallVCSite(ByVal sUrl As String) As JObject

    Try

      Dim req As WebRequest = WebRequest.Create(sUrl)

      Dim resp As WebResponse = req.GetResponse()

      Dim sr As IO.StreamReader = New IO.StreamReader(resp.GetResponseStream())

      Return JObject.Parse(sr.ReadToEnd())

    Catch ex As Exception

      Utils.LogError(String.Format("Error calling {0}: {1}", sUrl, ex.Message))

    End Try

    Return Nothing

  End Function

]]></Members>

  <Sequential Description="Back4 Workflow to import lineage and job ads from Gemstone and publish them to VirtualCMS" DisplayProgress="true"><![CDATA[

' Load parameters

    Dim sVCURL As String = LoadPar("VCWebsiteUrl")

    Dim sVCAuthCode As String = LoadPar("VCAuthCodeKey") ' Higgs: 897f42b8486a60685c7b248c6916dc73 

    Dim sJobsSectionId As String = LoadPar("JobsSectionId")

 Dim sClassId as String = LoadPar("DefaultClassId") ' default classification Id

 

    If String.IsNullOrEmpty(sVCURL) Or _

        String.IsNullOrEmpty(sVCAuthCode) Then Return

 

    If String.IsNullOrEmpty(sJobsSectionId) Then Utils.LogWarning("Missing or invalid key 'JobsSectionId': jobs will not be imported!")

 

    Dim lUrls As List(Of String) = New List(Of String)

    For Each aData As TeraDP.GN4.Workflow.IActivityData In Context.Data

      Try

        Dim loadXmlAct As LoadXml = New LoadXml(Context) With {

          .Name = "loadXml",

          .Description = "Load the xml file in memory",

          .Data = aData

        }

        Dim loadXmlRes As LoadXmlResult = loadXmlAct.Do()

 

        Dim xDoc As Xml.XmlDocument = New XmlDocument()

        Using read As XmlReader = loadXmlRes.XmlOut.CreateReader()

          xDoc.Load(read)

        End Using

        Dim root As XmlNode = xDoc.DocumentElement

 

        ' Process all new Jobs in the XML

        For Each job As XmlNode In root.SelectNodes("//JobAd|//ad")

          'Job Fields (2): http://setup.virtualcms.it/henley-standard/webservices/preset/getFields.jsp?presetId=2

          Dim sFrom, sTo As String

          Dim iPresetId As Integer = 3 ' Lineage Ad by default

          If job.Name = "JobAd" Then iPresetId = 2 ' Job

          Dim sTmp As String = "?presetId=" & iPresetId

          If iPresetId = 2 And Not String.IsNullOrEmpty(sJobsSectionId) Then

            ' Jobs

            Dim sTitle As String = job.Attributes("JobAdHeader").Value.ToString

            If String.IsNullOrEmpty(sTitle) Then sTitle = "missing title"

            sTmp &= "&title=" & HttpUtility.UrlEncode(sTitle)

            sTmp &= "&keywords=jobs%20" & HttpUtility.UrlEncode(job.Attributes("JobAdHeader").Value)

            sTmp &= "&field[20]=" & HttpUtility.UrlEncode(job.Attributes("JobAdHeader").Value) '        20 = "Job Title",

            sTmp &= "&field[21]=" & job.Attributes("SearchCriteriaJobType").Value '        21 = "Job Type",

            sTmp &= "&field[22]=" & HttpUtility.UrlEncode(job.Attributes("ContactAddress2").Value) '        22 = "Location",

            sTmp &= "&field[23]=" & HttpUtility.UrlEncode(job.Attributes("JobAdPlainText").Value) '        23 = "Description",

            sTmp &= "&text=" & HttpUtility.UrlEncode(job.Attributes("JobAdPlainText").Value) '        text is the alternative to the description

            '           24 = "Salary",

            '           25 = "Hours",

            sFrom = job.Attributes("ValidFrom").Value

            If Not String.IsNullOrEmpty(sFrom) Then sTmp &= "&field[26]=" & sFrom.Substring(0, 4) & "-" & sFrom.Substring(4, 2) & "-" & sFrom.Substring(6, 2) & "%2000:00:00" '        26 = "Date Posted",

            sTo = job.Attributes("ValidTo").Value

            If Not String.IsNullOrEmpty(sTo) Then sTmp &= "&field[27]=" & sTo.Substring(0, 4) & "-" & sTo.Substring(4, 2) & "-" & sTo.Substring(6, 2) & "%2000:00:00" '        27 = "Date Expiry",

            sTmp &= "&field[28]=" & job.Attributes("JobAdID").Value '        28 = "URN",

            Using MD5Hash As MD5 = MD5.Create()

              Dim hash As String = GetMd5Hash(MD5Hash, sTitle & sVCAuthCode)

              sTmp &= "&authCode=" & hash

            End Using

            sTmp &= "&m33sect=" & sJobsSectionId

            lUrls.Add(sTmp) ' Add the job to the list of URLS to call

          Else

            ' Classified ads

            Dim sTitle As String = job.SelectSingleNode("id").InnerText

            sTmp &= "&title=" & HttpUtility.UrlEncode(sTitle)

            sTmp &= "&keywords=" & HttpUtility.UrlEncode(sTitle)

            sTmp &= "&text=" & HttpUtility.UrlEncode(job.SelectSingleNode("text").InnerText)

            Using MD5Hash As MD5 = MD5.Create()

              Dim hash As String = GetMd5Hash(MD5Hash, sTitle & sVCAuthCode)

              sTmp &= "&authCode=" & hash

            End Using

            Dim sClassName As String = job.SelectSingleNode("section").InnerText ' Now we have to find this in the external (mapping XML)

            If Not String.IsNullOrEmpty(sClassName) Then

              Dim oClass As XElement = ClassificationMap.XPathSelectElement("./classification[@short_name='" & sClassName & "']")

              If Not IsNothing(oClass) Then

                If Not IsNothing(oClass.@vcId) Then

                           sClassId = oClass.@vcId.ToString

                Else

                  Utils.LogWarning(String.Format("Classified {0} does not have a vcId.", sClassName))

                End If

              Else

                Utils.LogWarning(String.Format("Cannot find Classification {0} in the map.", sClassName))

              End If ' Do we have a class

                 

                 sTmp &= "&m33sect=" & sClassId ' this is the classified section

                 lUrls.Add(sTmp) ' We don't want to add ads without a classification

                   

            End If ' Is the classification in the input node?

          End If ' is this a job or a classified?

 

        Next ' end for each job/ad

 

      Catch ex As Exception

        Utils.LogError(ex.Message)

      End Try

 

      ' Call VC's API for each URL we have generated

      For Each sPars As String In lUrls

        ' http://setup.virtualcms.it/henley-standard/

        Dim sUrl As String = sVCURL & "/webservices/preset/create.jsp" & sPars

        Dim VCResult As JObject = CallVCSite(sUrl)

 

        ' This is a JSON string with "OK" to signify all is fine, or "KO" if error. We don't store the id of the ad

        If Not IsNothing(VCResult) And VCResult.GetValue("status").ToString = "KO" Then

          Utils.LogWarning(String.Format("Error '{0}' creating Ad: {1}", VCResult.GetValue("error").ToString, sPars))

        Else

          Dim sSectionId As String = sPars.Substring(sPars.IndexOf("m33sect=") + 8)

          If Not String.IsNullOrEmpty(sSectionId) Then

            sUrl = sVCURL & "/webservices/article/publish.jsp?articleId=" & VCResult.GetValue("internalId").ToString & _

              "&sectionId=" & sSectionId & _

              "&type=shift"

            Using MD5Hash As MD5 = MD5.Create()

              Dim hash As String = GetMd5Hash(MD5Hash, VCResult.GetValue("internalId").ToString & sVCAuthCode)

              sUrl &= "&authCode=" & hash

            End Using

            Dim jResp As JObject = CallVCSite(sUrl)

            If Not IsNothing(jResp) And jResp.GetValue("status").ToString = "OK" Then

              Utils.LogInfo(String.Format("Ad: {0} published successfully!", VCResult.GetValue("internalId").ToString))

            Else

              Utils.LogWarning(String.Format("Ad: {0} failed to publish: {1}",

                                             VCResult.GetValue("internalId").ToString,

                                             jResp.GetValue("error").ToString))

            End If

          Else

            Utils.LogInfo(String.Format("Created Ad: {0}. Please, publish it manually.", VCResult.GetValue("internalId").ToString))

          End If

        End If

      Next

    Next

]]></Sequential>

</codeWorkflow>