public TagFilesDatabase GetReversePartialDatabase(List<FileTag> matchTags)
        {
            if (matchTags == null)
                throw new ArgumentNullException();
            if (matchTags.Count == 0)
                throw new ArgumentException();

            // The returned value
            TagFilesDatabase ret = new TagFilesDatabase();

            // Check each file if it needs to be added
            foreach (FileWithTags file in this.files)
            {
                bool skippFile = false;

                // Search for each tag in the file
                foreach (FileTag tag in matchTags)
                {
                    // If the tag exists skipp the file
                    if (file.Tags.Exists(tag.Compare))
                    {
                        skippFile = true;
                        break;
                    }
                }

                if (!skippFile)
                    ret.Files.Add(file);
            }

            // Create all the groups
            for (int i = 0; i < this.groupsKeys.Count; i++)
            {
                ret.CreateGroup(this.groupsNames[i], this.groupsKeys[i]);
            }
            // Add all the relevant mappings
            for (int i = 0; i < this.tags.Count; i++)
            {
                int index = ret.tags.FindIndex(this.tags[i].Compare);
                if (index >= 0)
                    ret.tagGroupMapping[index] = this.tagGroupMapping[i];
            }
            // Subscribe to the parent's events
            ret.FileAdded = this.FileAdded;
            ret.FileRemoved = this.FileRemoved;
            ret.TagAdded = this.TagAdded;
            ret.TagRemoved = this.TagRemoved;

            return ret;
        }
        /// <summary>
        /// Retrives a partial database that contains all the files that have a tag in the list of tags
        /// </summary>
        /// <param name="matchTag">List of tags to match with the current database of files</param>
        /// <returns>The partial database</returns>        
        public TagFilesDatabase GetPartialDatabase(List<FileTag> matchTags)
        {
            if (matchTags == null)
                throw new ArgumentNullException();
            if (matchTags.Count == 0)
                throw new ArgumentException();

            // The returned value
            TagFilesDatabase ret = new TagFilesDatabase();

            // Check each file if it needs to be added
            foreach (FileWithTags file in this.files)
            {
                // Search for each tag
                foreach (FileTag tag in matchTags)
                {
                    if (!tag.Inverse)
                    {
                        if ((tag.Value == FileTag.Empty.Value && file.Tags.Count == 0) ||
                            file.Tags.Exists(tag.Compare))
                        {
                            ret.Files.Add(file);
                            break;
                        }
                    }
                    else // Tag is inversed
                    {
                        if ((tag.Value == FileTag.Empty.Value && file.Tags.Count != 0) ||
                            !file.Tags.Exists(tag.Compare))
                        {
                            ret.Files.Add(file);
                            break;
                        }
                    }
                }
            }

            // Create all the groups
            for (int i = 0; i < this.groupsKeys.Count; i++)
            {
                ret.CreateGroup(this.groupsNames[i], this.groupsKeys[i]);
            }
            // Add all the relevant mappings
            for (int i = 0; i < this.tags.Count; i++)
            {
                int index = ret.tags.FindIndex(this.tags[i].Compare);
                if (index >= 0)
                    ret.tagGroupMapping[index] = this.tagGroupMapping[i];
            }
            // Subscribe to the parent's events
            ret.FileAdded = this.FileAdded;
            ret.FileRemoved = this.FileRemoved;
            ret.TagAdded = this.TagAdded;
            ret.TagRemoved = this.TagRemoved;

            return ret;
        }        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public TagFilesDatabase GetPartialDatabase(List<string> paths)
        {
            if (paths == null)
                throw new ArgumentNullException();
            if (paths.Count == 0)
                throw new ArgumentNullException();

            // The returned value
            TagFilesDatabase ret = new TagFilesDatabase();

            // Check each file if it needs to be added
            foreach (FileWithTags file in this.files)
            {
                // Search for each directory
                foreach (string path in paths)
                {
                    if (file.FileName.ToLower().StartsWith(path.ToLower()))
                    {
                        ret.Files.Add(file);
                        break;
                    }
                }
            }

            // Create all the groups
            for (int i = 0; i < this.groupsKeys.Count; i++)
            {
                ret.CreateGroup(this.groupsNames[i], this.groupsKeys[i]);
            }
            // Add all the relevant mappings
            for (int i = 0; i < this.tags.Count; i++)
            {
                int index = ret.tags.FindIndex(this.tags[i].Compare);
                if (index >= 0)
                    ret.tagGroupMapping[index] = this.tagGroupMapping[i];
            }
            // Subscribe to the parent's events
            ret.FileAdded = this.FileAdded;
            ret.FileRemoved = this.FileRemoved;
            ret.TagAdded = this.TagAdded;
            ret.TagRemoved = this.TagRemoved;

            return ret;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static TagFilesDatabase DeSerialize(string fileName)
        {
            TagFilesDatabase ret = new TagFilesDatabase();
            
            if (File.Exists(fileName))
            {
                string line = "";

                FileStream fileStream = new FileStream(fileName, FileMode.Open);
                StreamReader reader = new StreamReader(fileStream);

                while (!reader.EndOfStream)
                {
                    line = reader.ReadLine();

                    // Read the files
                    if (line == fileBeginString)
                    {
                        // Read the file name
                        FileWithTags file = new FileWithTags();
                        file.FileName = reader.ReadLine();

                        // Read the tags
                        line = reader.ReadLine();
                        while (line != fileEndString)
                        {
                            FileTag tag = new FileTag();
                            tag.Value = line;
                            file.Tags.Add(tag);

                            line = reader.ReadLine();
                        }
                        ret.Files.Add(file);
                    }
                    // Read the groups
                    else if (line == groupsBeginString)
                    {
                        line = reader.ReadLine();
                        while (line != groupsEndString)
                        {
                            string name = line;
                            string key = reader.ReadLine();
                            ret.CreateGroup(name, key);
                            line = reader.ReadLine();
                        }
                    }
                    // Read the mapping between tags and groups
                    else if (line == mappingBeginString)
                    {                        
                        line = reader.ReadLine();                        
                        int index = 0;
                        while (line != mappingEndString)
                        {
                            // read the tag line
                            FileTag tag = new FileTag(line);
                            // read the group index line
                            int groupIndex = int.Parse(reader.ReadLine());

                            // find the tag in the list
                            index = ret.tags.FindIndex(tag.Compare);
                            if (index >= 0)
                            {
                                ret.tagGroupMapping[index] = groupIndex;
                            }                                                      
                            line = reader.ReadLine();
                        }
                    }
                }

                reader.Dispose();
                fileStream.Close();
            }

            return ret;
        }