/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2010 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.test.contact; import java.io.ByteArrayOutputStream; import java.util.Vector; import java.util.Enumeration; import com.funambol.org.json.me.JSONObject; import com.funambol.org.json.me.JSONArray; import com.funambol.client.source.AppSyncSource; import com.funambol.client.source.AppSyncSourceManager; import com.funambol.client.configuration.Configuration; import com.funambol.client.test.ClientTestException; import com.funambol.client.test.Robot; import com.funambol.client.test.basic.BasicRobot; import com.funambol.sapisync.sapi.SapiHandler; import com.funambol.sync.SyncItem; import com.funambol.sync.SyncSource; import com.funambol.sync.ItemStatus; import com.funambol.util.StringUtil; import com.funambol.util.Log; public abstract class ContactsRobot extends Robot { private static final String TAG_LOG = "ContactsRobot"; protected static final char FOLDING_INDENT_CHAR = ' '; protected long currentContactId = -1; protected long incrementalServerItemkey = 10000000; protected String contactAsVcard = null; protected BasicRobot basicRobot; protected AppSyncSourceManager appSourceManager; protected SapiHandler sapiHandler = null; public ContactsRobot(AppSyncSourceManager appSourceManager) { this.appSourceManager = appSourceManager; } private SapiHandler getSapiHandler() { if (sapiHandler == null) { Configuration configuration = getConfiguration(); sapiHandler = new SapiHandler(StringUtil.extractAddressFromUrl( configuration.getSyncUrl()), configuration.getUsername(), configuration.getPassword()); } return sapiHandler; } public void saveContactOnServer(String firstName, String lastName) throws Throwable { SapiHandler sapiHandler = getSapiHandler(); Vector params = new Vector(); // Is this an add or an update? String id = findContactIdOnServer(firstName, lastName); StringBuffer jsonContact = new StringBuffer(); jsonContact.append("{"); if (id != null) { jsonContact.append("\"id\":\"").append(id).append("\","); } jsonContact.append("\"firstname\":\"").append(firstName) .append("\",\"lastname\":\"").append(lastName).append("\"}"); params.addElement("data=" + jsonContact.toString()); Log.trace(TAG_LOG, "Save contact: " + jsonContact.toString()); JSONObject resp = sapiHandler.query("contacts","contactsave",params,null,null); if (id == null) { id = resp.getString("id"); Log.debug(TAG_LOG, "The new contact has id=" + id); } } public void saveContactOnServer(String jsonObj) throws Throwable { // Unescape the parameter jsonObj = StringUtil.replaceAll(jsonObj, ""","\""); jsonObj = StringUtil.replaceAll(jsonObj, ",",","); Log.trace(TAG_LOG, "JSON contact is: " + jsonObj); JSONObject jsonContact = new JSONObject(jsonObj); // If the values are not available, an excpetion is thrown String firstName = jsonContact.getString("firstname"); String lastName = jsonContact.getString("lastname"); Log.trace(TAG_LOG, "firstName=" + firstName + ",lastName=" + lastName); SapiHandler sapiHandler = getSapiHandler(); Vector params = new Vector(); // Is this an add or an update? String id = findContactIdOnServer(firstName, lastName); Log.trace(TAG_LOG, "Server id=" + id); if (id != null) { jsonContact.put("id",id); } params.addElement("data=" + jsonContact.toString()); JSONObject resp = sapiHandler.query("contact","contactsave",params,null,null); if (id == null) { id = resp.getString("id"); Log.debug(TAG_LOG, "The new contact has id=" + id); } } private String findContactIdOnServer(String firstName, String lastName) throws Throwable { SapiHandler sapiHandler = getSapiHandler(); JSONObject resp = sapiHandler.query("contact","get",null,null,null); if (resp.has("contacts")) { JSONArray contacts = resp.getJSONArray("contacts"); for(int i=0;i<contacts.length();++i) { JSONObject c = contacts.getJSONObject(i); String fName = c.getString("firstname"); String lName = c.getString("lastname"); if (firstName.equals(fName) && lastName.equals(lName)) { String id = c.getString("id"); return id; } } } return null; } public void deleteContactOnServer(String firstName, String lastName) throws Throwable { String id = findContactIdOnServer(firstName, lastName); if (id == null) { throw new ClientTestException("Contact not available on server"); } Log.trace(TAG_LOG, "Deleting contact on server with key: " + id); SapiHandler sapiHandler = getSapiHandler(); Vector params = new Vector(); JSONObject param = new JSONObject(); Vector ids = new Vector(); ids.addElement(id); param.put("contacts", ids); params.addElement("data="+param.toString()); sapiHandler.query("contacts","contactsdelete",params,null,null); } public void deleteAllContactsOnServer() throws Throwable { // Do this via SAPI to increase performance SapiHandler sapiHandler = getSapiHandler(); sapiHandler.query("contacts","reset",null,null,null); } public void setContactAsVCard(String vCard) throws Throwable{ String[] sep = new String[]{"\\r\\n"}; String[] parts = StringUtil.split(vCard, sep); ByteArrayOutputStream ostream = new ByteArrayOutputStream(); for (int i=0;i<parts.length;i++){ ostream.write(parts[i].getBytes()); ostream.write("\r\n".getBytes()); } contactAsVcard = ostream.toString(); ostream.close(); } public void resetContacts() throws Throwable { // Remove locally deleteAllContacts(); deleteAllContactsOnServer(); } public void checkItemsCountOnServer(int count) throws Throwable { SapiHandler sapiHandler = getSapiHandler(); JSONObject resp = sapiHandler.query("contacts","count",null,null,null); int serverCount = resp.getInt("count"); assertTrue(count, serverCount, "Server contacts count mismatch"); } public void setContactFromServer(String vCard) throws Throwable { vCard = StringUtil.replaceAll(vCard, "\\r\\n", "\r\n"); // We add an item via the SyncSource SyncSource source = getSyncSource(); SyncItem item = new SyncItem("guid", "text/x-vcard", SyncItem.STATE_NEW, null); item.setContent(vCard.getBytes("UTF-8")); Vector items = new Vector(); items.addElement(item); source.applyChanges(items); } public void checkContactsCount(int count) throws Throwable { SyncSource source = getSyncSource(); source.beginSync(SyncSource.FULL_SYNC, false); // Resets the tracker status int itemsCount = 0; SyncItem item = source.getNextItem(); Vector items = new Vector(); while(item != null) { itemsCount++; items.addElement(new ItemStatus(item.getKey(), SyncSource.SUCCESS_STATUS)); item = source.getNextItem(); } source.applyItemsStatus(items); source.endSync(); assertTrue(count, itemsCount, "Contacts count mismatch"); } protected AppSyncSourceManager getAppSyncSourceManager() { return appSourceManager; } protected void checkContactAsVCard(String vcard) throws Throwable { String currentVCard = getCurrentContactVCard(); // The incoming vcard has \r\n as strings, we shall replace them vcard = StringUtil.replaceAll(vcard, "\\r\\n", "\r\n"); if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG_LOG, "vcard.length=" + vcard.length()); } if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG_LOG, "currentVCard.length=" + currentVCard.length()); } assertTrue(currentVCard, vcard, "VCard mismatch"); } private SyncSource getSyncSource() { Enumeration sources = getAppSyncSourceManager().getWorkingSources(); AppSyncSource appSource = null; while(sources.hasMoreElements()) { appSource = (AppSyncSource)sources.nextElement(); if (appSource.getId() == AppSyncSourceManager.CONTACTS_ID) { break; } } // We add an item via the SyncSource SyncSource source = appSource.getSyncSource(); return source; } protected abstract Configuration getConfiguration(); public abstract void createEmptyContact() throws Throwable; public abstract void setContactField(String field, String value) throws Throwable; public abstract void saveContact() throws Throwable; public abstract void deleteContact(String firstname, String lastname) throws Throwable; public abstract void deleteAllContacts() throws Throwable; public abstract void loadContact(String firstName, String lastName) throws Throwable; protected abstract String getCurrentContactVCard() throws Throwable; public abstract void createEmptyRawContact() throws Throwable; public abstract void setRawContactData(String mimeType, Vector dataValues) throws Throwable; public abstract void saveRawContact() throws Throwable; public abstract void checkRawContactData(String mimeType, Vector dataValues) throws Throwable; public abstract void checkRawContactAsVCard(String vcal) throws Throwable; }