示例#1
0
        private void FSEventListAnalysisTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            List <FSSyncEvent>  WorkingList;
            List <FSSyncEvent>  TempList;
            FSSyncEvent         TempEvent;
            FSSyncEvent         MyEvent;
            BasicActionEnum     TempFileChainStatus;
            string              TempFinalFileName  = String.Empty;
            string              TempFinalFileName2 = String.Empty;
            VirtualFile         TempVirtualFile;
            SyncEventIgnoreItem SEII;

            List <FSSyncEvent> FilteredList = new List <FSSyncEvent>();

            lock (FSEventListLock)
            {
                //Extract the list for analysis
                WorkingList = ObjectCopier.Clone(FSEventList);
                FSEventList.Clear();
            }

            #region Event Analysis

            for (int i = 0; i < WorkingList.Count; i++)
            {
                WorkingList[i].Index = i;                                         //Reindex the list of actions
            }
            lock (FSEventListAnalysisLock)
            {
                while (WorkingList.Count > 0)
                {
                    MyEvent = WorkingList[0];

                    switch (MyEvent.Action)
                    {
                    case BasicActionEnum.Created:

                        //Detect Temporary : Create / Update / Delete in the same batch
                        TempEvent = WorkingList.Find(x => x.Action.Equals(BasicActionEnum.Deleted) && x.Index > MyEvent.Index && x.OldOrCurrentFilePathFull.Equals(MyEvent.OldOrCurrentFilePathFull));
                        if (TempEvent != null)
                        {
                            //Log(String.Format("File {0} was temporary", MyEvent.OldOrCurrentFilePathFull)); //Temporary file, do nothing about it
                            WorkingList.Remove(TempEvent);
                        }
                        else
                        {
                            //Remove multiple Changed events for the same file
                            TempList = WorkingList.FindAll((x => x.Action.Equals(BasicActionEnum.Changed) && x.OldOrCurrentFilePathFull.Equals(MyEvent.OldOrCurrentFilePathFull)));
                            if (TempList != null)
                            {
                                foreach (FSSyncEvent xe in TempList)
                                {
                                    WorkingList.Remove(xe);
                                }
                            }

                            //Check what happened to this new file
                            TempFileChainStatus = BuildFileEventChain(MyEvent.OldOrCurrentFilePathFull, MyEvent.Index, WorkingList, ref TempFinalFileName /*, ref TempIndex*/);
                            if (TempFileChainStatus.Equals(BasicActionEnum.Renamed))
                            {
                                FilteredList.Add(new FSSyncEvent(BasicActionEnum.Created, TempFinalFileName, ""));
                                //Log(String.Format("File was created with name {0} and finally renamed to {1}", MyEvent.OldOrCurrentFilePathFull, TempFinalFileName));
                            }
                            else if (TempFileChainStatus.Equals(BasicActionEnum.Deleted))
                            {
                                //Log(String.Format("File {0} was a temporary file",MyEvent.OldOrCurrentFilePathFull));
                            }
                            else
                            {
                                FilteredList.Add(new FSSyncEvent(BasicActionEnum.Created, MyEvent.OldOrCurrentFilePathFull, ""));
                                //Log(String.Format("File {0} is new", MyEvent.OldOrCurrentFilePathFull));
                            }
                        }

                        break;

                    case BasicActionEnum.Changed:

                        //Is there are subsequent changes for this file, ignore them
                        WorkingList.RemoveAll((x => x.Action.Equals(BasicActionEnum.Changed) && x.Index > MyEvent.Index && x.OldOrCurrentFilePathFull.Equals(MyEvent.OldOrCurrentFilePathFull)));

                        //Check if the file is not deleted in a next step
                        TempEvent = WorkingList.Find(x => x.Action.Equals(BasicActionEnum.Deleted) && x.Index > MyEvent.Index && x.OldOrCurrentFileName.Equals(MyEvent.OldOrCurrentFileName));
                        if (TempEvent != null)
                        {
                            //Log(String.Format("File {0} was deleted", MyEvent.OldOrCurrentFilePathFull));
                            FilteredList.Add(new FSSyncEvent(BasicActionEnum.Deleted, MyEvent.OldOrCurrentFilePathFull, ""));
                            WorkingList.Remove(TempEvent);
                        }
                        else
                        {
                            //Log(String.Format("File {0} has changed", MyEvent.OldOrCurrentFilePathFull));
                            FilteredList.Add(new FSSyncEvent(BasicActionEnum.Changed, MyEvent.OldOrCurrentFilePathFull, ""));
                        }

                        break;

                    case BasicActionEnum.Deleted:
                        //Check if there is a following Create for the same file name, means it has been moved
                        //TODO : Maybe Move detected should be made on more than the filename / can add last modification date
                        TempEvent = WorkingList.Find(x => x.Action.Equals(BasicActionEnum.Created) && x.Index > MyEvent.Index && x.OldOrCurrentFileName.Equals(MyEvent.OldOrCurrentFileName));
                        if (TempEvent != null)
                        {
                            if (MyEvent.OldOrCurrentFilePathFull.Equals(TempEvent.OldOrCurrentFilePathFull))
                            {
                                //Log(String.Format("File {0} has been updated", MyEvent.OldOrCurrentFilePathFull)); //A file moved to the same location is an updated file and not a moved file
                                FilteredList.Add(new FSSyncEvent(BasicActionEnum.Changed, MyEvent.OldOrCurrentFilePathFull, ""));
                            }
                            else
                            {
                                //Log(String.Format("File {0} has moved to {1}", MyEvent.OldOrCurrentFilePathFull, TempEvent.OldOrCurrentFilePathFull));
                                FilteredList.Add(new FSSyncEvent(BasicActionEnum.Moved, MyEvent.OldOrCurrentFilePathFull, TempEvent.OldOrCurrentFilePathFull));
                            }

                            WorkingList.Remove(TempEvent);
                        }
                        else
                        {
                            //Log(String.Format("File {0} has been deleted", MyEvent.OldOrCurrentFilePathFull));
                            FilteredList.Add(new FSSyncEvent(BasicActionEnum.Deleted, MyEvent.OldOrCurrentFilePathFull, ""));
                        }
                        break;

                    case BasicActionEnum.Renamed:

                        TempFileChainStatus = BuildFileEventChain(MyEvent.NewFilePathFull, MyEvent.Index, WorkingList, ref TempFinalFileName /*, ref TempIndex*/);
                        if (TempFileChainStatus.Equals(BasicActionEnum.Renamed))
                        {
                            //Log(String.Format("File {0} was renamed to {1}", MyEvent.OldOrCurrentFilePathFull, TempFinalFileName));
                            FilteredList.Add(new FSSyncEvent(BasicActionEnum.Renamed, MyEvent.OldOrCurrentFilePathFull, TempFinalFileName));
                        }
                        else if (TempFileChainStatus.Equals(BasicActionEnum.Deleted))
                        {
                            //Log(String.Format("File {0} has been renammed and then deleted", MyEvent.OldOrCurrentFilePathFull));
                            FilteredList.Add(new FSSyncEvent(BasicActionEnum.Deleted, MyEvent.OldOrCurrentFilePathFull, ""));
                        }
                        else
                        {
                            //Log(String.Format("File {0} was renamed to {1}", MyEvent.OldOrCurrentFilePathFull, MyEvent.NewFilePathFull));
                            FilteredList.Add(new FSSyncEvent(BasicActionEnum.Renamed, MyEvent.OldOrCurrentFilePathFull, MyEvent.NewFilePathFull));
                        }

                        break;
                    }

                    WorkingList.Remove(MyEvent);
                }
            }

            #endregion

            #region Office documents handling

            for (int i = 0; i < FilteredList.Count; i++)
            {
                FilteredList[i].Index = i;
            }

            //Ms office changed documents will appear as Created and Deleted in the same round, detect this here
            TempList = FilteredList.FindAll(x => x.Action.Equals(BasicActionEnum.Created));
            for (int i = 0; i < TempList.Count; i++)
            {
                TempEvent = FilteredList.Find(x => x.Action.Equals(BasicActionEnum.Deleted) && x.Index > TempList[i].Index && x.OldOrCurrentFilePathFull.Equals(TempList[i].OldOrCurrentFilePathFull) && File.Exists(TempList[i].OldOrCurrentFilePathFull));
                if (TempEvent != null)
                {
                    //Office document upgrade detected
                    FilteredList.Add(new FSSyncEvent(BasicActionEnum.Changed, TempEvent.OldOrCurrentFilePathFull, ""));
                    FilteredList.Remove(TempEvent);
                    FilteredList.Remove(TempList[i]);
                }
            }

            //Ms office changed documents will appear as Deleted and Created in the same round, detect this here
            for (int i = 0; i < FilteredList.Count; i++)
            {
                FilteredList[i].Index = i;
            }
            TempList = FilteredList.FindAll(x => x.Action.Equals(BasicActionEnum.Deleted));
            for (int i = 0; i < TempList.Count; i++)
            {
                TempEvent = FilteredList.Find(x => x.Action.Equals(BasicActionEnum.Created) && x.Index > TempList[i].Index && x.OldOrCurrentFilePathFull.Equals(TempList[i].OldOrCurrentFilePathFull));
                if (TempEvent != null)
                {
                    //Office document upgrade detected
                    FilteredList.Add(new FSSyncEvent(BasicActionEnum.Changed, TempEvent.OldOrCurrentFilePathFull, ""));
                    FilteredList.Remove(TempEvent);
                    FilteredList.Remove(TempList[i]);
                }
            }

            //Remove Office Temporary files
            FilteredList.RemoveAll(x => x.Action.Equals(BasicActionEnum.Created) && x.OldOrCurrentFileName.StartsWith("~"));
            FilteredList.RemoveAll(x => x.Action.Equals(BasicActionEnum.Deleted) && x.OldOrCurrentFileName.StartsWith("~"));

            #endregion

            #region Dispatch Events

            if (FilteredList.Count > 0)
            {
                lock (FSIgnoreEventListLock)
                {
                    for (int i = 0; i < FilteredList.Count; i++)
                    {
                        OnLog(String.Format("[{0}] - {1} -> {2}", FilteredList[i].Action.ToString(), FilteredList[i].OldOrCurrentFileName, FilteredList[i].NewFileName));
                        switch (FilteredList[i].Action)
                        {
                        case BasicActionEnum.Created:

                            //Is this an event to be ignored ?
                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalCreate) > 0 && x.NewOrCurrentFilePathFull.Equals(FilteredList[i].OldOrCurrentFilePathFull));
                            if (SEII == null)
                            {
                                if (File.Exists(FilteredList[i].OldOrCurrentFilePathFull))
                                {
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalCreate, FilteredList[i].OldOrCurrentFilePathFull, false, false));
                                }
                            }
                            else
                            {
                                FSIgnoreEventList.Remove(SEII);
                                OnLog("Event Ignored");
                            }
                            break;

                        case BasicActionEnum.Deleted:

                            //Is there a file with this name ?
                            TempVirtualFile = _RootVirtualFolder.FindFileBasedOnPath(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull));
                            if (TempVirtualFile != null)
                            {
                                //Is this an event to be ignored ?
                                SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalDelete) > 0 && x.NewOrCurrentFilePathFull.Equals(FilteredList[i].OldOrCurrentFilePathFull));
                                if (SEII == null)
                                {
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalDelete, TempVirtualFile.FileId, false, false));
                                }
                                else
                                {
                                    FSIgnoreEventList.Remove(SEII);
                                    OnLog("Event Ignored");
                                }
                            }

                            /*
                             * else
                             * {
                             *  //This is a folder
                             *  var TempVirtualFileList = _RootVirtualFolder.FindAllFilesBasedOnFolder(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull) + @"\");
                             *  for (int k = 0; k < TempVirtualFileList.Count; k++)
                             *  {
                             *      SubTempVirtualFile = _RootVirtualFolder.FindFileBasedOnPath(TempVirtualFileList[k].FilePathRelative);
                             *      if (SubTempVirtualFile != null)
                             *      {
                             *          OnLog(String.Format("Found file {0}", SubTempVirtualFile.FilePathRelative));
                             *          OnDeleted(new SyncEventItem(SyncEventEnum.LocalDelete, SubTempVirtualFile.FileId));
                             *      }
                             *  }
                             * }
                             */
                            break;

                        case BasicActionEnum.Moved:

                            //Is this an event to be ignored ?
                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalMove) > 0 && x.NewOrCurrentFilePathFull.Equals(FilteredList[i].NewFilePathFull));
                            if (SEII == null)
                            {
                                if (File.Exists(FilteredList[i].NewFilePathFull))
                                {
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalMove, Guid.Empty, FilteredList[i].NewFilePathFull, FilteredList[i].OldOrCurrentFilePathFull, false, false));
                                }
                            }
                            else
                            {
                                FSIgnoreEventList.Remove(SEII);
                                OnLog("Event Ignored");
                            }
                            break;

                        case BasicActionEnum.Renamed:

                            //Is there a file with this name ?
                            TempVirtualFile = _RootVirtualFolder.FindFileBasedOnPath(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull));
                            if (TempVirtualFile != null)
                            {
                                //Is this an event to be ignored ?
                                SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalRename) > 0 && x.NewOrCurrentFilePathFull.Equals(FilteredList[i].NewFilePathFull));
                                if (SEII == null)
                                {
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalRename, Guid.Empty, FilteredList[i].NewFilePathFull, FilteredList[i].OldOrCurrentFilePathFull, false, false));
                                }
                                else
                                {
                                    FSIgnoreEventList.Remove(SEII);
                                    OnLog("Event Ignored");
                                }
                            }

                            /*else
                             * {
                             *  //This is a folder
                             *  var TempVirtualFileList = _RootVirtualFolder.FindAllFilesBasedOnFolder(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull) + @"\");
                             *  for (int k = 0; k < TempVirtualFileList.Count; k++)
                             *  {
                             *      SubTempVirtualFile = _RootVirtualFolder.FindFileBasedOnPath(TempVirtualFileList[k].FilePathRelative);
                             *      if (SubTempVirtualFile != null)
                             *      {
                             *          OnLog(String.Format("Found file {0}", SubTempVirtualFile.FilePathRelative));
                             *          OnRenamed(new SyncEventItem(SyncEventEnum.LocalRename, Guid.Empty, SubTempVirtualFile.FilePathRelative.Replace(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull), GetRelativeFilePath(FilteredList[i].NewFilePathFull)), SubTempVirtualFile.FilePathRelative));
                             *      }
                             *  }
                             * }
                             */
                            break;

                        case BasicActionEnum.Changed:

                            //Is this an event to be ignored ?
                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalUpdate) > 0 && x.NewOrCurrentFilePathFull.Equals(FilteredList[i].OldOrCurrentFilePathFull));
                            if (SEII == null)
                            {
                                if (File.Exists(FilteredList[i].OldOrCurrentFilePathFull))
                                {
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalUpdate, FilteredList[i].OldOrCurrentFilePathFull, false, false));
                                }
                            }
                            else
                            {
                                FSIgnoreEventList.Remove(SEII);
                                OnLog("Event Ignored");
                            }
                            break;
                        }
                    }
                }
            }

            #endregion
        }
        private void FSEventListAnalysisTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            List <FSSyncEvent>   WorkingList;
            List <FSSyncEvent>   WorkingListFiltered = new List <FSSyncEvent>();
            List <FSSyncEvent>   TempSubList;
            FSSyncEvent          TempEvent;
            FSSyncEvent          MyEvent;
            EventFileChainResult TempFileChainStatus;
            string              TempFinalFileName  = String.Empty;
            string              TempFinalFileName2 = String.Empty;
            VirtualFile         TempVirtualFile;
            SyncEventIgnoreItem SEII;

            lock (FSEventListLock)
            {
                //Extract the list for analysis
                WorkingList = ObjectCopier.Clone(FSEventList);
                FSEventList.Clear();
            }

            #region Event Analysis

            for (int i = 0; i < WorkingList.Count; i++)
            {
                WorkingList[i].Index = i;                                         //Reindex the list of actions
            }
            lock (FSEventListAnalysisLock)
            {
                while (WorkingList.Count > 0)
                {
                    MyEvent = WorkingList[0];

                    switch (MyEvent.Action)
                    {
                    case BasicActionEnum.FileCreated:

                        #region

                        //Detect Temporary : Create / Update / Delete in the same batch
                        TempEvent = WorkingList.Find(x => x.Action.Equals(BasicActionEnum.FileDeleted) && x.Index > MyEvent.Index && x.OldOrCurrentFilePathFull.Equals(MyEvent.OldOrCurrentFilePathFull));
                        if (TempEvent != null)
                        {
                            //Log(String.Format("File {0} was temporary", MyEvent.OldOrCurrentFilePathFull)); //Temporary file, do nothing about it
                            WorkingList.Remove(TempEvent);
                        }
                        else
                        {
                            //Remove multiple Changed events for the same file
                            TempSubList = WorkingList.FindAll((x => x.Action.Equals(BasicActionEnum.FileChanged) && x.OldOrCurrentFilePathFull.Equals(MyEvent.OldOrCurrentFilePathFull) && x.Index > MyEvent.Index));
                            if (TempSubList != null)
                            {
                                foreach (FSSyncEvent xe in TempSubList)
                                {
                                    WorkingList.Remove(xe);
                                }
                            }

                            //Check what happened to this new file
                            TempFileChainStatus = BuildFileEventChain(MyEvent.OldOrCurrentFilePathFull, MyEvent.Index, WorkingList, ref TempFinalFileName);
                            if (TempFileChainStatus.Action.Equals(BasicActionEnum.FileRenamed))
                            {
                                WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileCreated, TempFinalFileName, "", TempFileChainStatus.ElementIndex));

                                //Log(String.Format("File was created with name {0} and finally renamed to {1}", MyEvent.OldOrCurrentFilePathFull, TempFinalFileName));
                                TempSubList = WorkingList.FindAll((x => x.Action.Equals(BasicActionEnum.FileChanged) && x.OldOrCurrentFilePathFull.Equals(TempFinalFileName) && x.Index > TempFileChainStatus.ElementIndex));
                                if (TempSubList != null)
                                {
                                    foreach (FSSyncEvent xe in TempSubList)
                                    {
                                        WorkingList.Remove(xe);
                                    }
                                }
                            }
                            else if (TempFileChainStatus.Action.Equals(BasicActionEnum.FileDeleted))
                            {
                                //Log(String.Format("File {0} was a temporary file",MyEvent.OldOrCurrentFilePathFull));
                            }
                            else
                            {
                                WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileCreated, MyEvent.OldOrCurrentFilePathFull, "", TempFileChainStatus.ElementIndex));
                                //Log(String.Format("File {0} is new", MyEvent.OldOrCurrentFilePathFull));
                            }
                        }

                        #endregion

                        break;

                    case BasicActionEnum.FileChanged:

                        #region

                        //Is there are subsequent changes for this file, ignore them
                        WorkingList.RemoveAll((x => x.Action.Equals(BasicActionEnum.FileChanged) && x.Index > MyEvent.Index && x.OldOrCurrentFilePathFull.Equals(MyEvent.OldOrCurrentFilePathFull)));

                        //Check if the file is not deleted in a next step
                        TempEvent = WorkingList.Find(x => x.Action.Equals(BasicActionEnum.FileDeleted) && x.Index > MyEvent.Index && x.OldOrCurrentFileName.Equals(MyEvent.OldOrCurrentFileName));
                        if (TempEvent != null)
                        {
                            //Log(String.Format("File {0} was deleted", MyEvent.OldOrCurrentFilePathFull));
                            WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileDeleted, MyEvent.OldOrCurrentFilePathFull, ""));
                            WorkingList.Remove(TempEvent);
                        }
                        else
                        {
                            //Log(String.Format("File {0} has changed", MyEvent.OldOrCurrentFilePathFull));
                            WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileChanged, MyEvent.OldOrCurrentFilePathFull, ""));
                        }

                        #endregion

                        break;

                    case BasicActionEnum.FileDeleted:

                        #region

                        //Check if there is a following Create for the same file name, means it has been moved
                        //TODO : Maybe Move detection should be made on more than the filename / can add last modification date. This requires to make a request to the VirtualRootFolder and get a FileInfo on the new file
                        TempEvent = WorkingList.Find(x => x.Action.Equals(BasicActionEnum.FileCreated) && x.Index > MyEvent.Index && x.OldOrCurrentFileName.Equals(MyEvent.OldOrCurrentFileName));
                        if (TempEvent != null)
                        {
                            if (MyEvent.OldOrCurrentFilePathFull.Equals(TempEvent.OldOrCurrentFilePathFull))
                            {
                                //Log(String.Format("File {0} has been updated", MyEvent.OldOrCurrentFilePathFull)); //A file moved to the same location is an updated file and not a moved file
                                WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileChanged, MyEvent.OldOrCurrentFilePathFull, ""));
                            }
                            else
                            {
                                //Log(String.Format("File {0} has moved to {1}", MyEvent.OldOrCurrentFilePathFull, TempEvent.OldOrCurrentFilePathFull));
                                WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileMoved, MyEvent.OldOrCurrentFilePathFull, TempEvent.OldOrCurrentFilePathFull));
                            }

                            WorkingList.Remove(TempEvent);
                        }
                        else
                        {
                            //Log(String.Format("File {0} has been deleted", MyEvent.OldOrCurrentFilePathFull));
                            WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileDeleted, MyEvent.OldOrCurrentFilePathFull, ""));
                        }

                        #endregion

                        break;

                    case BasicActionEnum.FileRenamed:

                        #region

                        TempFileChainStatus = BuildFileEventChain(MyEvent.NewFilePathFull, MyEvent.Index, WorkingList, ref TempFinalFileName);
                        if (TempFileChainStatus.Action.Equals(BasicActionEnum.FileRenamed))
                        {
                            //Log(String.Format("File {0} was renamed to {1}", MyEvent.OldOrCurrentFilePathFull, TempFinalFileName));
                            WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileRenamed, MyEvent.OldOrCurrentFilePathFull, TempFinalFileName, TempFileChainStatus.ElementIndex));
                        }
                        else if (TempFileChainStatus.Action.Equals(BasicActionEnum.FileDeleted))
                        {
                            //Log(String.Format("File {0} has been renammed and then deleted", MyEvent.OldOrCurrentFilePathFull));
                            WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileDeleted, MyEvent.OldOrCurrentFilePathFull, "", TempFileChainStatus.ElementIndex));
                        }
                        else
                        {
                            //Log(String.Format("File {0} was renamed to {1}", MyEvent.OldOrCurrentFilePathFull, MyEvent.NewFilePathFull));
                            WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileRenamed, MyEvent.OldOrCurrentFilePathFull, MyEvent.NewFilePathFull, TempFileChainStatus.ElementIndex));
                        }

                        #endregion

                        break;

                    default:
                        //Passthrough events
                        WorkingListFiltered.Add(MyEvent);
                        break;
                    }

                    WorkingList.Remove(MyEvent);
                }
            }

            #endregion

            #region Office documents handling

            for (int i = 0; i < WorkingListFiltered.Count; i++)
            {
                WorkingListFiltered[i].Index = i;
            }

            //Ms office changed documents will appear as Created and Deleted in the same round, detect this here
            TempSubList = WorkingListFiltered.FindAll(x => x.Action.Equals(BasicActionEnum.FileCreated));
            for (int i = 0; i < TempSubList.Count; i++)
            {
                TempEvent = WorkingListFiltered.Find(x => x.Action.Equals(BasicActionEnum.FileDeleted) && x.Index > TempSubList[i].Index && x.OldOrCurrentFilePathFull.Equals(TempSubList[i].OldOrCurrentFilePathFull) && File.Exists(TempSubList[i].OldOrCurrentFilePathFull));
                if (TempEvent != null)
                {
                    //Office document upgrade detected
                    WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileChanged, TempEvent.OldOrCurrentFilePathFull, ""));
                    WorkingListFiltered.Remove(TempEvent);
                    WorkingListFiltered.Remove(TempSubList[i]);
                }
            }

            //Ms office changed documents will appear as Deleted and Created in the same round, detect this here
            for (int i = 0; i < WorkingListFiltered.Count; i++)
            {
                WorkingListFiltered[i].Index = i;
            }
            TempSubList = WorkingListFiltered.FindAll(x => x.Action.Equals(BasicActionEnum.FileDeleted));
            for (int i = 0; i < TempSubList.Count; i++)
            {
                TempEvent = WorkingListFiltered.Find(x => x.Action.Equals(BasicActionEnum.FileCreated) && x.Index > TempSubList[i].Index && x.OldOrCurrentFilePathFull.Equals(TempSubList[i].OldOrCurrentFilePathFull));
                if (TempEvent != null)
                {
                    //Office document upgrade detected
                    WorkingListFiltered.Add(new FSSyncEvent(BasicActionEnum.FileChanged, TempEvent.OldOrCurrentFilePathFull, ""));
                    WorkingListFiltered.Remove(TempEvent);
                    WorkingListFiltered.Remove(TempSubList[i]);
                }
            }

            //Remove Office Temporary files
            WorkingListFiltered.RemoveAll(x => x.Action.Equals(BasicActionEnum.FileCreated) && x.OldOrCurrentFileName.StartsWith("~"));
            WorkingListFiltered.RemoveAll(x => x.Action.Equals(BasicActionEnum.FileDeleted) && x.OldOrCurrentFileName.StartsWith("~"));
            WorkingListFiltered.RemoveAll(x => x.Action.Equals(BasicActionEnum.FileCreated) && x.OldOrCurrentFileName.StartsWith(".DS_Store"));
            WorkingListFiltered.RemoveAll(x => x.Action.Equals(BasicActionEnum.FileDeleted) && x.OldOrCurrentFileName.StartsWith(".DS_Store"));

            #endregion

            #region Dispatch Events

            WorkingListFiltered.Sort(); //Sort events. We do that so that detected file chain event do not occur before other events on which they depend (ex : file move before folder creation)

            if (WorkingListFiltered.Count > 0)
            {
                lock (FSIgnoreEventListLock)
                {
                    for (int i = 0; i < WorkingListFiltered.Count; i++)
                    {
                        switch (WorkingListFiltered[i].Action)
                        {
                        case BasicActionEnum.FileCreated:

                            #region

                            //Is this an event to be ignored ?
                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalCreate) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].OldOrCurrentFilePathFull));
                            if (SEII == null)
                            {
                                OnLog(String.Format("[{0}] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                OnEvent(new SyncEventItem(SyncEventEnum.LocalCreate, WorkingListFiltered[i].OldOrCurrentFilePathFull, false, false));
                            }
                            else
                            {
                                OnLog(String.Format("[{0}][Ignored] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                FSIgnoreEventList.Remove(SEII);
                            }

                            #endregion

                            break;

                        case BasicActionEnum.FileDeleted:

                            #region

                            //Is there a file with this name ?
                            TempVirtualFile = (VirtualFile)_RootVirtualFolder.FlatElementsGetElementBasedOnPath(GetRelativeFilePath(WorkingListFiltered[i].OldOrCurrentFilePathFull), VirtualElementType.File, false);
                            if (TempVirtualFile != null)
                            {
                                //Is this an event to be ignored ?
                                SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalDelete) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].OldOrCurrentFilePathFull));
                                if (SEII == null)
                                {
                                    OnLog(String.Format("[{0}] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalDelete, TempVirtualFile.ElementId, false, false));
                                }
                                else
                                {
                                    OnLog(String.Format("[{0}][Ignored] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                    FSIgnoreEventList.Remove(SEII);
                                }
                            }
                            //Obsolete
                            //else
                            //{
                            //    //This is a folder
                            //    var TempVirtualFileList = _RootVirtualFolder.FindAllFilesBasedOnFolder(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull) + @"\");
                            //    for (int k = 0; k < TempVirtualFileList.Count; k++)
                            //    {
                            //        SubTempVirtualFile = _RootVirtualFolder.FindFileBasedOnPath(TempVirtualFileList[k].FilePathRelative);
                            //        if (SubTempVirtualFile != null)
                            //        {
                            //            OnLog(String.Format("Found file {0}", SubTempVirtualFile.FilePathRelative));
                            //            OnDeleted(new SyncEventItem(SyncEventEnum.LocalDelete, SubTempVirtualFile.FileId));
                            //        }
                            //    }
                            //}
                            #endregion

                            break;

                        case BasicActionEnum.FileMoved:

                            #region

                            //Is this an event to be ignored ?
                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalMove) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].NewFilePathFull));
                            if (SEII == null)
                            {
                                OnLog(String.Format("[{0}] - {1} -> {2}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName, WorkingListFiltered[i].NewFileName));
                                OnEvent(new SyncEventItem(SyncEventEnum.LocalMove, Guid.Empty, WorkingListFiltered[i].NewFilePathFull, WorkingListFiltered[i].OldOrCurrentFilePathFull, false, false));
                            }
                            else
                            {
                                OnLog(String.Format("[{0}][Ignored] - {1} -> {2}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName, WorkingListFiltered[i].NewFileName));
                                FSIgnoreEventList.Remove(SEII);
                            }

                            #endregion

                            break;

                        case BasicActionEnum.FileRenamed:

                            #region

                            //Is there a file with this name ?
                            TempVirtualFile = (VirtualFile)_RootVirtualFolder.FlatElementsGetElementBasedOnPath(GetRelativeFilePath(WorkingListFiltered[i].OldOrCurrentFilePathFull), VirtualElementType.File, false);
                            if (TempVirtualFile != null)
                            {
                                //Is this an event to be ignored ?
                                SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalRename) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].NewFilePathFull));
                                if (SEII == null)
                                {
                                    OnLog(String.Format("[{0}] - {1} -> {2}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName, WorkingListFiltered[i].NewFileName));
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalRename, WorkingListFiltered[i].NewFilePathFull, WorkingListFiltered[i].OldOrCurrentFilePathFull, false, false));
                                }
                                else
                                {
                                    OnLog(String.Format("[{0}][Ignored] - {1} -> {2}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName, WorkingListFiltered[i].NewFileName));
                                    FSIgnoreEventList.Remove(SEII);
                                }
                            }
                            //Obsolete
                            //else
                            //{
                            //    //This is a folder
                            //    var TempVirtualFileList = _RootVirtualFolder.FindAllFilesBasedOnFolder(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull) + @"\");
                            //    for (int k = 0; k < TempVirtualFileList.Count; k++)
                            //    {
                            //        SubTempVirtualFile = _RootVirtualFolder.FindFileBasedOnPath(TempVirtualFileList[k].FilePathRelative);
                            //        if (SubTempVirtualFile != null)
                            //        {
                            //            OnLog(String.Format("Found file {0}", SubTempVirtualFile.FilePathRelative));
                            //            OnRenamed(new SyncEventItem(SyncEventEnum.LocalRename, Guid.Empty, SubTempVirtualFile.FilePathRelative.Replace(GetRelativeFilePath(FilteredList[i].OldOrCurrentFilePathFull), GetRelativeFilePath(FilteredList[i].NewFilePathFull)), SubTempVirtualFile.FilePathRelative));
                            //        }
                            //    }
                            //}

                            #endregion

                            break;

                        case BasicActionEnum.FileChanged:

                            #region

                            //Is this an event to be ignored ?
                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalUpdate) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].OldOrCurrentFilePathFull));
                            if (SEII == null)
                            {
                                OnLog(String.Format("[{0}] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                if (File.Exists(WorkingListFiltered[i].OldOrCurrentFilePathFull))
                                {
                                    OnEvent(new SyncEventItem(SyncEventEnum.LocalUpdate, WorkingListFiltered[i].OldOrCurrentFilePathFull, false, false));
                                }
                            }
                            else
                            {
                                OnLog(String.Format("[{0}][Ignored] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                FSIgnoreEventList.Remove(SEII);
                            }

                            #endregion

                            break;

                        case BasicActionEnum.DirCreated:

                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalCreate) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].OldOrCurrentFilePathFull));
                            if (SEII == null)
                            {
                                OnLog(String.Format("[{0}] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                OnEvent(new SyncEventItem(SyncEventEnum.LocalCreate, WorkingListFiltered[i].OldOrCurrentFilePathFull, true, false));
                            }
                            else
                            {
                                OnLog(String.Format("[{0}][Ignored] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                FSIgnoreEventList.Remove(SEII);
                            }

                            break;

                        case BasicActionEnum.DirRenamed:

                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalRename) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].NewFilePathFull));
                            if (SEII == null)
                            {
                                OnLog(String.Format("[{0}] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                OnEvent(new SyncEventItem(SyncEventEnum.LocalRename, WorkingListFiltered[i].NewFilePathFull, WorkingListFiltered[i].OldOrCurrentFilePathFull, true, false));
                            }
                            else
                            {
                                OnLog(String.Format("[{0}][Ignored] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                FSIgnoreEventList.Remove(SEII);
                            }

                            break;

                        case BasicActionEnum.DirDeleted:

                            SEII = FSIgnoreEventList.Find(x => (x.Event & SyncEventEnum.LocalDelete) > 0 && x.NewOrCurrentFilePathFull.Equals(WorkingListFiltered[i].OldOrCurrentFilePathFull));
                            if (SEII == null)
                            {
                                OnLog(String.Format("[{0}] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                OnEvent(new SyncEventItem(SyncEventEnum.LocalDelete, WorkingListFiltered[i].OldOrCurrentFilePathFull, true, false));
                            }
                            else
                            {
                                OnLog(String.Format("[{0}][Ignored] - {1}", WorkingListFiltered[i].Action.ToString(), WorkingListFiltered[i].OldOrCurrentFileName));
                                FSIgnoreEventList.Remove(SEII);
                            }

                            break;
                        }
                    }
                }
            }

            #endregion
        }