KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > server > engine > EngineHelper


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 package sync4j.server.engine;
19
20 import java.util.*;
21 import java.util.Map JavaDoc;
22 import java.util.logging.Logger JavaDoc;
23 import java.util.logging.Level JavaDoc;
24 import java.sql.Timestamp JavaDoc;
25
26 import java.security.Principal JavaDoc;
27
28 import sync4j.framework.core.*;
29 import sync4j.framework.protocol.CommandIdGenerator;
30 import sync4j.framework.protocol.ProtocolUtil;
31 import sync4j.framework.engine.SyncOperationStatus;
32 import sync4j.framework.engine.SyncOperation;
33 import sync4j.framework.engine.SyncItemKey;
34 import sync4j.framework.engine.SyncItem;
35 import sync4j.framework.engine.SyncItemImpl;
36 import sync4j.framework.engine.SyncProperty;
37 import sync4j.framework.engine.SyncItemMapping;
38 import sync4j.framework.engine.SyncItemState;
39 import sync4j.framework.engine.SyncConflict;
40 import sync4j.framework.engine.source.*;
41 import sync4j.framework.server.ClientMapping;
42 import sync4j.framework.server.error.MappingException;
43 import sync4j.framework.logging.Sync4jLogger;
44
45 import sync4j.server.engine.Sync4jOperationStatus;
46
47 /**
48  * This class collects helper methods used by the engine.
49  *
50  * @author Stefano Fornari
51  * @version $Id: EngineHelper.java,v 1.28 2005/03/02 20:57:39 harrie Exp $
52  */

53 public class EngineHelper {
54
55     public static Logger JavaDoc log = Sync4jLogger.getLogger(Sync4jEngine.LOG_NAME);
56
57      /**
58       * Status are grouped as per their original commands and status code so
59       * that the number of returned status will be minimal. This is done by
60       * generating an hash map where the key is a couple
61       * <i>(original command id, status code)</i> and the value is the
62       * <i>StatusCommand</i> object. Finally the hash map is iterated over to
63       * return the status commands array.<br>
64       * Note that Sync4jOperationStatus's command is meaningful only for items
65       * that derive from a SyncML command. If the associated command is null,
66       * there is no need to generate a status. Of course, also if the command was
67       * flagged as "noResponse" no status is required.
68       *
69       * @param operationStatus the status object returned as the result of
70       * commands execution
71       * @param msgId the message id
72       * @param the command id generator
73       *
74       * @return a <i>StatusCommand[]</i> array containing the status to return
75       * to the client
76       */

77     public static Status[]
78     generateStatusCommands(SyncOperationStatus[] operationStatus,
79                            String JavaDoc msgId ,
80                            CommandIdGenerator idGenerator ) {
81         HashMap statusMap = new HashMap();
82
83         ArrayList itemList = null;
84         StatusKey key = null;
85
86         ModificationCommand cmd = null;
87         for (int i=0; i < operationStatus.length ; ++i) {
88
89             cmd = ((Sync4jOperationStatus)operationStatus[i]).getCmd();
90
91             if ((cmd == null) || (cmd.isNoResp())) {
92                 continue; // skip the operation status
93
}
94
95             //
96
// Check if a status command has been already created for the given
97
// original command and status code. If it is found, than a new
98
// item is added to the existing ones, otherwise a new item list
99
// is created
100
//
101
key = new StatusKey(
102                       cmd,
103                       operationStatus[i].getStatusCode()
104                   );
105
106             itemList = (ArrayList)statusMap.get(key);
107
108             if (itemList == null){
109                 itemList = new ArrayList();
110                 statusMap.put(key, itemList);
111             }
112             //
113
// If the item is mapped then used the mapped key like SourceRef.
114
//
115
SyncItemKey keyA =
116                 operationStatus[i].getOperation().getSyncItemA().getKey();
117             SyncItemKey mapKeyA =
118                 operationStatus[i].getOperation().getSyncItemA().getMappedKey();
119             itemList.add(mapKeyA == null ? keyA : mapKeyA);
120         }
121
122         //
123
// Now we can loop over the map and create a list of status commands.
124
//
125
ArrayList ret = new ArrayList();
126
127         Item[] items = null;
128
129         Iterator i = statusMap.keySet().iterator();
130         while(i.hasNext()) {
131             key = (StatusKey)i.next();
132
133             itemList = (ArrayList)statusMap.get(key);
134
135             items = new Item[itemList.size()];
136
137             for (int j = 0; j<items.length; ++j) {
138                 items[j] = new Item(
139                                null,
140                                new Source(((SyncItemKey)itemList.get(j)).getKeyAsString()),
141                                null,
142                                null,
143                                false
144                            );
145
146             }
147             ret.add(
148                 new Status(
149                     idGenerator.next() ,
150                     msgId ,
151                     key.cmd.getCmdID().getCmdID() ,
152                     key.cmd.getName() ,
153                     null ,
154                     (items.length == 1) ?
155                     new SourceRef(items[0].getSource()) :
156                     null ,
157                     null /* credential */ ,
158                     null /* challenge */ ,
159                     new Data(key.statusCode) ,
160                     (items.length > 1) ?
161                     items :
162                     new Item[0]
163                 )
164            );
165         }
166         return (Status[])ret.toArray(new Status[ret.size()]);
167     }
168
169     /**
170      * Translates an array of <i>SyncOperation</i> objects to an array of
171      * <i>(Add,Delete,Replace)Command</i> objects. Only client side operations
172      * are translated.
173      *
174      * @param clientMapping the associated existing client mapping
175      * @param operations the operations to be translated
176      * @param sourceName the corresponding source name
177      * @param idGenerator the ID generator for command ids
178      *
179      * @return the sync4j commands corresponding to <i>operations</i>
180      */

181     public static
182     ItemizedCommand[] operationsToCommands(ClientMapping clientMapping,
183                                            SyncOperation[] operations ,
184                                            String JavaDoc sourceName ,
185                                            CommandIdGenerator idGenerator ) {
186         ArrayList commands = new ArrayList();
187
188         SyncItem item = null;
189         for (int i=0; ((operations != null) && (i<operations.length)); ++i) {
190
191             if (log.isLoggable(Level.FINEST)) {
192                 log.finest( "Converting the operation\n"
193                           + operations[i]
194                           + "\nfor the source "
195                           + sourceName
196                           );
197             }
198
199             item = operations[i].getSyncItemB(); // this is the server-side item
200

201             if (operations[i].isAOperation() && (item != null)) {
202
203                 char op = operations[i].getOperation();
204
205                 //
206
// Should not translates a NOP operation
207
//
208
if (op == SyncOperation.NOP) {
209                     continue;
210                 }
211                 if (op == SyncOperation.CONFLICT) {
212                     if (operations[i].getSyncItemA().getState() == SyncItemState.NEW &&
213                         operations[i].getSyncItemB().getState() == SyncItemState.SYNCHRONIZED
214                        ) {
215                        //
216
// This happens when the Client sent an item that have a twin
217
// synchronized on server: nothing command must be sent
218
//
219
continue;
220                     }
221                 }
222                 commands.add(operationToCommand(clientMapping, operations[i], idGenerator));
223             }
224         }
225
226         return (ItemizedCommand[])commands.toArray(new ItemizedCommand[0]);
227     }
228
229     /**
230      * Translates a <i>SyncOperation</i> object to a <i>(Add,Delete,Replace)Command</i>
231      * object.
232      *
233      * @param clientMapping the item ids mapping
234      * @param operation the operation to be translated
235      * @param command id generator to use to create command ids
236      *
237      * @return the sync4j command corresponding to <i>operation</i>
238      */

239     public static
240     ItemizedCommand operationToCommand(ClientMapping clientMapping,
241                                        SyncOperation operation ,
242                                        CommandIdGenerator idGenerator ) {
243         ItemizedCommand cmd = null;
244
245         if (idGenerator == null) {
246             log.finest("idGenerator is null. Cannot continue");
247             throw new NullPointerException JavaDoc("idGenerator cannot be null!");
248         }
249
250         char op = operation.getOperation();
251
252         //
253
// The item key must reflect the value known by the client agent. It
254
// thus must be adjusted using the client mapping, but if the
255
// operation is an addition. In this case the client key is generated
256
// by the engine (the client will provide the right key with a
257
// subsequent Map command).
258
//
259
String JavaDoc itemKey = operation.getSyncItemB().getKey().getKeyAsString();
260         if (op != SyncOperation.NEW) {
261             String JavaDoc mappedKey = clientMapping.getMappedValueForGuid(itemKey);
262             //
263
// Mapped key may be null in the case of a NN conflict. In such a
264
// case, we do not have other choice than keep the not mapped key
265
//
266
if (mappedKey != null) {
267                 itemKey = mappedKey;
268             }
269         }
270         assert (itemKey != null);
271
272         //
273
// The following rules apply:
274
// - If the operation is an addition, Targer MUST NOT be included.
275
// - If the operation is not an addition, Source MUST NOT be included.
276
// - If the operation is not a deletion, Data element MUST be used to carry data ifself
277
//
278
// TO DO: noResponse, credential
279
//
280
Meta m = new Meta();
281         if (operation.getSyncItemB().getPropertyValue(SyncItem.PROPERTY_FORMAT) != null) {
282             m.setFormat((String JavaDoc)operation.getSyncItemB().getPropertyValue(SyncItem.PROPERTY_FORMAT));
283         }
284         if (operation.getSyncItemB().getPropertyValue(SyncItem.PROPERTY_TYPE) != null) {
285             m.setType((String JavaDoc)operation.getSyncItemB().getPropertyValue(SyncItem.PROPERTY_TYPE));
286         } else {
287             m.setType(operation.getSyncItemB().getSyncSource().getType());
288         }
289
290         if (op == SyncOperation.NEW) {
291             cmd = new Add(
292                       idGenerator.next(),
293                       false ,
294                       null ,
295                       m , // meta
296
new Item[] {
297                           SyncItemHelper.toItem(
298                               itemKey ,
299                               operation.getSyncItemA(),
300                               false ,
301                               true ,
302                               true
303                           )
304                       }
305                   );
306         } else if (op == SyncOperation.DELETE) {
307             cmd = new Delete(
308                       idGenerator.next(),
309                       false ,
310                       false ,
311                       false ,
312                       null ,
313                       null , // meta
314
new Item[] {
315                           SyncItemHelper.toItem(
316                               itemKey,
317                               operation.getSyncItemA(),
318                               true,
319                               false,
320                               false
321                           )
322                       }
323                   );
324         } else if (op == SyncOperation.UPDATE) {
325             cmd = new Replace(
326                       idGenerator.next(),
327                       false ,
328                       null ,
329                       m ,
330                       new Item[] {
331                           SyncItemHelper.toItem(
332                               itemKey,
333                               operation.getSyncItemA(),
334                               true,
335                               false,
336                               true
337                           )
338                       }
339                   );
340         } else if (op == SyncOperation.CONFLICT) {
341             //
342
// Server wins!
343
//
344
//View the state of syncItemB and then say to client which the operation
345
//to do in order to resolve the conflict
346
//
347
char s = operation.getSyncItemB().getState();
348
349             if (operation.getSyncItemB().getState() == SyncItemState.NOT_EXISTING) {
350                 itemKey = operation.getSyncItemA().getKey().getKeyAsString();
351             }
352
353             switch (s) {
354                 case SyncItemState.UPDATED:
355                 case SyncItemState.SYNCHRONIZED:
356                     cmd = new Replace(
357                               idGenerator.next(),
358                               false ,
359                               null ,
360                               m ,
361                               new Item[] {
362                                   SyncItemHelper.toItem(
363                                       itemKey,
364                                       operation.getSyncItemA(),
365                                       true,
366                                       false,
367                                       true
368                                   )
369                               }
370                           );
371                     break;
372                 case SyncItemState.DELETED:
373                 case SyncItemState.NOT_EXISTING:
374                     cmd = new Delete(
375                               idGenerator.next(),
376                               false ,
377                               false ,
378                               false ,
379                               null ,
380                               null , // meta
381
new Item[] {
382                                   SyncItemHelper.toItem(
383                                       itemKey,
384                                       operation.getSyncItemA(),
385                                       true,
386                                       false,
387                                       false
388                                   )
389                               }
390                           );
391                     break;
392                 case SyncItemState.NEW:
393                     //itemKey == guid
394
itemKey = operation.getSyncItemB().getKey().getKeyAsString();
395                     cmd = new Add(
396                               idGenerator.next(),
397                               false ,
398                               null ,
399                               m , // meta
400
new Item[] {
401                                   SyncItemHelper.toItem(
402                                       itemKey ,
403                                       operation.getSyncItemA(),
404                                       false ,
405                                       true ,
406                                       true
407                                   )
408                               }
409                           );
410                     break;
411             }
412         }
413
414         return cmd;
415     }
416
417     /**
418      * Converts an array of <i>Item</i> objects belonging to the same
419      * <i>SyncSource</i> into an array of <i>SyncItem</i> objects.
420      * <p>
421      * The <i>Item</i>s created are enriched with an additional property
422      * called as in SyncItemHelper.PROPERTY_COMMAND, which is used to bound the
423      * newly created object with the original command.
424      *
425      * @param syncSource the <i>SyncSource</i> items belong to - NOT NULL
426      * @param items the <i>Item</i> objects
427      * @param state the state of the item as one of the values defined in
428      * <i>SyncItemState</i>
429      * @param the timestamp to assign to the last even on this item
430      *
431      *
432      * @return an array of <i>SyncItem</i> objects
433      */

434     public static SyncItem[] itemsToSyncItems(ClientMapping clientMapping,
435                                               SyncSource syncSource ,
436                                               ModificationCommand cmd ,
437                                               char state ,
438                                               long timestamp ) {
439
440         Item[] items = (Item[])cmd.getItems().toArray(new Item[0]);
441
442         if ((items == null) || (items.length == 0)) {
443             return new SyncItem[0];
444         }
445
446         SyncItem[] syncItems = new SyncItem[items.length];
447
448         Data d = null;
449         String JavaDoc content = null, key = null, mappedKey = null;
450         for (int i=0; i<items.length; ++i) {
451             d = items[i].getData();
452             content = (d != null) ? d.getData() : "";
453
454             key = items[i].getSource().getLocURI();
455             mappedKey = clientMapping.getMappedValueForLuid(key);
456
457             //
458
// NOTE: for the purpose of sync items comparison, the mappedKey,
459
// when not null, becomes the real item key, whilst the old key
460
// becomes the mapped key.
461
//
462
if (mappedKey != null) {
463                 String JavaDoc k = mappedKey;
464                 mappedKey = key;
465                 key = k;
466             }
467             syncItems[i] =
468                 new SyncItemImpl(syncSource, key, mappedKey, state);
469             syncItems[i].setProperty(
470                 new SyncProperty(SyncItemHelper.PROPERTY_COMMAND, cmd)
471             );
472             syncItems[i].setProperty(
473                 new SyncProperty(SyncItem.PROPERTY_BINARY_CONTENT, content.getBytes())
474             );
475             syncItems[i].setProperty(
476                 new SyncProperty(SyncItem.PROPERTY_TIMESTAMP, new Timestamp JavaDoc(timestamp))
477             );
478             if (items[i].isMoreData()) {
479                 syncItems[i].setState(SyncItemState.PARTIAL);
480                 Long JavaDoc size = ProtocolUtil.getLOSize(cmd);
481                 if (size != null) {
482                     syncItems[i].setProperty(
483                         new SyncProperty(SyncItem.PROPERTY_SIZE, size)
484                     );
485                 }
486             }
487         }
488
489         return syncItems;
490     }
491
492     /**
493      * Calculate the intersection between the given lists, returning a new list
494      * of <i>SyncItemMapping</i>s each containing the corresponding item couple.
495      * Items are matched using the <i>get()</i> method of the <i>List</i> object,
496      * therefore the rules for matching items are the ones specified by tha
497      * <i>List</i> interface.
498      *
499      * @param a the first list - NOT NULL
500      * @param b the seconf list - NOT NULL
501      *
502      * @return the intersection mapping list.
503      */

504     public static List intersect(final List a, final List b) {
505         int n = 0;
506         SyncItem itemA = null;
507         ArrayList ret = new ArrayList();
508         SyncItemMapping mapping = null;
509
510         Iterator i = a.iterator();
511         while(i.hasNext()) {
512             itemA = (SyncItem)i.next();
513             n = b.indexOf(itemA);
514             if (n >= 0) {
515                 mapping = new SyncItemMapping(itemA.getKey());
516                 mapping.setMapping(itemA, (SyncItem)b.get(n));
517                 ret.add(mapping);
518             }
519         }
520
521         return ret;
522     }
523
524     /**
525      * Calculate and build the cross set Am(B-Bm) that is the set of synchronized
526      * items of the source B interested by the modifications of source A.
527      *
528      * @param items source A items
529      * @param source the B source
530      * @param principal the pricipal data are related to
531      *
532      * @return a list of <i>SyncItemMapping</i> representing the item set
533      */

534     public static List buildAmBBm(List items ,
535                                   SyncSource source ,
536                                   Principal JavaDoc principal) {
537         SyncItem itemA, itemB;
538         SyncItemMapping mapping = null;
539
540         ArrayList ret = new ArrayList();
541
542         Iterator i = items.iterator();
543         while (i.hasNext()) {
544             itemA = (SyncItem)i.next();
545
546             //
547
// If the mapped key is null, it means that this item is not
548
// on the server, therefore, it cannot be in B.
549
//
550
if (itemA.getMappedKey() == null) {
551                 continue;
552             }
553
554             try {
555                 itemB = source.getSyncItemFromId(principal, itemA.getKey());
556
557                 if (itemB != null) {
558                     itemB.setState(SyncItemState.SYNCHRONIZED);
559                     mapping = new SyncItemMapping(itemA.getKey());
560                     mapping.setMapping(itemA, itemB);
561                     ret.add(mapping);
562                 }
563             } catch (SyncSourceException e) {
564                 String JavaDoc msg = "Error retrieving an item by its key "
565                            + itemA.getKey()
566                            + " from source "
567                            + source
568                            + ": "
569                            + e.getMessage();
570                 log.severe(msg);
571                 log.throwing("EngineHelper", "buildAmBBm", e);
572             }
573         }
574
575         return ret;
576     }
577
578      /**
579      * Calculate and build the cross set (A-Am)Bm that is the set of synchronized
580      * items of the source A interested by the modifications of source B.
581      *
582      * @param items source B items
583      * @param source the A source
584      * @param principal the pricipal data are related to
585      *
586      * @return a list of <i>SyncItemMapping</i> representing the item set
587      */

588     public static List buildAAmBm(List items ,
589                                   SyncSource source ,
590                                   Principal JavaDoc principal) {
591         SyncItem itemA, itemB;
592         SyncItemMapping mapping = null;
593
594         ArrayList ret = new ArrayList();
595
596         Iterator i = items.iterator();
597         while (i.hasNext()) {
598             itemB = (SyncItem)i.next();
599
600             try {
601                 itemA = source.getSyncItemFromId(principal, itemB.getKey());
602
603                 if (itemA != null) {
604                     itemA.setState(SyncItemState.SYNCHRONIZED);
605                     mapping = new SyncItemMapping(itemB.getKey());
606                     mapping.setMapping(itemA, itemB);
607                     ret.add(mapping);
608                 }
609             } catch (SyncSourceException e) {
610                 String JavaDoc msg = "Error retrieving an item by its key "
611                            + itemB.getKey()
612                            + " from source "
613                            + source
614                            + ": "
615                            + e.getMessage();
616                 log.severe(msg);
617                 log.throwing("EngineHelper", "buildAmBBm", e);
618             }
619         }
620
621         return ret;
622     }
623
624     /**
625      * Update the mapping given an array of operations. This is used for
626      * mappings sent by the client.
627      *
628      * @param clientMappings the client mappings for current synchronization
629      * @param operations the operation performed
630      * @param slowSync is true if slow synchronization
631      *
632      */

633     public static void updateClientMappings(Map JavaDoc clientMappings,
634                                             SyncOperation[] operations ,
635                                             boolean slowSync )
636     throws MappingException {
637
638         ClientMapping clientMapping = null;
639         String JavaDoc guid = null, luid = null;
640         SyncSource clientSource = null;
641
642         for (int i=0; ((operations != null) && (i<operations.length)); ++i) {
643             //
644
// Ignore conflicts
645
//
646
if (operations[i] instanceof SyncConflict) {
647                 continue;
648             }
649
650             clientSource = operations[i].getSyncItemA().getSyncSource();
651             if (clientSource == null) {
652                 //
653
// clientSource is null for unexsisting items
654
//
655
continue;
656             }
657
658             clientMapping = (ClientMapping)clientMappings.get(clientSource.getSourceURI());
659
660             //
661
//this is the case of slow sync and without mappings into db
662
//
663
if (slowSync &&
664                 operations[i].getOperation() != SyncOperation.DELETE) {
665                 if (operations[i].getSyncItemA() != null &&
666                     operations[i].getSyncItemB() != null) {
667
668                     guid = operations[i].getSyncItemB().getKey().getKeyAsString();
669
670                     SyncItemKey sikA = operations[i].getSyncItemA().getMappedKey();
671                     if (sikA != null) {
672                         luid = sikA.getKeyAsString();
673                     } else {
674                         luid = operations[i].getSyncItemA().getKey().getKeyAsString();
675                     }
676                     clientMapping.updateMapping(guid , luid);
677                     continue;
678                 }
679             } else if (operations[i].getOperation() == SyncOperation.DELETE) {
680                 guid = operations[i].getSyncItemB().getKey().getKeyAsString();
681                 clientMapping.removeMappedValuesForGuid(guid);
682             } else if (operations[i].getSyncItemA().getState() == SyncItemState.DELETED &&
683                        operations[i].getSyncItemB().getState() == SyncItemState.DELETED ) {
684                 guid = operations[i].getSyncItemB().getKey().getKeyAsString();
685                 clientMapping.removeMappedValuesForGuid(guid);
686             } else if (operations[i].getSyncItemA().getState() == SyncItemState.NEW &&
687                        operations[i].getSyncItemB().getState() == SyncItemState.DELETED ) {
688                 guid = operations[i].getSyncItemB().getKey().getKeyAsString();
689                 clientMapping.removeMappedValuesForGuid(guid);
690             }
691         }
692     }
693
694     /**
695      * Updates the LUID-GUIDmapping for the client modifications (that is the
696      * items directlry inserted or removed by the server).
697      *
698      * @param clientMappings the client mappings for current synchronization
699      * @param status the status of the performed operations
700      * @param slowSync is true if slow synchronization
701      *
702      */

703     public static void updateServerMappings(Map JavaDoc clientMappings,
704                                             SyncOperationStatus[] status ,
705                                             boolean slowSync )
706
707     throws MappingException {
708         char op;
709         ClientMapping clientMapping = null;
710         String JavaDoc luid = null, guid = null;
711         SyncSource serverSource = null;
712         SyncOperation operation;
713         for (int i=0; ((status != null) && (i<status.length)); ++i) {
714             operation = status[i].getOperation();
715             op = operation.getOperation();
716
717             serverSource = status[i].getSyncSource();
718             if (serverSource == null) {
719                 //
720
// clientSource is null for unexsisting items
721
//
722
continue;
723             }
724
725             clientMapping = (ClientMapping)clientMappings.get(serverSource.getSourceURI());
726
727             //
728
//this is the case of slow sync and without mappings into db
729
//
730
if (slowSync &&
731                 (op != SyncOperation.DELETE) && (op != SyncOperation.NEW)) {
732
733                 if (operation.getSyncItemA() != null &&
734                     operation.getSyncItemB() != null) {
735
736                     guid = operation.getSyncItemB().getKey().getKeyAsString();
737
738                     SyncItemKey sikA = operation.getSyncItemA().getMappedKey();
739                     if (sikA != null) {
740                         luid = sikA.getKeyAsString();
741                     } else {
742                         luid = operation.getSyncItemA().getKey().getKeyAsString();
743                     }
744                     clientMapping.updateMapping(guid , luid);
745                     continue;
746                 }
747             } else if(op == SyncOperation.DELETE) {
748                     guid = operation.getSyncItemB().getKey().getKeyAsString();
749                     clientMapping.removeMappedValuesForGuid(guid);
750             } else if (op == SyncOperation.NEW) {
751                 if (operation.isBOperation()) {
752                     luid = operation.getSyncItemA().getKey().getKeyAsString();
753                     guid = operation.getSyncItemB().getKey().getKeyAsString();
754                     clientMapping.updateMapping(guid, luid);
755                 }
756             } else if (op == SyncOperation.CONFLICT) {
757                 if (SyncConflict.STATE_UPDATED_DELETED.equals(((SyncConflict)operation).getType())) {
758                     guid = operation.getSyncItemB().getKey().getKeyAsString();
759                     clientMapping.removeMappedValuesForGuid(guid);
760                 } else if (SyncConflict.STATE_DELETED_UPDATED.equals(((SyncConflict)operation).getType())) {
761                     luid = operation.getSyncItemA().getKey().getKeyAsString();
762                     guid = operation.getSyncItemB().getKey().getKeyAsString();
763                     clientMapping.updateMapping(guid, luid);
764                 } else if (SyncConflict.STATE_UPDATED_UPDATED.equals(((SyncConflict)operation).getType())) {
765                     luid = operation.getSyncItemA().getKey().getKeyAsString();
766                     guid = operation.getSyncItemB().getKey().getKeyAsString();
767                     clientMapping.updateMapping(guid, luid);
768                 } else if (SyncConflict.STATE_NEW_NEW.equals(((SyncConflict)operation).getType())) {
769                     luid = operation.getSyncItemA().getKey().getKeyAsString();
770                     guid = operation.getSyncItemB().getKey().getKeyAsString();
771                     clientMapping.updateMapping(guid, luid);
772                 } else {
773
774                     //
775
// These cases shuold never happen
776
//
777
assert (!SyncConflict.STATE_DELETED_NEW.equals(((SyncConflict)operation).getType()));
778                     assert (!SyncConflict.STATE_DELETED_CONFLICT.equals(((SyncConflict)operation).getType()));
779                     assert (!SyncConflict.STATE_UPDATED_NEW.equals(((SyncConflict)operation).getType()));
780                     assert (!SyncConflict.STATE_UPDATED_CONFLICT.equals(((SyncConflict)operation).getType()));
781                     assert (!SyncConflict.STATE_NEW_DELETED.equals(((SyncConflict)operation).getType()));
782                     assert (!SyncConflict.STATE_NEW_UPDATED.equals(((SyncConflict)operation).getType()));
783                     assert (!SyncConflict.STATE_NEW_CONFLICT.equals(((SyncConflict)operation).getType()));
784                     assert (!SyncConflict.STATE_NONE_CONFLICT.equals(((SyncConflict)operation).getType()));
785                     assert (!SyncConflict.STATE_CONFLICT_DELETED.equals(((SyncConflict)operation).getType()));
786                     assert (!SyncConflict.STATE_CONFLICT_UPDATED.equals(((SyncConflict)operation).getType()));
787                     assert (!SyncConflict.STATE_CONFLICT_NEW.equals(((SyncConflict)operation).getType()));
788                     assert (!SyncConflict.STATE_CONFLICT_CONFLICT.equals(((SyncConflict)operation).getType()));
789                 }
790             }
791
792         }
793     }
794
795     /**
796      * Creates a <i>DataStore</i> from a <i>SyncSourceInfo</i>
797      *
798      * @param uri the source URI
799      * @param info the <i>SyncSourceInfo</i>
800      *
801      * @return the corresponding <i>DataStore</i>
802      */

803     public static DataStore toDataStore(String JavaDoc uri, SyncSourceInfo info) {
804         ContentTypeInfo[] supportedContents = null;
805         ContentTypeInfo preferredContent = null;
806
807         if (info != null) {
808             ContentType[] supportedTypes = info.getSupportedTypes();
809             ContentType preferredType = info.getPreferredType() ;
810
811             supportedContents =
812                 new ContentTypeInfo[supportedTypes.length];
813
814             for (int i=0; (i<supportedTypes.length); ++i) {
815                 supportedContents[i] = new ContentTypeInfo (
816                     supportedTypes[i].type,
817                     supportedTypes[i].version
818                 );
819             }
820
821             preferredContent = new ContentTypeInfo(
822                 preferredType.type,
823                 preferredType.version
824             );
825         }
826
827         return new DataStore(
828             new SourceRef(uri),
829             null,
830             32,
831             preferredContent ,
832             supportedContents,
833             preferredContent ,
834             supportedContents,
835             null,
836             new SyncCap(SyncType.ALL_SYNC_TYPES)
837         );
838     }
839
840     /**
841      * Resets the item state of the items passed in the given collection to
842      * the <i>synchronized</i> state, unless an item is in the <i>partial</i>.
843      *
844      * @param items items collection
845      */

846     public static void resetState(Collection items) {
847         if (items == null) {
848             return;
849         }
850
851         Iterator i = items.iterator();
852         while (i.hasNext()) {
853             SyncItem s = (SyncItem)i.next();
854             if (s.getState() != SyncItemState.PARTIAL) {
855                 s.setState(SyncItemState.SYNCHRONIZED);
856             }
857         }
858     }
859
860     /**
861      * Resets the item state of the items passed in the given collection to
862      * the <i>synchronized</i> state, unless an item is in the <i>partial</i>.
863      *
864      * @param items items collection
865      */

866     public static void resetState(SyncItem[] items) {
867         if ((items == null) || (items.length == 0)) {
868             return;
869         }
870
871         for (int i=0; i<items.length; ++i) {
872             if (items[i].getState() != SyncItemState.PARTIAL) {
873                 items[i].setState(SyncItemState.SYNCHRONIZED);
874             }
875         }
876     }
877 }
878
879 class StatusKey {
880     public ModificationCommand cmd = null;
881     public int statusCode = 0;
882
883     public StatusKey(ModificationCommand cmd, int statusCode) {
884         this.cmd = cmd;
885         this.statusCode = statusCode;
886     }
887
888     public boolean equals(Object JavaDoc o){
889         if ((o != null) && (o instanceof StatusKey)) {
890             return (((StatusKey)o).cmd.getCmdID().equals(this.cmd.getCmdID()))
891                 && (((StatusKey)o).statusCode == this.statusCode);
892         }
893
894         return false;
895     }
896
897     public int hashCode() {
898         return ( String.valueOf(cmd.getCmdID().getCmdID())
899                + String.valueOf(statusCode)
900                ).hashCode();
901     }
902 }
903
Popular Tags