/** * @license * Copyright (c) 2010 Zef Hemel * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ if(!window.persistence) { // persistence.js not loaded! throw new Error("persistence.js should be loaded before persistence.sync.js"); } persistence.sync = {}; persistence.sync.getJSON = function(uri, callback, errorCallback) { var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET", uri, true); xmlHttp.send(); xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState==4) { if(xmlHttp.status==200) { callback(JSON.parse(xmlHttp.responseText)); } else if(typeof errorCallback === 'function') { errorCallback(xmlHttp); } } }; }; persistence.sync.postJSON = function(uri, data, callback) { var xmlHttp = new XMLHttpRequest(); xmlHttp.open("POST", uri, true); xmlHttp.setRequestHeader('Content-Type', 'application/json'); xmlHttp.send(data); xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState==4 && xmlHttp.status==200) { callback(JSON.parse(xmlHttp.responseText)); } }; }; (function() { var argspec = persistence.argspec; persistence.sync.Sync = persistence.define('_Sync', { entity: "VARCHAR(255)", localDate: "BIGINT", serverDate: "BIGINT", serverPushDate: "BIGINT" }); persistence.sync.RemovedObject = persistence.define('_SyncRemovedObject', { entity: "VARCHAR(255)", objectId: "VARCHAR(32)" }); function getEpoch(date) { return date.getTime(); } persistence.sync.preferLocalConflictHandler = function(conflicts, updatesToPush, callback) { conflicts.forEach(function(conflict) { var update = {id: conflict.local.id}; conflict.properties.forEach(function(p) { update[p] = conflict.local._data[p]; }); updatesToPush.push(update); }); callback(); }; persistence.sync.preferRemoteConflictHandler = function(conflicts, updatesToPush, callback) { conflicts.forEach(function(conflict) { conflict.properties.forEach(function(p) { conflict.local[p] = conflict.remote[p]; }); }); persistence.flush(callback); }; function encodeUrlObj(obj) { var parts = []; for(var k in obj) { if(obj.hasOwnProperty(k)) { parts.push(encodeURI(k)+"="+encodeURI(obj[k])); } } return "?" + parts.join("&"); } /** * The main caching and updating function, would be nice to refactor this */ function cacheAndFindUpdates(session, Entity, objects, lastLocalSyncTime, lastServerPushTime, conflictCallback, callback) { var ids = []; var lookupTbl = {}; var conflicts = []; var updatesToPush = []; var meta = Entity.meta; var fieldSpec = meta.fields; var objectsToRemove = []; objects.forEach(function(item) { if(item._removed) { // special marker objectsToRemove.push(item.id); } else { ids.push(item.id); lookupTbl[item.id] = item; } }); // Step 1: Look at local versions of remotely updated entities var existingItems = [], groupedIds = []; for (var i=0,l=Math.floor((ids.length/100)+1);i 0) { conflicts.push({local: localItem, remote: remoteItem, properties: conflictingProperties}); } }); // Step 2: Remove all remotely removed objects var groupedObjectsToRemove = []; for (var i=0,l=Math.floor((objectsToRemove.length/100)+1);i", lastLocalSyncTime).list(function(allNewItems) { var newItems = []; for (var i=0,l=allNewItems.length;i