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 com.sun.syndication.feed.WireFeed;
020: import com.sun.syndication.feed.rss.*;
021: import com.sun.syndication.io.FeedException;
022: import org.jdom.Document;
023: import org.jdom.Element;
024: import org.jdom.Namespace;
025:
026: import java.util.List;
027:
028: /**
029: * Feed Generator for RSS 0.90
030: * <p/>
031: *
032: * @author Elaine Chien
033: */
034: public class RSS090Generator extends BaseWireFeedGenerator {
035:
036: private static final String RDF_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
037: private static final String RSS_URI = "http://my.netscape.com/rdf/simple/0.9/";
038: private static final String CONTENT_URI = "http://purl.org/rss/1.0/modules/content/";
039:
040: private static final Namespace RDF_NS = Namespace.getNamespace(
041: "rdf", RDF_URI);
042: private static final Namespace RSS_NS = Namespace
043: .getNamespace(RSS_URI);
044: private static final Namespace CONTENT_NS = Namespace.getNamespace(
045: "content", CONTENT_URI);
046:
047: public RSS090Generator() {
048: this ("rss_0.9");
049: }
050:
051: protected RSS090Generator(String type) {
052: super (type);
053: }
054:
055: public Document generate(WireFeed feed) throws FeedException {
056: Channel channel = (Channel) feed;
057: Element root = createRootElement(channel);
058: populateFeed(channel, root);
059: return createDocument(root);
060: }
061:
062: protected Namespace getFeedNamespace() {
063: return RSS_NS;
064: }
065:
066: protected Namespace getRDFNamespace() {
067: return RDF_NS;
068: }
069:
070: protected Namespace getContentNamespace() {
071: return CONTENT_NS;
072: }
073:
074: protected Document createDocument(Element root) {
075: return new Document(root);
076: }
077:
078: protected Element createRootElement(Channel channel) {
079: Element root = new Element("RDF", getRDFNamespace());
080: root.addNamespaceDeclaration(getFeedNamespace());
081: root.addNamespaceDeclaration(getRDFNamespace());
082: root.addNamespaceDeclaration(getContentNamespace());
083: generateModuleNamespaceDefs(root);
084: return root;
085: }
086:
087: protected void populateFeed(Channel channel, Element parent)
088: throws FeedException {
089: addChannel(channel, parent);
090: addImage(channel, parent);
091: addTextInput(channel, parent);
092: addItems(channel, parent);
093: generateForeignMarkup(parent, (List) channel.getForeignMarkup());
094: }
095:
096: protected void addChannel(Channel channel, Element parent)
097: throws FeedException {
098: Element eChannel = new Element("channel", getFeedNamespace());
099: populateChannel(channel, eChannel);
100: checkChannelConstraints(eChannel);
101: parent.addContent(eChannel);
102: generateFeedModules(channel.getModules(), eChannel);
103: }
104:
105: /**
106: * Populates the given channel with parsed data from the ROME element that holds the
107: * channel data.
108: *
109: * @param channel the channel into which parsed data will be added.
110: * @param eChannel the XML element that holds the data for the channel.
111: */
112: protected void populateChannel(Channel channel, Element eChannel) {
113: String title = channel.getTitle();
114: if (title != null) {
115: eChannel.addContent(generateSimpleElement("title", title));
116: }
117: String link = channel.getLink();
118: if (link != null) {
119: eChannel.addContent(generateSimpleElement("link", link));
120: }
121: String description = channel.getDescription();
122: if (description != null) {
123: eChannel.addContent(generateSimpleElement("description",
124: description));
125: }
126: }
127:
128: // maxLen == -1 means unlimited.
129: protected void checkNotNullAndLength(Element parent,
130: String childName, int minLen, int maxLen)
131: throws FeedException {
132: Element child = parent.getChild(childName, getFeedNamespace());
133: if (child == null) {
134: throw new FeedException("Invalid " + getType()
135: + " feed, missing " + parent.getName() + " "
136: + childName);
137: }
138: checkLength(parent, childName, minLen, maxLen);
139: }
140:
141: // maxLen == -1 means unlimited.
142: protected void checkLength(Element parent, String childName,
143: int minLen, int maxLen) throws FeedException {
144: Element child = parent.getChild(childName, getFeedNamespace());
145: if (child != null) {
146: if (minLen > 0 && child.getText().length() < minLen) {
147: throw new FeedException("Invalid " + getType()
148: + " feed, " + parent.getName() + " "
149: + childName + "short of " + minLen + " length");
150: }
151: if (maxLen > -1 && child.getText().length() > maxLen) {
152: throw new FeedException("Invalid " + getType()
153: + " feed, " + parent.getName() + " "
154: + childName + "exceeds " + maxLen + " length");
155: }
156: }
157: }
158:
159: protected void addImage(Channel channel, Element parent)
160: throws FeedException {
161: Image image = channel.getImage();
162: if (image != null) {
163: Element eImage = new Element("image", getFeedNamespace());
164: populateImage(image, eImage);
165: checkImageConstraints(eImage);
166: parent.addContent(eImage);
167: }
168: }
169:
170: protected void populateImage(Image image, Element eImage) {
171: String title = image.getTitle();
172: if (title != null) {
173: eImage.addContent(generateSimpleElement("title", title));
174: }
175: String url = image.getUrl();
176: if (url != null) {
177: eImage.addContent(generateSimpleElement("url", url));
178: }
179: String link = image.getLink();
180: if (link != null) {
181: eImage.addContent(generateSimpleElement("link", link));
182: }
183: }
184:
185: // Thxs DW for this one
186: protected String getTextInputLabel() {
187: return "textInput";
188: }
189:
190: protected void addTextInput(Channel channel, Element parent)
191: throws FeedException {
192: TextInput textInput = channel.getTextInput();
193: if (textInput != null) {
194: Element eTextInput = new Element(getTextInputLabel(),
195: getFeedNamespace());
196: populateTextInput(textInput, eTextInput);
197: checkTextInputConstraints(eTextInput);
198: parent.addContent(eTextInput);
199: }
200: }
201:
202: protected void populateTextInput(TextInput textInput,
203: Element eTextInput) {
204: String title = textInput.getTitle();
205: if (title != null) {
206: eTextInput
207: .addContent(generateSimpleElement("title", title));
208: }
209: String description = textInput.getDescription();
210: if (description != null) {
211: eTextInput.addContent(generateSimpleElement("description",
212: description));
213: }
214: String name = textInput.getName();
215: if (name != null) {
216: eTextInput.addContent(generateSimpleElement("name", name));
217: }
218: String link = textInput.getLink();
219: if (link != null) {
220: eTextInput.addContent(generateSimpleElement("link", link));
221: }
222: }
223:
224: protected void addItems(Channel channel, Element parent)
225: throws FeedException {
226: List items = channel.getItems();
227: for (int i = 0; i < items.size(); i++) {
228: addItem((Item) items.get(i), parent, i);
229: }
230: checkItemsConstraints(parent);
231: }
232:
233: protected void addItem(Item item, Element parent, int index)
234: throws FeedException {
235: Element eItem = new Element("item", getFeedNamespace());
236: populateItem(item, eItem, index);
237: checkItemConstraints(eItem);
238: generateItemModules(item.getModules(), eItem);
239: parent.addContent(eItem);
240: }
241:
242: protected void populateItem(Item item, Element eItem, int index) {
243: String title = item.getTitle();
244: if (title != null) {
245: eItem.addContent(generateSimpleElement("title", title));
246: }
247: String link = item.getLink();
248: if (link != null) {
249: eItem.addContent(generateSimpleElement("link", link));
250: }
251: generateForeignMarkup(eItem, (List) item.getForeignMarkup());
252: }
253:
254: protected Element generateSimpleElement(String name, String value) {
255: Element element = new Element(name, getFeedNamespace());
256: element.addContent(value);
257: return element;
258: }
259:
260: protected void checkChannelConstraints(Element eChannel)
261: throws FeedException {
262: checkNotNullAndLength(eChannel, "title", 0, 40);
263: checkNotNullAndLength(eChannel, "description", 0, 500);
264: checkNotNullAndLength(eChannel, "link", 0, 500);
265: }
266:
267: protected void checkImageConstraints(Element eImage)
268: throws FeedException {
269: checkNotNullAndLength(eImage, "title", 0, 40);
270: checkNotNullAndLength(eImage, "url", 0, 500);
271: checkNotNullAndLength(eImage, "link", 0, 500);
272: }
273:
274: protected void checkTextInputConstraints(Element eTextInput)
275: throws FeedException {
276: checkNotNullAndLength(eTextInput, "title", 0, 40);
277: checkNotNullAndLength(eTextInput, "description", 0, 100);
278: checkNotNullAndLength(eTextInput, "name", 0, 500);
279: checkNotNullAndLength(eTextInput, "link", 0, 500);
280: }
281:
282: protected void checkItemsConstraints(Element parent)
283: throws FeedException {
284: int count = parent.getChildren("item", getFeedNamespace())
285: .size();
286: if (count < 1 || count > 15) {
287: throw new FeedException("Invalid " + getType()
288: + " feed, item count is " + count
289: + " it must be between 1 an 15");
290: }
291: }
292:
293: protected void checkItemConstraints(Element eItem)
294: throws FeedException {
295: checkNotNullAndLength(eItem, "title", 0, 100);
296: checkNotNullAndLength(eItem, "link", 0, 500);
297: }
298:
299: }
|