/Code/Source/Teaching.Wpf.MediaBuddy/Library/MediaLibrary.cs
C# | 162 lines | 136 code | 22 blank | 4 comment | 22 complexity | 6e8a3a553ad29f1bdde109f37ef6a1f4 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
- using System.Linq;
- using System.Reactive.Linq;
- using System.Reactive.Threading.Tasks;
- using System.Threading;
- using System.Threading.Tasks;
- using Caliburn.Micro;
- using Raven.Client;
- using Raven.Client.Linq;
- using Teaching.Wpf.MediaBuddy.Io;
-
- namespace Teaching.Wpf.MediaBuddy.Library
- {
- public class MediaLibrary
- {
- private readonly MediaIndexer mediaIndexer;
- private readonly Func<IDocumentSession> sessionFactory;
- private readonly List<Task<int>> indexingTasks = new List<Task<int>>();
- private readonly IEnumerable<IFileSourceFactory> fileSourceFactories;
-
- public IEnumerable<string> Suggest(string searchQuery,int maxResults)
- {
- using( var session = sessionFactory())
- {
- return session.Query<MediaItem>().Search(m => m.FullText, searchQuery).Suggest().Suggestions;
- }
- }
-
- public IEnumerable<MediaItem> Search(string searchQuery,int pageIndex,int pageSize)
- {
- using( var session = sessionFactory())
- {
- if (!string.IsNullOrWhiteSpace(searchQuery))
- {
- return session.Query<MediaItem>().Search(m => m.FullText, searchQuery).Skip(pageIndex*pageSize).Take(pageSize).ToArray();
- }
-
- return session.Query<MediaItem>().OrderBy(m => m.Name).Skip(pageIndex * pageSize).Take(pageSize).ToArray();
- }
- }
-
- public IEnumerable<MediaItem> GetDuplicates(int pageIndex,int pageSize)
- {
- using( var session = sessionFactory())
- {
- return session.Query<MediaItem>().Where(m => m.Files.Count() > 1).Skip(pageIndex*pageSize).Take(pageSize);
- }
- }
-
- public async void AddFileSource(string typeName,string url)
- {
- Task<int> indexingTask = null;
-
- using( var session = sessionFactory())
- {
- var existingFileSourceEntry =
- session.Query<FileSourceEntry>().Customize(q => q.WaitForNonStaleResults()).Where(
- f => f.TypeName == typeName && f.Url == url).FirstOrDefault();
-
- if (existingFileSourceEntry != null)
- {
- if (!existingFileSourceEntry.IsAnalyzing)
- {
- existingFileSourceEntry.IsAnalyzing = true;
- session.Store(existingFileSourceEntry);
- indexingTask = StartIndexing(CreateFileSource(typeName, url));
- }
- }
- else
- {
- session.Store(new FileSourceEntry() {TypeName = typeName, Url = url, IsAnalyzing = true});
- indexingTask = StartIndexing(CreateFileSource(typeName, url));
- }
-
- session.SaveChanges();
-
- if ( indexingTask != null )
- {
- indexingTasks.Add(indexingTask);
- await indexingTask;
- indexingTasks.Remove(indexingTask);
- }
- }
- }
-
- private Task<int> StartIndexing(IFileSource fileSource)
- {
- var completionSource = new TaskCompletionSource<int>();
- var newItemsCounter = 0;
-
- // Start async indexing:
- fileSource.EnumerateAsync().SelectMany(f => mediaIndexer.Index(f)).Where(m => m != null).Subscribe(i =>
- {
- if (PersistItem(i))
- {
- Interlocked.Increment(ref newItemsCounter);
- }
- }, () => completionSource.SetResult(newItemsCounter));
-
- return completionSource.Task;
- }
-
- private bool PersistItem(MediaItem item)
- {
- using( var session = sessionFactory())
- {
- var existingItem =
- session.Query<MediaItem>().Where(m => m.MainFile.Hash == item.MainFile.Hash).FirstOrDefault();
-
- if ( existingItem != null )
- {
- if ( existingItem.Files.All(f => f.Id != item.MainFile.Id))
- {
- // We have an unknown file with the same hash -> duplicate
- existingItem.Files.Add(item.MainFile);
- session.Store(existingItem);
- session.SaveChanges();
- }
- else
- {
- // Already seen, so ignore
- }
- }
- else
- {
- // We have a totally new item
- session.Store(item);
- session.SaveChanges();
-
- return true;
- }
- }
-
- return false;
- }
-
- private IFileSource CreateFileSource(string typeName,string url)
- {
- var fileSourceFactory = fileSourceFactories.FirstOrDefault(f => f.TypeName == typeName);
-
- if ( fileSourceFactory != null )
- {
- return fileSourceFactory.CreateSource(url);
- }
-
- throw new InvalidOperationException(string.Format("Unknown file source factory of type {0}", typeName));
- }
-
- public MediaLibrary(MediaIndexer mediaIndexer,Func<IDocumentSession> sessionFactory,IEnumerable<IFileSourceFactory> fileSourceFactories )
- {
- Contract.Requires<ArgumentNullException>( mediaIndexer != null,"mediaItemIndex");
- Contract.Requires<ArgumentNullException>( sessionFactory != null,"sessionFactory");
- Contract.Requires<ArgumentNullException>( fileSourceFactories != null,"fileSourceFactories");
-
- this.mediaIndexer = mediaIndexer;
- this.sessionFactory = sessionFactory;
- this.fileSourceFactories = fileSourceFactories;
- }
- }
- }