001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019package org.apache.wiki.rss; 020 021import java.text.SimpleDateFormat; 022import java.util.Calendar; 023 024import org.apache.wiki.WikiContext; 025import org.apache.wiki.WikiEngine; 026import org.apache.wiki.WikiPage; 027import org.apache.wiki.util.XhtmlUtil; 028import org.jdom2.Element; 029import org.jdom2.Namespace; 030 031 032/** 033 * Provides an implementation of an RSS 1.0 feed. In addition, this class is 034 * capable of adding RSS 1.0 Wiki Extensions to the Feed, as defined in 035 * <A HREF="http://usemod.com/cgi-bin/mb.pl?ModWiki">UseMod:ModWiki</A>. 036 */ 037public class RSS10Feed extends Feed { 038 039 private static final Namespace NS_XMNLS = Namespace.getNamespace( "http://purl.org/rss/1.0/" ); 040 private static final Namespace NS_RDF = Namespace.getNamespace( "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ); 041 private static final Namespace NS_DC = Namespace.getNamespace( "dc", "http://purl.org/dc/elements/1.1/" ); 042 private static final Namespace NS_WIKI = Namespace.getNamespace( "wiki", "http://purl.org/rss/1.0/modules/wiki/" ); 043 044 /** 045 * Create an RSS 1.0 feed for a given context. 046 * 047 * @param context The WikiContext. 048 */ 049 public RSS10Feed( WikiContext context ) { 050 super( context ); 051 } 052 053 private Element getRDFItems() { 054 Element items = new Element( "items", NS_XMNLS ); 055 Element rdfseq = new Element( "Seq", NS_RDF ); 056 057 for( Entry e : m_entries ) { 058 String url = e.getURL(); 059 rdfseq.addContent( new Element( "li", NS_RDF ).setAttribute( "resource", url, NS_RDF ) ); 060 } 061 items.addContent( rdfseq ); 062 063 return items; 064 } 065 066 private void addItemList( Element root ) { 067 SimpleDateFormat iso8601fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 068 WikiEngine engine = m_wikiContext.getEngine(); 069 070 for( Entry entry : m_entries ) { 071 String url = entry.getURL(); 072 073 Element item = new Element( "item", NS_XMNLS ); 074 item.setAttribute( "about", url, NS_RDF ); 075 item.addContent( new Element( "title", NS_XMNLS ).addContent( entry.getTitle() ) ); 076 item.addContent( new Element( "link", NS_XMNLS ).addContent( url ) ); 077 078 Element content = new Element( "description", NS_XMNLS ); 079 // TODO: Add a size limiter here 080 content.addContent( entry.getContent() ); 081 item.addContent( content ); 082 083 WikiPage p = entry.getPage(); 084 if( p.getVersion() != -1 ) { 085 item.addContent( new Element( "version", NS_WIKI ).addContent( Integer.toString( p.getVersion() ) ) ); 086 } 087 088 if( p.getVersion() > 1 ) { 089 item.addContent( new Element( "diff", NS_WIKI ) 090 .addContent( engine.getURL( WikiContext.DIFF, p.getName(), "r1=-1", true ) ) ); 091 } 092 093 // 094 // Modification date. 095 Calendar cal = Calendar.getInstance(); 096 cal.setTime(p.getLastModified()); 097 cal.add( Calendar.MILLISECOND, 098 - ( cal.get( Calendar.ZONE_OFFSET ) + 099 ( cal.getTimeZone().inDaylightTime( p.getLastModified() ) ? cal.get( Calendar.DST_OFFSET ) 100 : 0 ) ) ); 101 102 item.addContent( new Element( "date", NS_DC ).addContent( iso8601fmt.format( cal.getTime() ) ) ); 103 104 // 105 // Author 106 String author = entry.getAuthor(); 107 if( author == null ) { 108 author = "unknown"; 109 } 110 111 Element contributor = new Element( "creator", NS_DC ); 112 item.addContent( contributor ); 113 114 /* 115 Element description = new Element("Description", NS_RDF); 116 if( m_wikiContext.getEngine().pageExists(author) ) { 117 description.setAttribute( "link", engine.getURL( WikiContext.VIEW, author, null, true ), NS_XMNLS ); 118 } 119 120 description.addContent( new Element("value", NS_XMNLS).addContent( author) ); 121 contributor.addContent( description ); 122 */ 123 124 // Not too many aggregators seem to like this. Therefore we're just adding the name here. 125 contributor.addContent( author ); 126 127 // 128 // PageHistory 129 item.addContent( new Element( "history", NS_WIKI ) 130 .addContent( engine.getURL( WikiContext.INFO, p.getName(), null, true ) ) ); 131 132 // 133 // Add to root 134 root.addContent( item ); 135 } 136 } 137 138 private Element getChannelElement() { 139 Element channel = new Element( "channel", NS_XMNLS ); 140 channel.setAttribute( "about", m_feedURL, NS_RDF ) 141 .addContent( new Element( "link", NS_XMNLS ).addContent( m_feedURL ) ); 142 143 if( m_channelTitle != null ) { 144 channel.addContent( new Element( "title", NS_XMNLS ).addContent( m_channelTitle ) ); 145 } 146 147 if( m_channelDescription != null ) { 148 channel.addContent( new Element( "description", NS_XMNLS ).addContent( m_channelDescription ) ); 149 } 150 151 if( m_channelLanguage != null ) { 152 channel.addContent( new Element( "language", NS_DC ).addContent( m_channelLanguage ) ); 153 } 154 channel.addContent( getRDFItems() ); 155 156 return channel; 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override 163 public String getString() { 164 Element root = new Element( "RDF", NS_RDF ); 165 root.addContent( getChannelElement() ); 166 root.addNamespaceDeclaration( NS_XMNLS ); 167 root.addNamespaceDeclaration( NS_RDF ); 168 root.addNamespaceDeclaration( NS_DC ); 169 root.addNamespaceDeclaration( NS_WIKI ); 170 addItemList( root ); 171 172 return XhtmlUtil.serialize( root, true ); 173 } 174 175}