Browse files

Initial Commit

  • Loading branch information...
0 parents commit 0022f2ae134ceceae981bc46da187bcf6b372cc6 @mohamedmansour committed Jun 23, 2010
Showing with 641 additions and 0 deletions.
  1. +16 −0 .classpath
  2. +3 −0 .gitignore
  3. +17 −0 .project
  4. +12 −0 .settings/org.eclipse.jdt.core.prefs
  5. +14 −0 README.md
  6. +124 −0 build.xml
  7. +19 −0 src/ContactsFoundCallback.java
  8. +173 −0 src/ContactsPanel.java
  9. +91 −0 src/GoogleContactsAPI.java
  10. +80 −0 src/LoginPanel.java
  11. +37 −0 src/Main.java
  12. +55 −0 src/MainFrame.java
16 .classpath
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="lib" path="lib/gdata-appsforyourdomain-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/gdata-appsforyourdomain-meta-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/gdata-base-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/gdata-client-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/gdata-client-meta-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/gdata-contacts-3.0.jar" sourcepath="C:/Sandbox/Code/GoogleContactManager/gdata"/>
+ <classpathentry kind="lib" path="lib/gdata-contacts-meta-3.0.jar"/>
+ <classpathentry kind="lib" path="lib/gdata-core-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/google-collect-1.0-rc1.jar"/>
+ <classpathentry kind="lib" path="lib/jsr305.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
3 .gitignore
@@ -0,0 +1,3 @@
+bin
+output
+lib
17 .project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>GoogleContactsManager</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
12 .settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Tue Jun 22 20:16:17 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
14 README.md
@@ -0,0 +1,14 @@
+Google Contacts Manager in Java
+=================================
+
+> Test project to experiment how the the GData API for Java functions.
+> This project will expand to be somewhat like a Google Contacts Manager
+> The User Interface is done in plane Simple Swing for quick prototype.
+
+Note: You have to download the GData API from Google Code and place the libs
+in the /lib/ directory. Then run 'ant' to compile/build the jar, or build it from
+Eclipse. http://code.google.com/p/gdata-java-client/
+
+This depends on Java6
+
+By Mohamed Mansour (http://www.mohamedmansour.com)
124 build.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0"?>
+
+<project name="Client" default="build.client">
+ <!--**************************************************
+ PRE SETUP "MUST EDIT"
+ **************************************************-->
+ <!-- Source file location -->
+ <property name="client.src.location" location="src"/>
+ <!-- JAR Files Location -->
+ <property name="client.lib.location" location="lib"/>
+ <!-- Main Class execute -->
+ <property name="client.main" value="Main"/>
+ <!-- Main Class execute -->
+ <property name="client.jar.name" value="GoogleContactsViewer"/>
+
+
+ <!--
+
+ YOU DO NOT NEED TO EDIT THESE UNLESS YOU WANT TO
+
+ -->
+ <!-- DEBUG Status -->
+ <property name="debug" value="on" />
+ <!-- DEPRECATION Status -->
+ <property name="deprecation" value="off" />
+ <!-- JAVA Source Version -->
+ <property name="compile.version" value="1.5" />
+ <!-- JAVA Max Memory -->
+ <property name="compile.memory.max" value="300m"/>
+ <!-- JAVA Initial Memory -->
+ <property name="compile.memory.initial" value="64m"/>
+ <!--
+ DO NOT EDIT NEVER!!!!!
+ -->
+ <!-- Compiled soruce location -->
+ <property name="client.bin.location" location="bin"/>
+ <!--Output Location -->
+ <property name="client.output.location" location="output"/>
+ <!--Output LIB Location -->
+ <property name="client.output.lib.location" location="${client.output.location}/lib"/>
+ <!-- Compiled Jar Name -->
+ <property name="client.output.jar" location="${client.output.location}/${client.jar.name}.jar"/>
+
+ <!--
+ Abstract routine to JAVAC parameters
+ -->
+ <presetdef name="javac.ns">
+ <javac
+ debug="${debug}"
+ deprecation="${deprecation}"
+ includeAntRuntime="off"
+ memoryInitialSize="${compile.memory.initial}"
+ memoryMaximumSize="${compile.memory.max}"
+ fork="true"
+ failonerror="true"
+ source="${compile.version}"
+ target="${compile.version}"
+ taskname="javac">
+ </javac>
+ </presetdef>
+
+ <!--
+ Cleans client
+ -->
+ <target name="clean.client" description="Cleans client">
+ <delete dir="${client.output.location}" quiet="true"/>
+ <delete dir="${client.bin.location}" quiet="true"/>
+ </target>
+
+ <!--
+ Prepares Output
+ -->
+ <target name="prepare.output" description="Prepares Output">
+ <mkdir dir="${client.bin.location}"/>
+ <mkdir dir="${client.output.location}"/>
+ <mkdir dir="${client.output.lib.location}"/>
+ <copy todir="${client.output.lib.location}">
+ <fileset dir="${client.lib.location}"/>
+ </copy>
+ </target>
+
+ <!--
+ To JAR the class files in the bin folder
+ Includes the librarys as well!
+ -->
+ <path id="lib.path">
+ <fileset dir="${client.output.lib.location}" includes="**/*.jar" />
+ </path>
+
+ <!--
+ Compiles source files
+ -->
+ <target name="compile.client" depends="clean.client, prepare.output" description="Compiles client">
+ <javac.ns
+ destdir="${client.bin.location}"
+ classpathref="lib.path">
+ <src path="${client.src.location}"/>
+ </javac.ns>
+ </target>
+
+ <!--
+ To JAR the class files in the bin folder
+ Includes the librarys as well!
+ -->
+ <target name="build.client" depends="compile.client">
+ <!--
+ Classpath reference location
+ -->
+ <manifestclasspath property="client.manifest" jarfile="${client.output.jar}">
+ <classpath refid="lib.path" />
+ </manifestclasspath>
+
+ <!--
+ Lets JAR IT
+ -->
+ <jar jarfile="${client.output.jar}">
+ <fileset dir="${client.bin.location}" />
+ <manifest>
+ <attribute name="Main-Class" value="${client.main}"/>
+ <attribute name="Class-Path" value="${client.manifest}"/>
+ </manifest>
+ </jar>
+ </target>
+</project>
19 src/ContactsFoundCallback.java
@@ -0,0 +1,19 @@
+import java.util.List;
+
+import com.google.gdata.data.contacts.ContactEntry;
+
+/**
+ * Entries found callback to stat
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+public interface ContactsFoundCallback {
+
+ /**
+ * When a entry has been found it will fire this callback.
+ * @param index The number of items it has fetched.
+ * @param list The list of new items that were received.
+ */
+ public void itemsFound(int index, List<ContactEntry> list);
+}
173 src/ContactsPanel.java
@@ -0,0 +1,173 @@
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.SwingWorker;
+import javax.swing.table.DefaultTableModel;
+
+import com.google.gdata.data.contacts.ContactEntry;
+import com.google.gdata.data.extensions.Email;
+import com.google.gdata.data.extensions.PhoneNumber;
+
+
+/**
+ * Contacts Panel Card View.
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+public class ContactsPanel extends JPanel implements ActionListener {
+
+ private MainFrame frame;
+ private JProgressBar progressBar;
+ private JButton btnFetch;
+ private FetchEntries entriesTask;
+ private JLabel lblStatus;
+ private DefaultTableModel model;
+
+ public ContactsPanel(MainFrame frame) {
+ this.frame = frame;
+ initComponents();
+ setupEntriesTask();
+ }
+
+
+ private void initComponents() {
+ setLayout(new BorderLayout(5,5));
+
+ // Top Panel that contains Progress and Status Label.
+ JPanel topPanel = new JPanel(new BorderLayout(5,5));
+ lblStatus = new JLabel("Press Fetch below to get all Entries.");
+ topPanel.add(lblStatus, BorderLayout.WEST);
+ progressBar = new JProgressBar();
+ topPanel.add(progressBar, BorderLayout.CENTER);
+ progressBar.setVisible(false);
+ add(topPanel, BorderLayout.NORTH);
+
+ // Center Panel that contains the table.
+ JTable tableEntries = new JTable();
+ model = new DefaultTableModel(new Object[][]{}, new String[] {
+ "Name", "E-Mail", "Phone"
+ });
+ tableEntries.setModel(model);
+ add(new JScrollPane(tableEntries), BorderLayout.CENTER);
+
+ // Bottom Panel that contains the buttons.
+ btnFetch = new JButton("Fetch");
+ btnFetch.addActionListener(this);
+ add(btnFetch, BorderLayout.SOUTH);
+ }
+
+ /**
+ * Setup the Contact Entries task.
+ */
+ private void setupEntriesTask() {
+ entriesTask = new FetchEntries();
+
+ // Add a change listener so that we can update the progress bar.
+ entriesTask.addPropertyChangeListener(new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if ("progress".equals(evt.getPropertyName())) {
+ progressBar.setValue((Integer)evt.getNewValue());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // For now until we figure out what to do with optional buttons if we need it.
+ if (btnFetch.getText().equals("Fetch")) {
+ progressBar.setVisible(true);
+ btnFetch.setVisible(false);
+ entriesTask.execute();
+ }
+ }
+
+ /**
+ * Asynchronous Worker to fetch entries and update the progress bar.
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+ class FetchEntries extends SwingWorker<List<ContactEntry>, ContactEntry> {
+ // Keep track of how many contacts we fetched.
+ private int count;
+
+ @Override
+ protected List<ContactEntry> doInBackground() throws Exception {
+ count = 0;
+ final int totalEntries = GoogleContactsAPI.getInstance().getTotalEntries();
+ List<ContactEntry> r = GoogleContactsAPI.getInstance().getEntries(new ContactsFoundCallback() {
+ @Override
+ public void itemsFound(int index, List<ContactEntry> entries) {
+ // Publish the results to the table model.
+ publish(entries.toArray(new ContactEntry[0]));
+
+ // Make use of the SwingWorkers progress feature.
+ setProgress(100 * index / totalEntries);
+ }
+ });
+ return r;
+ }
+
+ @Override
+ protected void process(List<ContactEntry> chunks) {
+ count += chunks.size();
+
+ // Change the status to state how many contacts we fetched.
+ lblStatus.setText("Processed " + count + " contacts!");
+
+ // Append the entries to the table model.
+ for (ContactEntry entry : chunks) {
+ model.addRow(new String[] {
+ entry.getTitle().getPlainText(),
+ getEmails(entry.getEmailAddresses()),
+ getPhoneNumbers(entry.getPhoneNumbers()),
+ });
+ }
+ }
+
+ @Override
+ protected void done() {
+ progressBar.setVisible(false);
+ btnFetch.setText("Fetch");
+ }
+ }
+
+ /**
+ * Helper method to stringify the phonenumber listings.
+ * @param phonenumbers New phonenumbers to convert.
+ * @return String version of the phonenumbers.
+ */
+ private String getPhoneNumbers(List<PhoneNumber> phonenumbers) {
+ StringBuilder builder = new StringBuilder();
+ for (PhoneNumber phonenumber : phonenumbers) {
+ builder.append(phonenumber.getPhoneNumber() + ", ");
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Helper method to stringify the email listings.
+ * @param emails New emails to convert.
+ * @return String version of the emails.
+ */
+ private String getEmails(List<Email> emails) {
+ StringBuilder builder = new StringBuilder();
+ for (Email email : emails) {
+ builder.append(email.getAddress() + ", ");
+ }
+ return builder.toString();
+ }
+}
91 src/GoogleContactsAPI.java
@@ -0,0 +1,91 @@
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gdata.client.Query;
+import com.google.gdata.client.contacts.ContactsService;
+import com.google.gdata.data.contacts.ContactEntry;
+import com.google.gdata.data.contacts.ContactFeed;
+import com.google.gdata.util.AuthenticationException;
+
+/**
+ * Google Contacts API as a singleton.
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+public class GoogleContactsAPI {
+ private static GoogleContactsAPI obj;
+ private final ContactsService service;
+ private static final String DEFAULT_FEED = "http://www.google.com/m8/feeds/contacts/";
+ private URL feedUrl;
+
+ /**
+ * Single instance.
+ * @return This object.
+ */
+ public static GoogleContactsAPI getInstance() {
+ if (obj == null) {
+ obj = new GoogleContactsAPI();
+ }
+ return obj;
+ }
+
+ private GoogleContactsAPI() {
+ service = new ContactsService("Google-Contacts-Management");
+ }
+
+ /**
+ * Login into Google Accounts.
+ * @param username Your Google email address.
+ * @param password Your Google password.
+ * @return
+ */
+ public boolean Login(String username, String password) {
+ try {
+ service.setUserCredentials(username, password);
+ String url = DEFAULT_FEED + username + "/full";
+ feedUrl = new URL(url);
+ return true;
+ } catch (AuthenticationException e) {
+ return false;
+ } catch (MalformedURLException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Get the total contact entries.
+ * @return number of entries.
+ */
+ public int getTotalEntries() {
+ Query query = new Query(feedUrl);
+ try {
+ ContactFeed feed = service.query(query, ContactFeed.class);
+ return feed.getTotalResults();
+ } catch (Exception e) {
+ return 0;
+ }
+ }
+
+ /**
+ * Fetch all contacts.
+ * @param callback Callback that gets fired everytime a request has been recieved.
+ * @return List of contacts.
+ * @throws Exception In case an exception occurred.
+ */
+ public List<ContactEntry> getEntries(ContactsFoundCallback callback) throws Exception {
+ ContactFeed feed;
+ Query query = new Query(feedUrl);
+ List<ContactEntry> googleContacts = new ArrayList<ContactEntry>();
+ do {
+ feed = service.query(query, ContactFeed.class);
+ googleContacts.addAll(feed.getEntries());
+ query.setStartIndex(feed.getEntries().size() + query.getStartIndex());
+ callback.itemsFound(query.getStartIndex(), feed.getEntries());
+ } while (feed.getTotalResults() > query.getStartIndex());
+
+ return googleContacts;
+ }
+}
80 src/LoginPanel.java
@@ -0,0 +1,80 @@
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+/**
+ * Login Panel to Google Accounts.
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+public class LoginPanel extends JPanel implements ActionListener {
+ private MainFrame frame;
+ private JTextField txtUser;
+ private JTextField txtPassword;
+ private JButton btnLogin;
+
+ public LoginPanel(MainFrame frame) {
+ this.frame = frame;
+ initComponents();
+ }
+
+ private void initComponents() {
+ setLayout(new GridBagLayout());
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.insets = new Insets(2, 2, 2, 2);
+ add(new JLabel("Username: "), gbc);
+
+ txtUser = new JTextField();
+ txtUser.setPreferredSize(new Dimension(200, 25));
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ gbc.insets = new Insets(2, 2, 2, 2);
+ add(txtUser, gbc);
+
+ gbc = new GridBagConstraints();
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.insets = new Insets(2, 2, 2, 2);
+ add(new JLabel("Password: "), gbc);
+
+ txtPassword = new JTextField();
+ txtPassword.setPreferredSize(new Dimension(200, 25));
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 1;
+ gbc.insets = new Insets(2, 2, 2, 2);
+ add(txtPassword, gbc);
+
+ btnLogin = new JButton("Login");
+ gbc = new GridBagConstraints();
+ gbc.gridx = 1;
+ gbc.gridy = 2;
+ gbc.insets = new Insets(2, 2, 2, 2);
+ add(btnLogin, gbc);
+ btnLogin.addActionListener(this);
+
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Once we log in, transfer the view to the Contacts Card.
+ if (GoogleContactsAPI.getInstance().Login(txtUser.getText(), txtPassword.getText())) {
+ frame.showView(MainFrame.CONTACTS);
+ } else {
+ frame.showInfoMessage("Error Logging in!");
+ }
+ }
+}
37 src/Main.java
@@ -0,0 +1,37 @@
+import java.awt.Dimension;
+
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+/**
+ * Entry Point.
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+public class Main {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ // Look and Feel.
+ try {
+ UIManager.setLookAndFeel(
+ UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e) { }
+
+ // Show the frame.
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ MainFrame frame = new MainFrame();
+ frame.setPreferredSize(new Dimension(500,500));
+ frame.setSize(new Dimension(500,500));
+ frame.setVisible(true);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ }
+ });
+ }
+}
55 src/MainFrame.java
@@ -0,0 +1,55 @@
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+/**
+ * Main Frame of the Applicaiton, contains a bunch of Card Layouts so we can
+ * have swappable views.
+ *
+ * @author Mohamed Mansour
+ * @since 2010-06-23
+ */
+public class MainFrame extends JFrame {
+ private JPanel cards;
+ private LoginPanel pnlLogin;
+ private ContactsPanel pnlContacts;
+
+ // TODO(mohamed): Make this an enum.
+ public static String LOGIN = "login";
+ public static String CONTACTS = "contacts";
+
+ public MainFrame() {
+ initComponents();
+ }
+
+ private void initComponents() {
+ setLayout(new BorderLayout(10,10));
+ cards = new JPanel();
+ cards.setLayout(new CardLayout(5,5));
+ pnlLogin = new LoginPanel(this);
+ cards.add(pnlLogin, LOGIN);
+ pnlContacts = new ContactsPanel(this);
+ cards.add(pnlContacts, CONTACTS);
+ add(cards, BorderLayout.CENTER);
+ }
+
+ /**
+ * Show an information dialog message box.
+ * @param msg The message to show.
+ */
+ public void showInfoMessage(String msg) {
+ JOptionPane.showMessageDialog(this, msg);
+ }
+
+ /**
+ * Switch to the view.
+ * @param view The view to show.
+ */
+ public void showView(String view) {
+ CardLayout cl = (CardLayout)(cards.getLayout());
+ cl.show(cards, view);
+ }
+}

0 comments on commit 0022f2a

Please sign in to comment.