Package org.rssowl.core.internal

Source Code of org.rssowl.core.internal.ApplicationServiceImpl

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2006 RSSOwl Development Team                                  **
**   http://www.rssowl.org/                                                 **
**                                                                          **
**   All rights reserved                                                    **
**                                                                          **
**   This program and the accompanying materials are made available under   **
**   the terms of the Eclipse Public License v1.0 which accompanies this    **
**   distribution, and is available at:                                     **
**   http://www.rssowl.org/legal/epl-v10.html                               **
**                                                                          **
**   A copy is found in the file epl-v10.html and important notices to the  **
**   license from the team is found in the textfile LICENSE.txt distributed **
**   in this package.                                                       **
**                                                                          **
**   This copyright notice MUST APPEAR in all copies of the file!           **
**                                                                          **
**   Contributors:                                                          **
**     RSSOwl Development Team - initial API and implementation             **
**                                                                          **
**  **********************************************************************  */

package org.rssowl.core.internal;

import org.rssowl.core.IApplicationService;
import org.rssowl.core.internal.persist.MergeResult;
import org.rssowl.core.internal.persist.News;
import org.rssowl.core.internal.persist.service.DBHelper;
import org.rssowl.core.internal.persist.service.DBManager;
import org.rssowl.core.internal.persist.service.DatabaseEvent;
import org.rssowl.core.internal.persist.service.DatabaseListener;
import org.rssowl.core.internal.persist.service.EventManager;
import org.rssowl.core.persist.IAttachment;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.IConditionalGet;
import org.rssowl.core.persist.IFeed;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.service.PersistenceException;
import org.rssowl.core.util.RetentionStrategy;

import com.db4o.ObjectContainer;
import com.db4o.ext.Db4oException;
import com.db4o.query.Query;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;

/**
* db4o implementation of IApplicationService
*/
public class ApplicationServiceImpl implements IApplicationService {
  private ObjectContainer fDb;
  private ReadWriteLock fLock;
  private Lock fWriteLock;

  /**
   * Creates an instance of this class.
   */
  public ApplicationServiceImpl() {
    DBManager.getDefault().addEntityStoreListener(new DatabaseListener() {
      public void databaseOpened(DatabaseEvent event) {
        fDb = event.getObjectContainer();
        fLock = event.getLock();
        fWriteLock = fLock.writeLock();
      }

      public void databaseClosed(DatabaseEvent event) {
        fDb = null;
      }
    });
  }

  /*
   * @see org.rssowl.core.model.dao.IApplicationLayer#handleFeedReload(org.rssowl.core.model.persist.IBookMark,
   * org.rssowl.core.model.persist.IFeed,
   * org.rssowl.core.model.persist.IConditionalGet, boolean)
   */
  public final void handleFeedReload(IBookMark bookMark, IFeed emptyFeed, IConditionalGet conditionalGet, boolean deleteConditionalGet) {
    fWriteLock.lock();
    try {
      /* Resolve reloaded Feed */
      IFeed feed = bookMark.getFeedLinkReference().resolve();

      /* Copy over Properties to reloaded Feed to keep them */
      Map<String, ? > feedProperties = feed.getProperties();
      if (feedProperties != null) {
        feedProperties.entrySet();
        for (Map.Entry<String, ? > entry : feedProperties.entrySet())
          emptyFeed.setProperty(entry.getKey(), entry.getValue());
      }

      /* Merge with existing (remember number of added new news) */
      List<INews> newNewsBeforeMerge = feed.getNewsByStates(EnumSet.of(INews.State.NEW));
      MergeResult mergeResult = feed.mergeAndCleanUp(emptyFeed);
      List<INews> newNewsAdded = getNewNewsAdded(feed, newNewsBeforeMerge);
      updateStateOfUnsavedNewNews(newNewsAdded);

      /* Retention Policy */
      List<INews> deletedNews = RetentionStrategy.process(bookMark, feed, newNewsAdded.size());

      for (INews news : deletedNews)
        mergeResult.addUpdatedObject(news);

      saveFeed(mergeResult);

      /* Update Conditional GET */
      if (conditionalGet != null) {
        if (deleteConditionalGet)
          fDb.delete(conditionalGet);
        else
          fDb.ext().set(conditionalGet, 1);
      }
      fDb.commit();
    } catch (Db4oException e) {
      throw new PersistenceException(e);
    } finally {
      fWriteLock.unlock();
    }
    DBHelper.cleanUpAndFireEvents();
  }

  private List<INews> getNewNewsAdded(IFeed feed, List<INews> newNewsBeforeMerge) {
    List<INews> newNewsAdded = feed.getNewsByStates(EnumSet.of(INews.State.NEW));
    newNewsAdded.removeAll(newNewsBeforeMerge);
    return newNewsAdded;
  }

  private <T> List<T> activateAll(List<T> list) {
    for (T o : list)
      fDb.ext().activate(o, Integer.MAX_VALUE);

    return list;
  }

  private void updateStateOfUnsavedNewNews(List<INews> news) {
    for (INews newsItem : news) {
      List<INews> equivalentNews = Collections.emptyList();
      if (newsItem.getGuid() != null)
        equivalentNews = getNewsFromGuid(newsItem);
      else if (newsItem.getLink() != null)
        equivalentNews = getNewsFromLink(newsItem);

      if (!equivalentNews.isEmpty())
        newsItem.setState(equivalentNews.get(0).getState());
    }
  }

  @SuppressWarnings("unchecked")
  private List<INews> getNewsFromLink(INews newsItem) {
    Query query = fDb.query();
    query.constrain(News.class);
    query.descend("fLinkText").constrain(newsItem.getLink().toString()); //$NON-NLS-1$
    return activateAll(query.execute());
  }

  @SuppressWarnings("unchecked")
  private List<INews> getNewsFromGuid(INews newsItem) {
    Query query = fDb.query();
    query.constrain(News.class);
    query.descend("fGuidValue").constrain(newsItem.getGuid().getValue()); //$NON-NLS-1$
    return activateAll(query.execute());
  }

  private void saveFeed(MergeResult mergeResult) {
    for (Object o : mergeResult.getRemovedObjects()) {
      /* We know that in these cases, the parent entity will be updated */
      if (o instanceof INews)
        EventManager.getInstance().addItemBeingDeleted(((INews) o).getFeedReference());
      else if (o instanceof IAttachment)
        EventManager.getInstance().addItemBeingDeleted(((IAttachment) o).getNews());

      fDb.delete(o);
    }

    List<Object> updatedEntities = new ArrayList<Object>(mergeResult.getUpdatedObjects());
    for (Object o : updatedEntities) {
      if (o instanceof INews)
        DBHelper.saveNews(fDb, (INews) o);
      else if (o instanceof IFeed)
        fDb.ext().set(o, 2);
      else
        fDb.ext().set(o, 1);
    }
  }
}
TOP

Related Classes of org.rssowl.core.internal.ApplicationServiceImpl

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.