[dryad] r5319 committed - 1st commit before to modify it.

0 views
Skip to first unread message

dr...@googlecode.com

unread,
Mar 2, 2012, 4:38:02 PM3/2/12
to dryad-...@googlegroups.com
Revision: 5319
Author: fabio.bolognesi75
Date: Fri Mar 2 13:37:04 2012
Log: 1st commit before to modify it.
http://code.google.com/p/dryad/source/detail?r=5319

Added:

/trunk/dryad/dspace/modules/api/src/main/java/org/dspace/app/util/SyndicationFeed.java

=======================================
--- /dev/null
+++
/trunk/dryad/dspace/modules/api/src/main/java/org/dspace/app/util/SyndicationFeed.java
Fri Mar 2 13:37:04 2012
@@ -0,0 +1,473 @@
+/**
+ * The contents of this file are subject to the license and copyright
+ * detailed in the LICENSE and NOTICE files at the root of the source
+ * tree and available online at
+ *
+ * http://www.dspace.org/license/
+ */
+package org.dspace.app.util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.w3c.dom.Document;
+
+import org.dspace.content.Bitstream;
+import org.dspace.content.Collection;
+import org.dspace.content.Community;
+import org.dspace.content.DCDate;
+import org.dspace.content.DCValue;
+import org.dspace.content.DSpaceObject;
+import org.dspace.content.Item;
+import org.dspace.core.ConfigurationManager;
+import org.dspace.core.Constants;
+import org.dspace.handle.HandleManager;
+
+import com.sun.syndication.feed.synd.SyndFeed;
+import com.sun.syndication.feed.synd.SyndFeedImpl;
+import com.sun.syndication.feed.synd.SyndEntry;
+import com.sun.syndication.feed.synd.SyndEntryImpl;
+import com.sun.syndication.feed.synd.SyndImage;
+import com.sun.syndication.feed.synd.SyndImageImpl;
+import com.sun.syndication.feed.synd.SyndPerson;
+import com.sun.syndication.feed.synd.SyndPersonImpl;
+import com.sun.syndication.feed.synd.SyndContent;
+import com.sun.syndication.feed.synd.SyndContentImpl;
+import com.sun.syndication.feed.module.DCModuleImpl;
+import com.sun.syndication.feed.module.DCModule;
+import com.sun.syndication.feed.module.Module;
+import com.sun.syndication.io.SyndFeedOutput;
+import com.sun.syndication.io.FeedException;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Invoke ROME library to assemble a generic model of a syndication
+ * for the given list of Items and scope. Consults configuration for the
+ * metadata bindings to feed elements. Uses ROME's output drivers to
+ * return any of the implemented formats, e.g. RSS 1.0, RSS 2.0, ATOM 1.0.
+ *
+ * The feed generator and OpenSearch call on this class so feed contents
are
+ * uniform for both.
+ *
+ * @author Larry Stone
+ */
+public class SyndicationFeed
+{
+ private static final Logger log =
Logger.getLogger(SyndicationFeed.class);
+
+
+ /** i18n key values */
+ public static final String MSG_UNTITLED = "notitle";
+ public static final String MSG_LOGO_TITLE = "logo.title";
+ public static final String MSG_FEED_TITLE = "feed.title";
+ public static final String MSG_FEED_DESCRIPTION
= "general-feed.description";
+ public static final String MSG_METADATA = "metadata.";
+ public static final String MSG_UITYPE = "ui.type";
+
+ // UI keywords
+ public static final String UITYPE_XMLUI = "xmlui";
+ public static final String UITYPE_JSPUI = "jspui";
+
+ // default DC fields for entry
+ private static String defaultTitleField = "dc.title";
+ private static String defaultAuthorField = "dc.contributor.author";
+ private static String defaultDateField = "dc.date.issued";
+ private static String defaultDescriptionFields
= "dc.description.abstract, dc.description, dc.title.alternative, dc.title";
+
+ // metadata field for Item title in entry:
+ private static String titleField =
+ getDefaultedConfiguration("webui.feed.item.title",
defaultTitleField);
+
+ // metadata field for Item publication date in entry:
+ private static String dateField =
+ getDefaultedConfiguration("webui.feed.item.date",
defaultDateField);
+
+ // metadata field for Item description in entry:
+ private static String descriptionFields[] =
+ getDefaultedConfiguration("webui.feed.item.description",
defaultDescriptionFields).split("\\s*,\\s*");
+
+ private static String authorField =
+ getDefaultedConfiguration("webui.feed.item.author",
defaultAuthorField);
+
+ // metadata field for Item dc:creator field in entry's DCModule (no
default)
+ private static String dcCreatorField =
ConfigurationManager.getProperty("webui.feed.item.dc.creator");
+
+ // metadata field for Item dc:date field in entry's DCModule (no
default)
+ private static String dcDateField =
ConfigurationManager.getProperty("webui.feed.item.dc.date");
+
+ // metadata field for Item dc:author field in entry's DCModule (no
default)
+ private static String dcDescriptionField =
ConfigurationManager.getProperty("webui.feed.item.dc.description");
+
+
+ // -------- Instance variables:
+
+ // the feed object we are building
+ private SyndFeed feed = null;
+
+ // memory of UI that called us, "xmlui" or "jspui"
+ // affects Bitstream retrieval URL and I18N keys
+ private String uiType = null;
+
+ /**
+ * Constructor.
+ * @param ui either "xmlui" or "jspui"
+ */
+ public SyndicationFeed(String ui)
+ {
+ feed = new SyndFeedImpl();
+ uiType = ui;
+ }
+
+ /**
+ * Returns list of metadata selectors used to compose the description
element
+ *
+ * @return selector list - format 'schema.element[.qualifier]'
+ */
+ public static String[] getDescriptionSelectors()
+ {
+ return (String[]) ArrayUtils.clone(descriptionFields);
+ }
+
+
+ /**
+ * Fills in the feed and entry-level metadata from DSpace objects.
+ */
+ public void populate(HttpServletRequest request, DSpaceObject dso,
+ DSpaceObject items[], Map<String, String> labels)
+ {
+ String logoURL = null;
+ String objectURL = null;
+ String defaultTitle = null;
+
+ // dso is null for the whole site, or a search without scope
+ if (dso == null)
+ {
+ defaultTitle = ConfigurationManager.getProperty("dspace.name");
+ feed.setDescription(localize(labels, MSG_FEED_DESCRIPTION));
+ objectURL = resolveURL(request, null);
+ logoURL =
ConfigurationManager.getProperty("webui.feed.logo.url");
+ }
+ else
+ {
+ Bitstream logo = null;
+ if (dso.getType() == Constants.COLLECTION)
+ {
+ Collection col = (Collection)dso;
+ defaultTitle = col.getMetadata("name");
+ feed.setDescription(col.getMetadata("short_description"));
+ logo = col.getLogo();
+ }
+ else if (dso.getType() == Constants.COMMUNITY)
+ {
+ Community comm = (Community)dso;
+ defaultTitle = comm.getMetadata("name");
+ feed.setDescription(comm.getMetadata("short_description"));
+ logo = comm.getLogo();
+ }
+ objectURL = resolveURL(request, dso);
+ if (logo != null)
+ {
+ logoURL = urlOfBitstream(request, logo);
+ }
+ }
+ feed.setTitle(labels.containsKey(MSG_FEED_TITLE) ?
+ localize(labels, MSG_FEED_TITLE) :
defaultTitle);
+ feed.setLink(objectURL);
+ feed.setPublishedDate(new Date());
+ feed.setUri(objectURL);
+
+ // add logo if we found one:
+ if (logoURL != null)
+ {
+ // we use the path to the logo for this, the logo itself cannot
+ // be contained in the rdf. Not all RSS-viewers show this logo.
+ SyndImage image = new SyndImageImpl();
+ image.setLink(objectURL);
+ image.setTitle(localize(labels, MSG_LOGO_TITLE));
+ image.setUrl(logoURL);
+ feed.setImage(image);
+ }
+
+ // add entries for items
+ if (items != null)
+ {
+ List<SyndEntry> entries = new ArrayList<SyndEntry>();
+ for (DSpaceObject itemDSO : items)
+ {
+ if (itemDSO.getType() != Constants.ITEM)
+ {
+ continue;
+ }
+ Item item = (Item)itemDSO;
+ boolean hasDate = false;
+ SyndEntry entry = new SyndEntryImpl();
+ entries.add(entry);
+
+ String entryURL = resolveURL(request, item);
+ entry.setLink(entryURL);
+ entry.setUri(entryURL);
+
+ String title = getOneDC(item, titleField);
+ entry.setTitle(title == null ? localize(labels,
MSG_UNTITLED) : title);
+
+ // "published" date -- should be dc.date.issued
+ String pubDate = getOneDC(item, dateField);
+ if (pubDate != null)
+ {
+ entry.setPublishedDate((new DCDate(pubDate)).toDate());
+ hasDate = true;
+ }
+ // date of last change to Item
+ entry.setUpdatedDate(item.getLastModified());
+
+ StringBuffer db = new StringBuffer();
+ for (String df : descriptionFields)
+ {
+ // Special Case: "(date)" in field name means render
as date
+ boolean isDate = df.indexOf("(date)") > 0;
+ if (isDate)
+ {
+ df = df.replaceAll("\\(date\\)", "");
+ }
+
+ DCValue dcv[] = item.getMetadata(df);
+ if (dcv.length > 0)
+ {
+ String fieldLabel = labels.get(MSG_METADATA + df);
+ if (fieldLabel != null && fieldLabel.length()>0)
+ {
+ db.append(fieldLabel).append(": ");
+ }
+ boolean first = true;
+ for (DCValue v : dcv)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ db.append("; ");
+ }
+ db.append(isDate ? new
DCDate(v.value).toString() : v.value);
+ }
+ db.append("\n");
+ }
+ }
+ if (db.length() > 0)
+ {
+ SyndContent desc = new SyndContentImpl();
+ desc.setType("text/plain");
+ desc.setValue(db.toString());
+ entry.setDescription(desc);
+ }
+
+ // This gets the authors into an ATOM feed
+ DCValue authors[] = item.getMetadata(authorField);
+ if (authors.length > 0)
+ {
+ List<SyndPerson> creators = new
ArrayList<SyndPerson>();
+ for (DCValue author : authors)
+ {
+ SyndPerson sp = new SyndPersonImpl();
+ sp.setName(author.value);
+ creators.add(sp);
+ }
+ entry.setAuthors(creators);
+ }
+
+ // only add DC module if any DC fields are configured
+ if (dcCreatorField != null || dcDateField != null ||
+ dcDescriptionField != null)
+ {
+ DCModule dc = new DCModuleImpl();
+ if (dcCreatorField != null)
+ {
+ DCValue dcAuthors[] =
item.getMetadata(dcCreatorField);
+ if (dcAuthors.length > 0)
+ {
+ List<String> creators = new
ArrayList<String>();
+ for (DCValue author : dcAuthors)
+ {
+ creators.add(author.value);
+ }
+ dc.setCreators(creators);
+ }
+ }
+ if (dcDateField != null && !hasDate)
+ {
+ DCValue v[] = item.getMetadata(dcDateField);
+ if (v.length > 0)
+ {
+ dc.setDate((new DCDate(v[0].value)).toDate());
+ }
+ }
+ if (dcDescriptionField != null)
+ {
+ DCValue v[] = item.getMetadata(dcDescriptionField);
+ if (v.length > 0)
+ {
+ StringBuffer descs = new StringBuffer();
+ for (DCValue d : v)
+ {
+ if (descs.length() > 0)
+ {
+ descs.append("\n\n");
+ }
+ descs.append(d.value);
+ }
+ dc.setDescription(descs.toString());
+ }
+ }
+ entry.getModules().add(dc);
+ }
+ }
+ feed.setEntries(entries);
+ }
+ }
+
+ /**
+ * Sets the feed type for XML delivery, e.g. "rss_1.0", "atom_1.0"
+ * Must match one of ROME's configured generators, see rome.properties
+ * (currently rss_1.0, rss_2.0, atom_1.0, atom_0.3)
+ */
+ public void setType(String feedType)
+ {
+ feed.setFeedType(feedType);
+ // XXX FIXME: workaround ROME 1.0 bug, it puts invalid image
element in rss1.0
+ if ("rss_1.0".equals(feedType))
+ {
+ feed.setImage(null);
+ }
+ }
+
+ /**
+ * @return the feed we built as DOM Document
+ */
+ public Document outputW3CDom()
+ throws FeedException
+ {
+ try
+ {
+ SyndFeedOutput feedWriter = new SyndFeedOutput();
+ return feedWriter.outputW3CDom(feed);
+ }
+ catch (FeedException e)
+ {
+ log.error(e);
+ throw e;
+ }
+ }
+
+ /**
+ * @return the feed we built as serialized XML string
+ */
+ public String outputString()
+ throws FeedException
+ {
+ SyndFeedOutput feedWriter = new SyndFeedOutput();
+ return feedWriter.outputString(feed);
+ }
+
+ /**
+ * send the output to designated Writer
+ */
+ public void output(java.io.Writer writer)
+ throws FeedException, IOException
+ {
+ SyndFeedOutput feedWriter = new SyndFeedOutput();
+ feedWriter.output(feed, writer);
+ }
+
+ /**
+ * Add a ROME plugin module (e.g. for OpenSearch) at the feed level.
+ */
+ public void addModule(Module m)
+ {
+ feed.getModules().add(m);
+ }
+
+ // utility to get config property with default value when not set.
+ private static String getDefaultedConfiguration(String key, String dfl)
+ {
+ String result = ConfigurationManager.getProperty(key);
+ return (result == null) ? dfl : result;
+ }
+
+ // returns absolute URL to download content of bitstream (which might
not belong to any Item)
+ private String urlOfBitstream(HttpServletRequest request, Bitstream
logo)
+ {
+ String name = logo.getName();
+ return resolveURL(request,null) +
+
(uiType.equalsIgnoreCase(UITYPE_XMLUI) ?"/bitstream/id/":"/retrieve/") +
+ logo.getID()+"/"+(name == null?"":name);
+ }
+
+ /**
+ * Return a url to the DSpace object, either use the official
+ * handle for the item or build a url based upon the current server.
+ *
+ * If the dspaceobject is null then a local url to the repository is
generated.
+ *
+ * @param dso The object to refrence, null if to the repository.
+ * @return
+ */
+ private String baseURL = null; // cache the result for null
+
+ private String resolveURL(HttpServletRequest request, DSpaceObject dso)
+ {
+ // If no object given then just link to the whole repository,
+ // since no offical handle exists so we have to use local
resolution.
+ if (dso == null)
+ {
+ if (baseURL == null)
+ {
+ if (request == null)
+ {
+ baseURL =
ConfigurationManager.getProperty("dspace.url");
+ }
+ else
+ {
+ baseURL =
(request.isSecure()) ? "https://" : "http://";
+ baseURL +=
ConfigurationManager.getProperty("dspace.hostname");
+ baseURL += ":" + request.getServerPort();
+ baseURL += request.getContextPath();
+ }
+ }
+ return baseURL;
+ }
+
+ // return a link to handle in repository
+ else if
(ConfigurationManager.getBooleanProperty("webui.feed.localresolve"))
+ {
+ return resolveURL(request, null) + "/handle/" +
dso.getHandle();
+ }
+
+ // link to the Handle server or other persistent URL source
+ else
+ {
+ return HandleManager.getCanonicalForm(dso.getHandle());
+ }
+ }
+
+ // retrieve text for localization key, or mark untranslated
+ private String localize(Map<String, String> labels, String s)
+ {
+ return labels.containsKey(s) ? labels.get(s) : ("Untranslated:"+s);
+ }
+
+ // spoonful of syntactic sugar when we only need first value
+ private String getOneDC(Item item, String field)
+ {
+ DCValue dcv[] = item.getMetadata(field);
+ return (dcv.length > 0) ? dcv[0].value : null;
+ }
+}
+

Reply all
Reply to author
Forward
0 new messages