/// <summary> /// Load sync content from the sync command buffer in Fcade.CommandsToSend. /// </summary> /// <param name="syncML"></param> private void LoadSyncContent(SyncMLSyncML syncML) { SyncMLSync syncContent = SyncMLSync.Create(); syncContent.CmdID = syncML.NextCmdID; syncContent.Source.LocURI.Content = Facade.LocalDataSource.DataSourceName; syncContent.Target.LocURI.Content = Facade.ContactDataSourceAtServer; if (numberOfChanges > 0) { syncContent.NumberOfChanges.Content = numberOfChanges.ToString(); } Facade.ExtractNextCommands(syncContent.Commands); foreach (SyncMLCommand command in syncContent.Commands) { command.CmdID = syncML.NextCmdID; //commands from XmlToSyncMLSyncCommands does not contain CmdID CommandAndStatusRegister.Add(command); } syncML.Body.Commands.Add(syncContent); CommandAndStatusRegister.Add(syncContent); numberOfCommandsToSend = syncContent.Commands.Count; }
public void TestSync() { XElement nav = XElement.Load(CaseFile("Sync.xml")); SyncMLSync f = SyncMLSync.Create(nav); Assert.IsTrue(CompareXml(nav, f.Xml), f.Xml.ToString()); }
/// <summary> /// Load sync content from the sync command buffer in Fcade.CommandsToSend. /// </summary> /// <param name="syncML"></param> protected void LoadSyncContent(SyncMLSyncML syncML) { SyncMLSync syncContent = SyncMLSync.Create(); syncContent.CmdID = syncML.NextCmdID; syncContent.Source.LocURI.Content = Facade.LocalDataSource.DataSourceName; syncContent.Target.LocURI.Content = Facade.ContactDataSourceAtServer; syncML.Body.Commands.Add(syncContent); CommandAndStatusRegister.Add(syncContent); }
/// <summary> /// Process a sync command from server. This will update the local address book, and prepare map commands to be sent back to the server /// </summary> /// <param name="syncCommand"></param> private void ApplySyncCommandToLocal(SyncMLSync syncCommand) { Collection <SyncMLCommand> commands = syncCommand.Commands; if (commands.Count > 0) { //Step1: Apply the sync command to local through LocalDataSource. NameValueCollection localIDServerIDCollection = Facade.LocalDataSource.ApplySyncCommands(commands, Facade.LastAnchorTimeText); //Step2: Report error from LocalDataSource if any if (!String.IsNullOrEmpty(Facade.LocalDataSource.ErrorMessage)) { Facade.DisplayOperationMessage("PlatformProvider error: " + Facade.LocalDataSource.ErrorMessage); } //Step3: Prepare map command for next message to notify the server SyncMLMap map = GenerateMapCommand(localIDServerIDCollection, syncCommand); if (map.MapItemCollection.Count > 0) { Facade.ResponseCommandPool.Add(map); } //Step4: Report to the end user about updated names if (!String.IsNullOrEmpty(Facade.LocalDataSource.NamesOfAddedItems)) { Facade.DisplayOperationMessage("Items added:"); Facade.DisplayOperationMessage(Facade.LocalDataSource.NamesOfAddedItems); } if (!String.IsNullOrEmpty(Facade.LocalDataSource.NamesOfUpdatedItems)) { Facade.DisplayOperationMessage("Items updated:"); Facade.DisplayOperationMessage(Facade.LocalDataSource.NamesOfUpdatedItems); } if (!String.IsNullOrEmpty(Facade.LocalDataSource.NamesOfDeletedItems)) { Facade.DisplayOperationMessage("Items deleted:"); Facade.DisplayOperationMessage(Facade.LocalDataSource.NamesOfDeletedItems); } } }
//private void SendEmptySyncContent() //{ // //1: Generate SyncCommands in a buffer // Facade.CommandsToSend = new DummyEmptyCommandSource(); // Facade.totalNumberOfChangesSending = Facade.CommandsToSend.NumberOfChanges; // //2: Send the first batch of sync commands. // SendingSyncMessage sendingSyncStep = new SendingSyncMessage(Facade, Facade.totalNumberOfChangesSending); // sendingSyncStep.Send(); //} /// <summary> /// Generate map command through LocalID/ServerID paris. /// </summary> /// <param name="localIDServerIDPairs">The pairs is returned by local address book.</param> /// <param name="previousServerSyncCommand">The map command need to obtain some data from previous sync command.</param> /// <returns>The map command to be integrated into next SyncML message sent back to the server. CmdID is not assigned yet.</returns> private static SyncMLMap GenerateMapCommand(NameValueCollection localIDServerIDPairs, SyncMLSync previousServerSyncCommand) { SyncMLMap map = SyncMLMap.Create(); map.Target.LocURI.Content = previousServerSyncCommand.Source.LocURI.Content; map.Source.LocURI.Content = previousServerSyncCommand.Target.LocURI.Content; for (int i = 0; i < localIDServerIDPairs.Count; i++) { SyncMLMapItem mapItem = SyncMLMapItem.Create(); mapItem.Target.LocURI.Content = localIDServerIDPairs.Get(i); mapItem.Source.LocURI.Content = localIDServerIDPairs.GetKey(i); map.MapItemCollection.Add(mapItem); } return(map); }
/// <summary> /// Generate status commands for received Sync command, and put the commands into the pool. /// </summary> /// <param name="syncCommand">Sync command from the server.</param> private void GenerateStatusCommandsForSyncCommand(SyncMLSync syncCommand) { SyncMLStatus syncStatus = SyncMLStatus.Create(); syncStatus.Cmd.Content = "Sync"; syncStatus.CmdRef.Content = syncCommand.CmdID.Content; syncStatus.Data.Content = "200"; syncStatus.MsgRef.Content = ServerSyncML.Hdr.MsgID.Content; syncStatus.TargetRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLTargetRef>(syncCommand.Target.LocURI.Content)); syncStatus.SourceRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLSourceRef>(syncCommand.Source.LocURI.Content)); Facade.ResponseCommandPool.Add(syncStatus); Collection <SyncMLCommand> commands = syncCommand.Commands; if (commands != null) { foreach (SyncMLCommand command in commands) { SyncMLAdd addCommand = command as SyncMLAdd; if (addCommand != null) { SyncMLStatus addStatus = SyncMLStatus.Create(); addStatus.Cmd.Content = "Add"; addStatus.CmdRef.Content = command.CmdID.Content; addStatus.Data.Content = "200"; addStatus.MsgRef.Content = syncStatus.MsgRef.Content; addStatus.SourceRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLSourceRef>(addCommand.ItemCollection[0].Source.LocURI.Content)); Facade.ResponseCommandPool.Add(addStatus); continue; } SyncMLReplace replaceCommand = command as SyncMLReplace; if (replaceCommand != null) { SyncMLStatus replaceStatus = SyncMLStatus.Create(); replaceStatus.Cmd.Content = "Replace"; replaceStatus.CmdRef.Content = command.CmdID.Content; replaceStatus.Data.Content = "200"; replaceStatus.MsgRef.Content = syncStatus.MsgRef.Content; replaceStatus.TargetRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLTargetRef>(replaceCommand.ItemCollection[0].Target.LocURI.Content)); Facade.ResponseCommandPool.Add(replaceStatus); continue; } SyncMLDelete deleteCommand = command as SyncMLDelete; if (deleteCommand != null) { SyncMLStatus deleteStatus = SyncMLStatus.Create(); deleteStatus.Cmd.Content = "Delete"; deleteStatus.CmdRef.Content = command.CmdID.Content; deleteStatus.Data.Content = "200"; deleteStatus.MsgRef.Content = syncStatus.MsgRef.Content; deleteStatus.SourceRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLSourceRef>(deleteCommand.ItemCollection[0].Target.LocURI.Content)); Facade.ResponseCommandPool.Add(deleteStatus); continue; } } } }
protected override bool ProcessResponse(string text) { if (!base.ProcessResponse(text)) { return(false); } // So now syncml model is created from text UpdateCurrentURI(ServerSyncML); //0: Always have a status response to the SyncHdr of the server message. However, this status may not be sent back if it is the only one in the queue. SyncMLStatus responseStatus = SyncMLStatus.Create(); responseStatus.MsgRef.Content = ServerSyncML.Hdr.MsgID.Content; responseStatus.Data.Content = "200"; responseStatus.Cmd.Content = "SyncHdr"; responseStatus.CmdRef.Content = "0"; responseStatus.TargetRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLTargetRef>(ServerSyncML.Hdr.Target.LocURI.Content)); responseStatus.SourceRefCollection.Add(SyncMLSimpleElementFactory.Create <SyncMLSourceRef>(ServerSyncML.Hdr.Source.LocURI.Content)); Facade.ResponseCommandPool.Add(responseStatus);//respond in next request. //1: Handle returned status commands Collection <SyncMLStatus> serverStatusCommands = AccessBody.GetStatusCommands(ServerSyncML); foreach (SyncMLStatus status in serverStatusCommands) { CommandAndStatusRegister.RegisterStatus(status.CmdRef.Content, status.Data.Content); HandleServerStatus(status); //this fn is still abstract here. Derived classes have different ways of handling. } //2: Prepare status commands for returned Alert commands. Derived classes then handle the alerts all the same way. Collection <SyncMLAlert> serverAlertCommands = AccessBody.GetAlertCommands(ServerSyncML); foreach (SyncMLAlert alert in serverAlertCommands) { Debug.WriteLine("Alert:" + alert.Xml.ToString()); PrepareStatusForReturnedAlert(alert); } //3: Handle returned Sync command. Derived classes handle sync commands the same way. SyncMLSync serverSyncCommand = AccessBody.GetSyncCommand(ServerSyncML); if (serverSyncCommand != null) { string numberOfChangesStr = serverSyncCommand.NumberOfChanges.Content; if (!String.IsNullOrEmpty(numberOfChangesStr)) {//where numberOfChanges > 0, display progress bar in GUI. Facade.totalNumberOfChangesReceiving = Convert.ToInt32(numberOfChangesStr); if (Facade.totalNumberOfChangesReceiving > 0) { Facade.DisplayOperationMessage(String.Format("Total number of changes received from the server: {0}", numberOfChangesStr)); Facade.InitProgressBarReceiving(0, Facade.totalNumberOfChangesReceiving, 1); Facade.DisplayStageMessageReceiving(String.Format("Receiving {0} updates ...", Facade.totalNumberOfChangesReceiving)); } } int numbersOfChangesThisMessage = serverSyncCommand.Commands.Count; // the server might send in multiple messages Facade.numberOfChangesReceived += numbersOfChangesThisMessage; if (Facade.numberOfChangesReceived == Facade.totalNumberOfChangesReceiving) { Facade.DisplayStageMessageReceiving("Receiving Done"); } GenerateStatusCommandsForSyncCommand(serverSyncCommand); if (Facade.GracefulStop) { return(true); // simply return, ture of false is meaningless. } Facade.IncrementProgressBarReceiving(numbersOfChangesThisMessage); ApplySyncCommandToLocal(serverSyncCommand); } //4: Verify if the server return all status codes to commands sent if (!CommandAndStatusRegister.IsAllCommandsReturnedWithStatus()) { Trace.TraceInformation("!!!! Not all commands got status code. Please check the log for details."); Trace.TraceInformation("Commands without status: " + CommandAndStatusRegister.CommandsXmlWithoutStatus); //It is expected CommandAndStatusRegister is not used any more, otherwise, should clear it here. } //5: At the end, do what the server ask to do, likely a new SyncML message to be sent ProcessServerAlertCommands(serverAlertCommands); return(true); }