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 item.addContent( new Element( "link", NS_XMNLS ).addContent( url ) ); 078 079 final Element content = new Element( "description", NS_XMNLS ); 080 // TODO: Add a size limiter here 081 content.addContent( entry.getContent() ); 082 item.addContent( content ); 083 084 final Page p = entry.getPage(); 085 if( p.getVersion() != -1 ) { 086 item.addContent( new Element( "version", NS_WIKI ).addContent( Integer.toString( p.getVersion() ) ) ); 087 } 088 089 if( p.getVersion() > 1 ) { 090 item.addContent( new Element( "diff", NS_WIKI ) 091 .addContent( engine.getURL( ContextEnum.PAGE_DIFF.getRequestContext(), p.getName(), "r1=-1" ) ) ); 092 } 093 094 // 095 // Modification date. 096 final Calendar cal = Calendar.getInstance(); 097 cal.setTime(p.getLastModified()); 098 cal.add( Calendar.MILLISECOND, 099 - ( cal.get( Calendar.ZONE_OFFSET ) + 100 ( cal.getTimeZone().inDaylightTime( p.getLastModified() ) ? cal.get( Calendar.DST_OFFSET ) 101 : 0 ) ) ); 102 103 item.addContent( new Element( "date", NS_DC ).addContent( iso8601fmt.format( cal.getTime() ) ) ); 104 105 // 106 // Author 107 String author = entry.getAuthor(); 108 if( author == null ) { 109 author = "unknown"; 110 } 111 112 final Element contributor = new Element( "creator", NS_DC ); 113 item.addContent( contributor ); 114 115 /* 116 Element description = new Element("Description", NS_RDF); 117 if( m_wikiContext.getEngine().pageExists(author) ) { 118 description.setAttribute( "link", engine.getURL( WikiContext.VIEW, author, null, true ), NS_XMNLS ); 119 } 120 121 description.addContent( new Element("value", NS_XMNLS).addContent( author) ); 122 contributor.addContent( description ); 123 */ 124 125 // Not too many aggregators seem to like this. Therefore we're just adding the name here. 126 contributor.addContent( author ); 127 128 // 129 // PageHistory 130 item.addContent( new Element( "history", NS_WIKI ) 131 .addContent( engine.getURL( ContextEnum.PAGE_INFO.getRequestContext(), p.getName(), null ) ) ); 132 133 // 134 // Add to root 135 root.addContent( item ); 136 } 137 } 138 139 private Element getChannelElement() { 140 final Element channel = new Element( "channel", NS_XMNLS ); 141 channel.setAttribute( "about", m_feedURL, NS_RDF ) 142 .addContent( new Element( "link", NS_XMNLS ).addContent( m_feedURL ) ); 143 144 if( m_channelTitle != null ) { 145 channel.addContent( new Element( "title", NS_XMNLS ).addContent( m_channelTitle ) ); 146 } 147 148 if( m_channelDescription != null ) { 149 channel.addContent( new Element( "description", NS_XMNLS ).addContent( m_channelDescription ) ); 150 } 151 152 if( m_channelLanguage != null ) { 153 channel.addContent( new Element( "language", NS_DC ).addContent( m_channelLanguage ) ); 154 } 155 channel.addContent( getRDFItems() ); 156 157 return channel; 158 } 159 160 /** 161 * {@inheritDoc} 162 */ 163 @Override 164 public String getString() { 165 final Element root = new Element( "RDF", NS_RDF ); 166 root.addContent( getChannelElement() ); 167 root.addNamespaceDeclaration( NS_XMNLS ); 168 root.addNamespaceDeclaration( NS_RDF ); 169 root.addNamespaceDeclaration( NS_DC ); 170 root.addNamespaceDeclaration( NS_WIKI ); 171 addItemList( root ); 172 173 return XhtmlUtil.serialize( root, true ); 174 } 175 176}