Source code: com/fm/rss/rssItem.java
1 /****************************************************************************
2 * Copyright (c) 2003 Andrew Duka | aduka@users.sourceforge.net
3 * All right reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 ****************************************************************************/
11 package com.fm.rss;
12
13 import java.util.Date;
14
15 import org.w3c.dom.Element;
16 import org.w3c.dom.DOMException;
17 import org.w3c.dom.Node;
18 import org.w3c.dom.NodeList;
19 import javax.xml.parsers.ParserConfigurationException;
20
21 /**
22 * RSS item
23 */
24 public class rssItem extends rssAbstractEntry {
25
26 /** Unique link to the item, serves as ID */
27 private String link;
28 /** dc:subject or category of the item */
29 private String subject;
30 /** item content author */
31 private String author;
32
33 /** Item freshness flag (true if item hasn't been read) */
34 public boolean isFresh;
35
36 /** Only for search operations (not persistent, not saved to storage) */
37 private String parentTitle;
38 private int parentID;
39
40 /**
41 * Dedault constructor.
42 *
43 * All attributes anre initialized by default to empty string
44 */
45 public rssItem()
46 {
47 title = "";
48 description = "";
49 link = "#";
50 dateCreated = new Date();
51 subject = "";
52 author = "";
53 docAdapter = null;
54 isFresh = true;
55
56
57 parentID = 0;
58 parentTitle = "";
59
60 }
61
62 public Element toDomElement()
63 {
64 Element root_elem;
65 Element temp;
66
67 if (this.docAdapter == null)
68 {
69 try
70 {
71 docAdapter = documentAdapter.newInstance();
72 }
73 catch (ParserConfigurationException pce)
74 {
75 //catch exception here
76 return null;
77 }
78 }
79
80 root_elem = this.docAdapter.createElement("item");
81
82 try
83 {
84 // ID & Version
85 // Title, Description, dateCreated
86 temp = this.docAdapter.createElement("title");
87 temp.appendChild(this.docAdapter.createTextNode(this.getTitle()));
88 root_elem.appendChild(temp);
89
90 temp = this.docAdapter.createElement("description");
91 temp.appendChild(this.docAdapter.createTextNode(this.getDescription()));
92 root_elem.appendChild(temp);
93
94 temp = this.docAdapter.createElement("link");
95 temp.appendChild(this.docAdapter.createTextNode(this.getLink()));
96 root_elem.appendChild(temp);
97
98 temp = this.docAdapter.createElement("dateCreated");
99 temp.appendChild(this.docAdapter.
100 createTextNode(rssDateHandler.
101 dateToString(getDateCreated(),
102 rssDateHandler.RSS_OUTPUT_PATTERN)));
103 root_elem.appendChild(temp);
104
105 temp = this.docAdapter.createElement("creator", "dc",
106 documentAdapter.DC_NAMESPACE_URI);
107 temp.appendChild(this.docAdapter.createTextNode(this.getAuthor()));
108 root_elem.appendChild(temp);
109
110 temp = this.docAdapter.createElement("subject", "dc",
111 documentAdapter.DC_NAMESPACE_URI);
112 temp.appendChild(this.docAdapter.createTextNode(this.getSubject()));
113 root_elem.appendChild(temp);
114
115 temp = this.docAdapter.createElement("isFresh");
116 temp.appendChild(this.docAdapter.createTextNode(Boolean.toString(isFresh)));
117 root_elem.appendChild(temp);
118 }
119 catch (DOMException e)
120 {
121 return null;
122 }
123
124 return root_elem;
125 }
126
127
128 /**
129 * Parse the content of the given document element and extract all entry related data.
130 *
131 * @param el Document element to parse
132 * @throws com.fm.rss.rssParseException
133 */
134 public synchronized void parse(Element el) throws rssParseException
135 {
136 Node curr_node;
137 Node temp; /* All optional elements may return null as a value,
138 so we need temporal string to check this out */
139 NodeList nl = el.getChildNodes();
140 int child_num = nl.getLength();
141
142 for (int i=0; i < child_num; i++)
143 {
144 curr_node = nl.item(i);
145
146 if (curr_node.getNodeType() == Node.ELEMENT_NODE)
147 {
148 String node_name = curr_node.getNodeName();
149 if (node_name.equalsIgnoreCase("title"))
150 {
151 if ((temp = curr_node.getFirstChild()) != null)
152 setTitle(temp.getNodeValue());
153 else
154 setTitle("");
155 }
156 else if (node_name.equalsIgnoreCase("description"))
157 {
158 if (getDescription().length() == 0) // since may be overriden by content:encoded
159 {
160 if ((temp = curr_node.getFirstChild()) != null)
161 setDescription(temp.getNodeValue());
162 else
163 setDescription("");
164 // 0.91 issue: throw new rssParseException("RSS item: description element contains no data");
165 }
166 }
167 else if (node_name.equalsIgnoreCase("content:encoded")) // RSS2.0 trick
168 {
169 if ((temp = curr_node.getFirstChild()) != null)
170 setDescription(temp.getNodeValue());
171 else
172 setDescription("");
173 }
174 else if (node_name.equalsIgnoreCase("dc:date"))
175 {
176 if ((temp = curr_node.getFirstChild()) != null)
177 setDateCreated(rssDateHandler.getDateInstanceFromDC(temp.getNodeValue()));
178 }
179 else if (node_name.equalsIgnoreCase("pubDate") || node_name.equalsIgnoreCase("dateCreated"))
180 {
181 if ((temp = curr_node.getFirstChild()) != null)
182 setDateCreated(rssDateHandler.getDateInstanceFromRSS(temp.getNodeValue()));
183 }
184 else if (node_name.equalsIgnoreCase("author") || node_name.equalsIgnoreCase("dc:creator"))
185 {
186 if ((temp = curr_node.getFirstChild()) != null)
187 setAuthor(temp.getNodeValue());
188 else
189 setAuthor("");
190 }
191 else if (node_name.equalsIgnoreCase("link") || node_name.equalsIgnoreCase("guid"))
192 {
193 if ((temp = curr_node.getFirstChild()) != null)
194 setLink(temp.getNodeValue());
195 else
196 throw new rssParseException("RSS item: link element contains no data");
197 }
198 else if (node_name.equalsIgnoreCase("dc:subject") || node_name.equalsIgnoreCase("category"))
199 {
200 if ((temp = curr_node.getFirstChild()) != null)
201 setSubject(temp.getNodeValue());
202 else
203 setSubject("");
204 }
205 else if (node_name.equalsIgnoreCase("isFresh"))
206 {
207 if ((temp = curr_node.getFirstChild()) != null)
208 isFresh = (new Boolean(temp.getNodeValue())).booleanValue();
209 }
210 }//end of ELEMENT_NODE
211 }//end of for
212
213 }
214
215 public String getLink()
216 {
217 return link;
218 }
219
220 /**
221 * Set item link
222 *
223 * @param link String with item link
224 */
225 public void setLink(String link)
226 {
227 this.link = new String(link);
228 }
229
230
231 public String getSubject()
232 {
233 return subject;
234 }
235
236 /**
237 * Set item subject
238 *
239 * @param subject String with item subject
240 */
241 public void setSubject(String subject)
242 {
243 this.subject = new String(subject);
244 }
245
246 /**
247 * Get item author
248 * @return String containing item author's credentials
249 */
250 public String getAuthor()
251 {
252 return author;
253 }
254
255 /**
256 * Set item author
257 * @param author
258 */
259 public void setAuthor(String author)
260 {
261 this.author = new String(author);
262 }
263
264 /**
265 * RSS item specific ID computation.
266 *
267 * <p>Since each RSS item has unique link, which globally identifies item,
268 * this link may used as source for fm IDs. Final ID value is calculated
269 * via hashing item link value.</p>
270 *
271 * @return long unique ID
272 */
273 public int generateID()
274 {
275 return getLink().hashCode();
276 }
277
278 ///////////////////////////////////////////////////////////////////////////
279 // The following functions are used only during search operation. These
280 // functions allow to set/get parent channel title and ID. Which will be
281 // used to correctly handle search results
282 /**
283 * Get parent channel ID
284 * @return parentID int value of the ID, 0 if not set
285 */
286 public int getParentID() {
287 return parentID;
288 }
289
290 /**
291 * Get parent channel title
292 * @return parentTitle parent title or empty string if not set
293 */
294 public String getParentTitle() {
295 return parentTitle;
296 }
297
298 /**
299 * Set parent ID and title
300 * @param ID integer value (not 0 to be valid value)
301 * @param title String with title of more than one character length
302 */
303 public void setParentInfo(int ID, String title) {
304 if ((ID != 0) && (title.length() != 0)) {
305 parentID = ID;
306 parentTitle = title;
307 }
308 }
309
310
311 }