/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2009 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 de.chbosync.android.syncmlclient;
import java.util.Vector;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
import com.funambol.client.customization.Customization;
import com.funambol.client.localization.Localization;
import com.funambol.client.source.AppSyncSource;
import com.funambol.client.source.AppSyncSourceConfig;
import com.funambol.client.source.AppSyncSourceManager;
import com.funambol.platform.DeviceInfo;
import com.funambol.platform.DeviceInfoInterface;
import com.funambol.storage.StringKeyValueMemoryStore;
import com.funambol.sync.SourceConfig;
import com.funambol.sync.SyncSource;
import com.funambol.sync.client.CacheTracker;
import com.funambol.sync.client.ChangesTracker;
import com.funambol.sync.client.ConfigSyncSource;
import com.funambol.syncml.protocol.CTCap;
import com.funambol.syncml.protocol.CTInfo;
import com.funambol.syncml.protocol.DataStore;
import com.funambol.syncml.protocol.SourceRef;
import com.funambol.syncml.protocol.SyncCap;
import com.funambol.syncml.protocol.SyncType;
import com.funambol.syncml.spds.SyncMLAnchor;
import com.funambol.syncml.spds.SyncMLSourceConfig;
import com.funambol.util.Log;
import de.chbosync.android.syncmlclient.activities.AndroidAloneUISyncSource;
import de.chbosync.android.syncmlclient.activities.AndroidButtonUISyncSource;
import de.chbosync.android.syncmlclient.activities.settings.AndroidDevSettingsUISyncSource;
import de.chbosync.android.syncmlclient.activities.settings.AndroidSettingsUISyncSource;
import de.chbosync.android.syncmlclient.services.AutoSyncServiceHandler;
import de.chbosync.android.syncmlclient.source.AbstractDataManager;
import de.chbosync.android.syncmlclient.source.pim.AndroidPIMCacheTracker;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarAppSyncSource;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarAppSyncSourceConfig;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarChangesTracker;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarExternalAppManager;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarManager;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarSettingsUISyncSource;
import de.chbosync.android.syncmlclient.source.pim.calendar.CalendarSyncSource;
import de.chbosync.android.syncmlclient.source.pim.calendar.EventSyncSource;
import de.chbosync.android.syncmlclient.source.pim.contact.ContactAppSyncSource;
import de.chbosync.android.syncmlclient.source.pim.contact.ContactAppSyncSourceConfig;
import de.chbosync.android.syncmlclient.source.pim.contact.ContactExternalAppManager;
import de.chbosync.android.syncmlclient.source.pim.contact.ContactManager;
import de.chbosync.android.syncmlclient.source.pim.contact.ContactSettingsUISyncSource;
import de.chbosync.android.syncmlclient.source.pim.contact.ContactSyncSource;
import de.chbosync.android.syncmlclient.source.pim.contact.DirtyChangesTracker;
import de.chbosync.android.syncmlclient.source.pim.contact.FunambolContactManager;
import de.chbosync.android.syncmlclient.source.pim.note.NoteSyncSource;
import de.chbosync.android.syncmlclient.source.pim.note.OINoteManager;
import de.chbosync.android.syncmlclient.source.pim.task.AstridTaskManager;
/**
* A manager for the AndroidAppSyncSource instances in use by the Android client
* The access to this class can be made invoking the static method getInstance()
* as the pattern was realized as Singleton. Once the instance is no more used
* by the caller it is suitable to call the dispose() method in order to release
* this class' resources as soon as possible.
*/
public class AndroidAppSyncSourceManager extends AppSyncSourceManager {
private static final String TAG_LOG = "AndroidAppSyncSourceManager";
private static AndroidAppSyncSourceManager instance = null;
private Localization localization;
private Context context;
private DeviceInfoInterface deviceInfo;
private AutoSyncServiceHandler autoSyncService;
/**
* The private constructor that enforce the Singleton implementation
* @param customization the Customization object to be referred to
* @param localization the Localization pattern for this manager
* @param context the Context object to be related to the manager
*/
private AndroidAppSyncSourceManager(Customization customization,
Localization localization,
Context context) {
super(customization);
this.localization = localization;
this.context = context;
this.deviceInfo = new DeviceInfo(context);
this.autoSyncService = new AutoSyncServiceHandler(context);
}
/**
* Single instance call
* @param customization the Customization object to be referred to
* @param localization the Localization pattern for this manager
* @param context the Context object to be related to the manager
* @return the single instance of this class, creating it if it has never
* been referenced
*/
public static AndroidAppSyncSourceManager getInstance(Customization customization,
Localization localization,
Context context) {
if (instance == null) {
instance = new AndroidAppSyncSourceManager(customization, localization, context);
}
return instance;
}
/**
* Dispose the single instance referencing it with the null object
*/
public static void dispose() {
instance = null;
}
/**
* Setup the SyncSource identified by its sourceId index
* @param sourceId the int that identifies the source
* @param configuration the AndroidConfiguration object used to setup the
* source
* @return AppSyncSource the instance of the setup AppSyncSource
* @throws Exception
*/
public AppSyncSource setupSource(int sourceId, AndroidConfiguration configuration) throws Exception {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG_LOG, "Setting up source: " + sourceId);
}
AppSyncSource appSource;
switch(sourceId) {
case CONTACTS_ID:
{
appSource = setupContactsSource(configuration);
break;
}
case EVENTS_ID:
{
appSource = setupEventsSource(configuration);
break;
}
case TASKS_ID:
{
appSource = setupTasksSource(configuration);
break;
}
case NOTES_ID:
{
appSource = setupNotesSource(configuration);
break;
}
case CONFIG_ID:
{
appSource = setupConfigSource(configuration);
break;
}
default:
throw new IllegalArgumentException("Unknown source: " + sourceId);
}
return appSource;
}
/**
* Setup the source for contacts
* @param configuration the AndroidConfiguration to be used to setup the
* source
* @return AppSyncSource related to contacts
* @throws Exception
*/
protected AppSyncSource setupContactsSource(AndroidConfiguration configuration) throws Exception {
int id = CONTACTS_ID;
String name = localization.getLanguage("type_contacts");
ContactAppSyncSource appSyncSource = new ContactAppSyncSource(context, name);
appSyncSource.setId(id);
// On the 2.0.x simulator there is no support for native sync, so in
// this case we revert to sync service method
appSyncSource.setSyncMethod(AndroidAppSyncSource.SERVICE);
appSyncSource.setAuthority(ContactsContract.AUTHORITY);
appSyncSource.setProviderUri(ContactsContract.Contacts.CONTENT_URI);
// Create the proper settings component for this source
Class basicSettings = ContactSettingsUISyncSource.class;
appSyncSource.setSettingsUIClass(basicSettings);
// Create the dev settings for this source
Class devSettings = AndroidDevSettingsUISyncSource.class;
appSyncSource.setDevSettingsUIClass(devSettings);
Class buttonView = AndroidButtonUISyncSource.class;
appSyncSource.setButtonUIClass(buttonView);
Class aloneView = (((AndroidCustomization)customization).getAloneUISyncSourceClass());
appSyncSource.setAloneUIClass(aloneView);
int order = getSourcePosition(id);
appSyncSource.setUiSourceIndex(order);
appSyncSource.setHasSetting(AppSyncSource.SYNC_MODE_SETTING,
customization.isSyncDirectionVisible(),
customization.getDefaultSourceSyncModes(id, deviceInfo.getDeviceRole()));
appSyncSource.setHasSetting(
ContactSettingsUISyncSource.DEFAULT_ADDRESS_BOOK_SETTING,
true, "");
appSyncSource.setBandwidthSaverUse(customization.useBandwidthSaverContacts());
// Create the contact manager
ContactManager cm = new FunambolContactManager(context);
SourceConfig sc = null;
if (SourceConfig.VCARD_TYPE.equals(customization.getContactType())) {
// This is vcard format
String defaultUri = customization.getDefaultSourceUri(id);
sc = new SyncMLSourceConfig("contacts", SourceConfig.VCARD_TYPE, defaultUri,
createDataStore("contacts", SourceConfig.VCARD_TYPE, "2.1", cm));
sc.setEncoding(SyncSource.ENCODING_NONE);
sc.setSyncMode(customization.getDefaultSourceSyncMode(id, deviceInfo.getDeviceRole()));
// Set this item anchor
SyncMLAnchor anchor = new SyncMLAnchor();
sc.setSyncAnchor(anchor);
}
if (sc != null) {
// Load the source config from the configuration
ContactAppSyncSourceConfig asc = new ContactAppSyncSourceConfig(
appSyncSource, customization, configuration);
asc.load(sc);
appSyncSource.setConfig(asc);
if(!asc.getUseDirtyChangesTracker()) {
// Migrate tracker store only if the user has already synced
SyncMLAnchor anchor = (SyncMLAnchor)sc.getSyncAnchor();
if(anchor.getLast() != 0) {
try {
ContactSyncSource.migrateToDirtyChangesTracker(sc, cm, context);
} catch(Throwable t) {
Log.error(TAG_LOG, "Failed to migrate changes tracker store", t);
}
}
asc.setUseDirtyChangesTracker(true);
asc.save();
}
ChangesTracker tracker = new DirtyChangesTracker(context, cm);
ContactSyncSource src = new ContactSyncSource(sc, tracker, context,
configuration, appSyncSource, cm);
appSyncSource.setSyncSource(src);
// Setup the external app manager
ContactExternalAppManager appManager =
new ContactExternalAppManager(context, appSyncSource);
appSyncSource.setAppManager(appManager);
// Inform the auto sync service that we shall monitor contacts for
// changes
autoSyncService.startMonitoringUri(appSyncSource.getProviderUri().toString(), appSyncSource.getId());
} else {
Log.error(TAG_LOG, "The contact sync source does not support the type: " +
customization.getContactType());
Log.error(TAG_LOG, "Contact source will be disabled as not working");
}
return appSyncSource;
}
/**
* Setup the source for tasks
* @param configuration the AndroidConfiguration to be used to setup the
* source
* @return AppSyncSource related to events
* @throws Exception
*/
protected AppSyncSource setupTasksSource(AndroidConfiguration configuration) throws Exception {
int id = TASKS_ID;
String name = localization.getLanguage("type_tasks");
AndroidAppSyncSource appSyncSource = new AndroidAppSyncSource(name);
appSyncSource.setId(id);
appSyncSource.setSyncMethod(AndroidAppSyncSource.SERVICE);
appSyncSource.setAuthority(AstridTaskManager.AUTHORITY);
appSyncSource.setProviderUri(AstridTaskManager.Tasks.CONTENT_URI);
// Create the proper settings component for this source
Class calendarSettings = CalendarSettingsUISyncSource.class;
appSyncSource.setSettingsUIClass(calendarSettings);
// Create the dev settings for this source
Class devSettings = AndroidDevSettingsUISyncSource.class;
appSyncSource.setDevSettingsUIClass(devSettings);
Class buttonView = AndroidButtonUISyncSource.class;
appSyncSource.setButtonUIClass(buttonView);
Class aloneView = AndroidAloneUISyncSource.class;
appSyncSource.setAloneUIClass(aloneView);
int order = getSourcePosition(id);
appSyncSource.setUiSourceIndex(order);
appSyncSource.setHasSetting(AppSyncSource.SYNC_MODE_SETTING,
customization.isSyncDirectionVisible(),
customization.getDefaultSourceSyncModes(id, deviceInfo.getDeviceRole()));
AstridTaskManager dm = new AstridTaskManager(context, appSyncSource);
SourceConfig sc = null;
String defaultUri = customization.getDefaultSourceUri(id);
sc = new SyncMLSourceConfig("task", customization.getCalendarType(), defaultUri,
createDataStore("task", customization.getCalendarType(), "1.0", dm));
sc.setEncoding(SyncSource.ENCODING_NONE);
sc.setSyncMode(customization.getDefaultSourceSyncMode(id, deviceInfo.getDeviceRole()));
// Set this item anchor
SyncMLAnchor anchor = new SyncMLAnchor();
sc.setSyncAnchor(anchor);
AppSyncSourceConfig asc = new AppSyncSourceConfig(appSyncSource, customization, configuration);
asc.load(sc);
appSyncSource.setConfig(asc);
// We need a third party app to sync task. At the moment we only support
// Astrid, so we check for its availability and version
PackageManager pm = context.getPackageManager();
try {
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Checking if Astrid is available");
}
//ProviderInfo info = pm.resolveContentProvider("com.todoroo.astrid", 0);
ProviderInfo info = pm.resolveContentProvider("com.eztransition.tasquid", 0); // Changed for ChBoSync
if (info != null) {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG_LOG, "Astrid provider found, enable task source");
}
} else {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG_LOG, "Astrid provider not found, disable task source");
}
asc.setActive(false);
return appSyncSource;
}
} catch (Exception e) {
Log.error(TAG_LOG, "Error detecting Astrid", e);
asc.setActive(false);
return appSyncSource;
}
// Create the sync source
IntKeyValueSQLiteStore trackerStore =
new IntKeyValueSQLiteStore(context,
((AndroidCustomization)customization).getFunambolSQLiteDbName(),
sc.getName());
// Since we sync calendars that our app does not owe, we cannot use sync
// fields and calendars do not have revisions, so we are forced to use a
// CacheTracker here (based on MD5)
AndroidPIMCacheTracker tracker = new AndroidPIMCacheTracker(context, trackerStore);
CalendarSyncSource src = new CalendarSyncSource(sc, tracker, context, configuration, appSyncSource, dm);
appSyncSource.setSyncSource(src);
// Setup the external app manager
//CalendarExternalAppManager appManager = new CalendarExternalAppManager(context, appSyncSource);
//appSyncSource.setAppManager(appManager);
// Inform the auto sync service that we shall monitor contacts for
// changes
autoSyncService.startMonitoringUri(appSyncSource.getProviderUri().toString(), appSyncSource.getId());
return appSyncSource;
}
/**
* Setup the source for notes
* @param configuration the AndroidConfiguration to be used to setup the
* source
* @return AppSyncSource related to events
* @throws Exception
*/
protected AppSyncSource setupNotesSource(AndroidConfiguration configuration) throws Exception {
int id = NOTES_ID;
String name = localization.getLanguage("type_notes");
AndroidAppSyncSource appSyncSource = new AndroidAppSyncSource(name);
appSyncSource.setId(id);
appSyncSource.setSyncMethod(AndroidAppSyncSource.SERVICE);
appSyncSource.setAuthority(OINoteManager.AUTHORITY);
appSyncSource.setProviderUri(OINoteManager.Notes.CONTENT_URI);
// Create the proper settings component for this source
Class calendarSettings = AndroidSettingsUISyncSource.class;
appSyncSource.setSettingsUIClass(calendarSettings);
// Create the dev settings for this source
Class devSettings = AndroidDevSettingsUISyncSource.class;
appSyncSource.setDevSettingsUIClass(devSettings);
Class buttonView = AndroidButtonUISyncSource.class;
appSyncSource.setButtonUIClass(buttonView);
Class aloneView = AndroidAloneUISyncSource.class;
appSyncSource.setAloneUIClass(aloneView);
int order = getSourcePosition(id);
appSyncSource.setUiSourceIndex(order);
appSyncSource.setHasSetting(AppSyncSource.SYNC_MODE_SETTING,
customization.isSyncDirectionVisible(),
customization.getDefaultSourceSyncModes(id, deviceInfo.getDeviceRole()));
OINoteManager dm = new OINoteManager(context, appSyncSource);
SourceConfig sc = null;
String defaultUri = customization.getDefaultSourceUri(id);
sc = new SyncMLSourceConfig("note", customization.getNoteType(), defaultUri,
createDataStore("note", customization.getNoteType(), "1.0", dm));
sc.setEncoding(SyncSource.ENCODING_NONE);
sc.setSyncMode(customization.getDefaultSourceSyncMode(id, deviceInfo.getDeviceRole()));
SyncMLAnchor anchor = new SyncMLAnchor();
sc.setSyncAnchor(anchor);
AppSyncSourceConfig asc = new AppSyncSourceConfig(appSyncSource, customization, configuration);
asc.load(sc);
appSyncSource.setConfig(asc);
// We need a third party app to sync task. At the moment we only support
// "OI Notepad", so we check for its availability and version
PackageManager pm = context.getPackageManager();
try {
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG_LOG, "Checking if Open Intent Notepad is available");
}
ProviderInfo info = pm.resolveContentProvider("org.openintents.notepad", 0);
if (info != null)
{
OINoteManager.setOINotepadInstalled(true);
if (Log.isLoggable(Log.INFO))
Log.info(TAG_LOG, "Open Intent Notepad provider found, enable note source");
}
else
{
OINoteManager.setOINotepadInstalled(false);
if (Log.isLoggable(Log.INFO))
Log.info(TAG_LOG, "Open Intent Notepad provider not found, disable note source");
asc.setActive(false);
return appSyncSource;
}
} catch (Exception e) {
Log.error(TAG_LOG, "Error detecting Open Intent Notepad", e);
asc.setActive(false);
return appSyncSource;
}
// Create the sync source
IntKeyValueSQLiteStore trackerStore =
new IntKeyValueSQLiteStore(context,
((AndroidCustomization)customization).getFunambolSQLiteDbName(),
sc.getName());
AndroidPIMCacheTracker tracker = new AndroidPIMCacheTracker(context, trackerStore);
NoteSyncSource src = new NoteSyncSource(sc, tracker, context, configuration, appSyncSource, dm);
appSyncSource.setSyncSource(src);
// Inform the auto sync service that we shall monitor contacts for
// changes
autoSyncService.startMonitoringUri(appSyncSource.getProviderUri().toString(), appSyncSource.getId());
// Setup the external app manager
//CalendarExternalAppManager appManager = new CalendarExternalAppManager(context, appSyncSource);
//appSyncSource.setAppManager(appManager);
return appSyncSource;
}
/**
* Setup the source for events
* @param configuration the AndroidConfiguration to be used to setup the
* source
* @return AppSyncSource related to events
* @throws Exception
*/
protected AppSyncSource setupEventsSource(AndroidConfiguration configuration) throws Exception {
int id = EVENTS_ID;
String name = localization.getLanguage("type_calendar");
CalendarAppSyncSource appSyncSource = new CalendarAppSyncSource(context, name);
appSyncSource.setId(id);
appSyncSource.setSyncMethod(AndroidAppSyncSource.SERVICE);
appSyncSource.setAuthority(CalendarContract.AUTHORITY);
appSyncSource.setProviderUri(CalendarContract.Events.CONTENT_URI);
// Create the proper settings component for this source
Class calendarSettings = CalendarSettingsUISyncSource.class;
appSyncSource.setSettingsUIClass(calendarSettings);
// Create the dev settings for this source
Class devSettings = AndroidDevSettingsUISyncSource.class;
appSyncSource.setDevSettingsUIClass(devSettings);
Class buttonView = AndroidButtonUISyncSource.class;
appSyncSource.setButtonUIClass(buttonView);
Class aloneView = (((AndroidCustomization)customization).getAloneUISyncSourceClass());
appSyncSource.setAloneUIClass(aloneView);
int order = getSourcePosition(id);
appSyncSource.setUiSourceIndex(order);
appSyncSource.setHasSetting(AppSyncSource.SYNC_MODE_SETTING,
customization.isSyncDirectionVisible(),
customization.getDefaultSourceSyncModes(id, deviceInfo.getDeviceRole()));
CalendarManager dm = new CalendarManager(context, appSyncSource);
SourceConfig sc = null;
String defaultUri = customization.getDefaultSourceUri(id);
sc = new SyncMLSourceConfig("calendar", customization.getCalendarType(), defaultUri,
createDataStore("calendar", customization.getCalendarType(), "1.0", dm));
sc.setEncoding(SyncSource.ENCODING_NONE);
sc.setSyncMode(customization.getDefaultSourceSyncMode(id, deviceInfo.getDeviceRole()));
// Set this item anchor
SyncMLAnchor anchor = new SyncMLAnchor();
sc.setSyncAnchor(anchor);
CalendarAppSyncSourceConfig asc = new CalendarAppSyncSourceConfig(
appSyncSource, customization, configuration);
asc.load(sc);
appSyncSource.setConfig(asc);
appSyncSource.setBandwidthSaverUse(customization.useBandwidthSaverEvents());
// Create the sync source
IntKeyValueSQLiteStore trackerStore =
new IntKeyValueSQLiteStore(context,
((AndroidCustomization)customization).getFunambolSQLiteDbName(),
sc.getName());
CalendarChangesTracker tracker = new CalendarChangesTracker(context, trackerStore, asc);
EventSyncSource src = new EventSyncSource(sc, tracker, context, configuration, appSyncSource, dm);
appSyncSource.setSyncSource(src);
// Setup the external app manager
CalendarExternalAppManager appManager = new CalendarExternalAppManager(context, appSyncSource);
appSyncSource.setAppManager(appManager);
// If the user is already logged in and there is no valid calendar to
// sync, then we better recreate it here
if (!configuration.getCredentialsCheckPending()) {
boolean recreateCalendar = false;
// If the calendar id is undefined, or no longer exists, then we
// recreate the funambol calendar
long calendarId = asc.getCalendarId();
if (calendarId == -1) {
recreateCalendar = true;
} else {
if (!dm.exists(""+calendarId)) {
recreateCalendar = true;
}
}
if (recreateCalendar) {
Log.info(TAG_LOG, "Creating account calendar because it does not exist");
try {
calendarId = appSyncSource.createCalendar();
Log.info(TAG_LOG, "Calendar created with id " + calendarId);
asc.setCalendarId(calendarId);
asc.save();
} catch (Exception e) {
Log.error(TAG_LOG, "Cannot create account calendar", e);
}
}
}
// Inform the auto sync service that we shall monitor contacts for
// changes
autoSyncService.startMonitoringUri(CalendarContract.Events.CONTENT_URI.toString(), appSyncSource.getId());
// Add the reminder table URI to the list of monitored uris
autoSyncService.startMonitoringUri(CalendarContract.Reminders.CONTENT_URI.toString(), appSyncSource.getId());
return appSyncSource;
}
/**
* Setup the source for config
* @param configuration the AndroidConfiguration to be used to setup the
* source
* @return AppSyncSource related to config
* @throws Exception
*/
private AppSyncSource setupConfigSource(AndroidConfiguration configuration) throws Exception {
int id = CONFIG_ID;
// This source is invisible, don't care about the name and its
// localization
String name = "config";
AndroidAppSyncSource configSource = new AndroidAppSyncSource(name);
configSource.setId(id);
configSource.setEnabledLabel(null);
configSource.setDisabledLabel(null);
configSource.setIconName(null);
configSource.setDisabledIconName(null);
configSource.setUiSourceIndex(0);
configSource.setIsRefreshSupported(false);
configSource.setIsVisible(false);
configSource.setSyncMethod(AndroidAppSyncSource.DIRECT);
SourceConfig sc = new SourceConfig("config", SourceConfig.BRIEFCASE_TYPE,
customization.getDefaultSourceUri(id));
sc.setEncoding(SyncSource.ENCODING_NONE);
sc.setSyncMode(customization.getDefaultSourceSyncMode(id, deviceInfo.getDeviceRole()));
// Set the sync anchor
SyncMLAnchor anchor = new SyncMLAnchor();
sc.setSyncAnchor(anchor);
AppSyncSourceConfig asc = new AppSyncSourceConfig(configSource, customization, configuration);
asc.load(sc);
configSource.setConfig(asc);
StringKeyValueMemoryStore configStore = new StringKeyValueMemoryStore();
StringKeyValueMemoryStore cacheStore = new StringKeyValueMemoryStore();
CacheTracker tracker = new CacheTracker(cacheStore);
SyncSource syncSource = new ConfigSyncSource(sc, tracker, configStore);
// Reset the underlying sync source
configSource.setSyncSource(syncSource);
return configSource;
}
@SuppressWarnings("unchecked")
private DataStore createDataStore(String name, String type, String version,
@SuppressWarnings("rawtypes") AbstractDataManager dm) {
DataStore ds = new DataStore();
SourceRef sr = new SourceRef();
sr.setValue(name);
ds.setSourceRef(sr);
CTInfo rxPref = new CTInfo();
rxPref.setCTType(type);
rxPref.setVerCT(version);
ds.setRxPref(rxPref);
CTInfo txPref = new CTInfo();
txPref.setCTType(type);
txPref.setVerCT(version);
ds.setTxPref(txPref);
SyncCap syncCap = new SyncCap();
@SuppressWarnings("rawtypes")
Vector types = new Vector();
types.addElement(SyncType.TWO_WAY);
types.addElement(SyncType.SLOW);
types.addElement(SyncType.SERVER_ALERTED);
syncCap.setSyncType(types);
ds.setSyncCap(syncCap);
// Max GUID size set to 2 bytes as default
ds.setMaxGUIDSize(2);
Vector properties = dm.getSupportedProperties();
if(properties != null) {
Vector ctCaps = new Vector();
CTCap ctCap = new CTCap();
ctCap.setCTInfo(new CTInfo(type, version));
ctCap.setProperties(properties);
ctCaps.add(ctCap);
ds.setCTCaps(ctCaps);
}
return ds;
}
}