private void CollectDeleteForeverTasks(SyncTaskBean syncTaskBean, Dictionary<String, Tasks> localTasks, TaskSyncModel taskSyncModel)
        {
            // DELETED_FOREVER操作直接删除本地task,并清楚TaskSyncedJson
            List<TasksProjects> deletedForeverTasks = syncTaskBean.DeletedForever;//DeleteChangeToTaskProjects(syncTaskBean.Delete);
            foreach (var taskProject in deletedForeverTasks)
            {
                String taskSid = taskProject.TaskId;
                if (!localTasks.ContainsKey(taskSid))
                {
                    continue;
                }
                Tasks localTask = localTasks[taskSid];
                if (localTask != null)
                {
                    taskSyncModel.AddDeletedForeverTask(localTask);
                    localTasks.Remove(taskSid);
                    // delete original task
                    TaskSyncedJson json = new TaskSyncedJson();
                    json.UserId = localTask.UserId;
                    json.TaskSID = taskSid;
                    taskSyncModel.AddDeletedTaskSyncedJson(json);
                }
            }

        }
        private async Task CollectDeleteInTrash(SyncTaskBean syncTaskBean, Dictionary<String, Tasks> localTasks, TaskSyncModel taskSyncModel)
        {

            //DELETED_IN_TRASH操作需要和本地task进行Merge
            List<TasksProjects> deletedTrashTasks = syncTaskBean.DeletedInTrash;//DeleteChangeToTaskProjects(syncTaskBean.Delete);//此处有坑DeletedInTrash;

            if (deletedTrashTasks.Count <= 0)
            {
                return;
            }

            HashSet<String> RestoreTaskIds = await SyncStatusBll.GetEntityIdsByType(UserId, ModelStatusEnum.SYNC_TYPE_TASK_RESTORE);

            foreach (var taskProject in deletedTrashTasks)
            {
                String taskSid = taskProject.TaskId;
                //本地restore操作覆盖remote删除操作
                if (RestoreTaskIds.Contains(taskSid))
                {
                    continue;
                }
                Tasks localTask = localTasks[taskSid];
                if (localTask != null)
                {
                    taskSyncModel.AddDeletedInTrashTask(localTask);
                }
            }
        }
        private async Task CollectDeletedTasksFromRemoteModel(SyncTaskBean syncTaskBean, Dictionary<String, Tasks> localTasks, TaskSyncModel taskSyncModel)
        {

            CollectDeleteForeverTasks(syncTaskBean, localTasks, taskSyncModel);

            await CollectDeleteInTrash(syncTaskBean, localTasks, taskSyncModel);

        }
        public async Task<TaskSyncModel> CollectSyncTaskBean(SyncTaskBean syncTaskBean, Dictionary<String, Tasks> localTasks)
        {
            TaskSyncModel taskSyncModel = new TaskSyncModel();

            await CollectDeletedTasksFromRemoteModel(syncTaskBean, localTasks, taskSyncModel);

            List<TasksServer> update = syncTaskBean.Update;//UpdateChangeToTasks(syncTaskBean.Update);

            if (update.Count <= 0)
            {
                return taskSyncModel;
            }
            await MergeUpdatedTasksFromService(localTasks, taskSyncModel, update);
            return taskSyncModel;
        }
    /**
 * 批量保存Task下面的Location和Attachment
 * @param taskSyncModel
 */
    private async Task SaveTaskOtherEntity(TaskSyncModel taskSyncModel)
    {
        LocationSyncBean locationSyncBean = taskSyncModel.LocationSyncBean;
        AttachmentSyncBean attachmentSyncBean = taskSyncModel.AttachmentSyncBean;
        if (locationSyncBean.IsEmpty() && attachmentSyncBean.IsEmpty())
        {
            return;
        }
        Dictionary<String, int> taskIdDic = await TaskBll.GetTaskSidToIdDic(userId);
        if (!locationSyncBean.IsEmpty())
        {
            if (LoggerHelper.IS_LOG_ENABLED)
            {
                await LoggerHelper.LogToAllChannels(null,"Save remote location, " + locationSyncBean.ToString());
            }
            await LocationBll.SaveServerMergeToDB(locationSyncBean, userId, taskIdDic);
        }
        if (!attachmentSyncBean.IsEmpty())
        {
            if (LoggerHelper.IS_LOG_ENABLED)
            {
                await LoggerHelper.LogToAllChannels(null, "Save remote attachment, " + attachmentSyncBean.ToString());
            }
            await AttachmentBll.SaveServerMergeToDB(attachmentSyncBean, userId, taskIdDic);
        }
    }
 private async Task SaveTaskJsonStrings(TaskSyncModel taskSyncModel)
 {
     await TaskSyncedJsonBll.SaveTaskSyncedJsons(taskSyncModel.TaskSyncedJsonBean, userId);
 }
 private async Task BatchSaveTaskSyncModel(TaskSyncModel taskSyncModel)
 {
     await SaveTaskSyncBean(taskSyncModel.TaskSyncBean);
     await SaveTaskOtherEntity(taskSyncModel);
     await SaveTaskJsonStrings(taskSyncModel);
 }
        private async Task AddRemoteTaskToLocal(TaskSyncModel taskSyncModel, TasksServer serverTask, string projectId)
        {
            taskSyncModel.AddAddedTaskSyncedJson(serverTask);

            if (HasLocation(serverTask))
            {
                taskSyncModel.AddUpdateLocation(await LocationTransfer.ConvertServerToLocal(serverTask));
            }

            if (HasAttachment(serverTask))
            {
                taskSyncModel.AddAllAddedAttachments(await AttachmentTransfer.ConvertServerToLocal(serverTask.Attachments, UserId, serverTask.Id));
            }

            Tasks newTask = TaskTransfer.ConvertServerTaskToLocalWithChecklistItem(serverTask);
            newTask.ProjectId = projectId;
            newTask.UserId = UserId;
            newTask.HasAttachment = serverTask.Attachments != null && serverTask.Attachments.Count > 0;
            taskSyncModel.AddAddedTask(newTask);
        }
        public async Task MergeUpdatedTasksFromService(Dictionary<String, Tasks> localTasks, TaskSyncModel taskSyncModel, List<TasksServer> updateServerTasks)
        {
            Dictionary<String, TaskSyncedJson> originalJsons = await TaskSyncedJsonBll.GetAllTaskSyncedJsonDic(UserId);
            Dictionary<String, String> moveListTasksDic = await SyncStatusBll.GetMoveFromIdDic(UserId);
            HashSet<String> contentChangeTaskIds = await SyncStatusBll.GetContentChangeEntityIds(UserId);

            HashSet<String> orderInGroupTaskIds = await SyncStatusBll.GetSortOrderChangeEntityIds(UserId);
            HashSet<String> assignTaskIds = await SyncStatusBll.GetAssignEntityIds(UserId);
            HashSet<String> moveToTrashStatusIds = await SyncStatusBll.GetMoveToTrashEntityIds(UserId);
            Dictionary<String, string> projectIdDic = await ProjectBll.GetProjectSidToIdsDic(UserId);

            //ObjectMapper mapper = new ObjectMapper();//json与对象映射,可以使用newton.json代替

            foreach (var serverTask in updateServerTasks)
            {
                //本地没有找到对应是Project,Task不添加到本地
                if (serverTask.ProjectId == null || !projectIdDic.ContainsKey(serverTask.ProjectId))
                {
                    //Log.e(TAG, "Local project not found : project_id = " + serverTask.getProjectId());
                    continue;
                }

                //Tasks localTask = localTasks[serverTask.Id];
                string projectId = projectIdDic[serverTask.ProjectId];
                if (serverTask.Id != null && localTasks.ContainsKey(serverTask.Id))
                {
                    Tasks localTask = localTasks[serverTask.Id];// 索引器必须有值,否则会报错    
                    if (LoggerHelper.IS_LOG_ENABLED)
                    {
                        await LoggerHelper.LogToAllChannels(null, "serverTask.etag = " + serverTask.Etag + " , localTask.etag = " + localTask.Etag);
                    }

                    // 本地的DELETE_FOREVER操作,舍弃server端的任何修改
                    if (localTask.IsDeletedForever())
                    {
                        continue;
                    }

                    // Etag作为判断两个版本是否一直的唯一标识
                    if (string.Equals(serverTask.Etag, localTask.Etag))
                    {
                        continue;
                    }

                    await MergeMoveListAction(moveListTasksDic, serverTask, localTask, projectId);

                    MergeTaskAssignee(assignTaskIds, serverTask, localTask);

                    await LocationSyncCollector.CollectRemoteLocations(serverTask, localTask, taskSyncModel.LocationSyncBean);

                    await AttachmentSyncCollector.CollectRemoteAttachments(serverTask, localTask, taskSyncModel.AttachmentSyncBean);

                    bool needMove2Trash = moveToTrashStatusIds.Contains(localTask.SId);

                    if (contentChangeTaskIds.Contains(localTask.SId) || orderInGroupTaskIds.Contains(localTask.SId))
                    {
                        // 先查找对应的Original版本
                        TaskSyncedJson originalJson = originalJsons[serverTask.Id];
                        Tasks originalTask = null;
                        if (originalJson != null)
                        {
                            originalTask = TaskTransfer.ConvertTaskSyncedJsonToLocal(originalJsons[serverTask.Id]);//这个方法中android的mapper可以在方法中使用newton.json替代进行json转对象的操作
                        }

                        // 没有Original版本时,不进行Merge,直接Local覆盖Server
                        if (originalTask != null)
                        {
                            //执行merge操作
                            Tasks deltaTask = TaskTransfer.ConvertServerTaskToLocalWithChecklistItem(serverTask);
                            TaskUtils.MergeTask(originalTask, deltaTask, localTask);

                            // 设置其他属性
                            localTask.Kind = localTask.ChecklistItems.Count <= 0 ? Constants.Kind.TEXT : Constants.Kind.CHECKLIST;
                            localTask.Etag = serverTask.Etag;
                            //localTask.RepeatReminderTime = localTask.IsRepeatTask() ? localTask.SnoozeRemindTime : DateTime.MinValue;
                            String repeatFromRemote = serverTask.RepeatFrom;
                            localTask.RepeatFrom = string.IsNullOrEmpty(repeatFromRemote) ? Constants.RepeatFromStatus.DEFAULT : repeatFromRemote;

                            if (needMove2Trash)
                            {
                                localTask.Deleted = ModelStatusEnum.DELETED_TRASH;
                            }
                            taskSyncModel.AddUpdatingTask(localTask);
                        }
                    }
                    else
                    {
                        TaskTransfer.ConvertServerTaskToLocalWithChecklistItem(localTask, serverTask);
                        if (needMove2Trash)
                        {
                            localTask.Deleted = ModelStatusEnum.DELETED_TRASH;
                        }
                        taskSyncModel.AddUpdatedTask(localTask);
                    }
                    taskSyncModel.AddUpdatedTaskSyncedJson(serverTask);
                }
                else
                {
                    await AddRemoteTaskToLocal(taskSyncModel, serverTask, projectId);
                }

            }
        }