/* * 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.source; import java.util.Hashtable; import com.funambol.client.controller.UISyncSourceController; import com.funambol.client.controller.SynchronizationController; import com.funambol.client.ui.SettingsUISyncSource; import com.funambol.client.ui.DevSettingsUISyncSource; import com.funambol.client.ui.UISyncSource; import com.funambol.client.ui.Screen; import com.funambol.sync.SyncListener; import com.funambol.sync.SyncSource; import com.funambol.syncml.protocol.SyncML; import com.funambol.util.Log; /** * This class represents a sync source in the application. In the application a * sync source is a pluggable component that allow users to deal with the * synchronization of a given type of data. An AppSyncSource abstracts the * following concepts: * * 1) SyncSource (at SyncML API level) * 2) Displayable name * 3) Icon (optional) * 4) Main configuration screen * 5) numerical ID (set by the application and optional) * 6) Persistable configuration (stored in AppSyncSourceConfig) * 7) Position in the UI * 8) UI representation in home and settings screens (the UI in the home screen * can be different for a stand alone source, and a multi sources situation) * 9) UI controller * * An abstract sync source can be in different status, depending on various * things: * * 1) active if it is enabled in the customization and the server supports it * 2) enabled if the user enabled it in the settings (or if enabled by default) * 3) working if the client was able to set up all the bits and pieces to * perform synchronizations * */ public class AppSyncSource { private static final String TAG_LOG = "AppSyncSource"; // Possible AppSyncSource settings public static final int SYNC_MODE_SETTING = 0; public static final int SYNC_FOLDER_SETTING = 1; protected SyncSource source; private String name; private int id = -1; private String enabledLabel = null; private String disabledLabel = null; private String iconName = null; private String iconDisabledName = null; private ExternalAppManager appManager = null; private int uiSourceIndex = -1; protected UISyncSource uiSource = null; private UISyncSourceController controller = null; protected SettingsUISyncSource settingsUISource = null; protected DevSettingsUISyncSource devSettingsUISource = null; protected boolean refreshFromServerSupported = true; protected boolean refreshToServerSupported = true; private Object nativeListener = null; private boolean visible = true; protected boolean useBandwidthSaver = false; protected AppSyncSourceConfig config; private boolean syncedInSession = false; private boolean isMedia = false; protected Class settingsClass = null; protected Class devSettingsClass = null; protected Class buttonClass = null; protected Class aloneClass = null; protected Class uiSyncSourceControllerClass = null; // Lists all the settings with the possible values assiciated with this source private Hashtable settings = new Hashtable(); public AppSyncSource(String name, SyncSource source) { this.name = name; this.source = source; this.enabledLabel = ""; this.disabledLabel = ""; } public AppSyncSource(String name) { this(name, null); } public void setConfig(AppSyncSourceConfig config) { this.config = config; } public AppSyncSourceConfig getConfig() { return config; } public void setId(int id) { this.id = id; } public int getId() { return id; } /** * Convenience method to get if a source is enabled. * @deprecated Use AppSyncSourceConfig directly instead */ public boolean isEnabled() { return config.getEnabled(); } public void setBandwidthSaverUse(boolean activate){ useBandwidthSaver = activate; } public boolean getBandwidthSaverUse(){ return useBandwidthSaver; } public int getUiSourceIndex() { return uiSourceIndex; } public void setUiSourceIndex(int index) { this.uiSourceIndex=index; } public void setSyncSource(final SyncSource source) { this.source = source; } public void setAppManager(ExternalAppManager manager) { this.appManager = manager; } public ExternalAppManager getAppManager() { return appManager; } public SyncSource getSyncSource() { return source; } public String getName() { return name; } public String getEnabledLabel() { return enabledLabel; } public void setEnabledLabel(String enabledLabel) { this.enabledLabel = enabledLabel; } public String getDisabledLabel() { return disabledLabel; } public void setDisabledLabel(String disabledLabel) { this.disabledLabel = disabledLabel; } public boolean isWorking() { return source != null; } public String getIconName() { return iconName; } public void setIconName(String name) { iconName = name; } public void setDisabledIconName(String name) { iconDisabledName = name; } public String getDisabledIconName() { return iconDisabledName; } public UISyncSource getUISyncSource() { return uiSource; } public void setButtonUIClass(Class buttonClass) { this.buttonClass = buttonClass; } public void setAloneUIClass(Class aloneClass) { this.aloneClass = aloneClass; } public void setUISyncSourceControllerClass(Class uiSyncSourceControllerClass) { this.uiSyncSourceControllerClass = uiSyncSourceControllerClass; } public UISyncSourceController getUISyncSourceController() { return controller; } public void setUISyncSourceController(UISyncSourceController controller) { this.controller = controller; } public Class getSettingsUIClass() { return settingsClass; } public void setSettingsUIClass(Class settingsClass) { this.settingsClass = settingsClass; } public Class getDevSettingsUIClass() { return devSettingsClass; } public void setDevSettingsUIClass(Class devSettingsClass) { this.devSettingsClass = devSettingsClass; } public SettingsUISyncSource getSettingsUISyncSource() { return settingsUISource; } public DevSettingsUISyncSource getDevSettingsUISyncSource() { return devSettingsUISource; } public boolean hasSettings() { return settings.size() > 0; } public boolean hasSetting(int setting) { return settings.containsKey(new Integer(setting)); } public Hashtable getSettings() { return settings; } public void setHasSetting(int setting, boolean value, Object possibleValues) { if(value) { settings.put(new Integer(setting), possibleValues); } else { settings.remove(new Integer(setting)); } } public int prepareRefresh(int direction) { int syncMode = 0; switch (direction) { case SynchronizationController.REFRESH_FROM_SERVER: syncMode = SyncSource.FULL_DOWNLOAD; break; case SynchronizationController.REFRESH_TO_SERVER: syncMode = SyncSource.FULL_UPLOAD; break; default: throw new IllegalArgumentException("Invalid refresh direction " + direction); } return syncMode; } public boolean isRefreshSupported(int direction) { boolean supported; switch (direction) { case SynchronizationController.REFRESH_FROM_SERVER: supported = refreshFromServerSupported; break; case SynchronizationController.REFRESH_TO_SERVER: supported = refreshToServerSupported; break; default: throw new IllegalArgumentException("Invalid refresh direction " + direction); } return supported; } public void setIsRefreshSupported(int direction, boolean value) { if (direction == SynchronizationController.REFRESH_FROM_SERVER) { refreshFromServerSupported = value; } else if (direction == SynchronizationController.REFRESH_TO_SERVER) { refreshToServerSupported = value; } else { throw new IllegalArgumentException("Invalid refresh direction " + direction); } } public void setIsRefreshSupported(boolean value) { refreshFromServerSupported = value; refreshToServerSupported = value; } public Object getNativeListener() { return nativeListener; } public void setNativeListener(Object nativeListener) { this.nativeListener = nativeListener; } public boolean isVisible() { return visible; } public void setIsVisible(boolean value) { visible = value; } /** * Returns true if this source was synced in this session. This is a * volatile property and it is reset across application restarts. * AppSyncSourceConfig has a similar property that lives across restarts */ public boolean getSyncedInSession() { return syncedInSession; } public void setSyncedInSession(boolean value) { syncedInSession = value; } /** * Returns true if this source is for media content */ public boolean getIsMedia() { return isMedia; } public void setIsMedia(boolean value) { isMedia = value; } /** * This method is invoked when there is a change in the configuration that * impacts the source config. By default the method does not do anything, * but the class can be derived to force specific behaviors */ public void reapplyConfiguration() { } public SettingsUISyncSource createSettingsUISyncSource(Screen screen) { if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG_LOG, "Creating settings UI for source: " + getName()); } if (settingsClass != null) { try { settingsUISource = (SettingsUISyncSource) settingsClass.newInstance(); } catch (Exception e) { Log.error(TAG_LOG, "Cannot instantiate settings class", e); } } else { Log.error(TAG_LOG, "Cannot create settings instance"); } if (settingsUISource == null) { throw new IllegalStateException("Cannot create UI settings"); } return settingsUISource; } /** * Factory method to create dev settings UI component. Dev Settings are * optional for each source, so this method may return null if a given * source has no advanced settings associated. */ public DevSettingsUISyncSource createDevSettingsUISyncSource(Screen screen) { if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG_LOG, "Creating dev settings UI for source: " + getName()); } if (devSettingsClass != null) { try { devSettingsUISource = (DevSettingsUISyncSource) devSettingsClass.newInstance(); } catch (Exception e) { Log.error(TAG_LOG, "Cannot instantiate dev settings class", e); } } else { Log.info(TAG_LOG, "No dev settings for source " + name); } return devSettingsUISource; } public UISyncSource createButtonUISyncSource(Screen screen) { if (buttonClass != null) { try { uiSource = (UISyncSource) buttonClass.newInstance(); } catch (Exception e) { Log.error(TAG_LOG, "Cannot instantiate button class"); } } else { Log.error(TAG_LOG, "Cannot create button instance"); } if (uiSource == null) { throw new IllegalStateException("Cannot create UI button"); } return uiSource; } public UISyncSource createAloneUISyncSource(Screen screen) { if (aloneClass != null) { try { uiSource = (UISyncSource) aloneClass.newInstance(); } catch (Exception e) { Log.error(TAG_LOG, "Cannot instantiate button class"); } } return uiSource; } /** * This method creates a proper controller for this AppSyncSource. If the * controller class has not been specified or it cannot be instantiated, * then a default UISyncSourceController is created instead. * The returned controller has not been initialized. The caller needs to * invoke its <i>init</i> method to complete the initialization. */ public UISyncSourceController createUISyncSourceController() { UISyncSourceController uiSyncSourceController = null; if (uiSyncSourceControllerClass != null) { try { uiSyncSourceController = (UISyncSourceController) uiSyncSourceControllerClass.newInstance(); } catch (Exception e) { Log.error(TAG_LOG, "Cannot instantiate button class, revert to default one"); } } if (uiSyncSourceController == null) { uiSyncSourceController = new UISyncSourceController(); } return uiSyncSourceController; } }