KickJava   Java API By Example, From Geeks To Geeks.

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


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.Event;
27 import javax.microedition.pim.EventList;
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
35 import sync4j.syncclient.util.StaticDataHelper;
36
37 import sync4j.syncclient.blackberry.parser.ParserFactory;
38 import sync4j.syncclient.blackberry.parser.EventParser;
39
40 /**
41  * This class provide methods
42  * to access device database and Event List
43  *
44  * @author Fabio Maggi @ Funambol
45  * $Id: EventDataStore.java,v 1.3 2005/02/22 16:48:13 fabius Exp $
46  */

47
48 public class EventDataStore extends DataStore {
49
50     //------------------------------------------------------------- Constants
51

52     protected static String TIMESTAMP_RECORDSTORE = "TimeStampEventRS" ;
53     protected static String EVENT_UID_RECORDSTORE = "EventUIDRS" ;
54     protected static long PERSISTENCE_KEY = 0xafd852c254393341L ;
55
56     //------------------------------------------------------------- Private Data
57

58     //------------------------------------------------------------- Public methods
59

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

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

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

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

208     private Event getEvent(String key, EventList list, boolean modify)
209     throws Exception {
210         if(!modify) {
211             return list.createEvent();
212         }else {
213             Enumeration enum = list.items(key);
214             while(enum.hasMoreElements()) {
215                 Event event = (Event)enum.nextElement();
216                 if(event.getString(Event.UID, 0).equals(key))
217                     return event;
218             }
219             return null;
220         }
221     }
222
223     /**
224      * Sync4j escapes <. This method replaces.
225      * @param content
226      * @return
227      */

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

246     public void deleteRecord(Record record) throws DataAccessException {
247         try {
248             EventList list = (EventList) PIM.getInstance().openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
249             Event event = getEvent(record.getKey(), list, true);
250             if(event != null)
251                 list.removeEvent(event);
252             list.close();
253         }catch(Exception expn) {
254             throw new DataAccessException(expn);
255         }
256     }
257
258     /**
259      * Rules to add to the datastore
260      * a) If there is already record with state 'N' and 'U' is recieved don't update.
261      * b) If there is already record with state 'N' and 'D' is recieved remove the entry
262      * c) If there is a record with state 'U' and 'U' is got ignore it
263      * d) If there is a record with state 'U' and 'D' is got replace it with 'D'
264      */

265     public void addRecord(String uid, char state, Event event) throws Exception{
266         String value = uid + "|" + state;
267
268         /**
269          * In case of deleted record, the information would not be available during sync.
270          * hence it is store along with the update information. In update/new case it is
271          * available in the event db so it is not store to save space
272          */

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

326     public Vector getNoDeletedRecords()
327     throws DataAccessException {
328
329         Enumeration enum = null ;
330         EventList list = null ;
331         Vector noDeletedRecords = null ;
332
333         Event event = null ;
334
335         Record record = null ;
336
337         try {
338
339             noDeletedRecords = new Vector();
340
341             list = (EventList) PIM.getInstance().openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
342
343             enum = list.items();
344
345             while(enum.hasMoreElements()) {
346
347                 event = (Event)enum.nextElement();
348
349                 record = new Record(event.getString(event.UID,0), RECORD_STATE_UNSIGNED, getEventString(list, event));
350
351                 noDeletedRecords.addElement(record);
352
353             }
354
355             list.close();
356
357             return noDeletedRecords;
358
359         } catch(Exception e) {
360             e.printStackTrace();
361             throw new DataAccessException(e);
362         }
363
364     }
365
366     /**
367      * return record from recordstore
368      * filter by record state
369      *
370      * @return find records
371      * @throws DataAccessException
372      **/

373     public Vector getRecords(char state)
374     throws DataAccessException {
375
376         int size ;
377
378         String[] eventsUid = null ;
379         String checkString = null ;
380
381         Vector changeVector = null ;
382         Vector detetedEvevent = null ;
383
384         Record rec = null ;
385
386         store = PersistentStore.getPersistentObject(PERSISTENCE_KEY);
387         if(store.getContents() == null) {
388             store.setContents(new Vector());
389             store.commit();
390         }
391
392         changes = (Vector) store.getContents() ;
393         size = changes.size() ;
394         checkString = "|"+state ;
395
396         changeVector = new Vector() ;
397         detetedEvevent = new Vector() ;
398
399         //
400
// - start code -
401
// this code is workaround
402
// blackberry bug in calendar event
403
//
404
if(state == RECORD_STATE_DELETED) {
405
406             try {
407
408                 EventList list = null ;
409                 String eventUid = null ;
410                 Event event = null ;
411
412                 list = (EventList) PIM.getInstance().openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
413
414                 eventsUid = getEventsUid();
415
416                 for (int i=0, l = eventsUid.length; i < l; i++) {
417
418                     eventUid = eventsUid[i];
419
420                     event = getEvent(eventUid, list, true);
421
422                     if (event == null) {
423                         rec = new Record(eventUid,state);
424                         detetedEvevent.addElement(rec);
425                     }
426
427                 }
428
429                 list.close();
430
431             } catch (Exception e) {
432                 throw new DataAccessException(e.getMessage());
433             }
434
435             return detetedEvevent;
436
437         }
438         //
439
// - end code -
440
// this code is workaround
441
// blackberry bug in calendar event
442
//
443

444         for(int i=0; i < size; i++) {
445             String record = (String)changes.elementAt(i);
446
447             int checkStringIndex = record.indexOf(checkString);
448             if(checkStringIndex != -1) {
449                 String uid = record.substring(0, checkStringIndex);
450                 try {
451
452                     //
453
// this code is disable because
454
// blackberry bug in calendar event
455
//
456
/**
457                     if(state == RECORD_STATE_DELETED)
458                         rec = new Record(record);
459                     else
460                         rec = new Record(uid,state, getEventAsString(uid));
461                     */

462
463                     rec = new Record(uid,state, getEventAsString(uid));
464
465                   changeVector.addElement(rec);
466                 } catch(DataAccessException e) {
467                     e.printStackTrace();
468                     throw new DataAccessException(e);
469                 }
470             }
471         }
472
473         return changeVector;
474     }
475
476     /**
477      * returns a given event as an xml string
478      * @param uid
479      * @return
480      * @throws DataAccessException
481      */

482     private String getEventAsString(String uid) throws DataAccessException{
483         try {
484
485             String contanctAsString = null;
486
487             EventList list = (EventList) PIM.getInstance().openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
488
489             Event event = getEvent(uid, list, true);
490
491             contanctAsString = getEventString(list, event);
492
493             list.close();
494
495             return contanctAsString;
496
497         } catch(Exception e) {
498             e.printStackTrace();
499             throw new DataAccessException(e);
500         }
501     }
502
503     /**
504      * Converts one event information from a black berry list to string format.
505      * @param String: uid [event UID]
506      * @param EventList: event list
507      * @param Event: event.
508      * @return String : returns null id event object is null else the method returns
509      * event information parsed to string.
510      * @throws Exception,PIMException
511      */

512     private String getEventString(EventList list, Event event) throws Exception, PIMException {
513         if(event == null) {
514             Dialog.inform("Event is null.");
515             return null;
516         }
517
518         EventParser parser = ParserFactory.getParserInstance(list, event, true);
519
520         String data = parser.toString(event);
521
522         return data;
523     }
524
525     /**
526      * execute init recordstore operations
527      */

528     public void startDSOperations() {
529     }
530
531     /**
532      * execute commit recordstore operations
533      * remove records signed as DELETED 'D'
534      * mark UNSIGNED ' ' records signed as NEW 'N' and UPDATED 'U'
535      *
536      * @throws DataAccessException
537      *
538      */

539     public void commitDSOperations()
540     throws DataAccessException {
541
542         changes.removeAllElements();
543         store.commit();
544         setEventsUid();
545     }
546
547     public long getNextKey() {
548         //da implementare
549
return 0;
550     }
551
552     //
553
// - start code -
554
// this code is workaround
555
// blackberry bug in calendar event
556
//
557

558     /**
559      *
560      * set in RecordStore UID of event in BlackBerry Calendar
561      *
562      */

563     private static void setEventsUid()
564     throws DataAccessException {
565
566         RecordStore recordStore = null ;
567
568         Enumeration eventsEnumeration = null ;
569         EventList list = null ;
570         Event event = null ;
571
572         String eventUid = null ;
573
574         try {
575
576             list = (EventList) PIM.getInstance().
577                         openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
578
579             eventsEnumeration = list.items();
580
581             list.close();
582
583             //
584
// if RecordStore don't exist next line deleteRecordStore fails
585
//
586
recordStore = RecordStore.openRecordStore(EVENT_UID_RECORDSTORE, true);
587             recordStore.closeRecordStore();
588
589             RecordStore.deleteRecordStore(EVENT_UID_RECORDSTORE);
590
591             recordStore = RecordStore.openRecordStore(EVENT_UID_RECORDSTORE, true);
592
593             while(eventsEnumeration.hasMoreElements()) {
594
595                 event = (Event)eventsEnumeration.nextElement() ;
596
597                 eventUid = event.getString(event.UID, 0 );
598
599                 recordStore.addRecord(eventUid.getBytes() ,
600                                       0 ,
601                                       (eventUid.getBytes()).length) ;
602             }
603
604         } catch (Exception e) {
605             throw new DataAccessException(e.getMessage());
606         } finally {
607             if (recordStore != null) {
608                 try {
609                     recordStore.closeRecordStore();
610                     recordStore = null;
611                 } catch (Exception e) {
612                     throw new DataAccessException(e.getMessage());
613                 }
614             }
615         }
616     }
617
618     /**
619      *
620      * read RecordStore UID of Event in BlackBerry Calendar at last sync
621      *
622      */

623     private static String[] getEventsUid()
624     throws DataAccessException {
625
626         String[] eventUids = null;
627         RecordStore recordStore = null;
628
629         try {
630
631             recordStore = RecordStore.openRecordStore(EVENT_UID_RECORDSTORE, true);
632
633             int numRecords = recordStore.getNumRecords();
634
635             eventUids = new String[numRecords];
636
637             for (int i= 1; i <= numRecords; i++) {
638                 eventUids[i-1] = new String(recordStore.getRecord(i));
639             }
640
641         } catch (Exception e) {
642             StaticDataHelper.log("error:" + e.getMessage());
643             throw new DataAccessException(e.getMessage());
644         } finally {
645             if (recordStore != null) {
646                 try {
647                     recordStore.closeRecordStore();
648                     recordStore = null;
649                 } catch (Exception e) {
650                     throw new DataAccessException(e.getMessage());
651                 }
652             }
653         }
654
655         return eventUids;
656
657     }
658     //
659
// - end code -
660
// this code is workaround
661
// blackberry bug in calendar event
662
//
663

664 }
665
Popular Tags