How to differ updated document from created one according to web feed

Eventually I found following codes work and it will include additional authors’ names and update dates. And more it try to add deleted document information. The deleted entry is marked as non-nil uri and null link. It might be a bit odd. Anyway it works.

{{velocity}}
## Backward compatibility redirect, if the RSS feed is called without the outputSyntax query argument, force it.
#if (("$!request.xpage" == 'plain' || "$!request.xpage" == 'rdf') && "$!request.outputSyntax" != 'plain')
  $response.sendRedirect($xwiki.getURL($doc.fullName, 'view', 'xpage=plain&outputSyntax=plain'))
#end
#if ("$!request.xpage" == 'plain' && "$!request.outputSyntax" == 'plain')
  $response.setContentType('application/rss+xml')
  ## ======================
  ## Compute Query to find documents
  ## ======================
  #if ("$!{request.tag}" != '')
    ## RSS feed for documents tagged with $request.tag
    #set ($query = 'from doc.object(XWiki.TagClass) as tag where (')
    #foreach ($tag in $request.getParameterValues('tag'))
      #set ($query = "$query :tag${foreach.count} member of tag.tags")
      #if ($foreach.hasNext)
        #set ($query = "$query OR ")
      #end
    #end
    #set ($query = "$query) AND ")
  #else
    #set ($query = 'where')
  #end
  #if ("$!{request.space}" == '')
    ## RSS feed for the whole wiki
    #set ($query = "$query 1=1")
  #else
    ## RSS feed for spaces
    #set ($query = "$query (")
    #foreach ($space in $request.getParameterValues('space'))
      #set ($query = "$query doc.space=:space${foreach.count} OR doc.space LIKE :space_nested${foreach.count}")
      #if ($foreach.hasNext)
        #set ($query = "$query OR ")
      #end
    #end
    #set ($query = "$query)")
  #end
  #set ($query = "$query order by doc.date desc")
  ## ==============
  ## Bind Query parameters
  ## ==============
  ## Bind query parameters depending on the passed query string parameters
  #set ($queryObject = $services.query.xwql($query).addFilter('hidden/document').addFilter('currentlanguage').setLimit(20).setOffset(0))
  #if ("$!{request.tag}" != '')
    #foreach ($tag in $request.getParameterValues('tag'))
      #set ($queryObject = $queryObject.bindValue("tag${foreach.count}", $tag))
    #end
  #end
  #if ("$!{request.space}" != '')
    #foreach ($space in $request.getParameterValues('space'))
      #set ($queryObject = $queryObject.bindValue("space${foreach.count}", $space))
      #set ($queryObject = $queryObject.bindValue("space_nested${foreach.count}", "${space}.%"))
    #end
  #end
  ## ================
  ## Compute feed description
  ## ================
  ## 4 cases to handle: no spaces and tags specified, only spaces specified, only tags specified and spaces and tags specified
  #if ("$!{request.space}" != '')
    #if ("$!{request.tag}" != '')
      #set ($description = $services.localization.render('activity.rss.feed.tagsAndSpaces.description', [$stringtool.join($request.getParameterValues('tag'), ','), $stringtool.join($request.getParameterValues('space'), ',')]))
    #else
      #set ($description = $services.localization.render('activity.rss.feed.spaces.description', [$stringtool.join($request.getParameterValues('space'), ',')]))
    #end
  #else
    #if ("$!{request.tag}" != '')
      #set ($description = $services.localization.render('activity.rss.feed.tags.description', [$stringtool.join($request.getParameterValues('tag'), ',')]))
    #else
      #set ($description = $services.localization.render('activity.rss.feed.description'))
    #end
  #end
  ## =====================
  ## Execute query and generate feed
  ## =====================
  #set ($feed = $xwiki.feed.getWebFeed($queryObject.execute()))
  #set ($feedURI = $xwiki.getDocument('Main.WebHome').getExternalURL('view'))
  #set ($discard = $feed.setLink($feedURI))
  #set ($discard = $feed.setUri($feedURI))
  #set ($discard = $feed.setAuthor('XWiki'))
  #set ($discard = $feed.setTitle($services.localization.render('activity.rss.feed.description')))
  #set ($discard = $feed.setDescription($description))
  #set ($discard = $feed.setLanguage("$xcontext.locale"))
  #set ($discard = $feed.setCopyright($xwiki.getXWikiPreference('copyright')))

  ## =====================
  ## Query activities
  ## =====================
  #set ($query = 'select act from ActivityEventImpl as act, ActivityEventImpl as act2')
  #set ($query = "$query where act.eventId=act2.eventId and")
  #set ($query = "$query (act.hidden <> true or act.hidden is null) and")
  #if ("$!{request.space}" == '')
    ## RSS feed for the whole wiki
    #set ($query = "$query 1=1")
  #else
    ## RSS feed for spaces
    #set ($query = "$query (")
    #foreach ($space in $request.getParameterValues('space'))
      #set ($query = "$query act.space=:space${foreach.count} OR act.space LIKE :space_nested${foreach.count}")
      #if ($foreach.hasNext)
        #set ($query = "$query OR ")
      #end
    #end
    #set ($query = "$query)")
  #end
  #set ($query = "$query group by act.requestId having (act.priority)=max(act2.priority) order by act.url, act.date desc")
  #set ($queryObject = $services.query.xwql($query).setOffset(0))
  #if ("$!{request.space}" != '')
    #foreach ($space in $request.getParameterValues('space'))
      #set ($queryObject = $queryObject.bindValue("space${foreach.count}", $space))
      #set ($queryObject = $queryObject.bindValue("space_nested${foreach.count}", "${space}.%"))
    #end
  #end
  #set ($activities = $queryObject.execute())
#end
{{/velocity}}

{{groovy}}
if (request.xpage == 'plain' && request.outputSyntax == 'plain') {
  def mapDocumentActivities = [:]
  //println(activities)
  for (activity in activities) {
    def name = activity.page
    //println "$name " + name.length()
    if (!mapDocumentActivities.containsKey("$name")) {
      mapDocumentActivities[(name)] = []
    }
    mapDocumentActivities[(name)].add(activity)
  }
  //println mapDocCreateActivities

  //println(feed)
  for (entry in feed?.getEntries()) {
    def decodedUri = URLDecoder.decode(entry.uri, 'UTF-8')
    def pathStartPos = decodedUri.indexOf('view') + 5
    def pathEndPos = decodedUri.indexOf(entry.title.replaceAll(' ', ''))
    if (-1 == pathStartPos || -1 == pathEndPos) {
      continue
    }

    def fullname = decodedUri.substring(pathStartPos, pathEndPos) + entry.title + ".WebHome"
    fullname = fullname.replaceAll('/', '.')
    //println fullname

    // add document content
    def document = xwiki.getDocument(fullname)
    def content = xwiki.renderText(document.getContent(), document)
    def syndContent = new com.sun.syndication.feed.synd.SyndContentImpl()
    syndContent.setValue(content)
    syndContent.setType('text/html')
    //println(content)
    entry.setContents([syndContent])

    if (null != mapDocumentActivities[(fullname)]) {
      for (module in entry.getModules()) {
        //println "$module.date " + mapDocumentActivities[(fullname)].date
        def activities = mapDocumentActivities[(fullname)]
        def contributors = []
        module.setContributors(contributors)
        def dates = module.dates
        for (activity in activities) {
          //println xwiki.getUserName(activity.user, false)
          contributors.add(xwiki.getUserName(activity.user, false))
          dates.add(activity.date)
        }
      }
      //println entry
    }
  }

  // add deleted document entry
  for (activity in activities) {
    if ('delete'.equals(activity.type)) {
      def docFullName = activity.page
      def path = ''
      def inNamePeriodReplacement = UUID.randomUUID().toString()
      def encodedPageName = activity.page.replaceAll('\\\\.', inNamePeriodReplacement)
      def lastPeriodPos = encodedPageName.lastIndexOf('.')
      if (lastPeriodPos > -1) {
        docFullName = encodedPageName.substring(lastPeriodPos + 1).replaceAll(inNamePeriodReplacement, '\\.')
        path = encodedPageName.substring(0, lastPeriodPos).replaceAll('\\.', '/').replaceAll(inNamePeriodReplacement, '\\.')
      }

      def deletedEntry = new com.sun.syndication.feed.synd.SyndEntryImpl()
      deletedEntry.setTitle(docFullName)
      deletedEntry.setUri(path)
      deletedEntry.setPublishedDate(activity.date)
      deletedEntry.setAuthor(xwiki.getUserName(activity.user, false))
      feed.getEntries().add(deletedEntry)
    }
  }
}
{{/groovy}}

{{velocity}}
#if ("$!request.xpage" == 'plain' && "$!request.outputSyntax" == 'plain')
  $xwiki.feed.getFeedOutput($feed, $xwiki.getXWikiPreference('feed_type', 'rss_2.0'))
#end
{{/velocity}}