PageRenderTime 46ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/Source/Teaching.Wpf.MediaBuddy/Library/MediaLibrary.cs

https://bitbucket.org/BernhardGlueck/teaching
C# | 162 lines | 136 code | 22 blank | 4 comment | 22 complexity | 6e8a3a553ad29f1bdde109f37ef6a1f4 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.Contracts;
  4. using System.Linq;
  5. using System.Reactive.Linq;
  6. using System.Reactive.Threading.Tasks;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using Caliburn.Micro;
  10. using Raven.Client;
  11. using Raven.Client.Linq;
  12. using Teaching.Wpf.MediaBuddy.Io;
  13. namespace Teaching.Wpf.MediaBuddy.Library
  14. {
  15. public class MediaLibrary
  16. {
  17. private readonly MediaIndexer mediaIndexer;
  18. private readonly Func<IDocumentSession> sessionFactory;
  19. private readonly List<Task<int>> indexingTasks = new List<Task<int>>();
  20. private readonly IEnumerable<IFileSourceFactory> fileSourceFactories;
  21. public IEnumerable<string> Suggest(string searchQuery,int maxResults)
  22. {
  23. using( var session = sessionFactory())
  24. {
  25. return session.Query<MediaItem>().Search(m => m.FullText, searchQuery).Suggest().Suggestions;
  26. }
  27. }
  28. public IEnumerable<MediaItem> Search(string searchQuery,int pageIndex,int pageSize)
  29. {
  30. using( var session = sessionFactory())
  31. {
  32. if (!string.IsNullOrWhiteSpace(searchQuery))
  33. {
  34. return session.Query<MediaItem>().Search(m => m.FullText, searchQuery).Skip(pageIndex*pageSize).Take(pageSize).ToArray();
  35. }
  36. return session.Query<MediaItem>().OrderBy(m => m.Name).Skip(pageIndex * pageSize).Take(pageSize).ToArray();
  37. }
  38. }
  39. public IEnumerable<MediaItem> GetDuplicates(int pageIndex,int pageSize)
  40. {
  41. using( var session = sessionFactory())
  42. {
  43. return session.Query<MediaItem>().Where(m => m.Files.Count() > 1).Skip(pageIndex*pageSize).Take(pageSize);
  44. }
  45. }
  46. public async void AddFileSource(string typeName,string url)
  47. {
  48. Task<int> indexingTask = null;
  49. using( var session = sessionFactory())
  50. {
  51. var existingFileSourceEntry =
  52. session.Query<FileSourceEntry>().Customize(q => q.WaitForNonStaleResults()).Where(
  53. f => f.TypeName == typeName && f.Url == url).FirstOrDefault();
  54. if (existingFileSourceEntry != null)
  55. {
  56. if (!existingFileSourceEntry.IsAnalyzing)
  57. {
  58. existingFileSourceEntry.IsAnalyzing = true;
  59. session.Store(existingFileSourceEntry);
  60. indexingTask = StartIndexing(CreateFileSource(typeName, url));
  61. }
  62. }
  63. else
  64. {
  65. session.Store(new FileSourceEntry() {TypeName = typeName, Url = url, IsAnalyzing = true});
  66. indexingTask = StartIndexing(CreateFileSource(typeName, url));
  67. }
  68. session.SaveChanges();
  69. if ( indexingTask != null )
  70. {
  71. indexingTasks.Add(indexingTask);
  72. await indexingTask;
  73. indexingTasks.Remove(indexingTask);
  74. }
  75. }
  76. }
  77. private Task<int> StartIndexing(IFileSource fileSource)
  78. {
  79. var completionSource = new TaskCompletionSource<int>();
  80. var newItemsCounter = 0;
  81. // Start async indexing:
  82. fileSource.EnumerateAsync().SelectMany(f => mediaIndexer.Index(f)).Where(m => m != null).Subscribe(i =>
  83. {
  84. if (PersistItem(i))
  85. {
  86. Interlocked.Increment(ref newItemsCounter);
  87. }
  88. }, () => completionSource.SetResult(newItemsCounter));
  89. return completionSource.Task;
  90. }
  91. private bool PersistItem(MediaItem item)
  92. {
  93. using( var session = sessionFactory())
  94. {
  95. var existingItem =
  96. session.Query<MediaItem>().Where(m => m.MainFile.Hash == item.MainFile.Hash).FirstOrDefault();
  97. if ( existingItem != null )
  98. {
  99. if ( existingItem.Files.All(f => f.Id != item.MainFile.Id))
  100. {
  101. // We have an unknown file with the same hash -> duplicate
  102. existingItem.Files.Add(item.MainFile);
  103. session.Store(existingItem);
  104. session.SaveChanges();
  105. }
  106. else
  107. {
  108. // Already seen, so ignore
  109. }
  110. }
  111. else
  112. {
  113. // We have a totally new item
  114. session.Store(item);
  115. session.SaveChanges();
  116. return true;
  117. }
  118. }
  119. return false;
  120. }
  121. private IFileSource CreateFileSource(string typeName,string url)
  122. {
  123. var fileSourceFactory = fileSourceFactories.FirstOrDefault(f => f.TypeName == typeName);
  124. if ( fileSourceFactory != null )
  125. {
  126. return fileSourceFactory.CreateSource(url);
  127. }
  128. throw new InvalidOperationException(string.Format("Unknown file source factory of type {0}", typeName));
  129. }
  130. public MediaLibrary(MediaIndexer mediaIndexer,Func<IDocumentSession> sessionFactory,IEnumerable<IFileSourceFactory> fileSourceFactories )
  131. {
  132. Contract.Requires<ArgumentNullException>( mediaIndexer != null,"mediaItemIndex");
  133. Contract.Requires<ArgumentNullException>( sessionFactory != null,"sessionFactory");
  134. Contract.Requires<ArgumentNullException>( fileSourceFactories != null,"fileSourceFactories");
  135. this.mediaIndexer = mediaIndexer;
  136. this.sessionFactory = sessionFactory;
  137. this.fileSourceFactories = fileSourceFactories;
  138. }
  139. }
  140. }