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 org.apache.wiki.api.core.Context; 022import org.apache.wiki.api.core.ContextEnum; 023import org.apache.wiki.api.core.Engine; 024import org.apache.wiki.api.core.Page; 025import org.apache.wiki.util.XhtmlUtil; 026import org.jdom2.Element; 027import org.jdom2.Namespace; 028 029import java.text.SimpleDateFormat; 030import java.util.Calendar; 031 032 033/** 034 * Provides an implementation of an RSS 1.0 feed. In addition, this class is 035 * capable of adding RSS 1.0 Wiki Extensions to the Feed, as defined in 036 * <A HREF="http://usemod.com/cgi-bin/mb.pl?ModWiki">UseMod:ModWiki</A>. 037 */ 038public class RSS10Feed extends Feed { 039 040 private static final Namespace NS_XMNLS = Namespace.getNamespace( "http://purl.org/rss/1.0/" ); 041 private static final Namespace NS_RDF = Namespace.getNamespace( "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ); 042 private static final Namespace NS_DC = Namespace.getNamespace( "dc", "http://purl.org/dc/elements/1.1/" ); 043 private static final Namespace NS_WIKI = Namespace.getNamespace( "wiki", "http://purl.org/rss/1.0/modules/wiki/" ); 044 045 /** 046 * Create an RSS 1.0 feed for a given context. 047 * 048 * @param context The WikiContext. 049 */ 050 public RSS10Feed( final Context context ) { 051 super( context ); 052 } 053 054 private Element getRDFItems() { 055 final Element items = new Element( "items", NS_XMNLS ); 056 final Element rdfseq = new Element( "Seq", NS_RDF ); 057 058 for( final Entry e : m_entries ) { 059 final String url = e.getURL(); 060 rdfseq.addContent( new Element( "li", NS_RDF ).setAttribute( "resource", url, NS_RDF ) ); 061 } 062 items.addContent( rdfseq ); 063 064 return items; 065 } 066 067 private void addItemList( final Element root ) { 068 final SimpleDateFormat iso8601fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 069 final Engine engine = m_wikiContext.getEngine(); 070 071 for( final Entry entry : m_entries ) { 072 final String url = entry.getURL(); 073 074 final Element item = new Element( "item", NS_XMNLS ); 075 item.setAttribute( "about", url, NS_RDF ); 076 item.addContent( new Element( "title", NS_XMNLS ).addContent( entry.getTitle() ) ); 077 //FIXME this needs to be an absolute url, not a relative one 078 item.addContent( new Element( "link", NS_XMNLS ).addContent( url ) ); 079 080 final Element content = new Element( "description", NS_XMNLS ); 081 // TODO: Add a size limiter here 082 content.addContent( entry.getContent() ); 083 item.addContent( content ); 084 085 final Page p = entry.getPage(); 086 if( p.getVersion() != -1 ) { 087 item.addContent( new Element( "version", NS_WIKI ).addContent( Integer.toString( p.getVersion() ) ) ); 088 } 089 090 if( p.getVersion() > 1 ) { 091 item.addContent( new Element( "diff", NS_WIKI ) 092 .addContent( engine.getURL( ContextEnum.PAGE_DIFF.getRequestContext(), p.getName(), "r1=-1" ) ) ); 093 } 094 095 // 096 // Modification date. 097 final Calendar cal = Calendar.getInstance(); 098 cal.setTime(p.getLastModified()); 099 cal.add( Calendar.MILLISECOND, 100 - ( cal.get( Calendar.ZONE_OFFSET ) + 101 ( cal.getTimeZone().inDaylightTime( p.getLastModified() ) ? cal.get( Calendar.DST_OFFSET ) 102 : 0 ) ) ); 103 104 item.addContent( new Element( "date", NS_DC ).addContent( iso8601fmt.format( cal.getTime() ) ) ); 105 106 // 107 // Author 108 String author = entry.getAuthor(); 109 if( author == null ) { 110 author = "unknown"; 111 } 112 113 final Element contributor = new Element( "creator", NS_DC ); 114 item.addContent( contributor ); 115 116 /* 117 Element description = new Element("Description", NS_RDF); 118 if( m_wikiContext.getEngine().pageExists(author) ) { 119 description.setAttribute( "link", engine.getURL( WikiContext.VIEW, author, null, true ), NS_XMNLS ); 120 } 121 122 description.addContent( new Element("value", NS_XMNLS).addContent( author) ); 123 contributor.addContent( description ); 124 */ 125 126 // Not too many aggregators seem to like this. Therefore we're just adding the name here. 127 contributor.addContent( author ); 128 129 // 130 // PageHistory 131 item.addContent( new Element( "history", NS_WIKI ) 132 .addContent( engine.getURL( ContextEnum.PAGE_INFO.getRequestContext(), p.getName(), null ) ) ); 133 134 // 135 // Add to root 136 root.addContent( item ); 137 } 138 } 139 140 private Element getChannelElement() { 141 final Element channel = new Element( "channel", NS_XMNLS ); 142 channel.setAttribute( "about", m_feedURL, NS_RDF ) 143 .addContent( new Element( "link", NS_XMNLS ).addContent( m_feedURL ) ); 144 145 if( m_channelTitle != null ) { 146 channel.addContent( new Element( "title", NS_XMNLS ).addContent( m_channelTitle ) ); 147 } 148 149 if( m_channelDescription != null ) { 150 channel.addContent( new Element( "description", NS_XMNLS ).addContent( m_channelDescription ) ); 151 } 152 153 if( m_channelLanguage != null ) { 154 channel.addContent( new Element( "language", NS_DC ).addContent( m_channelLanguage ) ); 155 } 156 channel.addContent( getRDFItems() ); 157 158 return channel; 159 } 160 161 /** 162 * {@inheritDoc} 163 */ 164 @Override 165 public String getString() { 166 final Element root = new Element( "RDF", NS_RDF ); 167 root.addContent( getChannelElement() ); 168 root.addNamespaceDeclaration( NS_XMNLS ); 169 root.addNamespaceDeclaration( NS_RDF ); 170 root.addNamespaceDeclaration( NS_DC ); 171 root.addNamespaceDeclaration( NS_WIKI ); 172 addItemList( root ); 173 174 return XhtmlUtil.serialize( root, true ); 175 } 176 177}