// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2006 by R. Pito Salas // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software Foundation; // either version 2 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with this program; // if not, write to the Free Software Foundation, Inc., 59 Temple Place, // Suite 330, Boston, MA 02111-1307 USA // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: RecalculateAction.java,v 1.5 2008/02/28 10:50:24 spyromus Exp $ // package com.salas.bb.sentiments; import com.jgoodies.uif.AbstractDialog; import com.salas.bb.core.GlobalController; import com.salas.bb.core.GlobalModel; import com.salas.bb.core.SearchFeedsManager; import com.salas.bb.domain.*; import com.salas.bb.utils.i18n.Strings; import com.salas.bb.utils.swingworker.SwingWorker; import com.salas.bb.utils.uif.ProgressPanel; import com.salas.bb.utils.uif.UifUtilities; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; /** * Recalculates all sentiments showing a nice progress dialog. */ public class RecalculateAction extends AbstractAction { private static RecalculateAction instance; /** Hidden singleton constructor. */ private RecalculateAction() { } /** * Returns an instance. * * @return instance. */ public static synchronized RecalculateAction getInstance() { if (instance == null) instance = new RecalculateAction(); return instance; } /** * Activates an action. * * @param onlyConnotation TRUE if expressions didn't change and we need to update only connotations. * * @throws IllegalStateException if called not from within EDT. */ public static void perform(boolean onlyConnotation) { if (!Calculator.getConfig().isEnabled()) return; if (!UifUtilities.isEDT()) throw new IllegalStateException("Not in EDT"); getInstance().actionPerformed(new ActionEvent(instance, 1, Boolean.toString(onlyConnotation))); } /** * Invoked to activate this action. * * @param e action. */ public void actionPerformed(ActionEvent e) { boolean onlyConnotation = Boolean.parseBoolean(e.getActionCommand()); GuidesSet set = GlobalModel.SINGLETON.getGuidesSet(); List<IFeed> feeds = set.getFeeds(); // Create progress dialog ProgressDialog dialog = new ProgressDialog(GlobalController.SINGLETON.getMainFrame()); // Create recalculator and subscribe the dialog to events Recalculator rec = new Recalculator(feeds, onlyConnotation); rec.addPropertyChangeListener(dialog); rec.execute(); } /** * Progress dialog. */ private class ProgressDialog extends AbstractDialog implements PropertyChangeListener { private static final long MAX_INVISIBLE_TIME = 100; // Stay invisible maximum for 2 seconds private final ProgressPanel pnlProgress; private long startedAt; /** * Creates a progress dialog. * * @param owner owner frame. */ public ProgressDialog(Frame owner) { super(owner, Strings.message("sentiment.analysis")); pnlProgress = new ProgressPanel(Strings.message("scanning.articles")); } /** * Returns the content. * * @return content. */ protected JComponent buildContent() { return pnlProgress; } /** * Invoked when the state or progress changes. * * @param evt event. */ public void propertyChange(PropertyChangeEvent evt) { String prop = evt.getPropertyName(); if ("state".equals(prop)) onState((SwingWorker.StateValue)evt.getNewValue()); else if ("progress".equals(prop)) onProgress((Integer)evt.getNewValue()); } /** * Invoked when state of the recalculation changes. * * @param state new state. */ private void onState(SwingWorker.StateValue state) { switch (state) { case STARTED: startedAt = System.currentTimeMillis(); break; case DONE: // Hide dialog when done close(); break; } } /** * Invoked when the scanner progress changes. * * @param progress [0 - 100]. */ private void onProgress(int progress) { long now = System.currentTimeMillis(); if (now - startedAt > MAX_INVISIBLE_TIME) open(); pnlProgress.setProgress(progress); } } /** * Recalculates feed article sentiments in the background. */ private static class Recalculator extends SwingWorker<Long, Integer> { private static final double MAX_PERCENT = 100.0; private static final double SEARCH_FEED_PERCENT = 20.0; private final List<IFeed> feeds; private boolean onlyConnotation; /** * Creates recalculator. * * @param feeds feeds. * @param onlyConnotation TRUE to update only connotation information. */ public Recalculator(List<IFeed> feeds, boolean onlyConnotation) { this.feeds = feeds; this.onlyConnotation = onlyConnotation; } /** * Calculate and report. * * @return total number of articles scanned. * * @throws Exception if anything fails. */ protected Long doInBackground() throws Exception { double feedPercents = MAX_PERCENT; double searchFeedPercents = 0; // See if there are any smart feeds to update and adjust the percents List<SearchFeed> searchFeeds = SearchFeedsManager.findFeedsWithSentimentsClause(); if (!searchFeeds.isEmpty()) { searchFeedPercents = SEARCH_FEED_PERCENT; feedPercents -= searchFeedPercents; } long articles = 0; int total = feeds.size(); double kf = feedPercents / total; double ksf = searchFeedPercents / Math.max(1, searchFeeds.size()); // Update all feeds first int count = 0; for (IFeed feed : feeds) { articles += recalculate(feed); count++; setProgress((int)(kf * count)); } // Update all search feeds now count = 0; for (SearchFeed feed : searchFeeds) { SearchFeedsManager.update(feed); count++; setProgress((int)(ksf * count + feedPercents)); } return articles; } /** * Recalculate a feed. * * @param feed feed. * * @return number of processed articles. */ private int recalculate(IFeed feed) { // Scan only data feeds that hold physical articles if (!(feed instanceof DataFeed)) return 0; int articles; synchronized (feed) { articles = feed.getArticlesCount(); for (int i = 0; i < articles; i++) { IArticle article = feed.getArticleAt(i); if (onlyConnotation) { article.recalculateConnotation(); } else { article.recalculateSentimentCounts(); } } } return articles; } } public static void main(String[] args) { byte[] a = { 1,2,3 }; byte[] b = { 1,2,3 }; System.out.println(a.equals(b)); } }