Android Open Source - mailinglistmoderator Mailinglist Moderator






From Project

Back to project page mailinglistmoderator.

License

The source code is released under:

Copyright (c) 2010, Magnus Hagander All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:...

If you think the Android project mailinglistmoderator listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * MailinglistModerator.java - This class holds the main activity for the program.
 * /*from w ww .j av a 2  s .c  o m*/
 * Copyright (C) 2010 Magnus Hagander <magnus@hagander.net>
 * 
 * This software is released under the BSD license.
 */
package net.hagander.mailinglistmoderator;

import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Vector;

import net.hagander.mailinglistmoderator.backend.ListServer;
import net.hagander.mailinglistmoderator.glue.ListServerAdapter;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

/**
 * @author Magnus Hagander <magnus@hagander.net>
 * 
 */
public class MailinglistModerator extends ListActivity {
  public static Vector<ListServer> servers;
  private ListServerAdapter serverAdapter;
  private SharedPreferences prefs;

  /* Menu constants */
  private final int MENU_EDIT_SERVERS = 1;
  private final int MENU_REFRESH = 2;

  /* Return codes when calling sub-actions */
  private final int REQUEST_CODE_EDITSERVERS = 7;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());

    servers = new Vector<ListServer>();
    LoadServers();

    serverAdapter = new ListServerAdapter(this, R.layout.main_item, servers);
    setListAdapter(serverAdapter);

    ListView lv = getListView();

    /* Handle server clicks by launching the QueueListActivity */
    lv.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView<?> parent, View view,
          int position, long id) {
        ListServer s = serverAdapter.getItem(position);
        if (s.isExceptioned()) {
          /* Show the complete error message */
          new AlertDialog.Builder(MailinglistModerator.this)
            .setTitle("Failed to load")
            .setMessage(String.format("This list failed to load with the following exception:\n\n%s", s.getStatus()))
            .setPositiveButton("Ok", null)
            .show();
          return;
        }
        if (!s.isPopulated())
          return;

        /*
         * Ugly way to pass information to the QueueListActivity we're
         * going to start - pass it through a static method.
         */
        QueueListActivity.setServerInfo(s, MailinglistModerator.this);
        startActivity(new Intent(getApplicationContext(),
            QueueListActivity.class));
      }
    });

    /* Populate list of unmoderated messages in the background */
    populateServers();
  }

  /**
   * Load the list of servers from the application preferences. Doesn't
   * actually connect and populate information about the server, just loads
   * the list.
   * 
   * If there is a server list already, it's cleared and replaced with the new
   * one.
   */
  private void LoadServers() {
    servers.clear();

    for (Map.Entry<String, ?> entry : prefs.getAll().entrySet()) {
      // Any property that ends in _listname is considered one of our
      // servers.
      if (entry.getKey().endsWith("_listname")) {
        try {
          servers
              .add(ListServer.CreateFromPreference(prefs, entry
                  .getKey().substring(0,
                      entry.getKey().length() - 9)));
        } catch (Exception ex) {
          final String msg = ex.toString();
          /* FIXME: replace with alertbox! */
          runOnUiThread(new Runnable() {
            public void run() {
              Toast.makeText(getApplicationContext(), msg,
                  Toast.LENGTH_SHORT).show();
            }
          });
        }
      }

    }
  }

  /**
   * Notify that the list of servers has changed, and do so on the UI thread
   * to make it safe for calling from anywhere.
   */
  public void notifyServersChanged() {
    runOnUiThread(new Runnable() {
      public void run() {
        serverAdapter.notifyDataSetChanged();
      }
    });
  }

  /**
   * Populate all our servers with information about unmoderated messages, by
   * connecting to the server and enumerating.
   * 
   * All checking will be run in a background thread.
   */
  private void populateServers() {
    /*
     * Update the server list before we get started, since it may take a
     * while...
     */
    notifyServersChanged();

    Runnable r = new Runnable() {
      public void run() {
        Vector<Thread> threads = new Vector<Thread>();
        
        for (int i = 0; i < servers.size(); i++) {
          final ListServer s = servers.get(i);
          Thread t = new Thread(new Runnable() {
            public void run() {
              // TODO Auto-generated method stub
              try {
                s.Populate();
              } catch (Exception e) {
                final String msg = String.format("%s", e);
                runOnUiThread(new Runnable() {
                  public void run() {
                    // FIXME: find better way to report errors
                    Toast.makeText(getApplicationContext(), msg,
                        Toast.LENGTH_SHORT).show();
                  }
                });
              }

              /*
               * Since servers are sorted by number of messages, re-sort
               * the list when it has updated.
               * 
               * We run this once in each loop so that servers with
               * messages to moderate on will "bubble up" to the top as we
               * run.
               */
              sortServers();
            }
          });
          threads.add(t);
          t.start();
        }

        /*
         * Now wait until all threads are done, but join()ing on them
         */
        for (int i = 0; i < threads.size(); i++) {
          try {
            threads.get(i).join();
          } catch (InterruptedException e) {
          }
        }
      }
    };
    Thread t = new Thread(r, "ServerPopulatingThread");
    t.start();
  }

  private void sortServers() {
    Collections.sort(servers, new Comparator<ListServer>() {
      public int compare(ListServer server1,
          ListServer server2) {
        if (!server1.isPopulated()) {
          if (!server2.isPopulated()) {
            // Neither server is populated, sort by name
            return server1.getName().compareTo(server2.getName());
          }
          // server1 is not populated, server2 is ==> server2 is bigger
          return 1;
        }
        else if (!server2.isPopulated()) {
          // server2 is not populated, server1 is ==> server1 is bigger.
          return -1;
        }
        // Both servers are populated
        if (server2.count() == server1.count()) {
          // Count is identical, so compare by name
          return server1.getName().compareTo(server2.getName());
        }
        // Both servers have valid values, and they are not the same,
        // so return the comparison of them.
        return server2.count() - server1.count();
        }
    });

    notifyServersChanged();
  }

  /**
   * Create the menu for when the Menu button is pressed.
   */
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(0, MENU_REFRESH, 0, "Refresh");
    menu.add(0, MENU_EDIT_SERVERS, 1, "Servers...");
    return true;
  }

  /**
   * Handle selections in the main menu.
   */
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case MENU_EDIT_SERVERS:
      /*
       * Edit servers - so launch the ServerEditor activity. We need to
       * track the result of this activity, so we can reload the list when
       * it returns.
       */
      Intent i = new Intent(getApplicationContext(), ServerEditor.class);
      startActivityForResult(i, REQUEST_CODE_EDITSERVERS);
      return true;
    case MENU_REFRESH:
      /* Refresh the server list */
      LoadServers();
      populateServers();
      return true;
    }
    return false;
  }

  /**
   * Callback for whenever a sub-activity finishes.
   */
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE_EDITSERVERS) {
      /*
       * The closed activity is our ServerEditor one.
       * 
       * It will return resultCode=2 if it has added a new server, in
       * which case we just want to restart the Activity so it'll pick up
       * the new entry.
       * 
       * In all other cases, just reload all the servers in case any vital
       * configuration has changed.
       */
      if (resultCode == 2) {
        Intent i = new Intent(getApplicationContext(),
            ServerEditor.class);
        startActivityForResult(i, REQUEST_CODE_EDITSERVERS);
      } else {
        LoadServers();
        populateServers();
      }
    }
  }
}




Java Source Code List

net.hagander.mailinglistmoderator.MailinglistModerator.java
net.hagander.mailinglistmoderator.MessageViewActivity.java
net.hagander.mailinglistmoderator.QueueListActivity.java
net.hagander.mailinglistmoderator.ServerEditor.java
net.hagander.mailinglistmoderator.backend.ListServer.java
net.hagander.mailinglistmoderator.backend.MailMessage.java
net.hagander.mailinglistmoderator.backend.providers.Dummy.java
net.hagander.mailinglistmoderator.backend.providers.Mailman.java
net.hagander.mailinglistmoderator.backend.providers.Majordomo2.java
net.hagander.mailinglistmoderator.backend.providers.Unconfigured.java
net.hagander.mailinglistmoderator.glue.ListServerAdapter.java
net.hagander.mailinglistmoderator.glue.MailMessageAdapter.java
net.hagander.mailinglistmoderator.preferences.SSLCertDialogPreference.java