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 java.io.StringReader;
20  import java.util.Iterator;
21  import java.util.List;
22  
23  import org.jdom.Attribute;
24  import org.jdom.Document;
25  import org.jdom.Element;
26  import org.jdom.Namespace;
27  import org.jdom.input.SAXBuilder;
28  
29  import com.sun.syndication.feed.WireFeed;
30  import com.sun.syndication.feed.atom.Category;
31  import com.sun.syndication.feed.atom.Content;
32  import com.sun.syndication.feed.atom.Entry;
33  import com.sun.syndication.feed.atom.Feed;
34  import com.sun.syndication.feed.atom.Generator;
35  import com.sun.syndication.feed.atom.Link;
36  import com.sun.syndication.feed.atom.Person;
37  import com.sun.syndication.io.FeedException;
38  
39  /***
40   * Feed Generator for Atom
41   * <p/>
42   *
43   * @author Elaine Chien
44   * @author Dave Johnson (updated for Atom 1.0)
45   *
46   */
47  
48  public class Atom10Generator extends BaseWireFeedGenerator {
49      private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
50      private static final Namespace ATOM_NS = Namespace.getNamespace(ATOM_10_URI);
51  
52      private String _version;
53  
54      public Atom10Generator() {
55          this("atom_1.0","1.0");
56      }
57  
58      protected Atom10Generator(String type,String version) {
59          super(type);
60          _version = version;
61      }
62  
63      protected String getVersion() {
64          return _version;
65      }
66  
67      protected Namespace getFeedNamespace() {
68          return ATOM_NS;
69      }
70  
71      public Document generate(WireFeed wFeed) throws FeedException {
72          Feed feed = (Feed) wFeed;
73          Element root = createRootElement(feed);
74          populateFeed(feed,root);
75          return createDocument(root);
76      }
77  
78      protected Document createDocument(Element root) {
79          return new Document(root);
80      }
81  
82      protected Element createRootElement(Feed feed) {
83          Element root = new Element("feed",getFeedNamespace());
84          root.addNamespaceDeclaration(getFeedNamespace());
85          //Attribute version = new Attribute("version", getVersion());
86          //root.setAttribute(version);
87          if (feed.getXmlBase() != null) {
88              root.setAttribute("base", feed.getXmlBase(), Namespace.XML_NAMESPACE);
89          }
90          generateModuleNamespaceDefs(root);
91          return root;
92      }
93  
94      protected void populateFeed(Feed feed,Element parent) throws FeedException  {
95          addFeed(feed,parent);
96          addEntries(feed,parent);
97      }
98  
99      protected void addFeed(Feed feed,Element parent) throws FeedException {
100         Element eFeed = parent;
101         populateFeedHeader(feed,eFeed);
102         checkFeedHeaderConstraints(eFeed);
103         generateFeedModules(feed.getModules(),eFeed);
104     }
105 
106     protected void addEntries(Feed feed,Element parent) throws FeedException {
107         List items = feed.getEntries();
108         for (int i=0;i<items.size();i++) {
109             addEntry((Entry)items.get(i),parent);
110         }
111         checkEntriesConstraints(parent);
112     }
113 
114     protected void addEntry(Entry entry,Element parent) throws FeedException {
115         Element eEntry = new Element("entry", getFeedNamespace());
116         if (entry.getXmlBase() != null) {
117             eEntry.setAttribute("base", entry.getXmlBase(), Namespace.XML_NAMESPACE);
118         }
119         populateEntry(entry,eEntry);
120         checkEntryConstraints(eEntry);
121         generateItemModules(entry.getModules(),eEntry);
122         parent.addContent(eEntry);
123     }
124 
125     protected void populateFeedHeader(Feed feed,Element eFeed) throws FeedException {
126         if (feed.getTitle() != null) {
127             eFeed.addContent(generateSimpleElement("title", feed.getTitle()));
128         }
129 
130         List links = feed.getAlternateLinks();
131         if (links != null) for (int i = 0; i < links.size(); i++) {
132             eFeed.addContent(generateLinkElement((Link)links.get(i)));
133         }
134         links = feed.getOtherLinks();
135         if (links != null) for (int j = 0; j < links.size(); j++) {
136             eFeed.addContent(generateLinkElement((Link)links.get(j)));
137         }
138 
139         List cats = feed.getCategories();
140         if (cats != null) for (Iterator iter=cats.iterator(); iter.hasNext();) {
141             eFeed.addContent(generateCategoryElement((Category)iter.next()));
142         }
143             
144         List authors = feed.getAuthors();
145         if (authors != null && authors.size() > 0) {
146             for (int i = 0; i < authors.size(); i++) {
147                 Element authorElement = new Element("author", getFeedNamespace());
148                 fillPersonElement(authorElement, (Person)feed.getAuthors().get(i));
149                 eFeed.addContent(authorElement);
150             }
151         }
152 
153         List contributors = feed.getContributors();
154         if (contributors != null && contributors.size() > 0) {
155             for (int i = 0; i < contributors.size(); i++) {
156                 Element contributorElement = new Element("contributor", getFeedNamespace());
157                 fillPersonElement(contributorElement, (Person)contributors.get(i));
158                 eFeed.addContent(contributorElement);
159             }
160         }
161 
162         if (feed.getSubtitle() != null) {
163             eFeed.addContent(
164                 generateSimpleElement("subtitle", feed.getSubtitle().getValue()));
165         }
166 
167         if (feed.getId() != null) {
168             eFeed.addContent(generateSimpleElement("id", feed.getId()));
169         }
170 
171         if (feed.getGenerator() != null) {
172             eFeed.addContent(generateGeneratorElement(feed.getGenerator()));
173         }
174 
175         if (feed.getRights() != null) {
176             eFeed.addContent(generateSimpleElement("rights", feed.getRights()));
177         }
178 
179         if (feed.getUpdated() != null) {
180             Element updatedElement = new Element("updated", getFeedNamespace());
181             updatedElement.addContent(DateParser.formatW3CDateTime(feed.getUpdated()));
182             eFeed.addContent(updatedElement);
183         }
184         generateForeignMarkup(eFeed, (List)feed.getForeignMarkup());
185     }
186 
187     protected void populateEntry(Entry entry, Element eEntry) throws FeedException {
188         if (entry.getTitle() != null) {
189             eEntry.addContent(generateSimpleElement("title", entry.getTitle()));
190         }
191         List links = entry.getAlternateLinks();
192         if (links != null) {
193             for (int i = 0; i < links.size(); i++) {
194                 eEntry.addContent(generateLinkElement((Link)links.get(i)));
195             }
196         }
197         links = entry.getOtherLinks();
198         if (links != null) {
199             for (int i = 0; i < links.size(); i++) {
200                 eEntry.addContent(generateLinkElement((Link)links.get(i)));
201             }
202         }
203 
204         List cats = entry.getCategories();
205         if (cats != null) {
206             for (int i = 0; i < cats.size(); i++) {
207                 eEntry.addContent(generateCategoryElement((Category)cats.get(i)));
208             }
209         }
210         
211         List authors = entry.getAuthors();
212         if (authors != null && authors.size() > 0) {
213             for (int i = 0; i < authors.size(); i++)  {
214                 Element authorElement = new Element("author", getFeedNamespace());
215                 fillPersonElement(authorElement, (Person)entry.getAuthors().get(i));
216                 eEntry.addContent(authorElement);            
217             }
218         }
219 
220         List contributors = entry.getContributors();
221         if (contributors != null && contributors.size() > 0) {
222             for (int i = 0; i < contributors.size(); i++) {
223                 Element contributorElement = new Element("contributor", getFeedNamespace());
224                 fillPersonElement(contributorElement, (Person)contributors.get(i));
225                 eEntry.addContent(contributorElement);
226             }
227         }
228         if (entry.getId() != null) {
229             eEntry.addContent(generateSimpleElement("id", entry.getId()));
230         }
231 
232         if (entry.getUpdated() != null) {
233             Element updatedElement = new Element("updated", getFeedNamespace());
234             updatedElement.addContent(DateParser.formatW3CDateTime(entry.getUpdated()));
235             eEntry.addContent(updatedElement);
236         }
237 
238         if (entry.getPublished() != null) {
239             Element publishedElement = new Element("published", getFeedNamespace());
240             publishedElement.addContent(DateParser.formatW3CDateTime(entry.getPublished()));
241             eEntry.addContent(publishedElement);
242         }
243 
244         if (entry.getContents() != null && entry.getContents().size() > 0) {
245             Element contentElement = new Element("content", getFeedNamespace());
246             Content content = (Content)entry.getContents().get(0);
247             fillContentElement(contentElement, content);
248             eEntry.addContent(contentElement);
249         }
250 
251         if (entry.getSummary() != null) {
252             Element summaryElement = new Element("summary", getFeedNamespace());
253             fillContentElement(summaryElement, entry.getSummary());
254             eEntry.addContent(summaryElement);
255         }
256 
257         generateForeignMarkup(eEntry, (List)entry.getForeignMarkup());
258     }
259 
260     protected void checkFeedHeaderConstraints(Element eFeed) throws FeedException {
261     }
262 
263     protected void checkEntriesConstraints(Element parent) throws FeedException {
264     }
265 
266     protected void checkEntryConstraints(Element eEntry) throws FeedException {
267     }
268 
269 
270     protected Element generateCategoryElement(Category cat) {
271         Element catElement = new Element("category", getFeedNamespace());
272 
273         if (cat.getTerm() != null) {
274             Attribute termAttribute = new Attribute("term", cat.getTerm());
275             catElement.setAttribute(termAttribute);
276         }
277 
278         if (cat.getLabel() != null) {
279             Attribute labelAttribute = new Attribute("label", cat.getLabel());
280             catElement.setAttribute(labelAttribute);
281         }
282 
283         if (cat.getScheme() != null) {
284             Attribute schemeAttribute = new Attribute("scheme", cat.getScheme());
285             catElement.setAttribute(schemeAttribute);
286         }
287         return catElement;
288     }
289 
290     protected Element generateLinkElement(Link link) {
291         Element linkElement = new Element("link", getFeedNamespace());
292 
293         if (link.getRel() != null) {
294             Attribute relAttribute = new Attribute("rel", link.getRel().toString());
295             linkElement.setAttribute(relAttribute);
296         }
297 
298         if (link.getType() != null) {
299             Attribute typeAttribute = new Attribute("type", link.getType());
300             linkElement.setAttribute(typeAttribute);
301         }
302 
303         if (link.getHref() != null) {
304             Attribute hrefAttribute = new Attribute("href", link.getHref());
305             linkElement.setAttribute(hrefAttribute);
306         }
307         
308         if (link.getHreflang() != null) {
309             Attribute hreflangAttribute = new Attribute("hreflang", link.getHreflang());
310             linkElement.setAttribute(hreflangAttribute);
311         }
312         return linkElement;
313     }
314 
315 
316     protected void fillPersonElement(Element element, Person person) {
317         if (person.getName() != null) {
318             element.addContent(generateSimpleElement("name", person.getName()));
319         }
320         if (person.getUri() != null) {
321             element.addContent(generateSimpleElement("uri", person.getUri()));
322         }
323 
324         if (person.getEmail() != null) {
325             element.addContent(generateSimpleElement("email", person.getEmail()));
326         }
327     }
328 
329     protected Element generateTagLineElement(Content tagline) {
330         Element taglineElement = new Element("subtitle", getFeedNamespace());
331 
332         if (tagline.getType() != null) {
333             Attribute typeAttribute = new Attribute("type", tagline.getType());
334             taglineElement.setAttribute(typeAttribute);
335         }
336 
337         if (tagline.getValue() != null) {
338             taglineElement.addContent(tagline.getValue());
339         }
340         return taglineElement;
341     }
342 
343     protected void fillContentElement(Element contentElement, Content content)
344         throws FeedException {
345 
346         String type = content.getType();
347         if (type != null) {
348             String atomType = type;
349             
350             // Fix for issue #39 "Atom 1.0 Text Types Not Set Correctly"
351             // we're not sure who set this value, so ensure Atom types are used
352             if ("text/plain".equals(type)) atomType = "TEXT";
353             else if ("text/html".equals(type)) atomType = "HTML";
354             else if ("application/xhtml+xml".equals(type)) atomType = "XHTML";
355             
356             Attribute typeAttribute = new Attribute("type", atomType);
357             contentElement.setAttribute(typeAttribute);
358         }
359         String href = content.getSrc();
360         if (href != null) {
361             Attribute srcAttribute = new Attribute("src", href);
362             contentElement.setAttribute(srcAttribute);
363         }
364         if (content.getValue() != null) {
365             if (type != null && (type.equals(Content.XHTML) || (type.indexOf("/xml")) != -1)) {
366                 StringBuffer tmpDocString = new StringBuffer("<tmpdoc>");
367                 tmpDocString.append(content.getValue());
368                 tmpDocString.append("</tmpdoc>");
369                 StringReader tmpDocReader = new StringReader(tmpDocString.toString());
370                 Document tmpDoc;
371                 try {
372                     SAXBuilder saxBuilder = new SAXBuilder();
373                     tmpDoc = saxBuilder.build(tmpDocReader);
374                 }
375                 catch (Exception ex) {
376                     throw new FeedException("Invalid XML",ex);
377                 }
378                 List children = tmpDoc.getRootElement().removeContent();
379                 contentElement.addContent(children);
380             } else { 
381                 // must be type html, text or some other non-XML format
382                 // JDOM will escape property for XML
383                 contentElement.addContent(content.getValue());
384             }
385         }
386     }
387 
388     protected Element generateGeneratorElement(Generator generator) {
389         Element generatorElement = new Element("generator", getFeedNamespace());
390 
391         if (generator.getUrl() != null) {
392             Attribute urlAttribute = new Attribute("uri", generator.getUrl());
393             generatorElement.setAttribute(urlAttribute);
394         }
395 
396         if (generator.getVersion() != null) {
397             Attribute versionAttribute = new Attribute("version", generator.getVersion());
398             generatorElement.setAttribute(versionAttribute);
399         }
400 
401         if (generator.getValue() != null) {
402             generatorElement.addContent(generator.getValue());
403         }
404 
405         return generatorElement;
406 
407     }
408 
409     protected Element generateSimpleElement(String name, String value) {
410         Element element = new Element(name, getFeedNamespace());
411         element.addContent(value);
412         return element;
413     }
414 
415 }