1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 import com.sun.syndication.io.WireFeedOutput;
39 import java.io.IOException;
40 import java.io.Writer;
41 import java.util.ArrayList;
42 import org.jdom.output.XMLOutputter;
43
44 /***
45 * Feed Generator for Atom
46 * <p/>
47 *
48 * @author Elaine Chien
49 * @author Dave Johnson (updated for Atom 1.0)
50 *
51 */
52
53 public class Atom10Generator extends BaseWireFeedGenerator {
54 private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
55 private static final Namespace ATOM_NS = Namespace.getNamespace(ATOM_10_URI);
56
57 private String _version;
58
59 public Atom10Generator() {
60 this("atom_1.0","1.0");
61 }
62
63 protected Atom10Generator(String type,String version) {
64 super(type);
65 _version = version;
66 }
67
68 protected String getVersion() {
69 return _version;
70 }
71
72 protected Namespace getFeedNamespace() {
73 return ATOM_NS;
74 }
75
76 public Document generate(WireFeed wFeed) throws FeedException {
77 Feed feed = (Feed) wFeed;
78 Element root = createRootElement(feed);
79 populateFeed(feed,root);
80 purgeUnusedNamespaceDeclarations(root);
81 return createDocument(root);
82 }
83
84 protected Document createDocument(Element root) {
85 return new Document(root);
86 }
87
88 protected Element createRootElement(Feed feed) {
89 Element root = new Element("feed",getFeedNamespace());
90 root.addNamespaceDeclaration(getFeedNamespace());
91
92
93 if (feed.getXmlBase() != null) {
94 root.setAttribute("base", feed.getXmlBase(), Namespace.XML_NAMESPACE);
95 }
96 generateModuleNamespaceDefs(root);
97 return root;
98 }
99
100 protected void populateFeed(Feed feed,Element parent) throws FeedException {
101 addFeed(feed,parent);
102 addEntries(feed,parent);
103 }
104
105 protected void addFeed(Feed feed,Element parent) throws FeedException {
106 Element eFeed = parent;
107 populateFeedHeader(feed,eFeed);
108 generateForeignMarkup(eFeed, (List)feed.getForeignMarkup());
109 checkFeedHeaderConstraints(eFeed);
110 generateFeedModules(feed.getModules(),eFeed);
111 }
112
113 protected void addEntries(Feed feed,Element parent) throws FeedException {
114 List items = feed.getEntries();
115 for (int i=0;i<items.size();i++) {
116 addEntry((Entry)items.get(i),parent);
117 }
118 checkEntriesConstraints(parent);
119 }
120
121 protected void addEntry(Entry entry,Element parent) throws FeedException {
122 Element eEntry = new Element("entry", getFeedNamespace());
123 if (entry.getXmlBase() != null) {
124 eEntry.setAttribute("base", entry.getXmlBase(), Namespace.XML_NAMESPACE);
125 }
126 populateEntry(entry,eEntry);
127 generateForeignMarkup(eEntry, (List)entry.getForeignMarkup());
128 checkEntryConstraints(eEntry);
129 generateItemModules(entry.getModules(),eEntry);
130 parent.addContent(eEntry);
131 }
132
133 protected void populateFeedHeader(Feed feed,Element eFeed) throws FeedException {
134 if (feed.getTitleEx() != null) {
135 Element titleElement = new Element("title", getFeedNamespace());
136 fillContentElement(titleElement, feed.getTitleEx());
137 eFeed.addContent(titleElement);
138 }
139
140 List links = feed.getAlternateLinks();
141 if (links != null) for (int i = 0; i < links.size(); i++) {
142 eFeed.addContent(generateLinkElement((Link)links.get(i)));
143 }
144 links = feed.getOtherLinks();
145 if (links != null) for (int j = 0; j < links.size(); j++) {
146 eFeed.addContent(generateLinkElement((Link)links.get(j)));
147 }
148
149 List cats = feed.getCategories();
150 if (cats != null) for (Iterator iter=cats.iterator(); iter.hasNext();) {
151 eFeed.addContent(generateCategoryElement((Category)iter.next()));
152 }
153
154 List authors = feed.getAuthors();
155 if (authors != null && authors.size() > 0) {
156 for (int i = 0; i < authors.size(); i++) {
157 Element authorElement = new Element("author", getFeedNamespace());
158 fillPersonElement(authorElement, (Person)feed.getAuthors().get(i));
159 eFeed.addContent(authorElement);
160 }
161 }
162
163 List contributors = feed.getContributors();
164 if (contributors != null && contributors.size() > 0) {
165 for (int i = 0; i < contributors.size(); i++) {
166 Element contributorElement = new Element("contributor", getFeedNamespace());
167 fillPersonElement(contributorElement, (Person)contributors.get(i));
168 eFeed.addContent(contributorElement);
169 }
170 }
171
172 if (feed.getSubtitle() != null) {
173 Element subtitleElement = new Element("subtitle", getFeedNamespace());
174 fillContentElement(subtitleElement, feed.getSubtitle());
175 eFeed.addContent(subtitleElement);
176 }
177
178 if (feed.getId() != null) {
179 eFeed.addContent(generateSimpleElement("id", feed.getId()));
180 }
181
182 if (feed.getGenerator() != null) {
183 eFeed.addContent(generateGeneratorElement(feed.getGenerator()));
184 }
185
186 if (feed.getRights() != null) {
187 eFeed.addContent(generateSimpleElement("rights", feed.getRights()));
188 }
189
190 if (feed.getIcon() != null) {
191 eFeed.addContent(generateSimpleElement("icon", feed.getIcon()));
192 }
193
194 if (feed.getLogo() != null) {
195 eFeed.addContent(generateSimpleElement("logo", feed.getLogo()));
196 }
197
198 if (feed.getUpdated() != null) {
199 Element updatedElement = new Element("updated", getFeedNamespace());
200 updatedElement.addContent(DateParser.formatW3CDateTime(feed.getUpdated()));
201 eFeed.addContent(updatedElement);
202 }
203 }
204
205 protected void populateEntry(Entry entry, Element eEntry) throws FeedException {
206 if (entry.getTitleEx() != null) {
207 Element titleElement = new Element("title", getFeedNamespace());
208 fillContentElement(titleElement, entry.getTitleEx());
209 eEntry.addContent(titleElement);
210 }
211 List links = entry.getAlternateLinks();
212 if (links != null) {
213 for (int i = 0; i < links.size(); i++) {
214 eEntry.addContent(generateLinkElement((Link)links.get(i)));
215 }
216 }
217 links = entry.getOtherLinks();
218 if (links != null) {
219 for (int i = 0; i < links.size(); i++) {
220 eEntry.addContent(generateLinkElement((Link)links.get(i)));
221 }
222 }
223
224 List cats = entry.getCategories();
225 if (cats != null) {
226 for (int i = 0; i < cats.size(); i++) {
227 eEntry.addContent(generateCategoryElement((Category)cats.get(i)));
228 }
229 }
230
231 List authors = entry.getAuthors();
232 if (authors != null && authors.size() > 0) {
233 for (int i = 0; i < authors.size(); i++) {
234 Element authorElement = new Element("author", getFeedNamespace());
235 fillPersonElement(authorElement, (Person)entry.getAuthors().get(i));
236 eEntry.addContent(authorElement);
237 }
238 }
239
240 List contributors = entry.getContributors();
241 if (contributors != null && contributors.size() > 0) {
242 for (int i = 0; i < contributors.size(); i++) {
243 Element contributorElement = new Element("contributor", getFeedNamespace());
244 fillPersonElement(contributorElement, (Person)contributors.get(i));
245 eEntry.addContent(contributorElement);
246 }
247 }
248 if (entry.getId() != null) {
249 eEntry.addContent(generateSimpleElement("id", entry.getId()));
250 }
251
252 if (entry.getUpdated() != null) {
253 Element updatedElement = new Element("updated", getFeedNamespace());
254 updatedElement.addContent(DateParser.formatW3CDateTime(entry.getUpdated()));
255 eEntry.addContent(updatedElement);
256 }
257
258 if (entry.getPublished() != null) {
259 Element publishedElement = new Element("published", getFeedNamespace());
260 publishedElement.addContent(DateParser.formatW3CDateTime(entry.getPublished()));
261 eEntry.addContent(publishedElement);
262 }
263
264 if (entry.getContents() != null && entry.getContents().size() > 0) {
265 Element contentElement = new Element("content", getFeedNamespace());
266 Content content = (Content)entry.getContents().get(0);
267 fillContentElement(contentElement, content);
268 eEntry.addContent(contentElement);
269 }
270
271 if (entry.getSummary() != null) {
272 Element summaryElement = new Element("summary", getFeedNamespace());
273 fillContentElement(summaryElement, entry.getSummary());
274 eEntry.addContent(summaryElement);
275 }
276
277 if (entry.getSource() != null) {
278 Element sourceElement = new Element("source", getFeedNamespace());
279 populateFeedHeader(entry.getSource(), sourceElement);
280 eEntry.addContent(sourceElement);
281 }
282 }
283
284 protected void checkFeedHeaderConstraints(Element eFeed) throws FeedException {
285 }
286
287 protected void checkEntriesConstraints(Element parent) throws FeedException {
288 }
289
290 protected void checkEntryConstraints(Element eEntry) throws FeedException {
291 }
292
293
294 protected Element generateCategoryElement(Category cat) {
295 Element catElement = new Element("category", getFeedNamespace());
296
297 if (cat.getTerm() != null) {
298 Attribute termAttribute = new Attribute("term", cat.getTerm());
299 catElement.setAttribute(termAttribute);
300 }
301
302 if (cat.getLabel() != null) {
303 Attribute labelAttribute = new Attribute("label", cat.getLabel());
304 catElement.setAttribute(labelAttribute);
305 }
306
307 if (cat.getScheme() != null) {
308 Attribute schemeAttribute = new Attribute("scheme", cat.getScheme());
309 catElement.setAttribute(schemeAttribute);
310 }
311 return catElement;
312 }
313
314 protected Element generateLinkElement(Link link) {
315 Element linkElement = new Element("link", getFeedNamespace());
316
317 if (link.getRel() != null) {
318 Attribute relAttribute = new Attribute("rel", link.getRel());
319 linkElement.setAttribute(relAttribute);
320 }
321
322 if (link.getType() != null) {
323 Attribute typeAttribute = new Attribute("type", link.getType());
324 linkElement.setAttribute(typeAttribute);
325 }
326
327 if (link.getHref() != null) {
328 Attribute hrefAttribute = new Attribute("href", link.getHref());
329 linkElement.setAttribute(hrefAttribute);
330 }
331
332 if (link.getHreflang() != null) {
333 Attribute hreflangAttribute = new Attribute("hreflang", link.getHreflang());
334 linkElement.setAttribute(hreflangAttribute);
335 }
336 if (link.getTitle() != null) {
337 Attribute title = new Attribute("title", link.getTitle());
338 linkElement.setAttribute(title);
339 }
340 if (link.getLength() != 0) {
341 Attribute lenght = new Attribute("length", Long.toString(link.getLength()));
342 linkElement.setAttribute(lenght);
343 }
344 return linkElement;
345 }
346
347
348 protected void fillPersonElement(Element element, Person person) {
349 if (person.getName() != null) {
350 element.addContent(generateSimpleElement("name", person.getName()));
351 }
352 if (person.getUri() != null) {
353 element.addContent(generateSimpleElement("uri", person.getUri()));
354 }
355
356 if (person.getEmail() != null) {
357 element.addContent(generateSimpleElement("email", person.getEmail()));
358 }
359 }
360
361 protected Element generateTagLineElement(Content tagline) {
362 Element taglineElement = new Element("subtitle", getFeedNamespace());
363
364 if (tagline.getType() != null) {
365 Attribute typeAttribute = new Attribute("type", tagline.getType());
366 taglineElement.setAttribute(typeAttribute);
367 }
368
369 if (tagline.getValue() != null) {
370 taglineElement.addContent(tagline.getValue());
371 }
372 return taglineElement;
373 }
374
375 protected void fillContentElement(Element contentElement, Content content)
376 throws FeedException {
377
378 String type = content.getType();
379 String atomType = type;
380 if (type != null) {
381
382
383 if ("text/plain".equals(type)) atomType = Content.TEXT;
384 else if ("text/html".equals(type)) atomType = Content.HTML;
385 else if ("application/xhtml+xml".equals(type)) atomType = Content.XHTML;
386
387 Attribute typeAttribute = new Attribute("type", atomType);
388 contentElement.setAttribute(typeAttribute);
389 }
390 String href = content.getSrc();
391 if (href != null) {
392 Attribute srcAttribute = new Attribute("src", href);
393 contentElement.setAttribute(srcAttribute);
394 }
395 if (content.getValue() != null) {
396 if (atomType != null && (atomType.equals(Content.XHTML) || (atomType.indexOf("/xml")) != -1 ||
397 (atomType.indexOf("+xml")) != -1)) {
398
399 StringBuffer tmpDocString = new StringBuffer("<tmpdoc>");
400 tmpDocString.append(content.getValue());
401 tmpDocString.append("</tmpdoc>");
402 StringReader tmpDocReader = new StringReader(tmpDocString.toString());
403 Document tmpDoc;
404 try {
405 SAXBuilder saxBuilder = new SAXBuilder();
406 tmpDoc = saxBuilder.build(tmpDocReader);
407 }
408 catch (Exception ex) {
409 throw new FeedException("Invalid XML",ex);
410 }
411 List children = tmpDoc.getRootElement().removeContent();
412 contentElement.addContent(children);
413 } else {
414
415
416 contentElement.addContent(content.getValue());
417 }
418 }
419 }
420
421 protected Element generateGeneratorElement(Generator generator) {
422 Element generatorElement = new Element("generator", getFeedNamespace());
423
424 if (generator.getUrl() != null) {
425 Attribute urlAttribute = new Attribute("uri", generator.getUrl());
426 generatorElement.setAttribute(urlAttribute);
427 }
428
429 if (generator.getVersion() != null) {
430 Attribute versionAttribute = new Attribute("version", generator.getVersion());
431 generatorElement.setAttribute(versionAttribute);
432 }
433
434 if (generator.getValue() != null) {
435 generatorElement.addContent(generator.getValue());
436 }
437
438 return generatorElement;
439
440 }
441
442 protected Element generateSimpleElement(String name, String value) {
443 Element element = new Element(name, getFeedNamespace());
444 element.addContent(value);
445 return element;
446 }
447
448 /***
449 * Utility method to serialize an entry to writer.
450 */
451 public static void serializeEntry(Entry entry, Writer writer)
452 throws IllegalArgumentException, FeedException, IOException {
453
454
455 List entries = new ArrayList();
456 entries.add(entry);
457 Feed feed1 = new Feed();
458 feed1.setFeedType("atom_1.0");
459 feed1.setEntries(entries);
460
461
462 WireFeedOutput wireFeedOutput = new WireFeedOutput();
463 Document feedDoc = wireFeedOutput.outputJDom(feed1);
464
465
466 Element entryElement= (Element)feedDoc.getRootElement().getChildren().get(0);
467
468 XMLOutputter outputter = new XMLOutputter();
469 outputter.output(entryElement, writer);
470 }
471
472 }