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    }