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.feed.synd;
018:
019: import com.sun.syndication.feed.impl.ObjectBean;
020: import com.sun.syndication.feed.module.*;
021: import com.sun.syndication.feed.module.impl.ModuleUtils;
022: import com.sun.syndication.feed.synd.impl.URINormalizer;
023: import com.sun.syndication.feed.impl.CopyFromHelper;
024:
025: import java.util.*;
026: import java.io.Serializable;
027:
028: /**
029: * Bean for entries of SyndFeedImpl feeds.
030: * <p>
031: * @author Alejandro Abdelnur
032: *
033: */
034: public class SyndEntryImpl implements Serializable, SyndEntry {
035: private ObjectBean _objBean;
036: private String _uri;
037: private String _link;
038: private Date _updatedDate;
039: private SyndContent _title;
040: private SyndContent _description;
041: private List _links;
042: private List _contents; // deprecated by Atom 1.0
043: private List _modules;
044: private List _enclosures;
045: private List _authors;
046: private List _contributors;
047: private List _foreignMarkup;
048:
049: // ISSUE: some converters assume this is never null
050: private List _categories = new ArrayList();
051:
052: private static final Set IGNORE_PROPERTIES = new HashSet();
053:
054: /**
055: * Unmodifiable Set containing the convenience properties of this class.
056: * <p>
057: * Convenience properties are mapped to Modules, for cloning the convenience properties
058: * can be ignored as the will be copied as part of the module cloning.
059: */
060: public static final Set CONVENIENCE_PROPERTIES = Collections
061: .unmodifiableSet(IGNORE_PROPERTIES);
062:
063: static {
064: IGNORE_PROPERTIES.add("publishedDate");
065: IGNORE_PROPERTIES.add("author");
066: }
067:
068: /**
069: * For implementations extending SyndEntryImpl to be able to use the ObjectBean functionality
070: * with extended interfaces.
071: * <p>
072: * @param beanClass
073: * @param convenienceProperties set containing the convenience properties of the SyndEntryImpl
074: * (the are ignored during cloning, check CloneableBean for details).
075: *
076: */
077: protected SyndEntryImpl(Class beanClass, Set convenienceProperties) {
078: _objBean = new ObjectBean(beanClass, this ,
079: convenienceProperties);
080: }
081:
082: /**
083: * Default constructor. All properties are set to <b>null</b>.
084: * <p>
085: *
086: */
087: public SyndEntryImpl() {
088: this (SyndEntry.class, IGNORE_PROPERTIES);
089: }
090:
091: /**
092: * Creates a deep 'bean' clone of the object.
093: * <p>
094: * @return a clone of the object.
095: * @throws CloneNotSupportedException thrown if an element of the object cannot be cloned.
096: *
097: */
098: public Object clone() throws CloneNotSupportedException {
099: return _objBean.clone();
100: }
101:
102: /**
103: * Indicates whether some other object is "equal to" this one as defined by the Object equals() method.
104: * <p>
105: * @param other he reference object with which to compare.
106: * @return <b>true</b> if 'this' object is equal to the 'other' object.
107: *
108: */
109: public boolean equals(Object other) {
110: // can't use foreign markup in equals, due to JDOM equals impl
111: Object fm = getForeignMarkup();
112: setForeignMarkup(((SyndEntryImpl) other).getForeignMarkup());
113: boolean ret = _objBean.equals(other);
114: // restore foreign markup
115: setForeignMarkup(fm);
116: return ret;
117: }
118:
119: /**
120: * Returns a hashcode value for the object.
121: * <p>
122: * It follows the contract defined by the Object hashCode() method.
123: * <p>
124: * @return the hashcode of the bean object.
125: *
126: */
127: public int hashCode() {
128: return _objBean.hashCode();
129: }
130:
131: /**
132: * Returns the String representation for the object.
133: * <p>
134: * @return String representation for the object.
135: *
136: */
137: public String toString() {
138: return _objBean.toString();
139: }
140:
141: /**
142: * Returns the entry URI.
143: * <p>
144: * How the entry URI maps to a concrete feed type (RSS or Atom) depends on
145: * the concrete feed type. This is explained in detail in Rome documentation,
146: * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
147: * <p>
148: * The returned URI is a normalized URI as specified in RFC 2396bis.
149: * <p>
150: * @return the entry URI, <b>null</b> if none.
151: *
152: */
153: public String getUri() {
154: return _uri;
155: }
156:
157: /**
158: * Sets the entry URI.
159: * <p>
160: * How the entry URI maps to a concrete feed type (RSS or Atom) depends on
161: * the concrete feed type. This is explained in detail in Rome documentation,
162: * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
163: * <p>
164: * @param uri the entry URI to set, <b>null</b> if none.
165: *
166: */
167: public void setUri(String uri) {
168: _uri = URINormalizer.normalize(uri);
169: }
170:
171: /**
172: * Returns the entry title.
173: * <p>
174: * @return the entry title, <b>null</b> if none.
175: *
176: */
177: public String getTitle() {
178: if (_title != null)
179: return _title.getValue();
180: return null;
181: }
182:
183: /**
184: * Sets the entry title.
185: * <p>
186: * @param title the entry title to set, <b>null</b> if none.
187: *
188: */
189: public void setTitle(String title) {
190: if (_title == null)
191: _title = new SyndContentImpl();
192: _title.setValue(title);
193: }
194:
195: /**
196: * Returns the entry title as a text construct.
197: * <p>
198: * @return the entry title, <b>null</b> if none.
199: *
200: */
201: public SyndContent getTitleEx() {
202: return _title;
203: }
204:
205: /**
206: * Sets the entry title as a text construct.
207: * <p>
208: * @param title the entry title to set, <b>null</b> if none.
209: *
210: */
211: public void setTitleEx(SyndContent title) {
212: _title = title;
213: }
214:
215: /**
216: * Returns the entry link.
217: * <p>
218: * @return the entry link, <b>null</b> if none.
219: *
220: */
221: public String getLink() {
222: return _link;
223: }
224:
225: /**
226: * Sets the entry link.
227: * <p>
228: * @param link the entry link to set, <b>null</b> if none.
229: *
230: */
231: public void setLink(String link) {
232: _link = link;
233: }
234:
235: /**
236: * Returns the entry description.
237: * <p>
238: * @return the entry description, <b>null</b> if none.
239: *
240: */
241: public SyndContent getDescription() {
242: return _description;
243: }
244:
245: /**
246: * Sets the entry description.
247: * <p>
248: * @param description the entry description to set, <b>null</b> if none.
249: *
250: */
251: public void setDescription(SyndContent description) {
252: _description = description;
253: }
254:
255: /**
256: * Returns the entry contents.
257: * <p>
258: * @return a list of SyndContentImpl elements with the entry contents,
259: * an empty list if none.
260: *
261: */
262: public List getContents() {
263: return (_contents == null) ? (_contents = new ArrayList())
264: : _contents;
265: }
266:
267: /**
268: * Sets the entry contents.
269: * <p>
270: * @param contents the list of SyndContentImpl elements with the entry contents to set,
271: * an empty list or <b>null</b> if none.
272: *
273: */
274: public void setContents(List contents) {
275: _contents = contents;
276: }
277:
278: /**
279: * Returns the entry enclosures.
280: * <p>
281: * @return a list of SyndEnclosure elements with the entry enclosures,
282: * an empty list if none.
283: *
284: */
285: public List getEnclosures() {
286: return (_enclosures == null) ? (_enclosures = new ArrayList())
287: : _enclosures;
288: }
289:
290: /**
291: * Sets the entry enclosures.
292: * <p>
293: * @param enclosures the list of SyndEnclosure elements with the entry enclosures to set,
294: * an empty list or <b>null</b> if none.
295: *
296: */
297: public void setEnclosures(List enclosures) {
298: _enclosures = enclosures;
299: }
300:
301: /**
302: * Returns the entry published date.
303: * <p>
304: * This method is a convenience method, it maps to the Dublin Core module date.
305: * <p>
306: * @return the entry published date, <b>null</b> if none.
307: *
308: */
309: public Date getPublishedDate() {
310: return getDCModule().getDate();
311: }
312:
313: /**
314: * Sets the entry published date.
315: * <p>
316: * This method is a convenience method, it maps to the Dublin Core module date.
317: * <p>
318: * @param publishedDate the entry published date to set, <b>null</b> if none.
319: *
320: */
321: public void setPublishedDate(Date publishedDate) {
322: getDCModule().setDate(publishedDate);
323: }
324:
325: /**
326: * Returns the entry categories.
327: * <p>
328: * @return a list of SyndCategoryImpl elements with the entry categories,
329: * an empty list if none.
330: *
331: */
332: public List getCategories() {
333: return _categories;
334: }
335:
336: /**
337: * Sets the entry categories.
338: * <p>
339: * This method is a convenience method, it maps to the Dublin Core module subjects.
340: * <p>
341: * @param categories the list of SyndCategoryImpl elements with the entry categories to set,
342: * an empty list or <b>null</b> if none.
343: *
344: */
345: public void setCategories(List categories) {
346: _categories = categories;
347: }
348:
349: /**
350: * Returns the entry modules.
351: * <p>
352: * @return a list of ModuleImpl elements with the entry modules,
353: * an empty list if none.
354: *
355: */
356: public List getModules() {
357: if (_modules == null) {
358: _modules = new ArrayList();
359: }
360: if (ModuleUtils.getModule(_modules, DCModule.URI) == null) {
361: _modules.add(new DCModuleImpl());
362: }
363: return _modules;
364: }
365:
366: /**
367: * Sets the entry modules.
368: * <p>
369: * @param modules the list of ModuleImpl elements with the entry modules to set,
370: * an empty list or <b>null</b> if none.
371: *
372: */
373: public void setModules(List modules) {
374: _modules = modules;
375: }
376:
377: /**
378: * Returns the module identified by a given URI.
379: * <p>
380: * @param uri the URI of the ModuleImpl.
381: * @return The module with the given URI, <b>null</b> if none.
382: */
383: public Module getModule(String uri) {
384: return ModuleUtils.getModule(getModules(), uri);
385: }
386:
387: /**
388: * Returns the Dublin Core module of the feed.
389: * @return the DC module, it's never <b>null</b>
390: *
391: */
392: private DCModule getDCModule() {
393: return (DCModule) getModule(DCModule.URI);
394: }
395:
396: public Class getInterface() {
397: return SyndEntry.class;
398: }
399:
400: public void copyFrom(Object obj) {
401: COPY_FROM_HELPER.copy(this , obj);
402: }
403:
404: private static final CopyFromHelper COPY_FROM_HELPER;
405:
406: static {
407: Map basePropInterfaceMap = new HashMap();
408: basePropInterfaceMap.put("uri", String.class);
409: basePropInterfaceMap.put("title", String.class);
410: basePropInterfaceMap.put("link", String.class);
411: basePropInterfaceMap.put("uri", String.class);
412: basePropInterfaceMap.put("description", SyndContent.class);
413: basePropInterfaceMap.put("contents", SyndContent.class);
414: basePropInterfaceMap.put("enclosures", SyndEnclosure.class);
415: basePropInterfaceMap.put("modules", Module.class);
416:
417: Map basePropClassImplMap = new HashMap();
418: basePropClassImplMap.put(SyndContent.class,
419: SyndContentImpl.class);
420: basePropClassImplMap.put(SyndEnclosure.class,
421: SyndEnclosureImpl.class);
422: basePropClassImplMap.put(DCModule.class, DCModuleImpl.class);
423: basePropClassImplMap.put(SyModule.class, SyModuleImpl.class);
424:
425: COPY_FROM_HELPER = new CopyFromHelper(SyndEntry.class,
426: basePropInterfaceMap, basePropClassImplMap);
427: }
428:
429: /**
430: * Returns the links
431: * <p>
432: * @return Returns the links.
433: */
434: public List getLinks() {
435: return (_links == null) ? (_links = new ArrayList()) : _links;
436: }
437:
438: /**
439: * Set the links
440: * <p>
441: * @param links The links to set.
442: */
443: public void setLinks(List links) {
444: _links = links;
445: }
446:
447: /**
448: * Returns the updatedDate
449: * <p>
450: * @return Returns the updatedDate.
451: */
452: public Date getUpdatedDate() {
453: return _updatedDate;
454: }
455:
456: /**
457: * Set the updatedDate
458: * <p>
459: * @param updatedDate The updatedDate to set.
460: */
461: public void setUpdatedDate(Date updatedDate) {
462: _updatedDate = updatedDate;
463: }
464:
465: public List getAuthors() {
466: return _authors;
467: }
468:
469: /* (non-Javadoc)
470: * @see com.sun.syndication.feed.synd.SyndEntry#setAuthors(java.util.List)
471: */
472: public void setAuthors(List authors) {
473: _authors = authors;
474: }
475:
476: /**
477: * Returns the entry author.
478: * <p>
479: * This method is a convenience method, it maps to the Dublin Core module creator.
480: * <p>
481: * @return the entry author, <b>null</b> if none.
482: *
483: */
484: public String getAuthor() {
485: String author;
486:
487: // Start out looking for one or more authors in _authors. For non-Atom
488: // feeds, _authors may actually be null.
489: if ((_authors != null) && (_authors.size() > 0)) {
490: author = ((SyndPerson) _authors.get(0)).getName();
491: } else {
492: author = getDCModule().getCreator();
493: }
494: if (author == null) {
495: author = "";
496: }
497:
498: return author;
499: }
500:
501: /**
502: * Sets the entry author.
503: * <p>
504: * This method is a convenience method, it maps to the Dublin Core module creator.
505: * <p>
506: * @param author the entry author to set, <b>null</b> if none.
507: *
508: */
509: public void setAuthor(String author) {
510: // Get the DCModule so that we can check to see if "creator" is already
511: // set.
512: DCModule dcModule = getDCModule();
513: String currentValue = dcModule.getCreator();
514:
515: if ((currentValue == null) || (currentValue.length() == 0)) {
516: getDCModule().setCreator(author);
517: }
518: }
519:
520: public List getContributors() {
521: return _contributors;
522: }
523:
524: /* (non-Javadoc)
525: * @see com.sun.syndication.feed.synd.SyndEntry#setContributors(java.util.List)
526: */
527: public void setContributors(List contributors) {
528: _contributors = contributors;
529: }
530:
531: /**
532: * Returns foreign markup found at channel level.
533: * <p>
534: * @return list of JDOM nodes containing channel-level foreign markup,
535: * an empty list if none.
536: *
537: */
538: public Object getForeignMarkup() {
539: return (_foreignMarkup == null) ? (_foreignMarkup = new ArrayList())
540: : _foreignMarkup;
541: }
542:
543: /**
544: * Sets foreign markup found at channel level.
545: * <p>
546: * @param foreignMarkup list of JDOM nodes containing channel-level foreign markup,
547: * an empty list if none.
548: *
549: */
550: public void setForeignMarkup(Object foreignMarkup) {
551: _foreignMarkup = (List) foreignMarkup;
552: }
553: }
|