2 * Funambol Citadel Connector
3 * (C) 2007-2008 Mathew McBride
4 * http://bionicmessage.net
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
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,
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
;
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
;
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
;
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.
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
);
117 userStoreLoc
= storeLoc
+ File
.separatorChar
+ ctx
.getPrincipal().getDeviceId()+"_"+ctx
.getPrincipal().getUsername();
119 File storeDir
= new File(userStoreLoc
);
120 if (!storeDir
.exists()) {
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) {
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
);
148 if (filter
!= null && filter
.getTime() != null)
149 fromTime
= filter
.getTime().getTime();
150 eos
.startSync(fromTime
);
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()");
167 if (eos
!= null && startedSync
) {
170 log
.info("Warning: email object store is null or sync never started");
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()");
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
,
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
,
230 throws SyncSourceException
{
231 log
.info("getDeletedSyncItemKeys()");
232 List
<CitadelMailObject
> deletedObjects
= eos
.getDeletedOnServerObjects();
233 SyncItemKey
[] deletedKeys
= new SyncItemKey
[deletedObjects
.size()];
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
;
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
,
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();
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
;
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
{
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() + ")");
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
) {
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() + ")");
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);
396 if (filter
!= null && filter
.getTime() != null) {
397 filterTime
= filter
.getTime().getTime();
398 mailIterator
= eos
.listMessagesInRoomFromTime("Mail", filterTime
).iterator();
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();
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
);
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();
448 cmo
= eos
.getFilledMessageByPointer(actual
.getKeyAsString());
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());
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
);
470 cmo
= eos
.getMessageByPointer(actual
.getKeyAsString());
471 omi
.setMailObject(cmo
);
474 SyncItemKey parent
= null;
475 if (cmo
.getCtdlMessageRoom().equals("Mail")) {
482 SyncItem si
= omi
.getSyncItem(this, actual
, parent
);
484 si
.setState(SyncItemState
.SYNCHRONIZED
);
486 si
.setState(SyncItemState
.UPDATED
);
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")) {
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
);
528 * Called by the engine to notify an operation status.
529 * @param operationName the name of the operation.
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;
560 if (syncSourceProperties
.getProperty(CtdlFnblConstants
.CONNECTOR_SINGLE_LOG_OPTION
) == null) {
561 suffix
= "-" + System
.currentTimeMillis();
563 connectorLog
= String
.format("%s%s%s%s.html",
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
);
576 public String
getType() {
580 public SyncItem
getSyncItemForFolder(SyncItemKey folder
) throws SyncSourceException
{
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");
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
);
618 private char determinePrefix(SyncItemKey fullKey
) {
619 String fullString
= fullKey
.getKeyAsString();
620 if (fullString
.substring(0, 3).contains("/")) {
621 return fullString
.charAt(0);
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
{
637 log
.log(Level
.FINER
, "isSyncItemInFilterClause(" + arg0
.getKey().getKeyAsString() + ")");
643 public boolean isSyncItemInFilterClause(SyncItemKey arg0
) throws SyncSourceException
{
645 log
.log(Level
.FINER
, "isSyncItemInFilterClause(" + arg0
.getKeyAsString() + ")");