Sync up to the latest version of my source code
[funambol-citadel-connector.git] / funambol-citadel-connector / src / main / java / net / bionicmessage / funambol / citadel / sync / CitadelSyncSource.java
blob4b61e219efe91514958b2d6a2a98ed27a2fd8c69
1 /*
2 * Funambol Citadel Connector
3 * (C) 2007-2008 Mathew McBride
4 * http://bionicmessage.net
5 *
6 * Portions of code may come from:
7 * Funambol is a mobile platform developed by Funambol, Inc.
8 * Copyright (C) 2003 - 2007 Funambol, Inc.
10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU Affero General Public License version 3 as published by
12 * the Free Software Foundation with the addition of the following permission
13 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
14 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
15 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
17 * This program is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
20 * details.
22 * You should have received a copy of the GNU Affero General Public License
23 * along with this program; if not, see http://www.gnu.org/licenses or write to
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 * MA 02110-1301 USA.
27 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
28 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
30 * The interactive user interfaces in modified source and object code versions
31 * of this program must display Appropriate Legal Notices, as required under
32 * Section 5 of the GNU Affero General Public License version 3.
34 * In accordance with Section 7(b) of the GNU Affero General Public License
35 * version 3, these Appropriate Legal Notices must retain the display of the
36 * "Powered by Funambol" logo. If the display of the logo is not reasonably
37 * feasible for technical reasons, the Appropriate Legal Notices must display
38 * the words "Powered by Funambol".
40 package net.bionicmessage.funambol.citadel.sync;
42 import com.funambol.email.engine.source.HelperForFilter;
43 import com.funambol.email.exception.EntityException;
44 import com.funambol.email.model.EmailFilter;
45 import com.funambol.email.pdi.converter.FolderToXML;
46 import com.funambol.email.pdi.folder.Folder;
47 import com.funambol.email.pdi.parser.XMLFolderParser;
48 import com.funambol.email.util.Def;
49 import com.funambol.framework.core.AlertCode;
50 import com.funambol.framework.engine.SyncItem;
51 import com.funambol.framework.engine.SyncItemImpl;
52 import com.funambol.framework.engine.SyncItemKey;
53 import com.funambol.framework.engine.SyncItemState;
54 import com.funambol.framework.engine.source.AbstractSyncSource;
55 import com.funambol.framework.engine.source.FilterableSyncSource;
56 import com.funambol.framework.engine.source.SyncContext;
57 import com.funambol.framework.engine.source.SyncSourceException;
58 import java.io.ByteArrayInputStream;
59 import java.io.File;
60 import java.io.IOException;
61 import java.sql.Timestamp;
62 import java.util.ArrayList;
63 import java.util.Date;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.Properties;
69 import java.util.logging.FileHandler;
70 import java.util.logging.Level;
71 import java.util.logging.Logger;
72 import net.bionicmessage.funambol.citadel.store.CitadelMailObject;
73 import net.bionicmessage.funambol.citadel.store.CtdlFnblConstants;
74 import net.bionicmessage.funambol.citadel.store.EmailObjectStore;
75 import net.bionicmessage.funambol.citadel.util.HTMLFormatter;
76 import net.bionicmessage.funambol.util.Lookup;
78 /**
80 * @author matt
82 public class CitadelSyncSource extends AbstractSyncSource implements FilterableSyncSource {
84 protected SyncContext ctx = null;
85 protected EmailObjectStore eos = null;
86 protected Properties syncSourceProperties = null;
87 protected Logger log = null;
88 protected String storeLoc = null;
89 protected FileHandler fh = null;
90 public static final SyncItemKey inboxKey = new SyncItemKey("ROOT/I");
91 public static final SyncItemKey sentKey = new SyncItemKey("ROOT/S");
92 public static final SyncItemKey trashKey = new SyncItemKey("ROOT/T");
93 public static final SyncItemKey outboxKey = new SyncItemKey("ROOT/O");
94 protected EmailFilter filter = null;
95 protected String userStoreLoc = null;
96 private SyncItemKey[] updatedSyncItemKeys = null;
98 private boolean startedSync = false;
99 public void CitadelSyncSource() {
103 * Called before any other synchronization method. To interrupt the sync
104 * process, throw a SyncSourceException.
106 * @param syncContext the context of the sync.
108 * @see SyncContext
110 * @throws SyncSourceException to interrupt the process with an error
112 public void beginSync(SyncContext syncContext) throws SyncSourceException {
113 log = Logger.getLogger(CtdlFnblConstants.SYNC_SOURCE_LOGGER + "-" + System.currentTimeMillis());
114 this.ctx = syncContext;
115 storeLoc = syncSourceProperties.getProperty(CtdlFnblConstants.STORE_LOC);
116 //todo: escape
117 userStoreLoc = storeLoc + File.separatorChar + ctx.getPrincipal().getDeviceId()+"_"+ctx.getPrincipal().getUsername();
119 File storeDir = new File(userStoreLoc);
120 if (!storeDir.exists()) {
121 storeDir.mkdirs();
123 try {
124 setupLogging();
125 log.info("beginSync(" + ctx.getPrincipal().getName() + ")");
126 } catch (IOException ex) {
127 throw new SyncSourceException("Cannot set up logging", ex);
129 Properties storeProps = new Properties(syncSourceProperties);
130 storeProps.setProperty(CtdlFnblConstants.STORE_LOC, userStoreLoc);
131 if (ctx.getSyncMode() == AlertCode.SLOW) {
132 log.info("Slow sync mode. Purging old data");
133 storeProps.setProperty(CtdlFnblConstants.PURGE_DB_OPTION, "");
135 eos = new EmailObjectStore(storeProps);
136 eos.setCredentials(ctx.getPrincipal().getUsername(),
137 ctx.getPrincipal().getUser().getPassword());
138 if (ctx.getFilterClause() != null && ctx.getFilterClause().getClause() != null) {
139 try {
140 filter = HelperForFilter.setFilter(ctx, 1, 2, true, true, false, false, false);
141 } catch (EntityException ex) {
142 log.log(Level.SEVERE, "Error setting up filter", ex);
146 try {
147 long fromTime = 0;
148 if (filter != null && filter.getTime() != null)
149 fromTime = filter.getTime().getTime();
150 eos.startSync(fromTime);
151 startedSync = true;
152 } catch (Exception ex) {
153 log.log(Level.SEVERE, "Failure in server sync", ex);
154 throw new SyncSourceException("Error in server sync", ex);
156 updatedSyncItemKeys = null;
160 * Called after the modifications have been applied.
162 * @throws SyncSourceException to interrupt the process with an error
164 public void endSync() throws SyncSourceException {
165 log.info("endSync()");
166 try {
167 if (eos != null && startedSync) {
168 eos.close();
169 } else {
170 log.info("Warning: email object store is null or sync never started");
172 fh.close();
173 } catch (Exception ex) {
174 throw new SyncSourceException("Error closing database", ex);
179 * Commits the changes applied during the sync session. If the underlying
180 * datastore can not commit the changes, a SyncSourceException is thrown.
182 * @throws SyncSourceException if the changes cannot be committed
184 public void commitSync() throws SyncSourceException {
185 log.info("commitSync()");
186 super.commitSync();
190 * Called to get the keys of the items updated in the time frame sinceTs - untilTs.
191 * <br><code>sinceTs</code> null means all keys of the items updated until <code>untilTs</code>.
192 * <br><code>untilTs</code> null means all keys of the items updated since <code>sinceTs</code>.
194 * @param sinceTs consider the changes since this point in time.
195 * @param untilTs consider the changes until this point in time.
197 * @return an array of keys containing the <code>SyncItemKey</code>'s key of the updated
198 * items in the given time frame. It MUST NOT return null for
199 * no keys, but instad an empty array.
201 public SyncItemKey[] getUpdatedSyncItemKeys(Timestamp sinceTs,
202 Timestamp untilTs)
203 throws SyncSourceException {
204 log.info("getUpdatedSyncItemKeys()");
205 List<CitadelMailObject> seenStatus = eos.getSeenStatusUpdated();
206 updatedSyncItemKeys = new SyncItemKey[seenStatus.size()];
207 for (int i = 0; i < seenStatus.size(); i++) {
208 CitadelMailObject cmo = seenStatus.get(i);
209 String key = "I/" + Long.toString(cmo.getCtdlMessagePointer());
210 updatedSyncItemKeys[i] = new SyncItemKey(key);
211 log.fine("Updated " + cmo.getCtdlMessagePointer());
213 return updatedSyncItemKeys;
217 * Called to get the keys of the items deleted in the time frame sinceTs - untilTs.
218 * <br><code>sinceTs</code> null means all keys of the items deleted until <code>untilTs</code>.
219 * <br><code>untilTs</code> null means all keys of the items deleted since <code>sinceTs</code>.
221 * @param sinceTs consider the changes since this point in time.
222 * @param untilTs consider the changes until this point in time.
224 * @return an array of keys containing the <code>SyncItemKey</code>'s key of the deleted
225 * items in the given time frame. It MUST NOT return null for
226 * no keys, but instad an empty array.
228 public SyncItemKey[] getDeletedSyncItemKeys(Timestamp sinceTs,
229 Timestamp untilTs)
230 throws SyncSourceException {
231 log.info("getDeletedSyncItemKeys()");
232 List<CitadelMailObject> deletedObjects = eos.getDeletedOnServerObjects();
233 SyncItemKey[] deletedKeys = new SyncItemKey[deletedObjects.size()];
234 int i = 0;
235 Iterator<CitadelMailObject> deletedIterator = deletedObjects.iterator();
236 while (deletedIterator.hasNext()) {
237 CitadelMailObject deleted = deletedIterator.next();
238 SyncItemKey dKey = new SyncItemKey(
239 Long.toString(deleted.getCtdlMessagePointer()));
240 deletedKeys[i++] = dKey;
242 return deletedKeys;
246 * Called to get the keys of the items created in the time frame sinceTs - untilTs.
247 * <br><code>sinceTs</code> null means all keys of the items created until <code>untilTs</code>.
248 * <br><code>untilTs</code> null means all keys of the items created since <code>sinceTs</code>.
250 * @param sinceTs consider the changes since this point in time.
251 * @param untilTs consider the changes until this point in time.
253 * @return an array of keys containing the <code>SyncItemKey</code>'s key of the created
254 * items in the given time frame. It MUST NOT return null for
255 * no keys, but instad an empty array.
257 public SyncItemKey[] getNewSyncItemKeys(Timestamp sinceTs,
258 Timestamp untilTs)
259 throws SyncSourceException {
260 log.info("getNewSyncItemKeys()");
261 List<CitadelMailObject> newOnServer = eos.getAddedOnServerObjects();
262 int newSize = newOnServer.size();
263 SyncItemKey[] newKeys = new SyncItemKey[newSize];
264 Iterator<CitadelMailObject> it = newOnServer.iterator();
265 int i = 0;
266 while (it.hasNext()) {
267 CitadelMailObject newMail = it.next();
268 String msgPointerF = "I/" + Long.toString(newMail.getCtdlMessagePointer());
269 SyncItemKey newKey = new SyncItemKey(msgPointerF);
270 newKeys[i++] = newKey;
272 return newKeys;
276 * Adds a new <code>SyncItem</code>.
277 * The item is also returned giving the opportunity to the
278 * source to modify its content and return the updated item (i.e. updating
279 * the id to the GUID).
281 * @param syncInstance the item to add
283 * @return the inserted item
285 * @throws SyncSourceException in case of error (for instance if the
286 * underlying data store runs into problems)
288 public SyncItem addSyncItem(SyncItem syncInstance)
289 throws SyncSourceException {
290 try {
291 log.info("addSyncItem(" + syncInstance.getKey().getKeyAsString() + ")");
292 InboundEmailItem iei = new InboundEmailItem();
293 iei.setSourceItem(syncInstance);
294 // What room does it belong to?
295 char prefix = determinePrefix(syncInstance.getKey());
296 String room = syncSourceProperties.getProperty(CtdlFnblConstants.ROOM_MAIL);
297 if (prefix != 'I' && prefix == 'S') {
298 room = syncSourceProperties.getProperty(CtdlFnblConstants.ROOM_SENT);
300 String toString = iei.getToAddresses();
301 String ccString = iei.getCCAddresses();
302 String bccString = iei.getBCCAddresses();
303 String subject = iei.getSubject();
304 String fromName = iei.getSenderPersonName();
305 String fromMail = iei.getSenderAddress();
306 String rfc822 = iei.getRFC822Content();
307 // Pray to $DEITY it works
308 eos.getToolkit().postMessage(room, toString, subject, fromName, ccString, bccString, fromMail, rfc822);
309 return iei.generateAckSyncItem(this);
310 } catch (Exception ex) {
311 log.throwing(this.getClass().getName(), "addSyncItem", ex);
312 throw new SyncSourceException(ex);
317 * Update a <code>SyncItem</code>.
318 * The item is also returned giving the opportunity to the
319 * source to modify its content and return the updated item (i.e. updating
320 * the id to the GUID).
322 * @param syncInstance the item to replace
324 * @return the updated item
326 * @throws SyncSourceException in case of error (for instance if the
327 * underlying data store runs into problems)
329 public SyncItem updateSyncItem(SyncItem syncInstance)
330 throws SyncSourceException {
331 log.info("updateSyncItem(" + syncInstance.getKey().getKeyAsString() + ")");
332 try {
333 InboundEmailItem inboundEmailItem = new InboundEmailItem();
334 inboundEmailItem.setSourceItem(syncInstance);
336 boolean isRead = inboundEmailItem.isRead();
337 SyncItemKey originalKey = removePrefix(syncInstance.getKey());
338 CitadelMailObject cmo = eos.getMessageByPointer(originalKey.getKeyAsString());
339 if (cmo.isSeen() != isRead) {
340 // Set message flag
341 cmo.setSeen(isRead);
342 eos.getToolkit().setSeenStatus(originalKey.getKeyAsString(), isRead);
344 } catch (Exception ex) {
345 log.log(Level.SEVERE, null, ex);
347 return getSyncItemFromId(syncInstance.getKey()); // don't do anything, just yet.
351 * Removes a SyncItem given its key.
353 * @param itemKey the key of the item to remove
354 * @param time the time of the deletion
355 * @param softDelete is a soft delete ?
357 * @throws SyncSourceException in case of error (for instance if the
358 * underlying data store runs into problems)
360 public void removeSyncItem(SyncItemKey itemKey, Timestamp time, boolean softDelete)
361 throws SyncSourceException {
362 log.info("removeSyncItem(" + itemKey.getKeyAsString() + ")");
363 if (!softDelete) {
364 try {
365 SyncItemKey withoutFolder = removePrefix(itemKey);
366 CitadelMailObject cmo = eos.getMessageByPointer(withoutFolder.getKeyAsString());
367 //eos.getToolkit().deleteMessage(withoutFolder.getKeyAsString());
368 eos.moveToTrash(withoutFolder.getKeyAsString());
369 } catch (Exception ex) {
370 log.log(Level.SEVERE, "Exception while deleting message", ex);
371 throw new SyncSourceException(ex);
377 * Called to get the keys of all items accordingly with the parameters
378 * used in the beginSync call.
379 * @return an array of all <code>SyncItemKey</code>s stored in this source.
380 * If there are no items an empty array is returned.
382 * @throws SyncSourceException in case of error (for instance if the
383 * underlying data store runs into problems)
385 public SyncItemKey[] getAllSyncItemKeys()
386 throws SyncSourceException {
387 log.info("getAllSyncItemKeys()");
388 ArrayList keysToOutput = new ArrayList();
389 Iterator<String> mailIterator = null;
390 /* Iterator<String> pointerIterator = allObjs.iterator();
391 while (pointerIterator.hasNext()) {
392 String msgPointer = pointerIterator.next();
393 allKeys[i++] = new SyncItemKey(msgPointer);
394 } */
395 long filterTime = 0;
396 if (filter != null && filter.getTime() != null) {
397 filterTime = filter.getTime().getTime();
398 mailIterator = eos.listMessagesInRoomFromTime("Mail", filterTime).iterator();
399 } else {
400 mailIterator = eos.listMessagesInRoom("Mail").iterator();
402 while (mailIterator.hasNext()) {
403 boolean allow = true;
404 String msgPointer = mailIterator.next();
405 String key = "I/" + msgPointer;
406 CitadelMailObject cmo = eos.getMessageByPointer(msgPointer);
407 Date mdate = cmo.getTime();
408 // Do filter check
409 if (filter != null &&
410 filter.getTime() != null &&
411 mdate.getTime() > filter.getTime().getTime()) {
412 keysToOutput.add(new SyncItemKey(key));
413 } else if (filter == null || filter.getTime() == null) {
414 keysToOutput.add(new SyncItemKey(key));
418 keysToOutput.add(inboxKey);
419 keysToOutput.add(outboxKey);
420 SyncItemKey[] allKeys = new SyncItemKey[keysToOutput.size()];
421 keysToOutput.toArray(allKeys);
422 return allKeys;
426 * Called to get the item with the given key.
428 * @return return the <code>SyncItem</code> corresponding to the given
429 * key. If no item is found, null is returned.
431 * @param syncItemKey the key of the SyncItem to return
433 * @throws SyncSourceException in case of errors (for instance if the
434 * underlying data store runs into problems)
436 public SyncItem getSyncItemFromId(SyncItemKey syncItemKey) throws SyncSourceException {
437 log.info("getSyncItemFromId(" + syncItemKey.getKeyAsString() + ")");
438 if (syncItemKey.getKeyAsString().startsWith("ROOT/")) {
439 return getSyncItemForFolder(syncItemKey);
441 SyncItemKey actual = removePrefix(syncItemKey);
442 log.info("Actual sync item key: " + actual.getKeyAsString());
443 boolean isAnUpdate = Lookup.isInArray(updatedSyncItemKeys, syncItemKey);
444 CitadelMailObject cmo = null;
445 OutboundEmailItem omi = new OutboundEmailItem();
446 if (!isAnUpdate) {
447 try {
448 cmo = eos.getFilledMessageByPointer(actual.getKeyAsString());
449 if (cmo == null) {
450 return new SyncItemImpl(this, syncItemKey, SyncItemState.DELETED);
452 } catch (Exception ex) {
453 Logger.getLogger(CitadelSyncSource.class.getName()).log(Level.SEVERE, null, ex);
454 throw new SyncSourceException("Error getting message: " + actual.getKeyAsString(), ex);
456 omi.setMailObject(cmo);
457 if (filter != null) {
458 omi.setCropAtBytes(filter.getNumBytes());
460 try {
461 if (filter != null && filter.getSize() == 63 && omi.doAttachmentsFitInsideCrop()) {
462 // Does it fit? Attach the parts
463 eos.fillPartsForMessage(cmo);
464 omi.setAddAttachments(true);
466 } catch (Exception e) {
467 log.log(Level.WARNING, "Unable to add attachments", e);
469 } else {
470 cmo = eos.getMessageByPointer(actual.getKeyAsString());
471 omi.setMailObject(cmo);
473 try {
474 SyncItemKey parent = null;
475 if (cmo.getCtdlMessageRoom().equals("Mail")) {
476 parent = inboxKey;
478 } else {
479 parent = sentKey;
482 SyncItem si = omi.getSyncItem(this, actual, parent);
483 if (!isAnUpdate) {
484 si.setState(SyncItemState.SYNCHRONIZED);
485 } else {
486 si.setState(SyncItemState.UPDATED);
488 return si;
489 } catch (Exception e) {
490 log.throwing(this.getClass().getName(), "getSyncItemFromId", e);
491 throw new SyncSourceException("Error converting message: " + syncItemKey.getKeyAsString(), e);
496 * Called to retrive the keys of the twins of the given item
498 * @param syncItem the twin item
500 * @return the keys of the twin. Each source implementation is free to
501 * interpret this as it likes (i.e.: comparing all fields).
505 * @throws SyncSourceException in case of errors (for instance if the
506 * underlying data store runs into problems)
508 public SyncItemKey[] getSyncItemKeysFromTwin(SyncItem syncItem) throws SyncSourceException {
509 log.info("getSyncItemKeysFromTwin(" + syncItem.getKey().getKeyAsString() + ")");
510 if (syncItem.getType().equals("application/vnd.omads-folder+xml")) {
511 try {
512 ByteArrayInputStream bis = new ByteArrayInputStream(syncItem.getContent());
513 XMLFolderParser xfp = new XMLFolderParser(bis);
514 Folder f = xfp.parse();
515 if (f.getRole().getPropertyValueAsString().equals(Def.FOLDER_INBOX_ROLE)) {
516 return new SyncItemKey[]{inboxKey};
517 } else if (f.getRole().getPropertyValueAsString().equals(Def.FOLDER_OUTBOX_ROLE)) {
518 return new SyncItemKey[]{outboxKey};
520 } catch (Exception e) {
521 log.log(Level.WARNING, "Error getting twin for folder", e);
524 return null;
528 * Called by the engine to notify an operation status.
529 * @param operationName the name of the operation.
530 * One between:
531 * - Add
532 * - Replace
533 * - Delete
534 * @param status the status of the operation
535 * @param keys the keys of the items
537 public void setOperationStatus(String operationName, int status, SyncItemKey[] keys) {
538 StringBuffer logOutput = new StringBuffer();
539 for (int i = 0; i < keys.length; i++) {
540 SyncItemKey syncItemKey = keys[i];
541 logOutput.append("setOperationStatus(").append(operationName).append(",");
542 logOutput.append(status).append(",").append(keys[i].getKeyAsString());
543 logOutput.append(")\n");
545 log.info(logOutput.toString());
549 public void setSyncSourceProperties(Properties syncSourceProperties) {
550 this.syncSourceProperties = syncSourceProperties;
553 public Properties getSyncSourceProperties() {
554 return syncSourceProperties;
557 protected void setupLogging() throws IOException {
558 String connectorLog = null;
559 String suffix = "";
560 if (syncSourceProperties.getProperty(CtdlFnblConstants.CONNECTOR_SINGLE_LOG_OPTION) == null) {
561 suffix = "-" + System.currentTimeMillis();
563 connectorLog = String.format("%s%s%s%s.html",
564 userStoreLoc,
565 File.separator,
566 "funambol",
567 suffix);
568 File logFile = new File(connectorLog);
569 fh = new FileHandler(connectorLog);
570 fh.setFormatter(new HTMLFormatter());
571 fh.setLevel(Level.ALL);
572 log.setLevel(Level.ALL);
573 log.addHandler(fh);
576 public String getType() {
577 return "";
580 public SyncItem getSyncItemForFolder(SyncItemKey folder) throws SyncSourceException {
581 try {
582 Folder fl = new Folder();
583 fl.getUID().setPropertyValue(folder.getKeyAsString());
584 if (folder.getKeyAsString().endsWith("I")) {
585 fl.getName().setPropertyValue(Def.FOLDER_INBOX_ENG);
586 fl.getRole().setPropertyValue(Def.FOLDER_INBOX_ROLE);
587 } else if (folder.getKeyAsString().endsWith("S")) {
588 fl.getName().setPropertyValue(Def.FOLDER_SENT_ENG);
589 fl.getRole().setPropertyValue(Def.FOLDER_SENT_ROLE);
590 } else if (folder.getKeyAsString().endsWith("O")) {
591 fl.getName().setPropertyValue(Def.FOLDER_OUTBOX_ENG);
592 fl.getRole().setPropertyValue(Def.FOLDER_OUTBOX_ROLE);
594 fl.getParentId().setPropertyValue("ROOT");
595 FolderToXML ftxml = new FolderToXML(null, null);
596 String content = ftxml.convert(fl);
597 SyncItemImpl si = new SyncItemImpl(this, folder);
598 si.setContent(content.getBytes("UTF-8"));
599 si.setType("application/vnd.omads-folder+xml");
600 return si;
601 } catch (Exception ex) {
602 log.throwing(this.getClass().getName(), "getSyncItemFromFolder", ex);
603 throw new SyncSourceException(ex);
607 /** Remove a prefix (I/, S/ etc.) */
608 private SyncItemKey removePrefix(SyncItemKey fullKey) {
609 String fullString = fullKey.getKeyAsString();
610 if (fullString.contains("/")) {
611 String[] split = fullString.split("/");
612 fullString = split[1];
614 fullKey.setKeyValue(fullString);
615 return fullKey;
618 private char determinePrefix(SyncItemKey fullKey) {
619 String fullString = fullKey.getKeyAsString();
620 if (fullString.substring(0, 3).contains("/")) {
621 return fullString.charAt(0);
622 } else {
623 return 'I';
627 public char getSyncItemStateFromId(SyncItemKey arg0) throws SyncSourceException {
628 log.log(Level.FINER, "getSyncItemStateFromId(" + arg0.getKeyAsString() + ")");
629 if (arg0.getKeyAsString().contains("O/")) {
630 return SyncItemState.DELETED;
632 return SyncItemState.SYNCHRONIZED;
635 public boolean isSyncItemInFilterClause(SyncItem arg0) throws SyncSourceException {
636 if (arg0 != null) {
637 log.log(Level.FINER, "isSyncItemInFilterClause(" + arg0.getKey().getKeyAsString() + ")");
638 return true;
640 return false;
643 public boolean isSyncItemInFilterClause(SyncItemKey arg0) throws SyncSourceException {
644 if (arg0 != null) {
645 log.log(Level.FINER, "isSyncItemInFilterClause(" + arg0.getKeyAsString() + ")");
646 return true;
648 return false;