View Javadoc

1   /*
2    * Copyright 2004 Sun Microsystems, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  package com.sun.syndication.io.impl;
18  
19  import com.sun.syndication.feed.WireFeed;
20  import com.sun.syndication.feed.rss.Channel;
21  import com.sun.syndication.feed.rss.Description;
22  import com.sun.syndication.feed.rss.Image;
23  import com.sun.syndication.feed.rss.Item;
24  import org.jdom.Attribute;
25  import org.jdom.DocType;
26  import org.jdom.Document;
27  import org.jdom.Element;
28  import org.jdom.Namespace;
29  
30  import java.util.Collections;
31  import java.util.List;
32  import java.util.ArrayList;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  /***
37   */
38  public class RSS091Parser extends RSS090Parser {
39  
40      public RSS091Parser() {
41          this("rss_0.91");
42      }
43  
44      protected RSS091Parser(String type) {
45          super(type);
46      }
47  
48      public boolean isMyType(Document document) {
49          boolean ok = false;
50          Element rssRoot = document.getRootElement();
51          ok = rssRoot.getName().equals("rss");
52          if (ok) {
53              ok = false;
54              Attribute version = rssRoot.getAttribute("version");
55              if (version!=null) {
56                  ok = version.getValue().equals(getRSSVersion());
57              }
58          }
59          return ok;
60      }
61  
62      protected String getRSSVersion() {
63              return "0.91";
64      }
65  
66      private static final String USERLAND = "Userland";
67      private static final String NETSCAPE = "Netscape";
68  
69      private static final String ELEMENT_NAME = "rss";
70      private static final String PUBLIC_ID = "-//Netscape Communications//DTD RSS 0.91//EN";
71      private static final String SYSTEM_ID = "http://my.netscape.com/publish/formats/rss-0.91.dtd";
72  
73      private String getVariant(Document document) {
74          String variant = USERLAND;
75          DocType docType = document.getDocType();
76  
77          if (docType!=null) {
78              boolean ok = ELEMENT_NAME.equals(docType.getElementName());
79              ok = ok && PUBLIC_ID.equals(docType.getPublicID());
80              ok = ok && SYSTEM_ID.equals(docType.getSystemID());
81              if (ok) {
82                  variant = NETSCAPE;
83              }
84          }
85          return variant;
86      }
87  
88      protected Namespace getRSSNamespace() {
89          return Namespace.getNamespace("");
90      }
91  
92      protected boolean isHourFormat24(Element rssRoot) {
93          String variant = getVariant((Document)rssRoot.getParent());
94          return variant.equals(USERLAND);
95      }
96  
97      /***
98       * Parses the root element of an RSS document into a Channel bean.
99       * <p/>
100      * It first invokes super.parseChannel and then parses and injects the following
101      * properties if present: language, pubDate, rating and copyright.
102      * <p/>
103      *
104      * @param rssRoot the root element of the RSS document to parse.
105      * @return the parsed Channel bean.
106      */
107     protected WireFeed parseChannel(Element rssRoot)  {
108         Channel channel = (Channel) super.parseChannel(rssRoot);
109 
110         Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
111 
112         Element e = eChannel.getChild("language",getRSSNamespace());
113         if (e!=null) {
114             channel.setLanguage(e.getText());
115         }
116         e = eChannel.getChild("rating",getRSSNamespace());
117         if (e!=null) {
118             channel.setRating(e.getText());
119         }
120         e = eChannel.getChild("copyright",getRSSNamespace());
121         if (e!=null) {
122             channel.setCopyright(e.getText());
123         }
124         e = eChannel.getChild("pubDate",getRSSNamespace());
125         if (e!=null) {
126             channel.setPubDate(DateParser.parseRFC822(e.getText()));
127         }
128         e = eChannel.getChild("lastBuildDate",getRSSNamespace());
129         if (e!=null) {
130             channel.setLastBuildDate(DateParser.parseRFC822(e.getText()));
131         }
132         e = eChannel.getChild("docs",getRSSNamespace());
133         if (e!=null) {
134             channel.setDocs(e.getText());
135         }
136         e = eChannel.getChild("docs",getRSSNamespace());
137         if (e!=null) {
138             channel.setDocs(e.getText());
139         }
140         e = eChannel.getChild("managingEditor",getRSSNamespace());
141         if (e!=null) {
142             channel.setManagingEditor(e.getText());
143         }
144         e = eChannel.getChild("webMaster",getRSSNamespace());
145         if (e!=null) {
146             channel.setWebMaster(e.getText());
147         }
148         e = eChannel.getChild("skipHours");
149         if (e!=null) {
150             List skipHours = new ArrayList();
151             List eHours = e.getChildren("hour",getRSSNamespace());
152             for (int i=0;i<eHours.size();i++) {
153                 Element eHour = (Element) eHours.get(i);
154                 skipHours.add(new Integer(eHour.getText()));
155             }
156             channel.setSkipHours(skipHours);
157         }
158 
159         e = eChannel.getChild("skipDays");
160         if (e!=null) {
161             List skipDays = new ArrayList();
162             List eDays = e.getChildren("day",getRSSNamespace());
163             for (int i=0;i<eDays.size();i++) {
164                 Element eDay = (Element) eDays.get(i);
165                 skipDays.add(DAYS.get(eDay.getText()));
166             }
167             channel.setSkipDays(skipDays);
168         }
169         return channel;
170     }
171 
172     private static final Map DAYS = new HashMap();
173 
174     static {
175         DAYS.put(Channel.SUNDAY.toString(),Channel.SUNDAY);
176         DAYS.put(Channel.MONDAY.toString(),Channel.MONDAY);
177         DAYS.put(Channel.TUESDAY.toString(),Channel.TUESDAY);
178         DAYS.put(Channel.WEDNESDAY.toString(),Channel.WEDNESDAY);
179         DAYS.put(Channel.THURSDAY.toString(),Channel.THURSDAY);
180         DAYS.put(Channel.FRIDAY.toString(),Channel.FRIDAY);
181         DAYS.put(Channel.SATURDAY.toString(),Channel.SATURDAY);
182     }
183 
184     /***
185      * Parses the root element of an RSS document looking for  image information.
186      * <p/>
187      * It first invokes super.parseImage and then parses and injects the following
188      * properties if present: url, link, width, height and description.
189      * <p/>
190      *
191      * @param rssRoot the root element of the RSS document to parse for image information.
192      * @return the parsed RSSImage bean.
193      */
194     protected Image parseImage(Element rssRoot) {
195         Image image = super.parseImage(rssRoot);
196         if (image!=null) {
197             Element eImage = getImage(rssRoot);
198             Element e = eImage.getChild("width",getRSSNamespace());
199             if (e!=null) {
200                 image.setWidth(Integer.parseInt(e.getText()));
201             }
202             e = eImage.getChild("height",getRSSNamespace());
203             if (e!=null) {
204                 image.setHeight(Integer.parseInt(e.getText()));
205             }
206             e = eImage.getChild("description",getRSSNamespace());
207             if (e!=null) {
208                 image.setLink(e.getText());
209             }
210         }
211         return image;
212     }
213 
214 
215     /***
216      * It looks for the 'item' elements under the 'channel' elemment.
217      */
218     protected List getItems(Element rssRoot) {
219         Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
220         return (eChannel!=null) ? eChannel.getChildren("item",getRSSNamespace()) : Collections.EMPTY_LIST;
221     }
222 
223     /***
224      * It looks for the 'image' elements under the 'channel' elemment.
225      */
226     protected Element getImage(Element rssRoot) {
227         Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
228         return (eChannel!=null) ? eChannel.getChild("image",getRSSNamespace()) : null;
229     }
230 
231     /***
232      * It looks for the 'textinput' elements under the 'channel' elemment.
233      */
234     protected Element getTextInput(Element rssRoot) {
235         String variant = getVariant((Document)rssRoot.getParent());
236         String elementName = (variant.equals(USERLAND)) ? "textInput" : "textinput";
237         Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
238         return (eChannel!=null) ? eChannel.getChild(elementName,getRSSNamespace()) : null;
239     }
240 
241     /***
242      * Parses an item element of an RSS document looking for item information.
243      * <p/>
244      * It first invokes super.parseItem and then parses and injects the description property if present.
245      * <p/>
246      *
247      * @param rssRoot the root element of the RSS document in case it's needed for context.
248      * @param eItem the item element to parse.
249      * @return the parsed RSSItem bean.
250      */
251     protected Item parseItem(Element rssRoot,Element eItem) {
252         Item item = super.parseItem(rssRoot,eItem);
253         Element e = eItem.getChild("description",getRSSNamespace());
254         if (e!=null) {
255             item.setDescription(parseItemDescription(rssRoot,e));
256         }
257         return item;
258     }
259 
260     protected Description parseItemDescription(Element rssRoot,Element eDesc) {
261         Description desc = new Description();
262         desc.setType("text/plain");
263         desc.setValue(eDesc.getText());
264         return desc;
265     }
266 
267 }