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 */
019 package org.apache.wiki.rss;
020
021 import java.text.SimpleDateFormat;
022 import java.util.Calendar;
023
024 import org.apache.wiki.WikiContext;
025 import org.apache.wiki.WikiEngine;
026 import org.apache.wiki.WikiPage;
027 import org.apache.wiki.util.XhtmlUtil;
028 import org.jdom2.Element;
029 import 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 */
037 public 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 {@inheritDoc}
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 }