Package com.metadot.book.connectr.server.domain

Source Code of com.metadot.book.connectr.server.domain.FeedIndex

/**
* Copyright 2010 Daniel Guermeur and Amy Unruh
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*
*   See http://connectrapp.appspot.com/ for a demo, and links to more information
*   about this app and the book that it accompanies.
*/
package com.metadot.book.connectr.server.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.net.URL;

import javax.jdo.JDOCanRetryException;
import javax.jdo.PersistenceManager;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

import javax.jdo.annotations.PrimaryKey;

import com.metadot.book.connectr.server.PMF;
import com.metadot.book.connectr.server.domain.StreamItem;
import com.metadot.book.connectr.server.utils.Utils;
import com.metadot.book.connectr.server.utils.ChannelServer;
import com.metadot.book.connectr.shared.messages.ContentAvailableMessage;

import com.sun.syndication.fetcher.impl.SyndFeedInfo;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import javax.jdo.Transaction;
import java.util.logging.*;


/**
* The FeedIndex persistence-capable class is used in conjunction with the FeedInfo class
* to store feed information in the Datastore.  This class points to the Friend object(s)
* for which this feed was specified.
* (See the book which accompanies this app for more information
* about the FeedIndex/FeedInfo design).
*/
@SuppressWarnings("serial")
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class FeedIndex implements Serializable {

  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;
 
  @Persistent
  private Set<String> friendKeys;
 
  private static Logger logger = Logger.getLogger(FeedIndex.class.getName());
  private static final int NUM_RETRIES = 5; // number of times to retry a failed transaction
 
  public FeedIndex(String fkey, String url) {
    this.friendKeys = new HashSet<String>();
    this.friendKeys.add(fkey);
    KeyFactory.Builder keyBuilder =
      new KeyFactory.Builder(FeedInfo.class.getSimpleName(), url);
    keyBuilder.addChild(FeedIndex.class.getSimpleName(), url);
    // make the child key
    Key ckey = keyBuilder.getKey();
    this.key = ckey;
  }

  public void setKey(Key key) {
      this.key = key;
  }
 
  public Key getKey() {
    return key;
  }

 
  private Set<String> getFriendKeys() {
    return friendKeys;
  }

  private void addFriendKey(String fkey) {
    this.friendKeys.add(fkey);
  }
 
  /**
   * used for existing Friend objects, with existing URLs lists.
   */
  public static Set<String> updateFeedURLs (Set<String> newurls, Set<String> origUrls, String id, boolean replace) {
    if (id == null || newurls == null || origUrls == null ) {
      return null;
    }
    Set<String> added = new HashSet<String>(newurls);
    added.removeAll(origUrls);
    Set<String> badUrls = FeedIndex.addFeedsFriend(added, id);
    if (replace) {
      Set<String> removed = new HashSet<String>(origUrls);
      removed.removeAll(newurls);
      FeedIndex.removeFeedsFriend(removed, id);
    }
    return badUrls;
  }

  /**
   * used for new Friends, with no existing urls
   */
  public static Set<String> addFeedURLs (Set<String> urls, String id) {
    if (id == null || urls == null) {
      return null;
    }
    Set<String> badUrls = FeedIndex.addFeedsFriend(urls, id);
    return badUrls;
  }


  /**
   * Query for a feed index with the given URL
   */
  public static FeedIndex findFeedIndex(String url, PersistenceManager pm) {
    FeedIndex fi = null;
    // query for a feed index with that url
    try {
      KeyFactory.Builder keyBuilder = new KeyFactory.Builder(FeedInfo.class.getSimpleName(), url);
      keyBuilder.addChild(FeedIndex.class.getSimpleName(), url);
      Key ckey = keyBuilder.getKey();
      fi = pm.getObjectById(FeedIndex.class, ckey);
    }
    catch (javax.jdo.JDOObjectNotFoundException e) {
      logger.warning(e.getMessage());
    }
    return fi;
  }
   
  public static void removeFeedsFriend(Set<String> urls, String fkey) {

      for (String url : urls) {
        removeFeedFriend(url, fkey);
      }
  }

  public static void removeFeedFriend(String urlstring, String fkey) {

    Transaction tx = null;
    // logger.fine("in removeFeedFriend, removing: " + urlstring);
    PersistenceManager pm = PMF.getTxnPm();
   
    try {
      for (int i = 0; i < NUM_RETRIES; i++) {
        tx = pm.currentTransaction();
        tx.begin();
        FeedIndex findex = findFeedIndex(urlstring, pm);
        if (findex != null) {
          Set<String> fkeys = findex.getFriendKeys();
          fkeys.remove(fkey);
          if (fkeys.isEmpty()) {
            // logger.fine("orphaned feed - deleting - " + urlstring);
            // then delete parent
            pm.deletePersistent(pm.getObjectById(FeedInfo.class, findex.getKey().getParent()));
            // then delete index obj
            pm.deletePersistent(findex);
          }
          else {
            // update the set of users associated with this feed
            FeedInfo feedInfo = pm.getObjectById(FeedInfo.class, urlstring);
            Set<Long> ukeys = findex.findUkeys();
            feedInfo.setUkeys(ukeys);
          }
          pm.makePersistent(findex);
          try {
            tx.commit();
            break;
          }
          catch (JDOCanRetryException e1) {
            if (i == (NUM_RETRIES - 1)) {
              throw e1;
            }
          }
        }
      } // end for
    }
    finally {
      if (tx.isActive()) {
        tx.rollback();
      }
      pm.close();
    }
  }
 
  public static Set<String> addFeedsFriend(Set<String> urls, String fkey) {

    boolean status;
    Set<String> badUrls = new HashSet<String>();
    PersistenceManager pm = PMF.getNonTxnPm();
    try {
      for (String url: urls) {
        try {
          status = FeedIndex.addFeedFriend(url, fkey);
          if (status == false) { // then malformed url or some issue with the feed
            badUrls.add(url);
          }
        }
        catch (Exception e) { // treat url as bad if anything else goes wrong
          // [if timeout issue on initial add, user can try again to add feed later]
          badUrls.add(url);
        }
      } // end for
      // push display of the new content
      // first, get parent user.
      Friend f = pm.getObjectById(Friend.class, fkey);
      UserAccount parent_user = f.getUser();
      // then trigger the notification, if the channel server is enabled.
      if (ChannelServer.channelAPIEnabled()) {
        logger.info("pushing 'new content' notification");
        ChannelServer.pushMessage(parent_user, new ContentAvailableMessage());
      }
    }
    finally {
      pm.close();
    }
    return badUrls;
  }
 

    /**
     * Add a feed for the given Friend.
     * Build a new feed object if necessary, otherwise add the
     * Friend's key (fkey) to existing feedinfo object
     */
    public static boolean addFeedFriend(String urlstring, String fkey) {

      FeedInfo feedInfo = null;

      FeedIndex findex = null;
      Transaction tx = null;
      boolean status = false;
      SyndFeedInfo fi = null;
     
      PersistenceManager pm = PMF.getTxnPm();
      PersistenceManager pm2 = PMF.getNonTxnPm();

      try {
        for (int i = 0; i < NUM_RETRIES; i++) {
          tx = pm.currentTransaction();
          tx.begin();
          // first just check if the url is valid -- if it's not, nothing else to do.
          URL url = new URL(urlstring);
          logger.fine("looking for feedindex for " + urlstring);
          findex = findFeedIndex(urlstring, pm);
          if (findex == null) {
            // then build new
            logger.fine("building new feed for " + urlstring);
            fi = FeedInfo.feedFetcher.retrieveFeedInfo(url, null);
            // create parent
            feedInfo = new FeedInfo(fi, urlstring, fkey);
            pm.makePersistent(feedInfo);
            // create child
            findex = new FeedIndex(fkey, urlstring);
            pm.makePersistent(findex);
          }
          else {
            findex.addFriendKey(fkey);
            pm.makePersistent(findex);
          }
          try {
            tx.commit();
            logger.fine("in addFeedFriend, commit was successful for " + urlstring);
            boolean np = false;
            if (feedInfo != null) {
              np = true;
            }
            feedInfo = pm2.getObjectById(FeedInfo.class, urlstring);
            // update the set of users associated with this feed
            Set<Long> ukeys = findex.findUkeys();
            feedInfo.setUkeys(ukeys);
            if (np) {
              // build the stream items for the new feed.
              StreamItem.buildItems(feedInfo, pm2);
            }
            else {
              feedInfo.updateRequestedFeed(pm2);
            }
            status = true;
            break;
          }
          catch (JDOCanRetryException e1) {
            logger.fine(Utils.stackTraceToString(e1));
            if (i == (NUM_RETRIES - 1)) {
              throw e1;
            }
          }
        } // end for
    }
    catch (Exception e) {
      e.printStackTrace();
      logger.fine(Utils.stackTraceToString(e));
      logger.warning(e.getMessage());
    }
    finally {
      if (tx.isActive()) {
        tx.rollback();
      }
      pm2.close();
      pm.close();
    }
    return status;
  }
 
  protected Set<Long> findUkeys() {

    Set<Long> ukeys = new HashSet<Long>();
    Long ukey;
    for (String fk : getFriendKeys()) {
      ukey = KeyFactory.stringToKey(fk).getParent().getId();
      ukeys.add(ukey);
    }
    return ukeys;
  }

} // end class
TOP

Related Classes of com.metadot.book.connectr.server.domain.FeedIndex

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.