/**
* Sencha GXT 3.0.0b - Sencha for GWT
* Copyright(c) 2007-2012, Sencha, Inc.
* licensing@sencha.com
*
* http://www.sencha.com/products/gxt/license/
*/
package com.sencha.gxt.desktopapp.client;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;
import com.google.web.bindery.autobean.shared.AutoBeanUtils;
import com.sencha.gxt.core.shared.FastMap;
import com.sencha.gxt.data.shared.event.StoreAddEvent;
import com.sencha.gxt.data.shared.event.StoreAddEvent.StoreAddHandler;
import com.sencha.gxt.data.shared.event.StoreRemoveEvent;
import com.sencha.gxt.data.shared.event.StoreRemoveEvent.StoreRemoveHandler;
import com.sencha.gxt.data.shared.event.StoreUpdateEvent;
import com.sencha.gxt.data.shared.event.StoreUpdateEvent.StoreUpdateHandler;
import com.sencha.gxt.data.shared.event.TreeStoreRemoveEvent;
import com.sencha.gxt.desktop.client.widget.Desktop;
import com.sencha.gxt.desktopapp.client.browser.BrowserPresenterImpl;
import com.sencha.gxt.desktopapp.client.event.AddFileModelEvent;
import com.sencha.gxt.desktopapp.client.event.LoginEvent;
import com.sencha.gxt.desktopapp.client.event.LogoutEvent;
import com.sencha.gxt.desktopapp.client.event.OpenFileModelEvent;
import com.sencha.gxt.desktopapp.client.event.OpenFileModelEvent.OpenFileModelHandler;
import com.sencha.gxt.desktopapp.client.event.RemoveFileModelEvent;
import com.sencha.gxt.desktopapp.client.event.UpdateFileModelEvent;
import com.sencha.gxt.desktopapp.client.event.UpdateProfileEvent;
import com.sencha.gxt.desktopapp.client.filemanager.FileManagerPresenterImpl;
import com.sencha.gxt.desktopapp.client.interpreter.InterpreterPresenterImpl;
import com.sencha.gxt.desktopapp.client.persistence.BackingStore;
import com.sencha.gxt.desktopapp.client.persistence.FileModel;
import com.sencha.gxt.desktopapp.client.persistence.FileSystem;
import com.sencha.gxt.desktopapp.client.persistence.MemoryBackingStore;
import com.sencha.gxt.desktopapp.client.persistence.StorageBackingStore;
import com.sencha.gxt.desktopapp.client.persistence.StorageProvider;
import com.sencha.gxt.desktopapp.client.spreadsheet.SpreadsheetPresenterImpl;
import com.sencha.gxt.desktopapp.client.wordprocessor.WordProcessorPresenterImpl;
import com.sencha.gxt.widget.core.client.info.Info;
/**
* Presents the desktop application to the user.
*
* @see DesktopAppPresenter
*/
public class DesktopAppPresenterImpl implements DesktopAppPresenter {
private static final String STORAGE_KEY_PREFIX = "com.sencha.gxt.desktop.client.desktopapp";
private static final String STORAGE_KEY_PREFIX_SYSTEM = STORAGE_KEY_PREFIX + ".system";
private static final String STORAGE_KEY_PREFIX_USER = STORAGE_KEY_PREFIX + ".user";
private static final String CURRENT_USER_KEY = "currentUser";
private static final String PROFILE_KEY = "profile";
private DesktopBus desktopBus;
private FileSystem fileSystem;
private StorageProvider storageProvider;
private ProfileFactory profileFactory;
private Boolean isLocalStorageSupported;
private FastMap<BackingStore> backingStoreCache = new FastMap<BackingStore>();
private OpenFileModelHandler openFileModelHandler;
private StoreAddHandler<FileModel> storeAddHandler;
private StoreUpdateHandler<FileModel> storeUpdateHandler;
private StoreRemoveHandler<FileModel> storeRemoveHandler;
private DesktopAppView desktopAppView;
private String currentUser;
/**
* Creates a desktop application presenter that communicates with the rest of
* the application using the specified desktop bus.
*
* @param desktopBus the application bus
*/
public DesktopAppPresenterImpl(DesktopBus desktopBus) {
this.desktopBus = desktopBus;
desktopBus.addOpenFileModelHandler(getOpenFileModelHandler());
}
@Override
public void clearLocalStorage() {
getStorageProvider().clearAll();
}
@Override
public String getCurrentUser() {
if (currentUser == null) {
currentUser = getSystemBackingStore().getItem(CURRENT_USER_KEY);
}
return currentUser;
}
@Override
public FileSystem getFileSystem() {
if (fileSystem == null) {
fileSystem = new FileSystem(getUserBackingStore(currentUser));
fileSystem.getTreeStore().addStoreAddHandler(getStoreAddHandler());
fileSystem.getTreeStore().addStoreUpdateHandler(getStoreUpdateHandler());
fileSystem.getTreeStore().addStoreRemoveHandler(getStoreRemoveHandler());
}
return fileSystem;
}
@Override
public ProfileModel getProfile() {
ProfileModel profileModel = getProfile(currentUser);
return profileModel;
}
@Override
public void go(HasWidgets hasWidgets) {
hasWidgets.add(getDesktopAppView().asWidget());
getDesktopAppView().setDesktopLayoutType(getProfile().getDesktopLayoutType());
}
@Override
public boolean isLocalStorageSupported() {
if (!isLocalStorageSupportChecked()) {
isLocalStorageSupported = Storage.isLocalStorageSupported();
}
return isLocalStorageSupported;
}
@Override
public boolean isLoggedIn() {
return getCurrentUser() != null;
}
@Override
public DesktopAppPresenter.LoginStatus onLogin(LoginModel loginModel) {
String userName = loginModel.getUserName();
String password = loginModel.getPassword();
boolean isNewUser = loginModel.isNewUser();
if (isExistingUser(userName)) {
if (isNewUser) {
return DesktopAppPresenter.LoginStatus.DUPLICATE_USER_NAME;
} else if (!validCredentials(userName, password)) {
return DesktopAppPresenter.LoginStatus.INVALID_NAME_OR_PASSWORD;
}
} else {
if (isNewUser) {
createNewUser(userName);
} else {
return DesktopAppPresenter.LoginStatus.INVALID_NAME_OR_PASSWORD;
}
}
setCurrentUser(userName);
getDesktopBus().fireLoginEvent(new LoginEvent(userName, isNewUser));
return DesktopAppPresenter.LoginStatus.SUCCESS;
}
@Override
public void onLogout() {
currentUser = null;
getSystemBackingStore().removeItem(CURRENT_USER_KEY);
getDesktopBus().fireLogoutEvent(new LogoutEvent());
}
@Override
public void onOpenFileManager() {
new FileManagerPresenterImpl(getFileSystem(), getDesktopBus()).go(getDesktopAppView());
}
@Override
public void onOpenProfile() {
getDesktopBus().invokeProfileService();
}
@Override
public DesktopAppPresenter.ProfileStatus onUpdateProfile(ProfileModel profileModel) {
boolean isUpdate = profileModel != null;
if (isUpdate) {
setProfile(profileModel);
getDesktopAppView().setDesktopLayoutType(profileModel.getDesktopLayoutType());
}
getDesktopBus().fireUpdateProfileEvent(new UpdateProfileEvent(profileModel, isUpdate));
return DesktopAppPresenter.ProfileStatus.SUCCESS;
}
protected boolean validCredentials(String userName, String password) {
return true;
}
private BackingStore createBackingStore(String storageKeyPrefix) {
BackingStore backingStore;
if (!isLocalStorageSupportChecked()) {
// Prevent unintentional use of MemoryBackingStore
throw new IllegalStateException("Must invoke isLocalStorageSupported before invoking getBackingStore");
}
if (!isLocalStorageSupported()) {
backingStore = new MemoryBackingStore(storageKeyPrefix);
} else {
backingStore = new StorageBackingStore(getStorageProvider().getStorage(), storageKeyPrefix);
}
return backingStore;
}
private void createNewUser(String userName) {
if (isExistingUser(userName)) {
throw new IllegalStateException("user " + userName + " already exists");
}
AutoBean<ProfileModel> profileAutoBean = getProfileAutoBeanFactory().profileModel();
ProfileModel profileModel = profileAutoBean.as();
initializeProfile(profileModel);
setProfile(profileModel, userName);
}
private BackingStore getBackingStore(String storeName) {
BackingStore backingStore = backingStoreCache.get(storeName);
if (backingStore == null) {
backingStore = createBackingStore(storeName);
backingStoreCache.put(storeName, backingStore);
}
return backingStore;
}
private DesktopAppView getDesktopAppView() {
if (desktopAppView == null) {
desktopAppView = new DesktopAppViewImpl(this);
}
return desktopAppView;
}
private DesktopBus getDesktopBus() {
return desktopBus;
}
private OpenFileModelHandler getOpenFileModelHandler() {
if (openFileModelHandler == null) {
openFileModelHandler = new OpenFileModelHandler() {
@Override
public void onOpenFileModel(OpenFileModelEvent openFileModelEvent) {
openFileModel(openFileModelEvent);
}
};
}
return openFileModelHandler;
}
private ProfileModel getProfile(String userName) {
String payload = getUserBackingStore(userName).getItem(PROFILE_KEY);
ProfileModel profileModel = AutoBeanCodex.decode(getProfileAutoBeanFactory(), ProfileModel.class, payload).as();
return profileModel;
}
private ProfileFactory getProfileAutoBeanFactory() {
if (profileFactory == null) {
profileFactory = GWT.create(ProfileFactory.class);
}
return profileFactory;
}
private StorageProvider getStorageProvider() {
if (storageProvider == null) {
storageProvider = new StorageProvider();
}
return storageProvider;
}
private StoreAddHandler<FileModel> getStoreAddHandler() {
if (storeAddHandler == null) {
storeAddHandler = new StoreAddHandler<FileModel>() {
@Override
public void onAdd(StoreAddEvent<FileModel> event) {
for (FileModel fileModel : event.getItems()) {
getDesktopBus().fireAddFileModelEvent(new AddFileModelEvent(fileModel));
}
}
};
}
return storeAddHandler;
}
private StoreRemoveHandler<FileModel> getStoreRemoveHandler() {
if (storeRemoveHandler == null) {
storeRemoveHandler = new StoreRemoveHandler<FileModel>() {
@Override
public void onRemove(StoreRemoveEvent<FileModel> event) {
getDesktopBus().fireRemoveFileModelEvent(new RemoveFileModelEvent(event.getItem()));
List<FileModel> children = ((TreeStoreRemoveEvent<FileModel>) event).getChildren();
for (FileModel child : children) {
getDesktopBus().fireRemoveFileModelEvent(new RemoveFileModelEvent(child));
}
}
};
}
return storeRemoveHandler;
}
private StoreUpdateHandler<FileModel> getStoreUpdateHandler() {
if (storeUpdateHandler == null) {
storeUpdateHandler = new StoreUpdateHandler<FileModel>() {
@Override
public void onUpdate(StoreUpdateEvent<FileModel> event) {
for (FileModel fileModel : event.getItems()) {
getDesktopBus().fireUpdateFileModelEvent(new UpdateFileModelEvent(fileModel));
}
}
};
}
return storeUpdateHandler;
}
private BackingStore getSystemBackingStore() {
return getBackingStore(STORAGE_KEY_PREFIX_SYSTEM);
}
private BackingStore getUserBackingStore(String userName) {
if (userName == null) {
throw new IllegalArgumentException("userName cannot be null");
}
return getBackingStore(STORAGE_KEY_PREFIX_USER + "." + userName);
}
private void initializeProfile(ProfileModel profileModel) {
profileModel.setDesktopLayoutType(Desktop.DEFAULT_DESKTOP_LAYOUT_TYPE);
}
private boolean isExistingUser(String userName) {
return getUserBackingStore(userName).getItem(PROFILE_KEY) != null;
}
private boolean isLocalStorageSupportChecked() {
return isLocalStorageSupported != null;
}
private void openFileModel(OpenFileModelEvent openFileModelEvent) {
Presenter presenter = null;
FileSystem fileSystem = openFileModelEvent.getFileSystem();
FileModel fileModel = openFileModelEvent.getFileModel();
switch (fileModel.getFileType()) {
case BOOKMARK:
presenter = new BrowserPresenterImpl(getDesktopBus(), fileSystem, fileModel);
break;
case DOCUMENT:
presenter = new WordProcessorPresenterImpl(getDesktopBus(), fileSystem, fileModel);
break;
case FOLDER:
// no action currently supported
break;
case PROGRAM:
presenter = new InterpreterPresenterImpl(getDesktopBus(), fileSystem, fileModel);
break;
case SPREADSHEET:
presenter = new SpreadsheetPresenterImpl(getDesktopBus(), fileSystem, fileModel);
break;
default:
Info.display("Desktop", "You opened " + fileModel.getName() + ", which is of type " + fileModel.getFileType()
+ " and currently not supported.");
break;
}
if (presenter != null) {
presenter.go(getDesktopAppView());
}
}
private void setCurrentUser(String currentUser) {
this.currentUser = currentUser;
getSystemBackingStore().setItem(CURRENT_USER_KEY, currentUser);
}
private void setProfile(ProfileModel profileModel) {
setProfile(profileModel, currentUser);
}
private void setProfile(ProfileModel profileModel, String userName) {
String payload = AutoBeanCodex.encode(AutoBeanUtils.getAutoBean(profileModel)).getPayload();
getUserBackingStore(userName).setItem(PROFILE_KEY, payload);
}
}