/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2008 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package com.funambol.client.controller;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
import com.funambol.client.source.AppSyncSource;
import com.funambol.client.source.ExternalAppManager;
import com.funambol.client.ui.HomeScreen;
import com.funambol.client.ui.UISyncSource;
import com.funambol.client.ui.Bitmap;
import com.funambol.client.ui.DisplayManager;
import com.funambol.syncml.spds.SyncStatus;
import com.funambol.sync.SyncException;
import com.funambol.sync.SyncListener;
import com.funambol.sync.SyncSource;
import com.funambol.util.Log;
import com.funambol.util.StringUtil;
import com.funambol.platform.NetworkStatus;
/**
* This class represents the controller for the home screen. Since the
* HomeScreen is a screen where synchronizations can be performed, the
* class extends the SynchronizationController. On top of this the class adds
* the ability of handling the home screen.
*/
public class HomeScreenController extends SynchronizationController {
private static final String TAG_LOG = "HomeScreenController";
protected HomeScreen homeScreen;
protected Vector items = null;
private Hashtable pushRequestQueue = new Hashtable();
private int selectedIndex = -1;
private boolean updateAvailableSources = false;
private boolean syncAllButtonAdded = false;
/**
* This flag is to switch off the storage limit warning after
* it is displayed once. The warning must be displayed also more
* than once if an individual-source sync is fired, but not for
* multiple-source sync, scheduled sync and push sync.
* See US7498.
*/
protected boolean dontDisplayStorageLimitWarning = false;
/**
* This flag is to switch off the server quota warning after
* it is displayed once. The warning must be displayed also more
* than once if an individual-source sync is fired, but not for
* multiple-source sync, scheduled sync and push sync.
* See US7499.
*/
protected boolean dontDisplayServerQuotaWarning = false;
private boolean homeScreenRegisteredAndInForeground = false;
public HomeScreenController(Controller controller, HomeScreen homeScreen,NetworkStatus networkStatus) {
super(controller, homeScreen,networkStatus);
this.controller = controller;
this.homeScreen = homeScreen;
forceUpdateAvailableSources();
}
public HomeScreen getHomeScreen() {
return homeScreen;
}
public void setHomeScreen(HomeScreen homeScreen) {
if (this.homeScreen != homeScreen) {
syncAllButtonAdded = false;
}
this.homeScreen = homeScreen;
// If required, we shall add the sync all button
addSyncAllButtonIfRequired();
super.setScreen(homeScreen);
}
public void updateAvailableSources() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "updateAvailableSources");
}
updateAvailableSources = true;
}
public boolean syncStarted(Vector sources) {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "syncStarted");
}
boolean res = super.syncStarted(sources);
lockHomeScreen(sources);
AppSyncSource appSource = (AppSyncSource)sources.elementAt(0);
changeSyncLabelsOnSync(appSource);
attachToSource(appSource);
return res;
}
public void attachToRunningSync(AppSyncSource appSource) {
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Attaching to running sync for " + appSource.getName());
}
if(homeScreen.isLocked()) {
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Cannot attach to running sync, home screen is locked");
}
return;
}
// First of all select the source to attach
setSelected(appSource.getUiSourceIndex(), false);
Vector sources = new Vector();
sources.addElement(appSource);
lockHomeScreen(sources);
changeSyncLabelsOnSync(appSource);
attachToSource(appSource);
}
public void endSync(Vector sources, boolean hadErrors) {
super.endSync(sources, hadErrors);
}
protected void displayStorageLimitWarning(Vector localStorageFullSources) {
logSyncSourceErrors(localStorageFullSources);
if (isInForeground()) {
if (!dontDisplayStorageLimitWarning) {
String message = localization.getLanguage("message_storage_limit");
controller.getDialogController().showMessageAndWaitUserConfirmation(message);
dontDisplayStorageLimitWarning = true; // Once is enough
}
} else {
super.displayStorageLimitWarning(localStorageFullSources);
}
}
protected void displayServerQuotaWarning(Vector serverQuotaFullSources) {
logSyncSourceErrors(serverQuotaFullSources);
// if we had at least one device full error, we must choose how show
// these errors to the user, according to US7498 and US7499
if (isInForeground()) {
if (!dontDisplayServerQuotaWarning) {
StringBuffer sourceNames = new StringBuffer("");
for(int i=0; i<serverQuotaFullSources.size(); i++) {
AppSyncSource appSource = (AppSyncSource)serverQuotaFullSources.elementAt(i);
if (sourceNames.length() > 0) {
sourceNames.append(",");
}
sourceNames.append(appSource.getName().toLowerCase());
}
String msg = localization.getLanguage("dialog_server_full");
msg = StringUtil.replaceAll(msg, "__source__", sourceNames.toString());
controller.getDialogController().showMessageAndWaitUserConfirmation(msg);
}
//error in sync when activity is in background
} else {
super.displayServerQuotaWarning(serverQuotaFullSources);
}
}
public void syncEnded() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "sync ended");
}
super.syncEnded();
changeSyncLabelsOnSyncEnded();
unlockHomeScreen();
setSelected(getFirstActiveItemIndex(), false);
for(int i=0;i<items.size();++i) {
AppSyncSource appSource = (AppSyncSource)items.elementAt(i);
// To make sure the UI is properly updated, we force a sync
// termination for each source
SyncSource source = appSource.getSyncSource();
if (source != null) {
SyncListener listener = source.getListener();
SyncStatus report = new SyncStatus(source.getName());
report.setStatusCode(SyncListener.CANCELLED);
SyncException se = new SyncException(SyncException.CANCELLED, "Sync cancelled");
report.setSyncException(se);
if (listener != null) {
listener.endSession(report);
}
}
}
// If there are pending syncs, we start serving them
synchronized(pushRequestQueue) {
if (pushRequestQueue.size() > 0) {
Vector sources = new Vector(pushRequestQueue.size());
Enumeration keys = pushRequestQueue.keys();
while(keys.hasMoreElements()) {
sources.addElement(keys.nextElement());
}
pushRequestQueue.clear();
synchronize(com.funambol.client.controller.SynchronizationController.PUSH, sources);
}
}
}
public void redraw() {
// We may need to update the list of
// visible items as the server may have sent its capabilities
if (updateAvailableSources) {
forceUpdateAvailableSources();
}
if (homeScreen != null) {
homeScreen.redraw();
}
}
public Vector getVisibleItems() {
return items;
}
public void buttonSelected(int index) {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "Button selected " + index);
}
AppSyncSource source = (AppSyncSource) items.elementAt(index);
if (source.getConfig().getEnabled()) {
setSelected(index, true);
}
}
public void buttonPressed(int index) {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "Button pressed " + index);
}
AppSyncSource source = (AppSyncSource) items.elementAt(index);
if (source.isWorking() && source.getConfig().getEnabled()) {
syncSource(MANUAL, source);
} else {
Log.error(TAG_LOG, "The user pressed a source disabled, this is an error in the code");
}
}
public void selectFirstAvailable() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "Select first source available");
}
setSelected(getFirstActiveItemIndex(), false);
}
public void sourceStarted(AppSyncSource appSource) {
super.sourceStarted(appSource);
// this selects the appSource and disable any previously selected one
setSelected(appSource.getUiSourceIndex(), false);
}
/**
* This method enques a sync request coming from a push notification. This
* method can be used when there is a sync running and a new request comes
* in. The request is enqueued and server as soon as the current sync
* terminates.
*
* @param sources the sources to be enqueued
*/
public void enquePushSyncRequest(Vector sources) {
synchronized(pushRequestQueue) {
for(int i=0;i<sources.size();++i) {
AppSyncSource source = (AppSyncSource)sources.elementAt(i);
pushRequestQueue.put(source, source);
}
}
}
/**
* This method enques a sync request coming from a push notification. This
* method can be used when there is a sync running and a new request comes
* in. The request is enqueued and server as soon as the current sync
* terminates.
*/
public void enquePushSyncRequest() {
synchronized(pushRequestQueue) {
for(int i=0;i<items.size();++i) {
AppSyncSource appSource = (AppSyncSource)items.elementAt(i);
if (appSource.getConfig().getEnabled() && appSource.isWorking()) {
pushRequestQueue.put(appSource, appSource);
}
}
}
}
protected void lockHomeScreen(Vector sources) {
if (homeScreen == null) {
return;
}
if (customization.syncAllOnMainScreenRequired()) {
// disable the sync all button (if it does not have the cancel sync
// role during a sync)
if (!customization.syncAllActsAsCancelSync()) {
homeScreen.setSyncAllEnabled(false);
}
}
for(int j=0;j<items.size();++j) {
AppSyncSource appSource = (AppSyncSource) items.elementAt(j);
// If this source is in sources then we shall enable it,
// otherwise we must disable it
boolean enable = false;
for(int i=0;i<sources.size();++i) {
AppSyncSource appSource2 = (AppSyncSource)sources.elementAt(i);
if (appSource2.getId() == appSource.getId()) {
enable = true;
break;
}
}
UISyncSource uiSource = appSource.getUISyncSource();
uiSource.setEnabled(enable);
}
redraw();
homeScreen.lock();
}
public void updateEnabledSources() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "updateEnabledSources");
}
// If a sync is in progress, then we don't change the sources status,
// otherwise we would corrupt the UI. On sync termination, the home
// screen will get refreshed
if (isSynchronizing()) {
return;
}
unlockHomeScreen();
Enumeration sources = items.elements();
boolean atLeastOneEnabled = false;
while (sources.hasMoreElements()) {
AppSyncSource appSource = (AppSyncSource)sources.nextElement();
UISyncSourceController sourceController = appSource.getUISyncSourceController();
if (sourceController != null) {
if (appSource.getConfig().getActive()) {
if (!appSource.isEnabled() || !appSource.isWorking()) {
sourceController.disable();
UISyncSource uiSource = appSource.getUISyncSource();
// If this is the selected source, then we shall move the
// selection to the first available
if (uiSource != null && uiSource.isSelected()) {
setSelected(getFirstActiveItemIndex(), false);
}
} else {
sourceController.enable();
atLeastOneEnabled = true;
}
}
}
}
// If there are no sources enabled, then we disable the sync all button
if (homeScreen != null) {
homeScreen.setSyncAllEnabled(atLeastOneEnabled);
}
if (!atLeastOneEnabled) {
// We must "deselect" all items because all are disabled
for(int i=0;i<items.size();++i) {
setSelected(i, false);
}
}
redraw();
}
protected void syncSource(String syncType, AppSyncSource appSource) {
Vector sources = new Vector();
sources.addElement(appSource);
synchronize(syncType, sources);
}
public void syncMenuSelected() {
if (selectedIndex != -1) {
AppSyncSource appSource = (AppSyncSource)items.elementAt(selectedIndex);
syncSource(MANUAL, appSource);
}
}
public void syncAllPressed() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "Sync All Button pressed");
}
// If a sync is in progress, then this is a cancel sync request
if (isSynchronizing() && customization.syncAllActsAsCancelSync()) {
if (!doCancel) {
cancelSync();
} else {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG_LOG, "Cancelling already in progress");
}
}
} else {
syncAllSources(MANUAL);
}
}
public void aloneSourcePressed() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "Alone Source Button pressed");
}
// If a sync is in progress, then this is a cancel sync request
if (isSynchronizing()) {
if (!doCancel) {
cancelSync();
} else {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG_LOG, "Cancelling already in progress");
}
}
} else {
AppSyncSource appSource = (AppSyncSource)items.elementAt(0);
syncSource(MANUAL, appSource);
}
}
public void syncAllSources(String syncType) {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG_LOG, "syncAllSources");
}
Vector sources = new Vector();
for(int i=0;i<items.size();++i) {
AppSyncSource appSource = (AppSyncSource)items.elementAt(i);
if (appSource.getConfig().getEnabled() && appSource.isWorking()) {
sources.addElement(appSource);
}
}
synchronize(syncType, sources);
}
/**
* Triggers a synchronization for the given syncSources. The caller can
* specify its type (manual, scheduled, push) to change the error handling
* behavior
*
* @param syncType the caller type (SYNC_TYPE_MANUAL, SYNC_TYPE_SCHEDULED)
* @param syncSources is a vector of AppSyncSource to be synchronized
*
*/
public synchronized void synchronize(String syncType, Vector syncSources) {
// For manual sync, always show alert message for storage/server
// quota limit. For other sync modes, doesn't display message if
// the previous sync ended with the same error.
if (MANUAL.equals(syncType)) {
dontDisplayStorageLimitWarning = false;
dontDisplayServerQuotaWarning = false;
} else {
for(int i = 0 ; i < syncSources.size(); ++i) {
AppSyncSource appSource = (AppSyncSource)syncSources.elementAt(i);
switch (appSource.getConfig().getLastSyncStatus()) {
case SyncListener.LOCAL_CLIENT_FULL_ERROR:
// If for at least one source the storage limit warning has
// already been shown, no warning should be displayed again
dontDisplayStorageLimitWarning = true;
break;
case SyncListener.SERVER_FULL_ERROR:
// If for at least one source the server full quota warning has
// already been shown, no warning should be displayed again
dontDisplayServerQuotaWarning = true;
break;
}
}
}
super.synchronize(syncType, syncSources);
}
public void cancelMenuSelected() {
cancelSync();
}
public void updateMenuSelected() {
controller.promptUpdate();
}
public void quitMenuSelected() {
controller.toBackground();
}
public boolean isUpdate() {
return controller.isUpdate();
}
public void exit() {
Controller globalController = getController();
DisplayManager dm = globalController.getDisplayManager();
dm.askYesNoQuestion(homeScreen, "Are you sure you want to exit?",
new ExitAction(), null, 0);
}
private class ExitAction implements Runnable {
public ExitAction() {
}
public void run() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "Exiting application");
}
}
}
public void showConfigurationScreen() {
Controller globalController = getController();
// If a sync is running, we wait for its termination before opening the
// settings screen
if (isSynchronizing()) {
showSyncInProgressMessage();
} else {
globalController.showScreen(homeScreen, Controller.CONFIGURATION_SCREEN_ID);
}
}
public void showAboutScreen() {
Controller globalController = getController();
globalController.showScreen(homeScreen, Controller.ABOUT_SCREEN_ID);
}
public void showAccountScreen() {
Controller globalController = getController();
globalController.showScreen(homeScreen, Controller.ACCOUNT_SCREEN_ID);
}
public void gotoMenuSelected() {
if (selectedIndex != -1) {
AppSyncSource source = (AppSyncSource)items.elementAt(selectedIndex);
ExternalAppManager manager = source.getAppManager();
if (manager != null) {
try {
manager.launch(source, null);
} catch (Exception e) {
// TODO FIXME: show a toast?
Log.error(TAG_LOG, "Cannot launch external app manager, because: " + e);
}
} else {
Log.error(TAG_LOG, "No external manager associated to source: " + source.getName());
}
}
}
/**
* Returns true when the associated screen is in foreground (visible
* to the user and with focus)
*/
public boolean isInForeground() {
//first of all, if an HomeScreen is not associated with the controller
//it's impossible that the screen is in foreground
if (null == homeScreen) {
return false;
}
//then, check for internal flag
return homeScreenRegisteredAndInForeground ;
}
/**
* Sets foreground status of the screen
*/
public void setForegroundStatus(boolean newValue) {
homeScreenRegisteredAndInForeground = newValue;
}
protected void unlockHomeScreen() {
if (homeScreen == null) {
return;
}
if (customization.syncAllOnMainScreenRequired()) {
// enable the sync all button
if (!customization.syncAllActsAsCancelSync()) {
homeScreen.setSyncAllEnabled(true);
}
}
for(int j=0;j<items.size();++j) {
AppSyncSource appSource = (AppSyncSource) items.elementAt(j);
// If this source is in sources then we shall enable it,
// otherwise we must disable it
UISyncSourceController uiSourceController = appSource.getUISyncSourceController();
if (appSource.isWorking() && appSource.isEnabled()) {
uiSourceController.enable();
} else {
uiSourceController.disable();
}
// If a UI Source is in the syncing state force it to stop
if(uiSourceController.isSyncing()) {
uiSourceController.resetStatus();
}
}
redraw();
homeScreen.unlock();
}
protected void showSyncInProgressMessage() {
// If the home screen is not displayed, we cannot show any warning and
// just ignore this event
Controller globalController = getController();
if (homeScreen != null) {
DisplayManager dm = globalController.getDisplayManager();
String msg = localization.getLanguage("message_sync_running_wait");
dm.showMessage(homeScreen, msg);
}
}
private int getFirstActiveItemIndex() {
int size = items.size();
for (int i=0; i<size; i++) {
AppSyncSource source = (AppSyncSource) items.elementAt(i);
if (source.isEnabled() && source.isWorking()) {
return i;
}
}
return 0;
}
private void addSyncAllButtonIfRequired() {
if (!syncAllButtonAdded && homeScreen != null) {
if (customization.syncAllOnMainScreenRequired()) {
Bitmap img = customization.getSyncAllIcon();
Bitmap bg = customization.getSyncAllBackground();
Bitmap bgSel = customization.getSyncAllHighlightedBackground();
homeScreen.addSyncAllButton(localization.getLanguage("home_sync_all"),
img, bg, bgSel);
}
syncAllButtonAdded = true;
}
}
private void computeVisibleItems() {
items = new Vector();
//Set the SyncAll Item if required
addSyncAllButtonIfRequired();
int realSize = controller.computeNumberOfVisibleSources();
if (realSize == 0) {
// There are no available sources, nothing to do
return;
}
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Number of visible sources: " + realSize);
}
items.setSize(realSize);
// Now recompute the ui position for all available sources
int sourcesOrder[] = customization.getSourcesOrder();
int uiOrder = 0;
for (int i=0;i<sourcesOrder.length;++i) {
int sourceId = sourcesOrder[i];
// If this is a working source, then set its UI position
AppSyncSource source = appSyncSourceManager.getSource(sourceId);
if (controller.isVisible(source)) {
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Setting source " + source.getName() + " at position: " + uiOrder);
}
source.setUiSourceIndex(uiOrder++);
}
}
// Add an item for each registered source that has to fit into the home
// screen. So far the only one we shall discard is the ConfigSyncSource
Enumeration sources = appSyncSourceManager.getRegisteredSources();
while (sources.hasMoreElements()) {
AppSyncSource appSource = (AppSyncSource)sources.nextElement();
if (controller.isVisible(appSource)) {
// Set the sources in the appropriate order
int index = appSource.getUiSourceIndex();
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Setting source at index: " + index);
}
items.setElementAt(appSource, index);
}
}
}
private void setSelected(int index, boolean fromUi) {
// First of all remove selection from the current selected item
if ((selectedIndex != index) &&
(selectedIndex != -1) &&
(selectedIndex < items.size())) {
AppSyncSource oldAppSource = (AppSyncSource)items.elementAt(selectedIndex);
UISyncSourceController sourceController = oldAppSource.getUISyncSourceController();
if (sourceController != null) {
sourceController.setSelected(false, fromUi);
}
}
AppSyncSource appSource = (AppSyncSource)items.elementAt(index);
if (!appSource.isEnabled() || !appSource.isWorking()) {
// Invalid selection, the source cannot be selected
return;
}
selectedIndex = index;
UISyncSourceController sourceController = appSource.getUISyncSourceController();
if (sourceController != null) {
sourceController.setSelected(true, fromUi);
} else {
Log.error(TAG_LOG, "Found a source without controller associated");
}
}
protected void changeSyncLabelsOnSync(AppSyncSource appSource) {
if (homeScreen == null) {
return;
}
if (customization.syncAllOnMainScreenRequired()) {
if (customization.syncAllActsAsCancelSync()) {
homeScreen.setSyncAllText(localization.getLanguage("menu_cancel_sync"));
} else {
homeScreen.setSyncAllText(localization.getLanguage("status_sync"));
}
}
homeScreen.setSyncMenuText(localization.getLanguage("menu_cancel_sync"));
}
protected void attachToSource(AppSyncSource appSource) {
// Force the source to start syncing, even though we have not received
// any event from the SyncEngine. This has two nice effects:
// 1) the source is marked immediately as syncing
// 2) the buttons and the sync status are always aligned, even if the
// sync takes time to start
UISyncSourceController sourceController = appSource.getUISyncSourceController();
if (sourceController != null) {
sourceController.attachToSession();
}
}
protected void changeSyncLabelsOnSyncEnded() {
if (homeScreen == null) {
return;
}
if (customization.syncAllOnMainScreenRequired()) {
homeScreen.setSyncAllText(localization.getLanguage("home_sync_all"));
}
homeScreen.setSyncMenuText(localization.getLanguage("menu_sync"));
}
private void forceUpdateAvailableSources() {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG_LOG, "forceUpdateAvailableSources");
}
// Compute the set of items to be displayed
computeVisibleItems();
if (homeScreen != null) {
homeScreen.updateVisibleItems();
}
setSelected(getFirstActiveItemIndex(), false);
updateAvailableSources = false;
}
protected void dontDisplayStorageLimitWarningAgain(AppSyncSource appSource) {
if (appSource.getConfig().getLastSyncStatus() == SyncListener.LOCAL_CLIENT_FULL_ERROR) {
// If for at least one source the storage limit warning has
// already been shown, no warning should be displayed again
dontDisplayStorageLimitWarning = true;
}
}
protected void dontDisplayServerQuotaWarningAgain(AppSyncSource appSource) {
if (appSource.getConfig().getLastSyncStatus() == SyncListener.SERVER_FULL_ERROR) {
// If for at least one source the server full quota warning has
// already been shown, no warning should be displayed again
dontDisplayServerQuotaWarning = true;
}
}
/**
* Logs sync sources where server full quota or storage limit error happened
* @param storageLimitOrserverQuotaFullSources
*/
protected void logSyncSourceErrors(Vector storageLimitOrserverQuotaFullSources) {
for(int i=0; i<storageLimitOrserverQuotaFullSources.size(); i++) {
AppSyncSource appSource = (AppSyncSource)storageLimitOrserverQuotaFullSources.elementAt(i);
switch (appSource.getConfig().getLastSyncStatus()) {
case SyncListener.LOCAL_CLIENT_FULL_ERROR:
Log.error(TAG_LOG, "Storage limit reached for source " + appSource.getName());
break;
case SyncListener.SERVER_FULL_ERROR:
Log.error(TAG_LOG, "Server quota full for source " + appSource.getName());
break;
}
}
}
}