/******************************************************************************* * Copyright (c) 2014 Pivotal Software, Inc. and others. * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License v1.0 * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). * * Contributors: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.springsource.ide.eclipse.commons.gettingstarted.dashboard; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import org.apache.commons.lang.StringEscapeUtils; import org.eclipse.jface.preference.IPreferenceStore; import org.springsource.ide.eclipse.dashboard.internal.ui.IIdeUiConstants; import org.springsource.ide.eclipse.dashboard.internal.ui.IdeUiPlugin; import org.springsource.ide.eclipse.dashboard.internal.ui.feeds.FeedMonitor; import com.sun.syndication.feed.synd.SyndContent; import com.sun.syndication.feed.synd.SyndEntry; /** * @author Miles Parker * */ public class BlogsProvider extends FeedProvider { protected static final int FEEDS_DESCRIPTION_MAX = 200; private Date lastUpdated = null; private Date currentUpdated = null; /** * @param manager */ public BlogsProvider() { super(FeedMonitor.RESOURCE_DASHBOARD_FEEDS_BLOGS); IPreferenceStore prefStore = IdeUiPlugin.getDefault().getPreferenceStore(); long lastUpdateLong = prefStore.getLong(IIdeUiConstants.PREF_FEED_ENTRY_LAST_UPDATE_DISPLAYED); lastUpdated = new Date(lastUpdateLong); currentUpdated = lastUpdated; } private String buildDescription(SyndEntry entry) { SyndContent content = entry.getDescription(); if (content == null) { List<?> nestedContent = entry.getContents(); if (!nestedContent.isEmpty()) { Object obj = nestedContent.get(0); if (obj instanceof SyndContent) { content = (SyndContent) obj; } } } if (content == null) { return ""; } String value = content.getValue(); if (value == null) { return ""; } if (value.startsWith("<form>")) { return value; } return removeHtmlEntities(value); } private String buildFeed(SyndEntry entry) { String html = ""; Date entryDate = new Date(0); if (entry.getUpdatedDate() != null) { entryDate = entry.getUpdatedDate(); } else { entryDate = entry.getPublishedDate(); } String dateString = ""; if (entryDate != null) { dateString = DateFormat.getDateInstance(DateFormat.MEDIUM).format(entryDate); } String entryAuthor = ""; if (entry.getAuthor() != null && entry.getAuthor().trim() != "") { entryAuthor = entry.getAuthor(); } html += "<div class=\"blog--container blog-preview\">"; html += " <div class=\"blog--title\">"; if (lastUpdated.before(entryDate)) { html += "<i class=\"fa fa-star new-star\"></i>"; } if (currentUpdated.before(entryDate)) { currentUpdated = entryDate; } html += " <a href=\"\" onclick=\"ide.call('openWebPage', '" + entry.getLink() + "')\">" + entry.getTitle() + "</a>"; html += " </div>"; html += " <div class=\"blog--post\">"; html += " <div>"; html += " <p>" + trimText(buildDescription(entry)); html += " <span class=\"author\">" + entryAuthor + " <i>" + dateString + "</i></span></p>"; html += " </div>"; html += " </div>"; html += "</div>"; return html; } /* * (non-Javadoc) * * @see * org.springsource.ide.eclipse.commons.browser.IEclipseToBrowserFunctionCall * .Adapter#getDynamicArgumentValue(java.lang.String) */ @Override public String getFeedHtml() { Set<SyndEntry> feedEntries = FeedMonitor.getInstance().getFeedEntries(); if (feedEntries == null || feedEntries.isEmpty()) { return null; } String html = ""; List<SyndEntry> sortedEntries = new ArrayList<SyndEntry>(feedEntries); Collections.sort(sortedEntries, new Comparator<SyndEntry>() { public int compare(SyndEntry o1, SyndEntry o2) { Date o1Date = o1.getPublishedDate() != null ? o1.getPublishedDate() : o1.getUpdatedDate(); Date o2Date = o2.getPublishedDate() != null ? o2.getPublishedDate() : o2.getUpdatedDate(); if (o1Date == null && o2Date == null) { return 0; } else if (o1Date == null) { return -1; } else if (o2Date == null) { return 1; } else { return o2Date.compareTo(o1Date); } } }); for (SyndEntry entry : sortedEntries) { html += buildFeed(entry); } return html; } private String trimText(String s) { // Remove html encoded entities s = StringEscapeUtils.unescapeHtml(s); // Remove line breaks and tabs s = s.replace("\n", " "); s = s.replace("\t", " "); // Remove whitespace between text String[] vals = s.split(" "); StringBuilder sb = new StringBuilder(); for (String v : vals) { if (v.trim().length() > 0) { sb.append(v).append(" "); } } if (sb.length() > FEEDS_DESCRIPTION_MAX) { return sb.substring(0, findEndOfWord(sb, FEEDS_DESCRIPTION_MAX)) + " ..."; // return sb.substring(0, FEEDS_DESCRIPTION_MAX) + " ..."; } return sb.toString(); } private int findEndOfWord(StringBuilder sb, int pos) { Pattern pattern = Pattern.compile("\\w"); while (pos < sb.length()) { if (pattern.matcher(sb.subSequence(pos, pos + 1)).matches()) { pos++; } else { return pos; } } return pos; } private String removeHtmlEntities(String value) { StringBuilder result = new StringBuilder(); boolean tagOpened = false; for (char currChar : value.toCharArray()) { if (currChar == '<') { tagOpened = true; } else if (currChar == '>') { tagOpened = false; } else { if (!tagOpened) { result.append(currChar); } } } return StringEscapeUtils.unescapeHtml(result.toString()); } @Override public boolean isFeedReady() { Set<SyndEntry> entries = FeedMonitor.getInstance().getFeedEntries(); return entries!=null && !entries.isEmpty(); } }