kitchensync Library API Documentation

syncalgo.cpp

00001 /* 00002 This file is part of KitchenSync. 00003 00004 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 #include <kdebug.h> 00023 00024 #include <syncee.h> 00025 00026 #include "syncalgo.h" 00027 00028 using namespace KSync; 00029 00030 PIMSyncAlg::PIMSyncAlg( SyncUi* ui ) 00031 : SyncAlgorithm( ui ) 00032 { 00033 } 00034 00035 PIMSyncAlg::~PIMSyncAlg() 00036 { 00037 } 00038 00039 /* 00040 * let's find the best algorithm first. If both are MetaMode 00041 * use meta mode or if not use syncFirst 00042 */ 00043 void PIMSyncAlg::syncToTarget( Syncee* syncee, 00044 Syncee* target, 00045 bool override) 00046 { 00047 if (syncee->syncMode() == Syncee::MetaLess || 00048 syncee->firstSync() ) 00049 return syncFirst(syncee, target, override); 00050 else if ( target->syncMode() == Syncee::MetaLess || 00051 target->firstSync() ) 00052 return syncFirst( syncee, target, override ); 00053 else 00054 return syncMeta( syncee, target, override ); 00055 } 00056 00057 /* 00058 * First Sync or no MetaData 00059 * slightly changed syncToTarget from StandardSync 00060 */ 00061 void PIMSyncAlg::syncFirst( Syncee* syncee, 00062 Syncee* target, 00063 bool override ) 00064 { 00065 kdDebug(5231) << "SyncFirst " << endl; 00066 SyncEntry *targetEntry = 0l; 00067 00068 /* start with the first */ 00069 SyncEntry *sourceEntry = syncee->firstEntry(); 00070 /* whilte it's not the last+1 one */ 00071 while (sourceEntry) { 00072 00073 if ( sourceEntry->state() == SyncEntry::Removed ) { 00074 kdDebug(5231) << "Entry removed " << sourceEntry->name() << endl; 00075 sourceEntry = syncee->nextEntry(); 00076 continue; 00077 } 00078 00079 /* let's see if it's in the other set */ 00080 targetEntry = 0l; 00081 targetEntry = target->findEntry(sourceEntry->id()); 00082 00083 /* if it is check if modified. if not it's new */ 00084 if (targetEntry) { 00085 kdDebug(5231) << "Found target " << endl; 00086 // Entry already exists in target 00087 if (sourceEntry->equals(targetEntry)) { 00088 kdDebug(5231) << "No action required" << endl; 00089 // Entries are equal, no action required 00090 } else { 00091 // Entries are different, resolve conflict 00092 if (override && targetEntry->state() != SyncEntry::Removed ) { 00093 // Force override 00094 kdDebug(5231) << "overriding and merging!" << endl; 00095 // we try to keep as much attributes as possible 00096 sourceEntry->mergeWith( targetEntry ); 00097 target->replaceEntry(targetEntry,sourceEntry->clone() ); 00098 } else { 00099 if (syncee->hasChanged(sourceEntry) && 00100 target->hasChanged(targetEntry)) { 00101 kdDebug(5231) << "Deconflict " << endl; 00102 kdDebug(5231) << "Entry 1 state: " << sourceEntry->state() << endl; 00103 kdDebug(5231) << "Entry 2 state: " << targetEntry->state() << endl; 00104 // Both entries have changed 00105 SyncEntry *result = deconflict(sourceEntry,targetEntry); 00106 if (result == sourceEntry) { 00107 kdDebug(5231) << "Merging and then replacing!" << endl; 00108 sourceEntry->mergeWith( targetEntry ); 00109 target->replaceEntry(targetEntry,sourceEntry->clone() ); 00110 }else 00111 targetEntry->mergeWith( sourceEntry ); 00112 00113 } else if (syncee->hasChanged(sourceEntry) && 00114 !target->hasChanged(targetEntry)) { 00115 // take source entry 00116 kdDebug(5231) << "Take source entry" << endl; 00117 sourceEntry->mergeWith( targetEntry ); 00118 target->replaceEntry(targetEntry,sourceEntry->clone() ); 00119 } else if (!syncee->hasChanged(sourceEntry) && 00120 target->hasChanged(targetEntry)) { 00121 // take target entry, no action required but merge 00122 kdDebug(5231) << "Take target entry" << endl; 00123 targetEntry->mergeWith(sourceEntry); 00124 } 00125 } 00126 } 00127 } else { 00128 // New entry if id starts with konnector id... set a new one 00129 kdDebug(5231) << "adding target " << endl; 00130 addEntry( syncee, target, sourceEntry ); 00131 } 00132 sourceEntry = syncee->nextEntry(); 00133 } 00134 } 00135 00136 /* 00137 * We're now in the MetaMode 00138 * First sync added. 00139 * Then check the modified 00140 * Case 1) 00141 * Modified ---- untouched ----> Modify 00142 * Modified ---- Modified ---> Deconflict 00143 * Modified ---- Removed ----> Deconflict 00144 * and vice versa 00145 * 00146 */ 00147 void PIMSyncAlg::syncMeta( Syncee* syncee, 00148 Syncee* target, 00149 bool over ) 00150 { 00151 kdDebug(5231) << "SyncMeta " << endl; 00152 QPtrList<SyncEntry> entries = syncee->added(); 00153 SyncEntry* entry; 00154 SyncEntry* targetEntry; 00155 /* added */ 00156 for ( entry = entries.first(); entry; entry = entries.next() ) { 00157 /* assign new uid */ 00158 targetEntry = target->findEntry( entry->id() ); 00159 kdDebug(5231) << "About to add " << entry->name() << endl; 00160 if(!targetEntry ){ 00161 kdDebug(5231) << "Not added before " << endl; 00162 addEntry( syncee, target, entry ); 00163 }else { 00164 kdDebug(5231) << "Added before " << endl; 00165 } 00166 } 00167 /* modified */ 00168 forAll( syncee->modified(), syncee, target, over ); 00169 forAll( syncee->removed(), syncee, target,over ); 00170 00171 } 00172 00173 void PIMSyncAlg::addEntry( Syncee* in, Syncee* out, SyncEntry* add ) 00174 { 00175 if ( add->id().startsWith("Konnector-") ) { 00176 QString oldId = add->id(); 00177 add->setId( in->newId() ); 00178 in->insertId( add->type(), oldId, add->id() ); 00179 out->insertId( add->type(), oldId, add->id() ); 00180 } 00181 out->addEntry( add->clone() ); 00182 } 00183 00184 /* 00185 * Ok we are either modified 00186 * or removed 00187 * Now go through each item and look for one with the 00188 * same uid 00189 * If found check if it was Modified or Removed too 00190 * If yes check if they're equal otherwise 00191 * we need to deconflict 00192 */ 00193 void PIMSyncAlg::forAll(QPtrList<SyncEntry> entries, Syncee* syncee, 00194 Syncee* target, 00195 bool over ) 00196 { 00197 kdDebug(5231) << "For All" << endl; 00198 SyncEntry* entry; 00199 SyncEntry* other; 00200 SyncEntry* result; 00201 /* for all modified and deleted*/ 00202 for ( entry = entries.first(); entry; entry = entries.next() ) { 00203 result = 0; 00204 other = target->findEntry( entry->id() ); 00205 if (other ) { // exists, should always do 00206 kdDebug(5231) << "Entry 1 " << entry->name() << endl; 00207 kdDebug(5231) << "Entry 2 " << other->name() << endl; 00208 00209 /* entry modified and other unchanged */ 00210 if(entry->wasModified() && other->state()== SyncEntry::Undefined ) { 00211 kdDebug(5231) << "Modified and unchanged " << endl; 00212 entry->mergeWith( other ); 00213 target->replaceEntry( other, entry->clone() ); 00214 } 00215 /* entry removed and other unchanged or removed too */ 00216 else if ( entry->wasRemoved() && 00217 other->wasRemoved() ) { 00218 kdDebug(5231) << "Removed and removed too " << endl; 00219 // no need for merge 00220 informBothDeleted( entry, other ); 00221 target->replaceEntry( other, entry->clone() ); 00222 /* entry removed and other undefined confirmDelete */ 00223 } else if ( entry->wasRemoved() && 00224 other->state() == SyncEntry::Undefined ) { 00225 /* if confirmed that is fairly easy */ 00226 if (confirmDelete(entry, other) ) 00227 target->replaceEntry( other, entry->clone() ); 00228 /* 00229 * aye aye how can we do this 00230 * first of all we need to remove the modified flag 00231 * then we need to set the support to 0 on the syncee 00232 * and call a mergeWith 00233 * then we reset the BitArray 00234 */ 00235 else { 00236 QBitArray ar = entry->syncee()->bitArray(); 00237 QBitArray oth; 00238 oth.fill( false, ar.size() ); 00239 entry->syncee()->setSupports( oth ); 00240 /* refill the object with life */ 00241 entry->mergeWith( other ); 00242 00243 /* 00244 * This is specefic to two Syncees 00245 * if!over we set the other to Modifed 00246 * so the original(other) one will replace the former deleted one 00247 * if we're on override there will be no second call 00248 */ 00249 if (!over ) { 00250 entry->setState( SyncEntry::Undefined ); 00251 other->setState( SyncEntry::Modified); 00252 } else 00253 entry->setState( SyncEntry::Modified); 00254 00255 /* restore */ 00256 entry->syncee()->setSupports( ar ); 00257 } 00258 } 00259 /* entry was removed and other changed */ 00260 else if ( entry->wasRemoved() && 00261 other->wasModified() ) { 00262 kdDebug(5231) << "Entry wasRemoved and other wasModified override is " 00263 << over << endl; 00264 if (!over) 00265 result = deconflict(entry,other); 00266 if (result == entry || over) { 00267 // no need to merge here too we still remove 00268 target->replaceEntry(other,entry->clone() ); 00269 } 00270 00271 } else if ( entry->wasModified() && other->wasModified() ) { 00272 kdDebug(5231) << "Both where modified override" << over<< endl; 00273 kdDebug(5231) << "Entry1 timestamp " << entry->timestamp() << endl; 00274 kdDebug(5231) << "Entry2 timestamp " << other->timestamp() << endl; 00275 kdDebug(5231) << "Equals " << entry->equals( other ) << endl; 00276 00277 if (!over ) 00278 result = deconflict(entry,other); 00279 00280 if (result == entry || over) { 00281 entry->mergeWith( other ); 00282 target->replaceEntry(other,entry->clone() ); 00283 } 00284 00285 } 00286 00287 } else { 00288 kdDebug(5231) << "added " << endl; 00289 addEntry(syncee, target, entry); 00290 } 00291 00292 } 00293 }
KDE Logo
This file is part of the documentation for kitchensync Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 1 15:18:59 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003