View Javadoc

1   // Copyright (C) 2004, Brian Enigma <enigma at netninja.com>
2   // This file is part of iGallery.
3   //
4   // iGallery is free software; you can redistribute it and/or modify
5   // it under the terms of the GNU General Public License as published by
6   // the Free Software Foundation; either version 2 of the License, or
7   // (at your option) any later version.
8   //
9   // iGallery is distributed in the hope that it will be useful,
10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  // GNU General Public License for more details.
13  //
14  // You should have received a copy of the GNU General Public License
15  // along with Foobar; if not, write to the Free Software
16  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  package org.ninjasoft.igallery.logic;
18  
19  import java.util.*;
20  import java.io.*;
21  import javax.xml.parsers.*;
22  import org.ninjasoft.igallery.data.*;
23  
24  /***
25   * This is where all the magic happens.
26   * @author enigma
27   */
28  public class IGalleryLogic {
29      private String username = "";
30      private String password = "";
31      private String url = "";
32      private GalleryConnection galleryConnection = null;
33      private StatusListener listener = null;
34      private Vector galleryAlbums = new Vector();
35      private Vector iPhotoAlbums = new Vector();
36      private Hashtable iPhotoPictures = new Hashtable();
37      private Vector missingLocal = new Vector();
38      private Vector missingRemote = new Vector();
39      private boolean cancelRequested = false;
40      
41      public IGalleryLogic(StatusListener listener) {
42          this.listener = listener;
43      }
44      
45      public boolean loadIPhotoAlbums() {
46          sendStatus("Loading iPhoto album list");
47          this.iPhotoAlbums.removeAllElements();
48          this.iPhotoPictures.clear();
49          AlbumSaxHandler handler = new AlbumSaxHandler();
50          File albumFile = new File(System.getProperty("user.home") + "/Pictures/iPhoto Library/AlbumData.xml");
51          if (!albumFile.exists()) {
52              sendError("Unable to locate iPhoto data file at " + albumFile.getPath() + "\nHas a 3rd party application moved it?");
53              return false;
54          }
55          try{
56              SAXParserFactory.newInstance().newSAXParser().parse(
57                      new FileInputStream(albumFile), 
58                      handler);
59          }catch(Throwable t){
60              t.printStackTrace();
61              sendError(t.toString());
62              return false;
63          }
64          sendStatus("Obtained data about " + handler.getAlbums().size() + " album(s), " + handler.getPictureHash().size() + " picture(s)");
65          this.iPhotoAlbums = handler.getAlbums();
66          this.iPhotoPictures = handler.getPictureHash();
67          return true;
68      }
69      
70      public boolean login(String url, String username, String password) {
71          sendStatus("Connecting");
72          try{
73          	this.galleryConnection = new GalleryConnection(url, listener);
74          	this.galleryConnection.login(username, password);
75          }catch(Throwable t) {
76              t.printStackTrace();
77              sendError(t.toString());
78              this.galleryConnection = null;
79              return false;
80          }
81          try{
82              sendStatus("Fetching list of albums");
83          	Hashtable albumList = galleryConnection.getAlbumList();
84              galleryAlbums.removeAllElements();
85              galleryAlbums.addAll(albumList.values());
86          }catch(Throwable t){
87              t.printStackTrace();
88              sendError(t.toString());
89              return false;
90          }
91          return true;
92      }
93      
94      public boolean getAlbumDetails() {
95      	for (Iterator i = this.galleryAlbums.iterator(); i.hasNext(); ) {
96              GalleryAlbum album = (GalleryAlbum) i.next();
97              if (album.getPictureCount() != -1)
98                  continue;
99              try{
100                 sendStatus("Getting photo list for " + album.getName());
101             	Hashtable photos = galleryConnection.getPhotoList(album);
102                 album.addPictures(photos.values());
103             }catch(Throwable t){
104                 t.printStackTrace();
105                 sendError(t.toString());
106                 return false;
107             }
108         }
109         sendStatus("Finished getting album details");
110         return true;
111     }
112     
113     public void compareAlbums(IPhotoAlbum iPhotoAlbum, GalleryAlbum galleryAlbum) {
114         Vector iPhotoPictures = iPhotoAlbum.getPictures();
115         Vector galleryPictures = galleryAlbum.getPictures();
116         missingLocal.removeAllElements();
117         missingRemote.removeAllElements();
118         // Not the most efficient way of doing this...sort of like a Bubble Sort...
119         // Check if local pics reside remotely
120         for (Iterator i = iPhotoPictures.iterator(); i.hasNext(); ) {
121             boolean found = false;
122             Integer index = (Integer) i.next();
123             IPhotoPicture iPhotoPicture = (IPhotoPicture) this.iPhotoPictures.get(index);
124             String name = new File(iPhotoPicture.getFilename()).getName();
125             for (Iterator j = galleryPictures.iterator(); j.hasNext(); ) {
126                 GalleryPicture galleryPicture = (GalleryPicture) j.next();
127                 if (name.equalsIgnoreCase(galleryPicture.getName())) {
128                     found = true;
129                     break;
130                 }
131             }
132             if (!found)
133                 missingRemote.add(iPhotoPicture);
134         }
135         // Check if remote pics reside locally
136         for (Iterator i = galleryPictures.iterator(); i.hasNext(); ) {
137             boolean found = false;
138             GalleryPicture galleryPicture = (GalleryPicture) i.next();
139             for (Iterator j = iPhotoPictures.iterator(); j.hasNext(); ) {
140                 Integer index = (Integer) j.next();
141                 IPhotoPicture iPhotoPicture = (IPhotoPicture) this.iPhotoPictures.get(index);
142                 String name = new File(iPhotoPicture.getFilename()).getName();
143                 if (galleryPicture.getName().equalsIgnoreCase(name)) {
144                     found = true;
145                     break;
146                 }
147             }
148             if (!found)
149                 missingLocal.add(galleryPicture);
150         }
151     }
152     
153     public void logout() {
154         this.galleryConnection = null;
155         this.galleryAlbums.removeAllElements();
156     }
157     
158     public void upload(GalleryAlbum remoteAlbum, IPhotoAlbum localAlbum) {
159         new Thread(new UploadThread(remoteAlbum, localAlbum)).start();
160     }
161     
162     public boolean upload(GalleryAlbum album, IPhotoPicture picture) {
163         try{
164         	File file = new File(picture.getFilename());
165         	this.galleryConnection.uploadPhoto(album, file, file.getName(), picture.getCaption());
166             return true;
167         }catch(Throwable t){
168             t.printStackTrace();
169             sendError(t.toString());
170             return false;
171         }
172     }
173     
174     public void cancel() {
175         this.cancelRequested = true;
176         sendStatus("Canceling...");
177     }
178     
179     private void sendStatus(String message) {
180         if (listener != null)
181             listener.setStatus(message);
182     }
183     private void sendError(String message) {
184         if (listener != null)
185             listener.setError(message);
186     }
187     
188     private void sendBusy(boolean b) {
189         if (listener != null)
190             listener.setBusy(b);
191     }
192     
193     public Vector getGalleryAlbums()        {return this.galleryAlbums;}
194     public Vector getIPhotoAlbums()         {return this.iPhotoAlbums;}
195     public Vector getMissingLocal()         {return this.missingLocal;}
196     public Vector getMissingRemote()        {return this.missingRemote;}
197     
198     public class UploadThread implements Runnable {
199         private GalleryAlbum remoteAlbum = null;
200         private IPhotoAlbum localAlbum = null;
201         
202         public UploadThread(GalleryAlbum remoteAlbum, IPhotoAlbum localAlbum) {
203             this.localAlbum = localAlbum;
204             this.remoteAlbum = remoteAlbum;
205         }
206         public void run() {
207             cancelRequested = false;
208             compareAlbums(localAlbum, remoteAlbum);
209             Vector extraLocal = getMissingRemote();
210             int extraLocalSize = extraLocal.size();
211             sendStatus("" + extraLocalSize + " picture" + (extraLocalSize == 1 ? "" : "s") + " to upload");
212             sendBusy(true);
213             int counter = 1;
214             int max = extraLocal.size();
215             for (Iterator i = extraLocal.iterator(); i.hasNext() && !cancelRequested; ) {
216                 IPhotoPicture picture = (IPhotoPicture) i.next();
217                 sendStatus("Uploading " + counter + " of " + max + ": " + picture.getCaption());
218                 upload(remoteAlbum, picture);
219                 counter++;
220             }
221             if (cancelRequested)
222                 sendStatus("...canceled");
223             // Clear the picture count/contents for this album
224             remoteAlbum.resetPictures();
225             // Fetch pictures and count from server (which should include all of the
226             // newly uploaded pics, unless there was an error during the upload)
227             getAlbumDetails();
228             sendBusy(false);
229         }
230     }
231 }