Code Search for Developers
 
 
  

MIDui.java from GridBlocks at Krugle


Show MIDui.java syntax highlighted

/*
 * Copyright (c) 2004
 * Helsinki Institute of Physics
 * see LICENSE file for details
 *
 * MIDui.java
 * Created on Aug 19, 2003
 */

package fi.hip.gb.client;

import java.util.Stack;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.rms.RecordStoreException;

import fi.hip.gb.bluetooth.BTService;
import fi.hip.gb.midlet.core.LiteDescription;
import fi.hip.gb.midlet.core.LiteResult;
import fi.hip.gb.midlet.core.LiteStorage;
import fi.hip.gb.midlet.net.BinaryClient;

/**
 * J2ME client MIDlet. Uses {@link BinaryClient } to talk with
 * the GBAgent server (<code>fi.hip.gb.server.J2meService</code>).
 * Currently can be used to send new jobs, receive the status messages 
 * and finally the results.
 * 
 * @author Juho Karppinen
 */
public abstract class MIDui extends MIDlet {
	/** our display */
	private static Display display;
	/** singleton instance of the main midlet */ 
	public static MIDui instance;
	/** flood the screen with debug messages */
	public static boolean debug;
	/** configuration storage and user interface for them */
	private static Configs configs;
	/** talks with GBAgent server using GPRS connection */
	private static BinaryClient client;
	/** bluetooth network and server */
	private BluetoothBrowser btBrowser;
	/** login routines and screen for typing username and password */
	private static Logging login;
	
	/** store and show the list of jobs */
	protected JobsForm jobs;
	
	/** main screen which shows the menu for different actions */
	private static Form mainForm;
	
	/** shows status of the job on the screen */
	private StatusForm statusForm;
	
	/** thumbnails of saved pictures */
	private Thumbnails thumbnailForm;
	
    /** list of available servers */
    protected String[] serverList = new String[0];
	
	/** 
	 * Recently used <code>Displayable</code> objects, current is almost
	 * on the top */
	public static Stack history = new Stack();
			
	/**
	 * Constructs the Midlet
	 */
	public MIDui() {
		MIDui.instance = this;
	}

	/**
	 * Network operation is started. Inform this to the subclass.
	 *
	 */
    protected abstract void operationStarted();
	
	/**
	 * Network operation in progress was completed. Informs this
	 * to the subclass.
	 */
	protected abstract void operationCompleted();
	
	
	/**
	 * Set the main screen
	 * 
	 * 	@param mainApplicationForm the main form which will be shown to the user
	 * after midlet has started
	 */
	protected void setMainForm(Form mainApplicationForm) {
		MIDui.mainForm = mainApplicationForm;
	}
	/**
	 * Get the main screen
	 * 
	 * @return mainApplicationForm the main form which will be shown to the user
	 * after midlet has started
	 */
	protected Form getMainForm() {
	    return MIDui.mainForm;
	}
	
	protected void startApp() throws MIDletStateChangeException {
		display = Display.getDisplay(this);

		if(this.getAppProperty("Debug") != null) {
		    debug = Integer.parseInt(this.getAppProperty("Debug")) != 0;
		}
		
		System.out.println("Starting");
		
		// read the configurations from memory
		configs = new Configs();
		// initialize communication to the GBAgent server
		client =  new BinaryClient(configs.getServerURL(), configs.getMyProxyServer());
		
		login = new Logging();
		
		// authentication info goes here
		mainForm.append(new StringItem("", null));
		
		// stores the list of jobs
		jobs = new JobsForm();
		mainForm.append(jobs.getChoiceGroup());

		// show configurations if program started first time
		if (configs.loadFailed()) {
			showConfigs();
		} else {
			showMainForm();
		}
		btBrowser = new BluetoothBrowser(configs.getBluetoothServer());
		System.out.println(btBrowser);
	}
	
	protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
		mainForm.set(0, new StringItem("Closing application...", ""));
		
		// attemp to close the server connection before existing...
		BTService.getInstance().stopServer();
		
		ProgressForm.cancel();
	}

	protected void pauseApp() {
	}
	
	/**
	 * Gets the display of the MIDlet
	 * @return Display object
	 */
	public static Display getDisplay() {
		return display;
	}
	
	/**
	 * Sets the new displayable to the screen. If screen is not
	 * progress form or already on the screen, 
	 * it will be pushed into history stack.
	 * 
	 * @param d displayable object to be shown
	 */
	public static void next(Displayable d) {
		// progress form is not inserted into the history, and no duplicates
		if(display.getCurrent() == null
		        || (display.getCurrent() != null
		                && ! d.getClass().getName().equals("fi.hip.gb.client.ProgressForm")
		                && (history.empty() || current().equals(d) == false))) {
		    System.out.println("next screen " + d.getClass().getName());
			history.push(d);
		}
		display.setCurrent(d);
	}
	
	/**
	 * Switch back to old form. If form history is empty, go to 
	 * main screen.
	 * @param show switch to previous form
	 * @return instance of previous form
	 */
	public static Displayable back(boolean show) {
	    System.out.println("back to " + current().getClass().getName());
	    
	    // let main screen be on the bottom
	    if(history.size() > 1) {
	        history.pop();    
	    }
	    
		if(show) {
		    if(current() == MIDui.mainForm)
		        showMainForm();
		    else
		        display.setCurrent(current());
		}
		return current();
	}
	
	/**
	 * Gets last known real display from the history. This doesn't
	 * return any progress forms.
	 * @return current display
	 */
	public static Displayable current() {
		return (Displayable)history.peek();
	}	
	
	/**
	 * Shows the main form. The history of screens is cleared.
	 */
	public static void showMainForm() {
		String time = client.getExpiration();
		if(time == null) {
			mainForm.set(0, new StringItem("Not logged in", ""));
		} else  {
			StringItem message;
			try {
				// throws exception if not logged in
				client.isLogged();
				message = new StringItem("Session is valid", "Time left " + time);
			} catch(Exception e) {
				message = new StringItem("Session has expired", time + " ago");
			}
			mainForm.set(0, message);
		}
		// clear the history
		history.removeAllElements();
		next(mainForm);	
	}

	
	/**
	 * Gets the connection to the GBAgent server
	 * @return instance of the client
	 */
	public static BinaryClient getClient() {
		return client;
	}
	/**
	 * Gets the configurations and config form
	 * @return instance of the configuration
	 */
	public static Configs getConfig() {
		return configs;
	}
	
	/**
	 * Gets the login name for the user
	 * @return login name
	 */
	public static String getLoginName() {
		return login.getLoginName();
	}
	
	/**
	 * Shows login screen with message
	 * @param message to be passed to the user, can be for example an 
	 * cause of failed login
	 */
	protected static void showLogin(String message) {
		login.set(0, new StringItem("info:", message));
		next(login);
	}
	
	/**
	 * Shows configuration form
	 */
	protected static void showConfigs() {
		next(configs);
	}
	/**
	 * Shows the bluetooth network form
	 */
	protected static void showBluetooth() {
		next(instance.btBrowser);
	}
	
	/**
	 * Opens the bluetooth network and allowes
	 * the sending of items into some or all
	 * endpoints.
	 *  
	 * @param item item to be sended
	 */
	protected void sendItem(LiteStorage item) {
		btBrowser.addToQueue(item);
		showBluetooth();
	}
	
	/**
	 * Shows the camera viewfinder on screen for taking 
	 * new pictures.
	 */
	protected static void showCamera() {
		next(new CameraCanvas());
	}
	/**
	 * Shows saved pictures as thumbnails 
	 */
	protected static void showThumbnails() {		
		if(instance.thumbnailForm == null)
			instance.thumbnailForm = new Thumbnails();
		
		next(instance.thumbnailForm);
	}
	/**
	 * Shows the results stored on the memory
	 */
	protected static void showSavedResults() {
		next(new Results());
	}

	/**
	 * Saves the job status with results into the memory.
	 * Make sure that all result files are already downloaded.
	 * @param storage container to be saved
	 */
	protected static void saveJob(LiteStorage storage) {
	    next(new ProgressForm("Saving result into memory"));
		try {
		    storage.store();
			showAlert("Result saved",
			        storage.getDescription().getJobname() + " saved succesfully",
					AlertType.INFO);
		} catch(Exception rse) {
			showException("Cannot save result " + storage.getDescription().getJobname(), rse);
		}
	}
	
	/**
	 * Saves the result into the memory
	 * @param result result to be saved
	 */
	protected static void saveResult(LiteResult result) {
	    LiteStorage storage = new LiteStorage(new Long(-1), result);
	    storage.getDescription().setJobname(result.getName());
		saveJob(storage);
	}
	
	/**
	 * Saves the picture to the memory
	 * @param imageContainer image to be saved with all metadata included
	 */
	protected static void savePicture(LiteResult imageContainer) {
	    next( new ProgressForm("Saving picture into memory"));
		if(instance.thumbnailForm == null)
			instance.thumbnailForm = new Thumbnails();
		try { 
			instance.thumbnailForm.addImage(imageContainer);
			showAlert("Image saved",
					imageContainer.getName() + " saved succesfully",
					AlertType.INFO);
		} catch(Exception rse) {
			showException("Cannot save picture " + imageContainer.getName(), rse);
		}
	}
	/**
	 * Shows the image on the screen
	 * @param image image to be shown
	 */
	protected static void showPicture(LiteResult image) {
		next(new PictureCanvas(image));
	}
	/**
	 * Deletes the image from the memory
	 * @param image image data
	 * @param moveBack move back in the history
	 */
	protected static void deletePicture(LiteResult image, boolean moveBack) {
		try {
		    if(moveBack) {
		        back(false);
		    }
			instance.thumbnailForm.deleteImage(image);
			showAlert("Image deleted",
				image.getName() + " deleted succesfully",
				AlertType.INFO);
		} catch (RecordStoreException rse) {
			showException("Cannot delete image " + image.getName(), rse);
		}
	}

	/**
	 * Shows dispatch options for creating a new job.
	 * Form returns to the main form
	 * 
	 * @param jobID append the job of this ID, or in case of null creates a new job.
	 * @param attachmentImage images to be attached into description, 
	 * or null if no attachments 
	 */
	protected static void showDispatch(Long jobID, LiteResult attachmentImage) {
		DispatchForm df = null;
		if(attachmentImage != null)
			df = new DispatchForm(attachmentImage, jobID, MIDui.instance.serverList);
		else
			df = new DispatchForm(jobID, MIDui.instance.serverList);
		 
		next(df);
	}
	
	/**
	 * Dispatch the job to the server. 
	 * After dispathing is done, the job id is added to the list of jobs.
	 * @param wds description to be sent to the server.
	 */
	protected static void dispatchJob(final LiteDescription wds) {
	    MIDui.next(new ProgressForm("Sending job"));
		
		new Thread( new Runnable() {
			public void run() {
			    MIDui.instance.operationStarted();
				try {
					DispatchForm.storeWds(wds);
					System.out.println("dispatch: " + wds.toString());
					MIDui.getClient().dispatch(wds);
					
					System.out.println("Sent new ID " + wds.getJobID());
                    Long jobID = wds.getJobID();
                    if(wds.getParentID() != null) {
                        jobID = wds.getParentID();
                    }
                    MIDui.instance.jobs.addJob(jobID, wds.getJobname());
                    MIDui.downloadStatus(jobID, wds, true);
				} catch (Exception e) {
					MIDui.showException(
							"Cannot send job to server "
									+ MIDui.getClient().getServiceURL(),
							e);
				}
				MIDui.instance.operationCompleted();
			}
		}).start();
	}
	
	/**
	 * Synchronize state with the server. Updates the list of jobs running on the server
	 * and dowloads list of knowns services if requested.
	 * <p>
	 * This is executed in a new background thread. The user should 
	 * already be logged in beforecalling this method.
	 * 
	 * @param filterString filter jobs by ClassName, use asterix to get all
	 */
	public void sync(final String filterString) {
	    next(new ProgressForm("Synchronizing"));
	    
		new Thread( new Runnable() {
			public void run() {
			    operationStarted();
				
				jobs.clearJobs("[sync in progress]");
				try {				    
					// update the list of jobs
					String[] jobNames = client.getJoblist(true, filterString);
					jobs.clearJobs();
					if(jobNames.length > 0) {
						for(int i=0; i < jobNames.length; i++) {
						    System.out.println("found " + jobNames[i]);
							jobs.addJob(jobNames[i]);
						}
					}

				    // synchronize servers
				    MIDui.instance.serverList = MIDui.getClient().listServices("");
				    next(current());
				} catch (Exception e) {
				    jobs.clearJobs("[sync failed]");
					showException("Error while listing jobs", e);
				}
				operationCompleted();
			}
		}).start();
	}	
	
	/**
	 * Shows status of the job inside <code>StatusForm</code>.
	 * 
	 * @param storage container for the job data
	 */
	protected static void showStatus(LiteStorage storage) {
		next(new StatusForm(storage));
	}
	
	/**
	 * Gets status for the job and show it inside <code>StatusForm</code>.
	 * Status is updated as long as job is finished or canceled.
	 * 
	 * @param jobID id of the requested job
	 * @param description description for the job, if null it will be downloaded from the server
	 * @param recreate recreate existing <code>StatusForm</code> or use existing
	 */
	protected static void downloadStatus(final Long jobID, 
	        final LiteDescription description, 
	        final boolean recreate) {
		next(new ProgressForm("Transfering status"));
		
		if(recreate) {
		    // clear the existing form
		    instance.statusForm = null;
		}
		
		int refreshRate = configs.getUpdateInterval();
		TimerTask timer = new TimerTask() {
		    private LiteStorage storage = new LiteStorage(jobID);
		    // set special tab
		    private int oldTransfer = -1;
		    
			public void run() {
			    try {
			        // runnning the loop first time?
					if(oldTransfer == -1) {
					    if(description == null) {
					        // download the description from the server if not given as parameter
					        storage.setDescription(MIDui.client.getDescription(jobID));
					    } else {
					        storage.setDescription(description);
					    }
					    oldTransfer = 0;
					}
					
					// update the status
					this.storage.setStatus(MIDui.client.getStatus(jobID));
					
					// update the list of results if the size has changed
					if(this.storage.getStatus().getTransferModel()[1] != this.oldTransfer) {
					    this.storage.addResults(client.getResult(jobID, new String[0], new Boolean(false)));
					    this.oldTransfer = this.storage.getStatus().getTransferModel()[1];
					}
					
					if(instance.statusForm == null) {
						instance.statusForm = new StatusForm(storage);
						// if job is already finished, cancel the thread
						if(storage.getStatus().isFinished() || storage.getStatus().isWaiting()) {
						    //System.out.println("----------finished-------------");
						    cancel();
						}
					} else if(instance.statusForm.update(storage)){
					    //System.out.println("CANCEL-------------");
						cancel();
					}
					
					next(instance.statusForm);
				} catch (Exception e) {
					showException("Error receiving status", e);
					cancel();
				}
			}
		};
		
		// either download status messages only once, or frequently
		if(recreate && refreshRate > 0) {
			new Timer().schedule(timer, refreshRate, refreshRate);
		} else {
			new Thread(timer).start();
		}
	}

	/**
	 * Shows the result, currently supported formats are
	 * audio, images and text results.
	 * @param result result container with all metadata and payload
	 * @param description description of the job which owns the result
	 */
	public static void showResult(LiteResult result, LiteDescription description) {
		if(result.getType() == LiteResult.TEXT_TYPE) {
			next(new TextForm(result));
		} else if(result.getType() == LiteResult.IMAGE_TYPE) {
			next(new GraphicsCanvas(result, description));
		} else if(result.getType() == LiteResult.AUDIO_TYPE) {
			next(new MediaPlayer(result));
		}
	}
	
	/**
	 * Downloads given results from the server.
	 * 
	 * @param query an array of result names to be retrieved,
	 * all available results will be downloaded if array is empty
	 * @param operation after result is downloaded:
	 * <ul> 
	 * <li>0=show the first result
	 * <li>1= save results to the disk 
	 * <li>2=no operation, just download the files and update UI
	 * @param storage storage which ID is used to download results. Results are 
	 * also put there and work description is also used when showing results.
	 * @param includePayload download payload data from the server or only the status
	 * @param form which will be updated when results are downloaded 
	 */
	protected static void downloadResult(final String[] query, 
	        final int operation,
	        final LiteStorage storage,
	        final Boolean includePayload,
	        final StatusForm form) {
		next(new ProgressForm("Transfering results"));
		
		new Thread(new Runnable() {
			public void run() {
			    MIDui.instance.operationStarted();
				try {
                    Long jobID = storage.getDescription().getJobID();
                    if(storage.getDescription().getParentID() != null)
                        jobID = storage.getDescription().getParentID();
				    Vector results = client.getResult(jobID, query, includePayload);
					if(results.size() == 0) {
					    throw new Exception("No results found.");
					}
					
					storage.addResults(results);
					form.update(storage);
					
					if(operation == 0) {
					    // show the first element
					    LiteResult res = (LiteResult) results.elementAt(0);
					    
						System.out.println("Returned result type of " + res.getType()
								+ " for query of " + query.length + " items");
						showResult(res, storage.getDescription());
					} else if(operation == 1) {
						saveJob(storage);
					} else {
					    next(MIDui.current());
					}
				} catch (Exception e) {
					showException("Error downloading results: " + e.getMessage(), e);
				}
				MIDui.instance.operationCompleted();
			}
		}).start();
	}

	/**
	 * Aborts and removes the job. Shows to job list after deletion
	 * @param id id of the job to be aborted and/or removed
	 * @param remove should job be removed permanently
	 * @param moveBack move back in the history
	 */
	protected static void abortJob(final Long id, final boolean remove, final boolean moveBack) {
	    if(remove == false) {
			next(new ProgressForm("Aborting job"));
		} else {
			next(new ProgressForm("Removing job"));
		}
	    
	    if(moveBack) {
	        back(false);
	    }
		
		new Thread(new Runnable() {
			public void run() {
			    MIDui.instance.operationStarted();
				String message = null;
				try {
					boolean succeeded = client.abortJob(id, remove);
					if(remove) {
						MIDui.instance.jobs.removeJob();
						message = (succeeded) ? "Job was successfully removed" :  "Could not remove the job";
					} else {
						message = remove ? "Job was succesfully aborted" : "Could not abort the job";
					}
					
					showAlert("Succeeded", message, AlertType.INFO);
				} catch (Exception e) {
					showException(message, e);
				}
				MIDui.instance.operationCompleted();
			}
		}).start();
	}
	
	/**
	 * Prints debug message into init form. Should be removed
	 * when GBAgent hits the market.
	 * 
	 * @param message message to be printed
	 */
	public static void log(String message) {
		mainForm.append("\n" + message);
	}
	
	/**
	 * Shows an exception message in an alert box
	 * @param title cause of the error
	 * @param e exception to be shown
	 */
	public static void showException(String title, Exception e) {
		String msg = "Exception: " + e.getClass().getName() + " " + e.getMessage();
		
		e.printStackTrace();
		
		if(MIDui.debug) {
		    log(title + ":");
		    log(msg);
		}
		
		showAlert(title, msg, AlertType.ERROR);
	}
	
	/**
	 * Shows an alert to the user. Alert is modal, so user
	 * have to dismiss it before normal operation can be continued
	 * @param title title for the error screen
	 * @param message error message
	 * @param type type of the message
	 */
	public static void showAlert(String title,	
			String message, 
			AlertType type) {
		Alert alert = new Alert(title, message, null, type);
		alert.setTimeout(Alert.FOREVER);
		
		display.setCurrent(alert, current());
	}
}



See more files for this project here

GridBlocks

GridBlocks builds a grid application framework via easy-to-use building blocks in distributed environment. The framework offers components for Grid security, distributed storage, computing, and Portlet web interfaces.

Project homepage: http://sourceforge.net/projects/gridblocks
Programming language(s): Java,JSP,XML
License: other

  BluetoothBrowser.java
  Broadcasts.java
  CameraCanvas.java
  Configs.java
  DispatchForm.java
  GPSForm.java
  GenericImageCanvas.java
  GenericResultForm.java
  GraphicsCanvas.java
  InfoForm.java
  InputUI.java
  JobsForm.java
  Logging.java
  MIDui.java
  MediaPlayer.java
  PictureCanvas.java
  ProgressForm.java
  Results.java
  StatusForm.java
  TextForm.java
  Thumbnails.java