    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}