001: /*
002: * Copyright 2004 Sun Microsystems, Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: */
017: package com.sun.syndication.io.impl;
018:
019: import java.io.StringReader;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.jdom.Attribute;
024: import org.jdom.Document;
025: import org.jdom.Element;
026: import org.jdom.Namespace;
027: import org.jdom.input.SAXBuilder;
028:
029: import com.sun.syndication.feed.WireFeed;
030: import com.sun.syndication.feed.atom.Category;
031: import com.sun.syndication.feed.atom.Content;
032: import com.sun.syndication.feed.atom.Entry;
033: import com.sun.syndication.feed.atom.Feed;
034: import com.sun.syndication.feed.atom.Generator;
035: import com.sun.syndication.feed.atom.Link;
036: import com.sun.syndication.feed.atom.Person;
037: import com.sun.syndication.io.FeedException;
038:
039: /**
040: * Feed Generator for Atom
041: * <p/>
042: *
043: * @author Elaine Chien
044: * @author Dave Johnson (updated for Atom 1.0)
045: *
046: */
047:
048: public class Atom10Generator extends BaseWireFeedGenerator {
049: private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
050: private static final Namespace ATOM_NS = Namespace
051: .getNamespace(ATOM_10_URI);
052:
053: private String _version;
054:
055: public Atom10Generator() {
056: this ("atom_1.0", "1.0");
057: }
058:
059: protected Atom10Generator(String type, String version) {
060: super (type);
061: _version = version;
062: }
063:
064: protected String getVersion() {
065: return _version;
066: }
067:
068: protected Namespace getFeedNamespace() {
069: return ATOM_NS;
070: }
071:
072: public Document generate(WireFeed wFeed) throws FeedException {
073: Feed feed = (Feed) wFeed;
074: Element root = createRootElement(feed);
075: populateFeed(feed, root);
076: return createDocument(root);
077: }
078:
079: protected Document createDocument(Element root) {
080: return new Document(root);
081: }
082:
083: protected Element createRootElement(Feed feed) {
084: Element root = new Element("feed", getFeedNamespace());
085: root.addNamespaceDeclaration(getFeedNamespace());
086: //Attribute version = new Attribute("version", getVersion());
087: //root.setAttribute(version);
088: if (feed.getXmlBase() != null) {
089: root.setAttribute("base", feed.getXmlBase(),
090: Namespace.XML_NAMESPACE);
091: }
092: generateModuleNamespaceDefs(root);
093: return root;
094: }
095:
096: protected void populateFeed(Feed feed, Element parent)
097: throws FeedException {
098: addFeed(feed, parent);
099: addEntries(feed, parent);
100: }
101:
102: protected void addFeed(Feed feed, Element parent)
103: throws FeedException {
104: Element eFeed = parent;
105: populateFeedHeader(feed, eFeed);
106: checkFeedHeaderConstraints(eFeed);
107: generateFeedModules(feed.getModules(), eFeed);
108: }
109:
110: protected void addEntries(Feed feed, Element parent)
111: throws FeedException {
112: List items = feed.getEntries();
113: for (int i = 0; i < items.size(); i++) {
114: addEntry((Entry) items.get(i), parent);
115: }
116: checkEntriesConstraints(parent);
117: }
118:
119: protected void addEntry(Entry entry, Element parent)
120: throws FeedException {
121: Element eEntry = new Element("entry", getFeedNamespace());
122: if (entry.getXmlBase() != null) {
123: eEntry.setAttribute("base", entry.getXmlBase(),
124: Namespace.XML_NAMESPACE);
125: }
126: populateEntry(entry, eEntry);
127: checkEntryConstraints(eEntry);
128: generateItemModules(entry.getModules(), eEntry);
129: parent.addContent(eEntry);
130: }
131:
132: protected void populateFeedHeader(Feed feed, Element eFeed)
133: throws FeedException {
134: if (feed.getTitle() != null) {
135: eFeed.addContent(generateSimpleElement("title", feed
136: .getTitle()));
137: }
138:
139: List links = feed.getAlternateLinks();
140: if (links != null)
141: for (int i = 0; i < links.size(); i++) {
142: eFeed.addContent(generateLinkElement((Link) links
143: .get(i)));
144: }
145: links = feed.getOtherLinks();
146: if (links != null)
147: for (int j = 0; j < links.size(); j++) {
148: eFeed.addContent(generateLinkElement((Link) links
149: .get(j)));
150: }
151:
152: List cats = feed.getCategories();
153: if (cats != null)
154: for (Iterator iter = cats.iterator(); iter.hasNext();) {
155: eFeed
156: .addContent(generateCategoryElement((Category) iter
157: .next()));
158: }
159:
160: List authors = feed.getAuthors();
161: if (authors != null && authors.size() > 0) {
162: for (int i = 0; i < authors.size(); i++) {
163: Element authorElement = new Element("author",
164: getFeedNamespace());
165: fillPersonElement(authorElement, (Person) feed
166: .getAuthors().get(i));
167: eFeed.addContent(authorElement);
168: }
169: }
170:
171: List contributors = feed.getContributors();
172: if (contributors != null && contributors.size() > 0) {
173: for (int i = 0; i < contributors.size(); i++) {
174: Element contributorElement = new Element("contributor",
175: getFeedNamespace());
176: fillPersonElement(contributorElement,
177: (Person) contributors.get(i));
178: eFeed.addContent(contributorElement);
179: }
180: }
181:
182: if (feed.getSubtitle() != null) {
183: eFeed.addContent(generateSimpleElement("subtitle", feed
184: .getSubtitle().getValue()));
185: }
186:
187: if (feed.getId() != null) {
188: eFeed.addContent(generateSimpleElement("id", feed.getId()));
189: }
190:
191: if (feed.getGenerator() != null) {
192: eFeed.addContent(generateGeneratorElement(feed
193: .getGenerator()));
194: }
195:
196: if (feed.getRights() != null) {
197: eFeed.addContent(generateSimpleElement("rights", feed
198: .getRights()));
199: }
200:
201: if (feed.getUpdated() != null) {
202: Element updatedElement = new Element("updated",
203: getFeedNamespace());
204: updatedElement.addContent(DateParser.formatW3CDateTime(feed
205: .getUpdated()));
206: eFeed.addContent(updatedElement);
207: }
208: generateForeignMarkup(eFeed, (List) feed.getForeignMarkup());
209: }
210:
211: protected void populateEntry(Entry entry, Element eEntry)
212: throws FeedException {
213: if (entry.getTitle() != null) {
214: eEntry.addContent(generateSimpleElement("title", entry
215: .getTitle()));
216: }
217: List links = entry.getAlternateLinks();
218: if (links != null) {
219: for (int i = 0; i < links.size(); i++) {
220: eEntry.addContent(generateLinkElement((Link) links
221: .get(i)));
222: }
223: }
224: links = entry.getOtherLinks();
225: if (links != null) {
226: for (int i = 0; i < links.size(); i++) {
227: eEntry.addContent(generateLinkElement((Link) links
228: .get(i)));
229: }
230: }
231:
232: List cats = entry.getCategories();
233: if (cats != null) {
234: for (int i = 0; i < cats.size(); i++) {
235: eEntry
236: .addContent(generateCategoryElement((Category) cats
237: .get(i)));
238: }
239: }
240:
241: List authors = entry.getAuthors();
242: if (authors != null && authors.size() > 0) {
243: for (int i = 0; i < authors.size(); i++) {
244: Element authorElement = new Element("author",
245: getFeedNamespace());
246: fillPersonElement(authorElement, (Person) entry
247: .getAuthors().get(i));
248: eEntry.addContent(authorElement);
249: }
250: }
251:
252: List contributors = entry.getContributors();
253: if (contributors != null && contributors.size() > 0) {
254: for (int i = 0; i < contributors.size(); i++) {
255: Element contributorElement = new Element("contributor",
256: getFeedNamespace());
257: fillPersonElement(contributorElement,
258: (Person) contributors.get(i));
259: eEntry.addContent(contributorElement);
260: }
261: }
262: if (entry.getId() != null) {
263: eEntry
264: .addContent(generateSimpleElement("id", entry
265: .getId()));
266: }
267:
268: if (entry.getUpdated() != null) {
269: Element updatedElement = new Element("updated",
270: getFeedNamespace());
271: updatedElement.addContent(DateParser
272: .formatW3CDateTime(entry.getUpdated()));
273: eEntry.addContent(updatedElement);
274: }
275:
276: if (entry.getPublished() != null) {
277: Element publishedElement = new Element("published",
278: getFeedNamespace());
279: publishedElement.addContent(DateParser
280: .formatW3CDateTime(entry.getPublished()));
281: eEntry.addContent(publishedElement);
282: }
283:
284: if (entry.getContents() != null
285: && entry.getContents().size() > 0) {
286: Element contentElement = new Element("content",
287: getFeedNamespace());
288: Content content = (Content) entry.getContents().get(0);
289: fillContentElement(contentElement, content);
290: eEntry.addContent(contentElement);
291: }
292:
293: if (entry.getSummary() != null) {
294: Element summaryElement = new Element("summary",
295: getFeedNamespace());
296: fillContentElement(summaryElement, entry.getSummary());
297: eEntry.addContent(summaryElement);
298: }
299:
300: generateForeignMarkup(eEntry, (List) entry.getForeignMarkup());
301: }
302:
303: protected void checkFeedHeaderConstraints(Element eFeed)
304: throws FeedException {
305: }
306:
307: protected void checkEntriesConstraints(Element parent)
308: throws FeedException {
309: }
310:
311: protected void checkEntryConstraints(Element eEntry)
312: throws FeedException {
313: }
314:
315: protected Element generateCategoryElement(Category cat) {
316: Element catElement = new Element("category", getFeedNamespace());
317:
318: if (cat.getTerm() != null) {
319: Attribute termAttribute = new Attribute("term", cat
320: .getTerm());
321: catElement.setAttribute(termAttribute);
322: }
323:
324: if (cat.getLabel() != null) {
325: Attribute labelAttribute = new Attribute("label", cat
326: .getLabel());
327: catElement.setAttribute(labelAttribute);
328: }
329:
330: if (cat.getScheme() != null) {
331: Attribute schemeAttribute = new Attribute("scheme", cat
332: .getScheme());
333: catElement.setAttribute(schemeAttribute);
334: }
335: return catElement;
336: }
337:
338: protected Element generateLinkElement(Link link) {
339: Element linkElement = new Element("link", getFeedNamespace());
340:
341: if (link.getRel() != null) {
342: Attribute relAttribute = new Attribute("rel", link.getRel()
343: .toString());
344: linkElement.setAttribute(relAttribute);
345: }
346:
347: if (link.getType() != null) {
348: Attribute typeAttribute = new Attribute("type", link
349: .getType());
350: linkElement.setAttribute(typeAttribute);
351: }
352:
353: if (link.getHref() != null) {
354: Attribute hrefAttribute = new Attribute("href", link
355: .getHref());
356: linkElement.setAttribute(hrefAttribute);
357: }
358:
359: if (link.getHreflang() != null) {
360: Attribute hreflangAttribute = new Attribute("hreflang",
361: link.getHreflang());
362: linkElement.setAttribute(hreflangAttribute);
363: }
364: return linkElement;
365: }
366:
367: protected void fillPersonElement(Element element, Person person) {
368: if (person.getName() != null) {
369: element.addContent(generateSimpleElement("name", person
370: .getName()));
371: }
372: if (person.getUri() != null) {
373: element.addContent(generateSimpleElement("uri", person
374: .getUri()));
375: }
376:
377: if (person.getEmail() != null) {
378: element.addContent(generateSimpleElement("email", person
379: .getEmail()));
380: }
381: }
382:
383: protected Element generateTagLineElement(Content tagline) {
384: Element taglineElement = new Element("subtitle",
385: getFeedNamespace());
386:
387: if (tagline.getType() != null) {
388: Attribute typeAttribute = new Attribute("type", tagline
389: .getType());
390: taglineElement.setAttribute(typeAttribute);
391: }
392:
393: if (tagline.getValue() != null) {
394: taglineElement.addContent(tagline.getValue());
395: }
396: return taglineElement;
397: }
398:
399: protected void fillContentElement(Element contentElement,
400: Content content) throws FeedException {
401:
402: String type = content.getType();
403: if (type != null) {
404: String atomType = type;
405:
406: // Fix for issue #39 "Atom 1.0 Text Types Not Set Correctly"
407: // we're not sure who set this value, so ensure Atom types are used
408: if ("text/plain".equals(type))
409: atomType = "TEXT";
410: else if ("text/html".equals(type))
411: atomType = "HTML";
412: else if ("application/xhtml+xml".equals(type))
413: atomType = "XHTML";
414:
415: Attribute typeAttribute = new Attribute("type", atomType);
416: contentElement.setAttribute(typeAttribute);
417: }
418: String href = content.getSrc();
419: if (href != null) {
420: Attribute srcAttribute = new Attribute("src", href);
421: contentElement.setAttribute(srcAttribute);
422: }
423: if (content.getValue() != null) {
424: if (type != null
425: && (type.equals(Content.XHTML) || (type
426: .indexOf("/xml")) != -1)) {
427: StringBuffer tmpDocString = new StringBuffer("<tmpdoc>");
428: tmpDocString.append(content.getValue());
429: tmpDocString.append("</tmpdoc>");
430: StringReader tmpDocReader = new StringReader(
431: tmpDocString.toString());
432: Document tmpDoc;
433: try {
434: SAXBuilder saxBuilder = new SAXBuilder();
435: tmpDoc = saxBuilder.build(tmpDocReader);
436: } catch (Exception ex) {
437: throw new FeedException("Invalid XML", ex);
438: }
439: List children = tmpDoc.getRootElement().removeContent();
440: contentElement.addContent(children);
441: } else {
442: // must be type html, text or some other non-XML format
443: // JDOM will escape property for XML
444: contentElement.addContent(content.getValue());
445: }
446: }
447: }
448:
449: protected Element generateGeneratorElement(Generator generator) {
450: Element generatorElement = new Element("generator",
451: getFeedNamespace());
452:
453: if (generator.getUrl() != null) {
454: Attribute urlAttribute = new Attribute("uri", generator
455: .getUrl());
456: generatorElement.setAttribute(urlAttribute);
457: }
458:
459: if (generator.getVersion() != null) {
460: Attribute versionAttribute = new Attribute("version",
461: generator.getVersion());
462: generatorElement.setAttribute(versionAttribute);
463: }
464:
465: if (generator.getValue() != null) {
466: generatorElement.addContent(generator.getValue());
467: }
468:
469: return generatorElement;
470:
471: }
472:
473: protected Element generateSimpleElement(String name, String value) {
474: Element element = new Element(name, getFeedNamespace());
475: element.addContent(value);
476: return element;
477: }
478:
479: }
|