1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.sun.syndication.feed.synd;
18
19 import com.sun.syndication.feed.impl.ObjectBean;
20 import com.sun.syndication.feed.impl.CopyFromHelper;
21 import com.sun.syndication.feed.WireFeed;
22 import com.sun.syndication.feed.module.*;
23 import com.sun.syndication.feed.module.impl.ModuleUtils;
24 import com.sun.syndication.feed.synd.impl.Converters;
25 import com.sun.syndication.feed.synd.impl.URINormalizer;
26
27 import java.util.*;
28 import java.io.Serializable;
29
30 /***
31 * Bean for all types of feeds.
32 * <p>
33 * It handles all RSS versions and Atom 0.3, it normalizes all info, it may lose information.
34 * <p>
35 * @author Alejandro Abdelnur
36 *
37 */
38 public class SyndFeedImpl implements Serializable,SyndFeed {
39 private ObjectBean _objBean;
40 private String _encoding;
41 private String _uri;
42 private String _title;
43 private String _feedType;
44 private String _link;
45 private String _description;
46 private SyndImage _image;
47 private List _entries;
48 private List _modules;
49
50 private static final Converters CONVERTERS = new Converters();
51
52 private static final Set IGNORE_PROPERTIES = new HashSet();
53
54 /***
55 * Unmodifiable Set containing the convenience properties of this class.
56 * <p>
57 * Convenience properties are mapped to Modules, for cloning the convenience properties
58 * can be ignored as the will be copied as part of the module cloning.
59 */
60
61 public static final Set CONVENIENCE_PROPERTIES = Collections.unmodifiableSet(IGNORE_PROPERTIES);
62
63 static {
64 IGNORE_PROPERTIES.add("publishedDate");
65 IGNORE_PROPERTIES.add("author");
66 IGNORE_PROPERTIES.add("copyright");
67 IGNORE_PROPERTIES.add("categories");
68 IGNORE_PROPERTIES.add("language");
69 }
70
71 /***
72 * Returns the real feed types the SyndFeedImpl supports when converting from and to.
73 * <p>
74 * @return the real feed type supported.
75 */
76 public List getSupportedFeedTypes() {
77 return CONVERTERS.getSupportedFeedTypes();
78 }
79
80 /***
81 * For implementations extending SyndFeedImpl to be able to use the ObjectBean functionality
82 * with extended interfaces.
83 * <p>
84 * @param beanClass
85 * @param convenienceProperties set containing the convenience properties of the SyndEntryImpl
86 * (the are ignored during cloning, check CloneableBean for details).
87 *
88 */
89 protected SyndFeedImpl(Class beanClass,Set convenienceProperties) {
90 _objBean = new ObjectBean(beanClass,this,convenienceProperties);
91 }
92
93 /***
94 * Default constructor. All properties are set to <b>null</b>.
95 * <p>
96 *
97 */
98 public SyndFeedImpl() {
99 this(null);
100 }
101
102 /***
103 * Creates a SyndFeedImpl and populates all its properties out of the
104 * given RSS Channel or Atom Feed properties.
105 * <p>
106 * @param feed the RSS Channel or the Atom Feed to populate the properties from.
107 *
108 */
109 public SyndFeedImpl(WireFeed feed) {
110 this(SyndFeed.class,IGNORE_PROPERTIES);
111 if (feed!=null) {
112 _feedType = feed.getFeedType();
113 Converter converter = CONVERTERS.getConverter(_feedType);
114 if (converter==null) {
115 throw new IllegalArgumentException("Invalid feed type ["+_feedType+"]");
116 }
117 converter.copyInto(feed,this);
118 }
119 }
120
121 /***
122 * Creates a deep 'bean' clone of the object.
123 * <p>
124 * @return a clone of the object.
125 * @throws CloneNotSupportedException thrown if an element of the object cannot be cloned.
126 *
127 */
128 public Object clone() throws CloneNotSupportedException {
129 return _objBean.clone();
130 }
131
132 /***
133 * Indicates whether some other object is "equal to" this one as defined by the Object equals() method.
134 * <p>
135 * @param other he reference object with which to compare.
136 * @return <b>true</b> if 'this' object is equal to the 'other' object.
137 *
138 */
139 public boolean equals(Object other) {
140 return _objBean.equals(other);
141 }
142
143 /***
144 * Returns a hashcode value for the object.
145 * <p>
146 * It follows the contract defined by the Object hashCode() method.
147 * <p>
148 * @return the hashcode of the bean object.
149 *
150 */
151 public int hashCode() {
152 return _objBean.hashCode();
153 }
154
155 /***
156 * Returns the String representation for the object.
157 * <p>
158 * @return String representation for the object.
159 *
160 */
161 public String toString() {
162 return _objBean.toString();
163 }
164
165 /***
166 * Creates a real feed containing the information of the SyndFeedImpl.
167 * <p>
168 * The feed type of the created WireFeed is taken from the SyndFeedImpl feedType property.
169 * <p>
170 * @return the real feed.
171 *
172 */
173 public WireFeed createWireFeed() {
174 return createWireFeed(_feedType);
175 }
176
177 /***
178 * Creates a real feed containing the information of the SyndFeedImpl.
179 * <p>
180 * @param feedType the feed type for the WireFeed to be created.
181 * @return the real feed.
182 *
183 */
184 public WireFeed createWireFeed(String feedType) {
185 if (feedType==null) {
186 throw new IllegalArgumentException("Feed type cannot be null");
187 }
188 Converter converter = CONVERTERS.getConverter(feedType);
189 if (converter==null) {
190 throw new IllegalArgumentException("Invalid feed type ["+feedType+"]");
191 }
192 return converter.createRealFeed(this);
193 }
194
195 /***
196 * Returns the wire feed type the feed had/will-have when coverted from/to a WireFeed.
197 * <p>
198 * @return the feed type, <b>null</b> if none.
199 *
200 */
201 public String getFeedType() {
202 return _feedType;
203 }
204
205 /***
206 * Sets the wire feed type the feed will-have when coverted to a WireFeed.
207 * <p>
208 * @param feedType the feed type to set, <b>null</b> if none.
209 *
210 */
211 public void setFeedType(String feedType) {
212 _feedType = feedType;
213 }
214
215 /***
216 * Returns the charset encoding of a the feed. This is not set by Rome parsers.
217 * <p>
218 * @return the charset encoding of the feed.
219 *
220 */
221 public String getEncoding() {
222 return _encoding;
223 }
224
225 /***
226 * Sets the charset encoding of a the feed. This is not set by Rome parsers.
227 * <p>
228 * @param encoding the charset encoding of the feed.
229 *
230 */
231 public void setEncoding(String encoding) {
232 _encoding = encoding;
233 }
234
235 /***
236 * Returns the feed URI.
237 * <p>
238 * How the feed URI maps to a concrete feed type (RSS or Atom) depends on
239 * the concrete feed type. This is explained in detail in Rome documentation,
240 * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
241 * <p>
242 * The returned URI is a normalized URI as specified in RFC 2396bis.
243 * <p>
244 * @return the feed URI, <b>null</b> if none.
245 *
246 */
247 public String getUri() {
248 return _uri;
249 }
250
251 /***
252 * Sets the feed URI.
253 * <p>
254 * How the feed URI maps to a concrete feed type (RSS or Atom) depends on
255 * the concrete feed type. This is explained in detail in Rome documentation,
256 * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
257 * <p>
258 * @param uri the feed URI to set, <b>null</b> if none.
259 *
260 */
261 public void setUri(String uri) {
262 _uri = URINormalizer.normalize(uri);
263 }
264
265 /***
266 * Returns the feed title.
267 * <p>
268 * @return the feed title, <b>null</b> if none.
269 *
270 */
271 public String getTitle() {
272 return _title;
273 }
274
275 /***
276 * Sets the feed title.
277 * <p>
278 * @param title the feed title to set, <b>null</b> if none.
279 *
280 */
281 public void setTitle(String title) {
282 _title = title;
283 }
284
285 /***
286 * Returns the feed link.
287 * <p>
288 * @return the feed link, <b>null</b> if none.
289 *
290 */
291 public String getLink() {
292 return _link;
293 }
294
295 /***
296 * Sets the feed link.
297 * <p>
298 * @param link the feed link to set, <b>null</b> if none.
299 *
300 */
301 public void setLink(String link) {
302 _link = link;
303 }
304
305 /***
306 * Returns the feed description.
307 * <p>
308 * @return the feed description, <b>null</b> if none.
309 *
310 */
311 public String getDescription() {
312 return _description;
313 }
314
315 /***
316 * Sets the feed description.
317 * <p>
318 * @param description the feed description to set, <b>null</b> if none.
319 *
320 */
321 public void setDescription(String description) {
322 _description = description;
323 }
324
325 /***
326 * Returns the feed published date.
327 * <p>
328 * This method is a convenience method, it maps to the Dublin Core module date.
329 * <p>
330 * @return the feed published date, <b>null</b> if none.
331 *
332 */
333 public Date getPublishedDate() {
334 return getDCModule().getDate();
335 }
336
337 /***
338 * Sets the feed published date.
339 * <p>
340 * This method is a convenience method, it maps to the Dublin Core module date.
341 * <p>
342 * @param publishedDate the feed published date to set, <b>null</b> if none.
343 *
344 */
345 public void setPublishedDate(Date publishedDate) {
346 getDCModule().setDate(publishedDate);
347 }
348
349 /***
350 * Returns the feed author.
351 * <p>
352 * This method is a convenience method, it maps to the Dublin Core module creator.
353 * <p>
354 * @return the feed author, <b>null</b> if none.
355 *
356 */
357 public String getAuthor() {
358 return getDCModule().getCreator();
359 }
360
361 /***
362 * Sets the feed author.
363 * <p>
364 * This method is a convenience method, it maps to the Dublin Core module creator.
365 * <p>
366 * @param author the feed author to set, <b>null</b> if none.
367 *
368 */
369 public void setAuthor(String author) {
370 getDCModule().setCreator(author);
371 }
372
373 /***
374 * Returns the feed copyright.
375 * <p>
376 * This method is a convenience method, it maps to the Dublin Core module rights.
377 * <p>
378 * @return the feed copyright, <b>null</b> if none.
379 *
380 */
381 public String getCopyright() {
382 return getDCModule().getRights();
383 }
384
385 /***
386 * Sets the feed copyright.
387 * <p>
388 * This method is a convenience method, it maps to the Dublin Core module rights.
389 * <p>
390 * @param copyright the feed copyright to set, <b>null</b> if none.
391 *
392 */
393 public void setCopyright(String copyright) {
394 getDCModule().setRights(copyright);
395 }
396
397 /***
398 * Returns the feed image.
399 * <p>
400 * @return the feed image, <b>null</b> if none.
401 *
402 */
403 public SyndImage getImage() {
404 return _image;
405 }
406
407 /***
408 * Sets the feed image.
409 * <p>
410 * @param image the feed image to set, <b>null</b> if none.
411 *
412 */
413 public void setImage(SyndImage image) {
414 _image = image;
415 }
416
417 /***
418 * Returns the feed categories.
419 * <p>
420 * This method is a convenience method, it maps to the Dublin Core module subjects.
421 * <p>
422 * @return a list of SyndCategoryImpl elements with the feed categories,
423 * an empty list if none.
424 *
425 */
426 public List getCategories() {
427 return new SyndCategoryListFacade(getDCModule().getSubjects());
428 }
429
430 /***
431 * Sets the feed categories.
432 * <p>
433 * This method is a convenience method, it maps to the Dublin Core module subjects.
434 * <p>
435 * @param categories the list of SyndCategoryImpl elements with the feed categories to set,
436 * an empty list or <b>null</b> if none.
437 *
438 */
439 public void setCategories(List categories) {
440 getDCModule().setSubjects(SyndCategoryListFacade.convertElementsSyndCategoryToSubject(categories));
441 }
442
443 /***
444 * Returns the feed entries.
445 * <p>
446 * @return a list of SyndEntryImpl elements with the feed entries,
447 * an empty list if none.
448 *
449 */
450 public List getEntries() {
451 return (_entries==null) ? (_entries=new ArrayList()) : _entries;
452 }
453
454 /***
455 * Sets the feed entries.
456 * <p>
457 * @param entries the list of SyndEntryImpl elements with the feed entries to set,
458 * an empty list or <b>null</b> if none.
459 *
460 */
461 public void setEntries(List entries) {
462 _entries = entries;
463 }
464
465 /***
466 * Returns the feed language.
467 * <p>
468 * This method is a convenience method, it maps to the Dublin Core module language.
469 * <p>
470 * @return the feed language, <b>null</b> if none.
471 *
472 */
473 public String getLanguage() {
474 return getDCModule().getLanguage();
475 }
476
477 /***
478 * Sets the feed language.
479 * <p>
480 * This method is a convenience method, it maps to the Dublin Core module language.
481 * <p>
482 * @param language the feed language to set, <b>null</b> if none.
483 *
484 */
485 public void setLanguage(String language) {
486 getDCModule().setLanguage(language);
487 }
488
489 /***
490 * Returns the feed modules.
491 * <p>
492 * @return a list of ModuleImpl elements with the feed modules,
493 * an empty list if none.
494 *
495 */
496 public List getModules() {
497 if (_modules==null) {
498 _modules=new ArrayList();
499 }
500 if (ModuleUtils.getModule(_modules,DCModule.URI)==null) {
501 _modules.add(new DCModuleImpl());
502 }
503 return _modules;
504 }
505
506
507 /***
508 * Sets the feed modules.
509 * <p>
510 * @param modules the list of ModuleImpl elements with the feed modules to set,
511 * an empty list or <b>null</b> if none.
512 *
513 */
514 public void setModules(List modules) {
515 _modules = modules;
516 }
517
518 /***
519 * Returns the module identified by a given URI.
520 * <p>
521 * @param uri the URI of the ModuleImpl.
522 * @return The module with the given URI, <b>null</b> if none.
523 */
524 public Module getModule(String uri) {
525 return ModuleUtils.getModule(getModules(),uri);
526 }
527
528 /***
529 * Returns the Dublin Core module of the feed.
530 * @return the DC module, it's never <b>null</b>
531 *
532 */
533 private DCModule getDCModule() {
534 return (DCModule) getModule(DCModule.URI);
535 }
536
537 public Class getInterface() {
538 return SyndFeed.class;
539 }
540
541 public void copyFrom(Object obj) {
542 COPY_FROM_HELPER.copy(this,obj);
543 }
544
545
546
547
548 private static final CopyFromHelper COPY_FROM_HELPER;
549
550 static {
551 Map basePropInterfaceMap = new HashMap();
552 basePropInterfaceMap.put("feedType",String.class);
553 basePropInterfaceMap.put("encoding",String.class);
554 basePropInterfaceMap.put("uri",String.class);
555 basePropInterfaceMap.put("title",String.class);
556 basePropInterfaceMap.put("link",String.class);
557 basePropInterfaceMap.put("description",String.class);
558 basePropInterfaceMap.put("image",SyndImage.class);
559 basePropInterfaceMap.put("entries",SyndEntry.class);
560 basePropInterfaceMap.put("modules",Module.class);
561
562 Map basePropClassImplMap = new HashMap();
563 basePropClassImplMap.put(SyndEntry.class,SyndEntryImpl.class);
564 basePropClassImplMap.put(SyndImage.class,SyndImageImpl.class);
565 basePropClassImplMap.put(DCModule.class,DCModuleImpl.class);
566 basePropClassImplMap.put(SyModule.class,SyModuleImpl.class);
567
568 COPY_FROM_HELPER = new CopyFromHelper(SyndFeed.class,basePropInterfaceMap,basePropClassImplMap);
569 }
570
571 }