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.atom.Content;
21  import com.sun.syndication.feed.atom.Entry;
22  import com.sun.syndication.feed.atom.Generator;
23  import com.sun.syndication.feed.atom.Link;
24  import com.sun.syndication.feed.atom.Person;
25  import com.sun.syndication.io.FeedException;
26  import com.sun.syndication.io.WireFeedParser;
27  import org.jdom.Document;
28  import org.jdom.Element;
29  import org.jdom.Namespace;
30  import org.jdom.output.XMLOutputter;
31  
32  import java.util.ArrayList;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Map;
36  
37  /***
38   */
39  public class Atom03Parser implements WireFeedParser {
40  
41      /***
42       * atom_0.3.feed.ModuleParser.classes=  [className] ...
43       *
44       */
45      public static final String FEED_MODULE_PARSERS_KEY = "atom_0.3.feed.ModuleParser.classes";
46  
47      /***
48       * atom_0.3.item.ModuleParser.classes= [className] ...
49       *
50       */
51      public static final String ITEM_MODULE_PARSERS_KEY = "atom_0.3.item.ModuleParser.classes";
52  
53      private static ModuleParsers FEED_MODULES_PARSER = new ModuleParsers(FEED_MODULE_PARSERS_KEY);
54      private static ModuleParsers ITEM_MODULES_PARSER = new ModuleParsers(ITEM_MODULE_PARSERS_KEY);
55  
56  
57      private static final String ATOM_URI = "http://purl.org/atom/ns#";
58  
59      public Atom03Parser() {
60      }
61  
62      public String getType() {
63          return "atom_0.3";
64      }
65  
66      protected Namespace getAtomNamespace() {
67          return Namespace.getNamespace(ATOM_URI);
68      }
69  
70      public boolean isMyType(Document document) {
71          Element rssRoot = document.getRootElement();
72          Namespace defaultNS = rssRoot.getNamespace();
73          return (defaultNS!=null) && defaultNS.equals(getAtomNamespace());
74      }
75  
76      public WireFeed parse(Document document, boolean validate) throws IllegalArgumentException,FeedException {
77          if (validate) {
78              validateFeed(document);
79          }
80          Element rssRoot = document.getRootElement();
81          return parseFeed(rssRoot);
82      }
83  
84      protected void validateFeed(Document document) throws FeedException {
85          // TBD
86          // here we have to validate the Feed against a schema or whatever
87          // not sure how to do it
88          // one posibility would be to produce an ouput and attempt to parse it again
89          // with validation turned on.
90          // otherwise will have to check the document elements by hand.
91      }
92  
93      protected WireFeed parseFeed(Element eFeed) {
94  
95          com.sun.syndication.feed.atom.Feed feed = new com.sun.syndication.feed.atom.Feed(getType());
96  
97          Element e = eFeed.getChild("title",getAtomNamespace());
98          if (e!=null) {
99              feed.setTitle(e.getText());
100         }
101 
102         List eList = eFeed.getChildren("link",getAtomNamespace());
103         feed.setAlternateLinks(parseAlternateLinks(eList));
104         feed.setOtherLinks(parseOtherLinks(eList));
105 
106         e = eFeed.getChild("author",getAtomNamespace());
107         if (e!=null) {
108             feed.setAuthor(parsePerson(e));
109         }
110 
111         eList = eFeed.getChildren("contributor",getAtomNamespace());
112         if (eList.size()>0) {
113             feed.setContributors(parsePersons(eList));
114         }
115 
116         e = eFeed.getChild("tagline",getAtomNamespace());
117         if (e!=null) {
118             feed.setTagline(parseContent(e));
119         }
120 
121         e = eFeed.getChild("id",getAtomNamespace());
122         if (e!=null) {
123             feed.setId(e.getText());
124         }
125 
126         e = eFeed.getChild("generator",getAtomNamespace());
127         if (e!=null) {
128             Generator gen = new Generator();
129             gen.setValue(e.getText());
130             String att = e.getAttributeValue("url");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
131             if (att!=null) {
132                 gen.setUrl(att);
133             }
134             att = e.getAttributeValue("version");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
135             if (att!=null) {
136                 gen.setVersion(att);
137             }
138             feed.setGenerator(gen);
139         }
140 
141         e = eFeed.getChild("copyright",getAtomNamespace());
142         if (e!=null) {
143             feed.setCopyright(e.getText());
144         }
145 
146         e = eFeed.getChild("info",getAtomNamespace());
147         if (e!=null) {
148             feed.setInfo(parseContent(e));
149         }
150 
151         e = eFeed.getChild("modified",getAtomNamespace());
152         if (e!=null) {
153             feed.setModified(DateParser.parseW3CDateTime(e.getText()));
154         }
155 
156         eList = eFeed.getChildren("entry",getAtomNamespace());
157         if (eList.size()>0) {
158             feed.setEntries(parseEntries(eList));
159         }
160 
161         List modules = FEED_MODULES_PARSER.parseModules(eFeed);
162         if (modules!=null) {
163             feed.setModules(modules);
164         }
165 
166         return feed;
167     }
168 
169     private static final Map RELS = new HashMap();
170 
171     static {
172         RELS.put(Link.ALTERNATE.toString(),Link.ALTERNATE);
173         RELS.put(Link.START.toString(),Link.START);
174         RELS.put(Link.NEXT.toString(),Link.NEXT);
175         RELS.put(Link.PREV.toString(),Link.PREV);
176         RELS.put(Link.SERVICE_EDIT.toString(),Link.SERVICE_EDIT);
177         RELS.put(Link.SERVICE_POST.toString(),Link.SERVICE_POST);
178         RELS.put(Link.SERVICE_FEED.toString(),Link.SERVICE_FEED);
179     }
180 
181     private Link parseLink(Element eLink) {
182         Link link = new Link();
183         String att = eLink.getAttributeValue("rel");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
184         if (att!=null) {
185             link.setRel((Link.Rel) RELS.get(att));
186         }
187         att = eLink.getAttributeValue("type");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
188         if (att!=null) {
189             link.setType(att);
190         }
191         att = eLink.getAttributeValue("href");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
192         if (att!=null) {
193             link.setHref(att);
194         }
195         return link;
196     }
197 
198     // List(Elements) -> List(Link)
199     private List parseLinks(List eLinks,boolean alternate) {
200         List links = new ArrayList();
201         for (int i=0;i<eLinks.size();i++) {
202             Element eLink = (Element) eLinks.get(i);
203             //Namespace ns = getAtomNamespace();
204             String rel = eLink.getAttributeValue("rel");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
205             if (alternate) {
206                 if ("alternate".equals(rel)) {
207                     links.add(parseLink(eLink));
208                 }
209             }
210             else {
211                 if (!("alternate".equals(rel))) {
212                     links.add(parseLink(eLink));
213                 }
214             }
215         }
216         return (links.size()>0) ? links : null;
217     }
218 
219     // List(Elements) -> List(Link)
220     private List parseAlternateLinks(List eLinks) {
221         return parseLinks(eLinks,true);
222     }
223 
224     // List(Elements) -> List(Link)
225     private List parseOtherLinks(List eLinks) {
226         return parseLinks(eLinks,false);
227     }
228 
229     private Person parsePerson(Element ePerson) {
230         Person person = new Person();
231         Element e = ePerson.getChild("name",getAtomNamespace());
232         if (e!=null) {
233             person.setName(e.getText());
234         }
235         e = ePerson.getChild("url",getAtomNamespace());
236         if (e!=null) {
237             person.setUrl(e.getText());
238         }
239         e = ePerson.getChild("email",getAtomNamespace());
240         if (e!=null) {
241             person.setEmail(e.getText());
242         }
243         return person;
244     }
245 
246     // List(Elements) -> List(Persons)
247     private List parsePersons(List ePersons) {
248         List persons = new ArrayList();
249         for (int i=0;i<ePersons.size();i++) {
250             persons.add(parsePerson((Element)ePersons.get(i)));
251         }
252         return (persons.size()>0) ? persons : null;
253     }
254 
255     private static final Map MODES = new HashMap();
256 
257     static {
258         MODES.put(Content.XML.toString(),Content.XML);
259         MODES.put(Content.ESCAPED.toString(),Content.ESCAPED);
260         MODES.put(Content.BASE64.toString(),Content.BASE64);
261         MODES.put(null,Content.XML);
262     }
263 
264     private Content parseContent(Element e) {
265         String value = null;
266         String type = e.getAttributeValue("type");//getAtomNamespace()); DONT KNOW WHY DOESN'T WORK
267         type = (type!=null) ? type : "text/plain";
268         Content.Mode mode = (Content.Mode)MODES.get(e.getAttributeValue("mode"));//getAtomNamespace())); DONT KNOW WHY DOESN'T WORK
269         if (mode.equals(Content.ESCAPED)) {
270             // do nothing XML Parser took care of this
271             value = e.getText();
272         }
273         else
274         if (mode.equals(Content.BASE64)) {
275                 value = Base64.decode(e.getText());
276         }
277         else
278         if (mode.equals(Content.XML)) {
279             StringBuffer sb = new StringBuffer();
280             XMLOutputter outputter = new XMLOutputter();
281             List children = e.getChildren();
282             for (int i=0;i<children.size();i++) {
283                 sb.append(outputter.outputString((Element)children.get(i))).append("\n");
284             }
285             value = sb.toString();
286         }
287 
288         Content content = new Content();
289         content.setType(type);
290         content.setMode(mode);
291         content.setValue(value);
292         return content;
293     }
294 
295     // List(Elements) -> List(Entries)
296     private List parseEntries(List eEntries) {
297         List entries = new ArrayList();
298         for (int i=0;i<eEntries.size();i++) {
299             entries.add(parseEntry((Element)eEntries.get(i)));
300         }
301         return (entries.size()>0) ? entries : null;
302     }
303 
304     private Entry parseEntry(Element eEntry) {
305         Entry entry = new Entry();
306 
307         Element e = eEntry.getChild("title",getAtomNamespace());
308         if (e!=null) {
309             entry.setTitle(e.getText());
310         }
311 
312         List eList = eEntry.getChildren("link",getAtomNamespace());
313         entry.setAlternateLinks(parseAlternateLinks(eList));
314         entry.setOtherLinks(parseOtherLinks(eList));
315 
316         e = eEntry.getChild("author",getAtomNamespace());
317         if (e!=null) {
318             entry.setAuthor(parsePerson(e));
319         }
320 
321         eList = eEntry.getChildren("contributor",getAtomNamespace());
322         if (eList.size()>0) {
323             entry.setContributors(parsePersons(eList));
324         }
325 
326         e = eEntry.getChild("id",getAtomNamespace());
327         if (e!=null) {
328             entry.setId(e.getText());
329         }
330 
331         e = eEntry.getChild("modified",getAtomNamespace());
332         if (e!=null) {
333             entry.setModified(DateParser.parseW3CDateTime(e.getText()));
334         }
335 
336         e = eEntry.getChild("issued",getAtomNamespace());
337         if (e!=null) {
338             entry.setIssued(DateParser.parseW3CDateTime(e.getText()));
339         }
340 
341         e = eEntry.getChild("summary",getAtomNamespace());
342         if (e!=null) {
343             entry.setSummary(parseContent(e));
344         }
345 
346         eList = eEntry.getChildren("content",getAtomNamespace());
347         if (eList.size()>0) {
348             List content = new ArrayList();
349             for (int i=0;i<eList.size();i++) {
350                 content.add(parseContent((Element)eList.get(i)));
351             }
352             entry.setContents(content);
353         }
354 
355         List modules = ITEM_MODULES_PARSER.parseModules(eEntry);
356         if (modules!=null) {
357             entry.setModules(modules);
358         }
359 
360         return entry;
361     }
362 
363 
364 }