//# 0 errors, 384 messages
//#
/*
    //#newsfeedcache.java:1:1: class: net.sourceforge.pebble.aggregator.NewsFeedCache
 * Copyright (c) 2003-2006, Simon Brown
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   - Neither the name of Pebble nor the names of its contributors may
 *     be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package net.sourceforge.pebble.aggregator;

import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.atom.Content;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.feed.rss.Channel;
import com.sun.syndication.feed.rss.Item;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.WireFeedInput;
import com.sun.syndication.io.XmlReader;
import net.sourceforge.pebble.domain.Blog;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * A cache of newsfeed subscriptions and their entries.
 *
 * @author    Simon Brown
 */
public class NewsFeedCache {

  private static final int FEED_ENTRY_LIMIT = 20;

  private static final Log log = LogFactory.getLog(NewsFeedCache.class);
    //#newsfeedcache.java:60: method: net.sourceforge.pebble.aggregator.NewsFeedCache.net.sourceforge.pebble.aggregator.NewsFeedCache__static_init
    //#newsfeedcache.java:60: Warning: method not available
    //#    -- call on Log org.apache.commons.logging.LogFactory:getLog(Class)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: net.sourceforge.pebble.aggregator.NewsFeedCache__static_init
    //#    unanalyzed callee: Log org.apache.commons.logging.LogFactory:getLog(Class)
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeedCache]
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.addSubscription(Lnet/sourceforge/pebble/domain/Blog;Ljava/lang/String;)V
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.getFeed(Ljava/lang/String;)Lnet/sourceforge/pebble/aggregator/NewsFeed;
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.getNewsFeedEntries(Lnet/sourceforge/pebble/domain/Blog;)Ljava/util/List;
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.getUrls(Ljava/lang/String;)Ljava/util/Set;
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.refreshFeeds()V
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.removeAllSubscriptions(Lnet/sourceforge/pebble/domain/Blog;)V
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.updateFeed(Ljava/lang/String;)Lnet/sourceforge/pebble/aggregator/NewsFeed;
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): log
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#1) num objects
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#2) num objects
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#3) num objects
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new NewsFeedCache(NewsFeedCache__static_init#1) num objects
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.__Tag
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.entries
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.feeds
    //#output(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.subscriptions
    //#new obj(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#1)
    //#new obj(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#2)
    //#new obj(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#3)
    //#new obj(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new NewsFeedCache(NewsFeedCache__static_init#1)
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeedCache] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.addSubscription(Lnet/sourceforge/pebble/domain/Blog;Ljava/lang/String;)V == &addSubscription
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.getFeed(Ljava/lang/String;)Lnet/sourceforge/pebble/aggregator/NewsFeed; == &getFeed
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.getNewsFeedEntries(Lnet/sourceforge/pebble/domain/Blog;)Ljava/util/List; == &getNewsFeedEntries
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.getUrls(Ljava/lang/String;)Ljava/util/Set; == &getUrls
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.refreshFeeds()V == &refreshFeeds
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.removeAllSubscriptions(Lnet/sourceforge/pebble/domain/Blog;)V == &removeAllSubscriptions
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): __Dispatch_Table.updateFeed(Ljava/lang/String;)Lnet/sourceforge/pebble/aggregator/NewsFeed; == &updateFeed
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance == &new NewsFeedCache(NewsFeedCache__static_init#1)
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): init'ed(log)
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#1) num objects == 1
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#2) num objects == 1
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new HashMap(NewsFeedCache#3) num objects == 1
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): new NewsFeedCache(NewsFeedCache__static_init#1) num objects == 1
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.__Tag == net/sourceforge/pebble/aggregator/NewsFeedCache
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.entries == &new HashMap(NewsFeedCache#3)
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.feeds == &new HashMap(NewsFeedCache#2)
    //#post(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): instance.subscriptions == &new HashMap(NewsFeedCache#1)
    //#unanalyzed(net.sourceforge.pebble.aggregator.NewsFeedCache__static_init): Effects-of-calling:java.util.HashMap
  private static final NewsFeedCache instance = new NewsFeedCache();
    //#newsfeedcache.java:61: end of method: net.sourceforge.pebble.aggregator.NewsFeedCache.net.sourceforge.pebble.aggregator.NewsFeedCache__static_init

  private final Map<String,Set<String>> subscriptions = new HashMap<String,Set<String>>();
  private final Map<String, NewsFeed> feeds = new HashMap<String, NewsFeed>();
  private final Map<String,List<NewsFeedEntry>> entries = new HashMap<String,List<NewsFeedEntry>>();
  
  private NewsFeedCache() {
    //#newsfeedcache.java:67: method: void net.sourceforge.pebble.aggregator.NewsFeedCache.net.sourceforge.pebble.aggregator.NewsFeedCache()
    //#input(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this
    //#output(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#1) num objects
    //#output(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#2) num objects
    //#output(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#3) num objects
    //#output(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this.entries
    //#output(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this.feeds
    //#output(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this.subscriptions
    //#new obj(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#1)
    //#new obj(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#2)
    //#new obj(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#3)
    //#post(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this.entries == &new HashMap(NewsFeedCache#3)
    //#post(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this.feeds == &new HashMap(NewsFeedCache#2)
    //#post(void net.sourceforge.pebble.aggregator.NewsFeedCache()): this.subscriptions == &new HashMap(NewsFeedCache#1)
    //#post(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#1) num objects == 1
    //#post(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#2) num objects == 1
    //#post(void net.sourceforge.pebble.aggregator.NewsFeedCache()): new HashMap(NewsFeedCache#3) num objects == 1
  }
    //#newsfeedcache.java:68: end of method: void net.sourceforge.pebble.aggregator.NewsFeedCache.net.sourceforge.pebble.aggregator.NewsFeedCache()

  public static NewsFeedCache getInstance() {
    return instance;
    //#newsfeedcache.java:71: method: NewsFeedCache net.sourceforge.pebble.aggregator.NewsFeedCache.getInstance()
    //#input(NewsFeedCache getInstance()): instance
    //#output(NewsFeedCache getInstance()): return_value
    //#post(NewsFeedCache getInstance()): return_value == &new NewsFeedCache(NewsFeedCache__static_init#1)
    //#newsfeedcache.java:71: end of method: NewsFeedCache net.sourceforge.pebble.aggregator.NewsFeedCache.getInstance()
  }

  public void addSubscription(Blog blog, String url) {
    synchronized (feeds) {
    //#newsfeedcache.java:75: method: void net.sourceforge.pebble.aggregator.NewsFeedCache.addSubscription(Blog, String)
    //#input(void addSubscription(Blog, String)): blog
    //#input(void addSubscription(Blog, String)): blog.__Tag
    //#input(void addSubscription(Blog, String)): blog.id
    //#input(void addSubscription(Blog, String)): log
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeed]
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[others]
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.add(Lnet/sourceforge/pebble/aggregator/NewsFeedEntry;)V
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.setLink(Ljava/lang/String;)V
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.setTitle(Ljava/lang/String;)V
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeedEntry]
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Descendant_Table[others]
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Dispatch_Table.setFeed(Lnet/sourceforge/pebble/aggregator/NewsFeed;)V
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/domain/Blog.__Descendant_Table[net/sourceforge/pebble/domain/Blog]
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/domain/Blog.__Descendant_Table[others]
    //#input(void addSubscription(Blog, String)): net/sourceforge/pebble/domain/Blog.__Dispatch_Table.getId()Ljava/lang/String;
    //#input(void addSubscription(Blog, String)): this
    //#input(void addSubscription(Blog, String)): this.feeds
    //#input(void addSubscription(Blog, String)): this.subscriptions
    //#input(void addSubscription(Blog, String)): url
    //#pre[1] (void addSubscription(Blog, String)): blog != null
    //#pre[2] (void addSubscription(Blog, String)): blog.__Tag == net/sourceforge/pebble/domain/Blog
    //#pre[3] (void addSubscription(Blog, String)): init'ed(blog.id)
    //#pre[5] (void addSubscription(Blog, String)): this.feeds != null
    //#pre[6] (void addSubscription(Blog, String)): this.subscriptions != null
    //#presumption(void addSubscription(Blog, String)): java.util.Map:get(...).__Tag@79 == net/sourceforge/pebble/aggregator/NewsFeed
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.HashSet
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:org.apache.commons.logging.Log:warn
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.List:size
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.System:currentTimeMillis
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:org.apache.commons.logging.Log:debug
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.io.WireFeedInput
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.net.URL
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.io.XmlReader
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.io.WireFeedInput:build
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.WireFeed:getFeedType
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Channel:getTitle
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Channel:getLink
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Channel:getItems
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Item:getLink
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Item:getTitle
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Item:getDescription
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Description:getValue
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Item:getAuthor
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.rss.Item:getPubDate
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.List:add
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Feed:getTitle
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Feed:getAlternateLinks
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Link:getType
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Link:getHref
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Feed:getEntries
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getAlternateLinks
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getContents
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Content:getType
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Content:getValue
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getSummary
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getAuthors
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.util.List:get
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:java.lang.Object:toString
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getTitle
    //#unanalyzed(void addSubscription(Blog, String)): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getPublished
      Set<String> urls = getUrls(blog.getId());
      urls.add(url);

      NewsFeed feed = feeds.get(url);
      if (feed == null) {
        feed = updateFeed(url);
        feeds.put(url, feed);
      }
    }
  }
    //#newsfeedcache.java:85: end of method: void net.sourceforge.pebble.aggregator.NewsFeedCache.addSubscription(Blog, String)

  public void removeAllSubscriptions(Blog blog) {
    synchronized (feeds) {
    //#newsfeedcache.java:88: method: void net.sourceforge.pebble.aggregator.NewsFeedCache.removeAllSubscriptions(Blog)
    //#input(void removeAllSubscriptions(Blog)): blog
    //#input(void removeAllSubscriptions(Blog)): blog.__Tag
    //#input(void removeAllSubscriptions(Blog)): blog.id
    //#input(void removeAllSubscriptions(Blog)): net/sourceforge/pebble/domain/Blog.__Descendant_Table[net/sourceforge/pebble/domain/Blog]
    //#input(void removeAllSubscriptions(Blog)): net/sourceforge/pebble/domain/Blog.__Descendant_Table[others]
    //#input(void removeAllSubscriptions(Blog)): net/sourceforge/pebble/domain/Blog.__Dispatch_Table.getId()Ljava/lang/String;
    //#input(void removeAllSubscriptions(Blog)): this
    //#input(void removeAllSubscriptions(Blog)): this.feeds
    //#input(void removeAllSubscriptions(Blog)): this.subscriptions
    //#pre[1] (void removeAllSubscriptions(Blog)): blog != null
    //#pre[2] (void removeAllSubscriptions(Blog)): blog.__Tag == net/sourceforge/pebble/domain/Blog
    //#pre[3] (void removeAllSubscriptions(Blog)): init'ed(blog.id)
    //#pre[6] (void removeAllSubscriptions(Blog)): this.subscriptions != null
    //#unanalyzed(void removeAllSubscriptions(Blog)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void removeAllSubscriptions(Blog)): Effects-of-calling:java.util.HashSet
    //#unanalyzed(void removeAllSubscriptions(Blog)): Effects-of-calling:java.util.Map:put
      Set<String> urls = getUrls(blog.getId());
      urls.clear();
    }
  }
    //#newsfeedcache.java:92: end of method: void net.sourceforge.pebble.aggregator.NewsFeedCache.removeAllSubscriptions(Blog)

  public void refreshFeeds() {
    for (String url : feeds.keySet()) {
    //#newsfeedcache.java:95: method: void net.sourceforge.pebble.aggregator.NewsFeedCache.refreshFeeds()
    //#input(void refreshFeeds()): log
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeed]
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[others]
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.add(Lnet/sourceforge/pebble/aggregator/NewsFeedEntry;)V
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.getEntries()Ljava/util/List;
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.setLink(Ljava/lang/String;)V
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.setTitle(Ljava/lang/String;)V
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeedEntry]
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Descendant_Table[others]
    //#input(void refreshFeeds()): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Dispatch_Table.setFeed(Lnet/sourceforge/pebble/aggregator/NewsFeed;)V
    //#input(void refreshFeeds()): this
    //#input(void refreshFeeds()): this.entries
    //#input(void refreshFeeds()): this.feeds
    //#input(void refreshFeeds()): this.subscriptions
    //#pre[3] (void refreshFeeds()): this.feeds != null
    //#pre[4] (void refreshFeeds()): this.subscriptions != null
    //#pre[2] (void refreshFeeds()): (soft) this.entries != null
    //#presumption(void refreshFeeds()): java.util.Map:get(...).__Tag@109 == net/sourceforge/pebble/aggregator/NewsFeed
    //#presumption(void refreshFeeds()): java.util.Map:get(...)@109 != null
    //#presumption(void refreshFeeds()): java.util.Map:keySet(...)@106 != null
    //#presumption(void refreshFeeds()): java.util.Map:keySet(...)@95 != null
    //#presumption(void refreshFeeds()): org.apache.commons.logging.LogFactory:getLog(...)@60 != null
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.HashSet
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:org.apache.commons.logging.Log:warn
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.List:size
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.System:currentTimeMillis
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:org.apache.commons.logging.Log:debug
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.io.WireFeedInput
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.net.URL
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.io.XmlReader
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.io.WireFeedInput:build
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.WireFeed:getFeedType
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Channel:getTitle
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Channel:getLink
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Channel:getItems
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Item:getLink
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Item:getTitle
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Item:getDescription
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Description:getValue
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Item:getAuthor
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.rss.Item:getPubDate
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.List:add
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Feed:getTitle
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Feed:getAlternateLinks
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Link:getType
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Link:getHref
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Feed:getEntries
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getAlternateLinks
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getContents
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Content:getType
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Content:getValue
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getSummary
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getAuthors
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.util.List:get
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:java.lang.Object:toString
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getTitle
    //#unanalyzed(void refreshFeeds()): Effects-of-calling:com.sun.syndication.feed.atom.Entry:getPublished
    //#test_vector(void refreshFeeds()): java.util.Iterator:hasNext(...)@106: {1}, {0}
    //#test_vector(void refreshFeeds()): java.util.Iterator:hasNext(...)@108: {1}, {0}
    //#test_vector(void refreshFeeds()): java.util.Iterator:hasNext(...)@95: {1}, {0}
    //#test_vector(void refreshFeeds()): java.util.List:size(...)@114: {-2_147_483_648..20}, {21..4_294_967_295}
      try {
        NewsFeed updatedFeed = updateFeed(url);
        synchronized (feeds) {
          feeds.put(url, updatedFeed);
        }
      } catch (Exception e) {
        log.warn("Couldn't update feed from " + url, e);
    //#newsfeedcache.java:102: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:warn(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: void refreshFeeds()
    //#    unanalyzed callee: void org.apache.commons.logging.Log:warn(Object, Throwable)
      }
    }

    for (String blogId : subscriptions.keySet()) {
      List<NewsFeedEntry> entriesForBlog = new LinkedList<NewsFeedEntry>();
      for (String url : getUrls(blogId)) {
        entriesForBlog.addAll(feeds.get(url).getEntries());
      }

      Collections.sort(entriesForBlog, new NewsFeedEntryComparator());

      if (entriesForBlog.size() > FEED_ENTRY_LIMIT) {
        entriesForBlog = entriesForBlog.subList(0, FEED_ENTRY_LIMIT);
      }

      entries.put(blogId, entriesForBlog);
    }
  }
    //#newsfeedcache.java:120: end of method: void net.sourceforge.pebble.aggregator.NewsFeedCache.refreshFeeds()

  private NewsFeed updateFeed(String url) {
    NewsFeed feed = new NewsFeed(url);
    //#newsfeedcache.java:123: method: NewsFeed net.sourceforge.pebble.aggregator.NewsFeedCache.updateFeed(String)
    //#input(NewsFeed updateFeed(String)): log
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeed]
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.add(Lnet/sourceforge/pebble/aggregator/NewsFeedEntry;)V
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.setLink(Ljava/lang/String;)V
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeed.__Dispatch_Table.setTitle(Ljava/lang/String;)V
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeedEntry]
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Descendant_Table[others]
    //#input(NewsFeed updateFeed(String)): net/sourceforge/pebble/aggregator/NewsFeedEntry.__Dispatch_Table.setFeed(Lnet/sourceforge/pebble/aggregator/NewsFeed;)V
    //#input(NewsFeed updateFeed(String)): url
    //#output(NewsFeed updateFeed(String)): new LinkedList(NewsFeed#1) num objects
    //#output(NewsFeed updateFeed(String)): new NewsFeed(updateFeed#1) num objects
    //#output(NewsFeed updateFeed(String)): return_value.__Tag
    //#output(NewsFeed updateFeed(String)): return_value.entries
    //#output(NewsFeed updateFeed(String)): return_value.link
    //#output(NewsFeed updateFeed(String)): return_value.timestamp
    //#output(NewsFeed updateFeed(String)): return_value.title
    //#output(NewsFeed updateFeed(String)): return_value.url
    //#output(NewsFeed updateFeed(String)): return_value
    //#new obj(NewsFeed updateFeed(String)): new LinkedList(NewsFeed#1)
    //#new obj(NewsFeed updateFeed(String)): new NewsFeed(updateFeed#1)
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.WireFeed:getFeedType(...)@150 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.WireFeed:getFeedType(...)@165 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Entry:getAlternateLinks(...)@175 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Entry:getAuthors(...)@190 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Entry:getAuthors(...)@190 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Entry:getContents(...)@180 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Entry:getSummary(...)@185 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Feed:getAlternateLinks(...)@168 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.atom.Feed:getEntries(...)@173 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.rss.Channel:getItems(...)@155 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.feed.rss.Item:getDescription(...)@159 != null
    //#presumption(NewsFeed updateFeed(String)): com.sun.syndication.io.WireFeedInput:build(...)@148 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.Iterator:next(...)@155 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.Iterator:next(...)@168 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.Iterator:next(...)@173 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.Iterator:next(...)@175 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.Iterator:next(...)@180 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.Iterator:next(...)@185 != null
    //#presumption(NewsFeed updateFeed(String)): java.util.List:get(...)@190 != null
    //#presumption(NewsFeed updateFeed(String)): org.apache.commons.logging.LogFactory:getLog(...)@60 != null
    //#post(NewsFeed updateFeed(String)): return_value == &new NewsFeed(updateFeed#1)
    //#post(NewsFeed updateFeed(String)): new LinkedList(NewsFeed#1) num objects == 1
    //#post(NewsFeed updateFeed(String)): new NewsFeed(updateFeed#1) num objects == 1
    //#post(NewsFeed updateFeed(String)): return_value.__Tag == net/sourceforge/pebble/aggregator/NewsFeed
    //#post(NewsFeed updateFeed(String)): return_value.entries == &new LinkedList(NewsFeed#1)
    //#post(NewsFeed updateFeed(String)): init'ed(return_value.link)
    //#post(NewsFeed updateFeed(String)): init'ed(return_value.timestamp)
    //#post(NewsFeed updateFeed(String)): init'ed(return_value.title)
    //#post(NewsFeed updateFeed(String)): return_value.url == url
    //#post(NewsFeed updateFeed(String)): init'ed(return_value.url)
    //#unanalyzed(NewsFeed updateFeed(String)): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(NewsFeed updateFeed(String)): Effects-of-calling:java.lang.System:currentTimeMillis
    //#unanalyzed(NewsFeed updateFeed(String)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(NewsFeed updateFeed(String)): Effects-of-calling:java.util.List:add
    //#test_vector(NewsFeed updateFeed(String)): com.sun.syndication.feed.WireFeed:getFeedType(...)@150: Addr_Set{null}, Inverse{null}
    //#test_vector(NewsFeed updateFeed(String)): com.sun.syndication.feed.WireFeed:getFeedType(...)@165: Addr_Set{null}, Inverse{null}
    //#test_vector(NewsFeed updateFeed(String)): java.lang.String:equals(...)@169: {0}, {1}
    //#test_vector(NewsFeed updateFeed(String)): java.lang.String:equals(...)@176: {0}, {1}
    //#test_vector(NewsFeed updateFeed(String)): java.lang.String:equals(...)@181: {0}, {1}
    //#test_vector(NewsFeed updateFeed(String)): java.lang.String:equals(...)@186: {0}, {1}
    //#test_vector(NewsFeed updateFeed(String)): java.lang.String:startsWith(...)@150: {0}, {1}
    //#test_vector(NewsFeed updateFeed(String)): java.lang.String:startsWith(...)@165: {0}, {1}
    //#test_vector(NewsFeed updateFeed(String)): java.util.Iterator:hasNext(...)@168: {1}, {0}
    //#test_vector(NewsFeed updateFeed(String)): java.util.Iterator:hasNext(...)@173: {1}, {0}
    //#test_vector(NewsFeed updateFeed(String)): java.util.Iterator:hasNext(...)@175: {1}, {0}
    //#test_vector(NewsFeed updateFeed(String)): java.util.Iterator:hasNext(...)@180: {1}, {0}
    //#test_vector(NewsFeed updateFeed(String)): java.util.Iterator:hasNext(...)@185: {1}, {0}

    try {
      log.debug("Refreshing feed from " + url);
    //#newsfeedcache.java:126: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:debug(Object)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:debug(Object)

//      SyndFeedInput input = new SyndFeedInput(true);
//      SyndFeed sf = input.build(new XmlReader(new URL(url)));
//
//      feed.setTitle(sf.getTitle());
//      feed.setLink(sf.getLink());
//
//        for (SyndEntry se : (List<SyndEntry>)sf.getEntries()) {
//          log.info(se);
//          NewsFeedEntry fe = new NewsFeedEntry(
//              se.getLink(),
//              se.getTitle(),
//              se.getDescription() != null ? se.getDescription().getValue() : "",
//              se.getAuthor(),
//              se.getPublishedDate()
//          );
//          feed.add(fe);
//          log.info(fe);
//        }

      WireFeedInput input = new WireFeedInput(true);
    //#newsfeedcache.java:147: Warning: method not available
    //#    -- call on void com.sun.syndication.io.WireFeedInput(bool)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: void com.sun.syndication.io.WireFeedInput(bool)
      WireFeed wf = input.build(new XmlReader(new URL(url)));
    //#newsfeedcache.java:148: Warning: method not available
    //#    -- call on void com.sun.syndication.io.XmlReader(URL)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: void com.sun.syndication.io.XmlReader(URL)
    //#newsfeedcache.java:148: Warning: method not available
    //#    -- call on WireFeed com.sun.syndication.io.WireFeedInput:build(Reader)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: WireFeed com.sun.syndication.io.WireFeedInput:build(Reader)

      if (wf.getFeedType() != null && wf.getFeedType().startsWith("rss")) {
    //#newsfeedcache.java:150: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.WireFeed:getFeedType()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.WireFeed:getFeedType()
        Channel rssFeed = (Channel)wf;
        feed.setTitle(rssFeed.getTitle());
    //#newsfeedcache.java:152: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.rss.Channel:getTitle()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.rss.Channel:getTitle()
        feed.setLink(rssFeed.getLink());
    //#newsfeedcache.java:153: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.rss.Channel:getLink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.rss.Channel:getLink()

        for (Item item : (List<Item>)rssFeed.getItems()) {
    //#newsfeedcache.java:155: Warning: method not available
    //#    -- call on List com.sun.syndication.feed.rss.Channel:getItems()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: List com.sun.syndication.feed.rss.Channel:getItems()
          NewsFeedEntry fe = new NewsFeedEntry(
              item.getLink(),
    //#newsfeedcache.java:157: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.rss.Item:getLink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.rss.Item:getLink()
              item.getTitle(),
    //#newsfeedcache.java:158: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.rss.Item:getTitle()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.rss.Item:getTitle()
              item.getDescription() != null ? item.getDescription().getValue() : "",
    //#newsfeedcache.java:159: Warning: method not available
    //#    -- call on Description com.sun.syndication.feed.rss.Item:getDescription()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: Description com.sun.syndication.feed.rss.Item:getDescription()
    //#newsfeedcache.java:159: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.rss.Description:getValue()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.rss.Description:getValue()
              item.getAuthor(),
    //#newsfeedcache.java:160: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.rss.Item:getAuthor()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.rss.Item:getAuthor()
              item.getPubDate()
    //#newsfeedcache.java:161: Warning: method not available
    //#    -- call on Date com.sun.syndication.feed.rss.Item:getPubDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: Date com.sun.syndication.feed.rss.Item:getPubDate()
          );
          feed.add(fe);
        }
      } else if (wf.getFeedType() != null && wf.getFeedType().startsWith("atom")) {
    //#newsfeedcache.java:165: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.WireFeed:getFeedType()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.WireFeed:getFeedType()
        com.sun.syndication.feed.atom.Feed atomFeed = (com.sun.syndication.feed.atom.Feed)wf;
        feed.setTitle(atomFeed.getTitle());
    //#newsfeedcache.java:167: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Feed:getTitle()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Feed:getTitle()
        for (Link link : (List<Link>)atomFeed.getAlternateLinks()) {
    //#newsfeedcache.java:168: Warning: method not available
    //#    -- call on List com.sun.syndication.feed.atom.Feed:getAlternateLinks()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: List com.sun.syndication.feed.atom.Feed:getAlternateLinks()
          if ("text/html".equals(link.getType()))
    //#newsfeedcache.java:169: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Link:getType()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Link:getType()
            feed.setLink(link.getHref());
    //#newsfeedcache.java:170: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Link:getHref()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Link:getHref()
        }

        for (Entry entry : (List<Entry>)atomFeed.getEntries()) {
    //#newsfeedcache.java:173: Warning: method not available
    //#    -- call on List com.sun.syndication.feed.atom.Feed:getEntries()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: List com.sun.syndication.feed.atom.Feed:getEntries()
          String href = "";
          for (Link link : (List<Link>)entry.getAlternateLinks()) {
    //#newsfeedcache.java:175: Warning: method not available
    //#    -- call on List com.sun.syndication.feed.atom.Entry:getAlternateLinks()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: List com.sun.syndication.feed.atom.Entry:getAlternateLinks()
            if ("text/html".equals(link.getType()))
    //#newsfeedcache.java:176: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Link:getType()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Link:getType()
              href = link.getHref();
    //#newsfeedcache.java:177: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Link:getHref()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Link:getHref()
          }
          String body = null;
          for (Content content : (List<Content>)entry.getContents()) {
    //#newsfeedcache.java:180: Warning: method not available
    //#    -- call on List com.sun.syndication.feed.atom.Entry:getContents()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: List com.sun.syndication.feed.atom.Entry:getContents()
            if ("html".equals(content.getType()))
    //#newsfeedcache.java:181: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Content:getType()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Content:getType()
              body = content.getValue();
    //#newsfeedcache.java:182: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Content:getValue()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Content:getValue()
          }
          if (body == null) {
            for (Content content : (List<Content>)entry.getSummary()) {
    //#newsfeedcache.java:185: Warning: method not available
    //#    -- call on Content com.sun.syndication.feed.atom.Entry:getSummary()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: Content com.sun.syndication.feed.atom.Entry:getSummary()
              if ("html".equals(content.getType()))
    //#newsfeedcache.java:186: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Content:getType()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Content:getType()
                body = content.getValue();
    //#newsfeedcache.java:187: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Content:getValue()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Content:getValue()
            }
          }
          String author = entry.getAuthors() != null && entry.getAuthors().size() > 0 ? entry.getAuthors().get(0).toString() : "";
    //#newsfeedcache.java:190: Warning: method not available
    //#    -- call on List com.sun.syndication.feed.atom.Entry:getAuthors()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: List com.sun.syndication.feed.atom.Entry:getAuthors()
          NewsFeedEntry fe = new NewsFeedEntry(
              href,
              entry.getTitle(),
    //#newsfeedcache.java:193: Warning: method not available
    //#    -- call on String com.sun.syndication.feed.atom.Entry:getTitle()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: String com.sun.syndication.feed.atom.Entry:getTitle()
              body,
              author,
              entry.getPublished()
    //#newsfeedcache.java:196: Warning: method not available
    //#    -- call on Date com.sun.syndication.feed.atom.Entry:getPublished()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: Date com.sun.syndication.feed.atom.Entry:getPublished()
          );
          feed.add(fe);
        }
      }

      log.debug("Refreshed feed from " + url);
    //#newsfeedcache.java:202: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:debug(Object)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:debug(Object)
    } catch (FeedException e) {
      log.warn("Error while updating feed from " + url, e);
    //#newsfeedcache.java:204: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:warn(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:warn(Object, Throwable)
    } catch (IOException e) {
      log.warn("Error while updating feed from " + url, e);
    //#newsfeedcache.java:206: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:warn(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.aggregator.NewsFeedCache
    //#    method: NewsFeed updateFeed(String)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:warn(Object, Throwable)
    }

    return feed;
    //#newsfeedcache.java:209: end of method: NewsFeed net.sourceforge.pebble.aggregator.NewsFeedCache.updateFeed(String)
  }

  public NewsFeed getFeed(String url) {
    return feeds.get(url);
    //#newsfeedcache.java:213: method: NewsFeed net.sourceforge.pebble.aggregator.NewsFeedCache.getFeed(String)
    //#input(NewsFeed getFeed(String)): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[net/sourceforge/pebble/aggregator/NewsFeed]
    //#input(NewsFeed getFeed(String)): net/sourceforge/pebble/aggregator/NewsFeed.__Descendant_Table[others]
    //#input(NewsFeed getFeed(String)): this
    //#input(NewsFeed getFeed(String)): this.feeds
    //#input(NewsFeed getFeed(String)): url
    //#output(NewsFeed getFeed(String)): return_value
    //#pre[2] (NewsFeed getFeed(String)): this.feeds != null
    //#presumption(NewsFeed getFeed(String)): java.util.Map:get(...).__Tag@213 == net/sourceforge/pebble/aggregator/NewsFeed
    //#post(NewsFeed getFeed(String)): init'ed(return_value)
    //#newsfeedcache.java:213: end of method: NewsFeed net.sourceforge.pebble.aggregator.NewsFeedCache.getFeed(String)
  }

  public List<NewsFeedEntry> getNewsFeedEntries(Blog blog) {
    List<NewsFeedEntry> list = entries.get(blog.getId());
    //#newsfeedcache.java:217: method: List net.sourceforge.pebble.aggregator.NewsFeedCache.getNewsFeedEntries(Blog)
    //#input(List getNewsFeedEntries(Blog)): blog
    //#input(List getNewsFeedEntries(Blog)): blog.__Tag
    //#input(List getNewsFeedEntries(Blog)): blog.id
    //#input(List getNewsFeedEntries(Blog)): net/sourceforge/pebble/domain/Blog.__Descendant_Table[net/sourceforge/pebble/domain/Blog]
    //#input(List getNewsFeedEntries(Blog)): net/sourceforge/pebble/domain/Blog.__Descendant_Table[others]
    //#input(List getNewsFeedEntries(Blog)): net/sourceforge/pebble/domain/Blog.__Dispatch_Table.getId()Ljava/lang/String;
    //#input(List getNewsFeedEntries(Blog)): this
    //#input(List getNewsFeedEntries(Blog)): this.entries
    //#output(List getNewsFeedEntries(Blog)): new LinkedList(getNewsFeedEntries#1) num objects
    //#output(List getNewsFeedEntries(Blog)): return_value
    //#new obj(List getNewsFeedEntries(Blog)): new LinkedList(getNewsFeedEntries#1)
    //#pre[1] (List getNewsFeedEntries(Blog)): blog != null
    //#pre[2] (List getNewsFeedEntries(Blog)): blog.__Tag == net/sourceforge/pebble/domain/Blog
    //#pre[3] (List getNewsFeedEntries(Blog)): init'ed(blog.id)
    //#pre[5] (List getNewsFeedEntries(Blog)): this.entries != null
    //#post(List getNewsFeedEntries(Blog)): return_value != null
    //#post(List getNewsFeedEntries(Blog)): new LinkedList(getNewsFeedEntries#1) num objects <= 1
    //#test_vector(List getNewsFeedEntries(Blog)): java.util.Map:get(...)@217: Inverse{null}, Addr_Set{null}
    if (list == null) {
      list = new LinkedList<NewsFeedEntry>();
    }

    return list;
    //#newsfeedcache.java:222: end of method: List net.sourceforge.pebble.aggregator.NewsFeedCache.getNewsFeedEntries(Blog)
  }

  private Set<String> getUrls(String blogId) {
    Set<String> urls = subscriptions.get(blogId);
    //#newsfeedcache.java:226: method: Set net.sourceforge.pebble.aggregator.NewsFeedCache.getUrls(String)
    //#input(Set getUrls(String)): blogId
    //#input(Set getUrls(String)): this
    //#input(Set getUrls(String)): this.subscriptions
    //#output(Set getUrls(String)): new HashSet(getUrls#1) num objects
    //#output(Set getUrls(String)): return_value
    //#new obj(Set getUrls(String)): new HashSet(getUrls#1)
    //#pre[3] (Set getUrls(String)): this.subscriptions != null
    //#post(Set getUrls(String)): return_value != null
    //#post(Set getUrls(String)): new HashSet(getUrls#1) num objects <= 1
    //#test_vector(Set getUrls(String)): java.util.Map:get(...)@226: Inverse{null}, Addr_Set{null}
    if (urls == null) {
      urls = new HashSet<String>();
      subscriptions.put(blogId, urls);
    }

    return urls;
    //#newsfeedcache.java:232: end of method: Set net.sourceforge.pebble.aggregator.NewsFeedCache.getUrls(String)
  }

}
    //#newsfeedcache.java:: end of class: net.sourceforge.pebble.aggregator.NewsFeedCache
