KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > syncclient > sps > ContactDataStore


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package sync4j.syncclient.sps;
20
21 import java.util.Enumeration;
22 import java.util.Vector;
23
24 import javax.microedition.rms.RecordStore;
25
26 import javax.microedition.pim.Contact;
27 import javax.microedition.pim.ContactList;
28 import javax.microedition.pim.PIM;
29 import javax.microedition.pim.PIMException;
30 import net.rim.device.api.system.PersistentObject;
31 import net.rim.device.api.system.PersistentStore;
32 import net.rim.device.api.ui.component.Dialog;
33 import net.rim.device.api.util.StringMatch;
34 import sync4j.syncclient.util.StaticDataHelper;
35
36 import sync4j.syncclient.blackberry.parser.ParserFactory;
37 import sync4j.syncclient.blackberry.parser.ContactParser;
38
39 /**
40  * This class provide methods
41  * to access device database and Contact List
42  *
43  * @author Fabio Maggi @ Funambol
44  * $Id: ContactDataStore.java,v 1.3 2005/02/22 16:48:13 fabius Exp $
45  */

46 public class ContactDataStore extends DataStore {
47
48     //------------------------------------------------------------- Constants
49

50     private static final String TIMESTAMP_RECORDSTORE = "TimeStampContactRS" ;
51     private static final long PERSISTENCE_KEY = 0x83cab9f064294a3aL ;
52     //------------------------------------------------------------- Private Data
53

54     //------------------------------------------------------------- Public methods
55

56     protected static PersistentObject store;
57     protected static Vector changes;
58
59     static {
60
61         store = PersistentStore.getPersistentObject(PERSISTENCE_KEY);
62
63         if(store.getContents() == null) {
64             store.setContents(new Vector());
65             store.commit();
66         }
67
68         changes = (Vector) store.getContents();
69
70     }
71
72     /**
73      * Set last timestamp in dedicate recordStore
74      * @param lastTimestamp
75      * @throws DataAccessException
76      **/

77     public void setLastTimestamp(long lastTimestamp)
78     throws DataAccessException {
79
80         RecordStore recordStore = null;
81
82         try {
83
84             recordStore = RecordStore.openRecordStore(TIMESTAMP_RECORDSTORE, true);
85
86             int numRecords = recordStore.getNumRecords();
87
88             String recordValue = String.valueOf(lastTimestamp);
89
90             if (numRecords == 1) {
91                 recordStore.setRecord(1, recordValue.getBytes(), 0, (recordValue.getBytes()).length);
92             } else {
93                 recordStore.addRecord(recordValue.getBytes(), 0, (recordValue.getBytes()).length);
94             }
95
96
97         } catch (Exception e) {
98             StaticDataHelper.log("error:" + e.getMessage());
99             throw new DataAccessException(e.getMessage());
100         } finally {
101             if (recordStore != null) {
102                 try {
103                     recordStore.closeRecordStore();
104                     recordStore = null;
105                 } catch (Exception e) {
106                     throw new DataAccessException(e.getMessage());
107                 }
108             }
109         }
110
111     }
112
113     /**
114      * @return last timestamp from dedicate recordstore
115      * @throws DataAccessException
116      **/

117     public long getLastTimestamp()
118     throws DataAccessException {
119
120         RecordStore recordStore = null;
121
122         long lastTimestamp = 0;
123
124         try {
125
126             recordStore = RecordStore.openRecordStore(TIMESTAMP_RECORDSTORE, true);
127
128             int numRecords = recordStore.getNumRecords();
129
130             if (numRecords == 0) {
131                 lastTimestamp = 0;
132             } else {
133                 lastTimestamp = Long.parseLong(new String(recordStore.getRecord(1)));
134             }
135
136         } catch (Exception e) {
137             StaticDataHelper.log("error:" + e.getMessage());
138             throw new DataAccessException(e.getMessage());
139         } finally {
140             if (recordStore != null) {
141                 try {
142                     recordStore.closeRecordStore();
143                     recordStore = null;
144                 } catch (Exception e) {
145                     throw new DataAccessException(e.getMessage());
146                 }
147             }
148         }
149
150         return lastTimestamp;
151
152     }
153
154     /**
155      * if record exist in database, update records
156      * if record not exist in database, add record
157      * @param record record to store
158      * @throws DataAccessException
159      **/

160     public Record setRecord(Record record, boolean modify)
161     throws DataAccessException{
162         try {
163
164             ContactList list = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
165
166             Contact contact = getContact(record.getKey(), list, modify);
167
168             if(contact == null) {
169                 Dialog.inform("Contact is null.");
170                 return null;
171             }
172             String content = fixTag(record.getUid());
173
174             ContactParser parser = ParserFactory.getParserInstance(list, contact, modify);
175
176             parser.parseContact(content);
177
178             contact.commit();
179
180             String uid = contact.getString(Contact.UID, 0);
181
182             record.setKey(uid);
183
184             list.close();
185         }catch(Exception e) {
186             e.printStackTrace();
187             throw new DataAccessException(e);
188         }
189         return record;
190
191     }
192
193     /**
194      * Obtains/Creates a Contact object depending on the modify option.
195      * @param String: key [contact UID]
196      * @param ContactList: contact list
197      * @param boolean: modify flag determines if the contact needs to be created/searched for from
198      * contact list the.
199      * @return Contact : returns a new contact object if modify flag was ser to false.else searches
200      * for contacts from the contact list for key matching existing UID and returns that.
201      * @throws Exception
202      */

203     private Contact getContact(String key, ContactList list, boolean modify) throws Exception{
204         if(!modify) {
205             return list.createContact();
206         }else {
207             Enumeration enum = list.items(key);
208             while(enum.hasMoreElements()) {
209                 Contact contact = (Contact)enum.nextElement();
210                 if(contact.getString(Contact.UID, 0).equals(key))
211                     return contact;
212             }
213             return null;
214         }
215     }
216
217     /**
218      * Sync4j escapes <. This method replaces.
219      * @param content
220      * @return
221      */

222     private String fixTag(String content) {
223         StringBuffer contentBuffer = new StringBuffer(content);
224         StringMatch matcher = new StringMatch("<");
225         int matchOffset = matcher.indexOf(contentBuffer, 0);
226         while(matchOffset != -1){
227             contentBuffer.delete(matchOffset,matchOffset+4);
228             contentBuffer.insert(matchOffset,"<");
229             matchOffset = matcher.indexOf(contentBuffer, 0);
230         }
231         return contentBuffer.toString();
232
233     }
234
235     /**
236      * Delete a record from the contact database.
237      * @param record
238      * @throws DataAccessException
239      */

240     public void deleteRecord(Record record) throws DataAccessException {
241         try {
242             ContactList list = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
243             Contact contact = getContact(record.getKey(), list, true);
244             if(contact != null)
245                 list.removeContact(contact);
246             list.close();
247         }catch(Exception expn) {
248             throw new DataAccessException(expn);
249         }
250     }
251
252     /**
253      * Rules to add to the datastore
254      * a) If there is already record with state 'N' and 'U' is recieved don't update.
255      * b) If there is already record with state 'N' and 'D' is recieved remove the entry
256      * c) If there is a record with state 'U' and 'U' is got ignore it
257      * d) If there is a record with state 'U' and 'D' is got replace it with 'D'
258      */

259     public void addRecord(String uid, char state, Contact contact) throws Exception{
260         String value = uid + "|" + state;
261
262         /**
263          * In case of deleted record, the information would not be available during sync.
264          * hence it is store along with the update information. In update/new case it is
265          * available in the contact db so it is not store to save space
266          */

267         if(state == RECORD_STATE_DELETED) {
268             ContactList list = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
269
270             String data = getContactString(list, contact);
271
272             list.close();
273
274             value += "|" + data;
275
276         }
277
278         int size = changes.size();
279         String data = "";
280         boolean dataSet = false;
281         if(changes.contains(value))
282             return;
283
284         for(int i=size-1;i >= 0; --i) {
285             data = (String)changes.elementAt(i);
286             String dataUID = data.substring(0, data.indexOf("|"));
287             char dataState = data.substring(data.indexOf("|")+1).charAt(0);
288             if(!dataUID.equals(uid)) {
289                 continue;
290             } else if(dataState == RECORD_STATE_NEW && state == RECORD_STATE_UPDATED) {
291                 dataSet = true;
292             } else if (dataState == RECORD_STATE_NEW && state == RECORD_STATE_DELETED) {
293                 changes.removeElement(data);
294                 i = i-1;
295                 dataSet = true;
296             }
297             else if(dataState == RECORD_STATE_UPDATED && state == RECORD_STATE_DELETED) {
298                  changes.setElementAt(value,i);
299                  changes.removeElement(data);
300                  dataSet = true;
301              }
302         }
303
304         if(!dataSet) {
305            changes.addElement(value);
306         }
307         store.commit();
308
309     }
310
311     /**
312      * return no deleted records from device recordstore
313      *
314      * @return find records
315      * @throws DataAccessException
316      **/

317     public Vector getNoDeletedRecords()
318     throws DataAccessException {
319
320         Enumeration enum = null ;
321         ContactList list = null ;
322         Vector noDeletedRecords = null ;
323
324         Contact contact = null ;
325
326         Record record = null ;
327
328         try {
329
330             noDeletedRecords = new Vector();
331
332             list = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
333
334             enum = list.items();
335
336             while(enum.hasMoreElements()) {
337
338                 contact = (Contact)enum.nextElement();
339
340                 record = new Record(contact.getString(contact.UID,0), RECORD_STATE_UNSIGNED, getContactString(list, contact));
341
342                 noDeletedRecords.addElement(record);
343
344             }
345
346             list.close();
347
348             return noDeletedRecords;
349
350         } catch(Exception e) {
351             e.printStackTrace();
352             throw new DataAccessException(e);
353         }
354
355     }
356
357     /**
358      * return record from recordstore
359      * filter by record state
360      *
361      * @return find records
362      * @throws DataAccessException
363      **/

364     public Vector getRecords(char state)
365     throws DataAccessException {
366
367         store = PersistentStore.getPersistentObject(PERSISTENCE_KEY);
368         if(store.getContents() == null) {
369             store.setContents(new Vector());
370             store.commit();
371         }
372
373         changes = (Vector) store.getContents();
374
375         int size = changes.size();
376         String checkString = "|"+state;
377         Vector changeVector = new Vector();
378         Record rec = null;
379
380         for(int i=0;i < size; i++) {
381             String record = (String)changes.elementAt(i);
382
383             int checkStringIndex = record.indexOf(checkString);
384             if(checkStringIndex != -1) {
385                 String uid = record.substring(0, checkStringIndex);
386                 try {
387
388                     if(state == RECORD_STATE_DELETED)
389                         rec = new Record(record);
390                     else
391                         rec = new Record(uid,state, getContactAsString(uid));
392
393                   changeVector.addElement(rec);
394                 } catch(DataAccessException e) {
395                     e.printStackTrace();
396                     throw new DataAccessException(e);
397                 }
398             }
399         }
400
401         return changeVector;
402     }
403
404     /**
405      * returns a given contact as an xml string
406      * @param uid
407      * @return
408      * @throws DataAccessException
409      */

410     private String getContactAsString(String uid) throws DataAccessException{
411         try {
412
413             String contanctAsString = null;
414
415             ContactList list = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
416
417             Contact contact = getContact(uid, list, true);
418
419             contanctAsString = getContactString(list, contact);
420
421             list.close();
422
423             return contanctAsString;
424
425         }catch(Exception e) {
426             e.printStackTrace();
427             throw new DataAccessException(e);
428         }
429     }
430
431
432     /**
433      * Converts one contact information from a black berry list to string format.
434      * @param String: uid [contact UID]
435      * @param ContactList: contact list
436      * @param Contact: contact.
437      * @return String : returns null id contact object is null else the method returns
438      * contact information parsed to string.
439      * @throws Exception,PIMException
440      */

441     private String getContactString(ContactList list, Contact contact) throws Exception, PIMException {
442         if(contact == null) {
443             Dialog.inform("Contact is null.");
444             return null;
445         }
446
447         ContactParser parser = ParserFactory.getParserInstance(list, contact, true);
448
449         String data = parser.toString(contact);
450
451         return data;
452     }
453
454     /**
455      * execute init recordstore operations
456      */

457     public void startDSOperations() {
458     }
459
460     /**
461      * execute commit recordstore operations
462      * remove records signed as DELETED 'D'
463      * mark UNSIGNED ' ' records signed as NEW 'N' and UPDATED 'U'
464      *
465      * @throws DataAccessException
466      *
467      */

468     public void commitDSOperations()
469     throws DataAccessException {
470         changes.removeAllElements();
471         store.commit();
472     }
473
474     public long getNextKey() {
475         //da implementare
476
return 0;
477     }
478 }
479
Popular Tags