PageRenderTime 45ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/ABB.SrcML/AbstractArchive.cs

https://github.com/nkcsgexi/SrcML.NET
C# | 226 lines | 107 code | 26 blank | 93 comment | 2 complexity | b579b082416d13f8247d29e5443e6610 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml.Linq;
  6. using System.IO;
  7. using System.Xml;
  8. using System.Collections.ObjectModel;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using ABB.SrcML.Utilities;
  12. namespace ABB.SrcML
  13. {
  14. /// <summary>
  15. /// The abstract archive class is the base class for archives. Archives are responsible for recording changes to files and then raising an <see cref="FileChanged">event</see> when they are done.
  16. /// </summary>
  17. public abstract class AbstractArchive : IArchive
  18. {
  19. private string _archivePath;
  20. protected TaskManager _taskManager;
  21. protected AbstractArchive(string baseDirectory, string archiveSubDirectory) {
  22. this.ArchivePath = Path.Combine(baseDirectory, archiveSubDirectory);
  23. this._taskManager = new TaskManager(this);
  24. }
  25. /// <summary>
  26. /// Sets the archive path for AbstractArchive objects
  27. /// </summary>
  28. /// <param name="baseDirectory">the base directory</param>
  29. /// <param name="archiveSubDirectory">the relative path within <paramref name="baseDirectory"/></param>
  30. /// <param name="scheduler">the scheduler to use for asynchronous methods</param>
  31. protected AbstractArchive(string baseDirectory, string archiveSubDirectory, TaskScheduler scheduler) {
  32. this.ArchivePath = Path.Combine(baseDirectory, archiveSubDirectory);
  33. this._taskManager = new TaskManager(this, scheduler);
  34. }
  35. private AbstractArchive()
  36. {
  37. }
  38. /// <summary>
  39. /// Archives are "ready" when they have no running tasks. This property automatically changes to false
  40. /// when the number of running tasks is zero. Whenever the value changes, the <see cref="IsReadyChanged"/> event fires.
  41. /// </summary>
  42. public bool IsReady {
  43. get { return this._taskManager.IsReady; }
  44. }
  45. /// <summary>
  46. /// Task factory for the asynchronous methods
  47. /// </summary>
  48. public TaskScheduler Scheduler {
  49. get { return this._taskManager.Scheduler; }
  50. set { this._taskManager.Scheduler = value; }
  51. }
  52. /// <summary>
  53. /// the extensions supported by this collection. The strings returned by this property should match the ones returned by <see cref="System.IO.Path.GetExtension(string)"/>
  54. /// </summary>
  55. public abstract ICollection<string> SupportedExtensions { get; }
  56. /// <summary>
  57. /// This event should be raised whenever the archive updates its internal representation for a file
  58. /// </summary>
  59. public event EventHandler<FileEventRaisedArgs> FileChanged;
  60. /// <summary>
  61. /// Event fires when the <see cref="IsReady"/> property changes
  62. /// </summary>
  63. public event EventHandler<IsReadyChangedEventArgs> IsReadyChanged {
  64. add { this._taskManager.IsReadyChanged += value; }
  65. remove { this._taskManager.IsReadyChanged -= value; }
  66. }
  67. /// <summary>
  68. /// Sub-classes of AbstractArchive should implement the "add or update file" functionality here in order to enable <see cref="AddOrUpdateFile"/> and <see cref="AddOrUpdateFileAsync"/>
  69. /// </summary>
  70. /// <param name="fileName">The file name to add or update. If the file exists, it is deleted and then added regardless of whether or not the file is outdated</param>
  71. protected abstract void AddOrUpdateFileImpl(string fileName);
  72. /// <summary>
  73. /// Sub-classes of AbstractArchive should implement the "delete file" functionality here in order to enable <see cref="DeleteFile"/> and <see cref="DeleteFileAsync"/>
  74. /// </summary>
  75. /// <param name="fileName">The file name to delete. If it does not exist, nothing happens</param>
  76. protected abstract void DeleteFileImpl(string fileName);
  77. /// <summary>
  78. /// Sub-classes of AbstractArchive should implement the "rename file" functionality here in order to enable <see cref="RenameFile"/> and <see cref="RenameFileAsync"/>
  79. /// </summary>
  80. /// <param name="oldFileName">the existing path</param>
  81. /// <param name="newFileName">the new path</param>
  82. protected abstract void RenameFileImpl(string oldFileName, string newFileName);
  83. /// <summary>
  84. /// Adds or updates <paramref name="fileName"/> within the archive
  85. /// </summary>
  86. /// <param name="fileName">The file name to add or update. If the file exists, it is deleted and then added regardless of whether or not the file is outdated</param>
  87. public virtual void AddOrUpdateFile(string fileName) {
  88. var task = new Task(() => AddOrUpdateFileImpl(fileName));
  89. LogExceptions(task);
  90. _taskManager.Run(task);
  91. }
  92. /// <summary>
  93. /// Adds or updates <paramref name="fileName"/> within the archive asynchronously. A new <see cref="System.Threading.Tasks.Task"/> is run via <see cref="TaskFactory"/>.
  94. /// </summary>
  95. /// <param name="fileName">The file name to add or update. If the file exists, it is deleted and then added regardless of whether or not the file is outdated</param>
  96. public virtual void AddOrUpdateFileAsync(string fileName) {
  97. var task = new Task(() => AddOrUpdateFileImpl(fileName));
  98. LogExceptions(task);
  99. _taskManager.RunAsync(task);
  100. }
  101. /// <summary>
  102. /// Deletes <paramref name="fileName"/> from the archive
  103. /// </summary>
  104. /// <param name="fileName">The file name to delete. If it does not exist, nothing happens</param>
  105. public virtual void DeleteFile(string fileName) {
  106. var task = new Task(() => DeleteFileImpl(fileName));
  107. LogExceptions(task);
  108. _taskManager.Run(task);
  109. }
  110. /// <summary>
  111. /// Deletes <paramref name="fileName"/> from the archive asynchronously. A new <see cref="System.Threading.Tasks.Task"/> is run via <see cref="TaskFactory"/>.
  112. /// </summary>
  113. /// <param name="fileName">The file name to delete. If it does not exist, nothing happens</param>
  114. public virtual void DeleteFileAsync(string fileName) {
  115. var task = new Task(() => DeleteFileImpl(fileName));
  116. LogExceptions(task);
  117. _taskManager.RunAsync(task);
  118. }
  119. /// <summary>
  120. /// Renames the file to the new file name
  121. /// </summary>
  122. /// <param name="oldFileName">the existing path</param>
  123. /// <param name="newFileName">the new path</param>
  124. public virtual void RenameFile(string oldFileName, string newFileName) {
  125. var task = new Task(() => RenameFileImpl(oldFileName, newFileName));
  126. LogExceptions(task);
  127. _taskManager.Run(task);
  128. }
  129. /// <summary>
  130. /// Renames the file to the new file name asynchronously. A new <see cref="System.Threading.Tasks.Task"/> is run via <see cref="TaskFactory"/>.
  131. /// </summary>
  132. /// <param name="oldFileName">the existing path</param>
  133. /// <param name="newFileName">the new path</param>
  134. public virtual void RenameFileAsync(string oldFileName, string newFileName) {
  135. var task = new Task(() => RenameFileImpl(oldFileName, newFileName));
  136. LogExceptions(task);
  137. _taskManager.RunAsync(task);
  138. }
  139. /// <summary>
  140. /// Tests to see if the archive contains <paramref name="fileName"/>
  141. /// </summary>
  142. /// <param name="fileName">the file name to check for</param>
  143. /// <returns>True if the file is in the archive; false otherwise</returns>
  144. public abstract bool ContainsFile(string fileName);
  145. /// <summary>
  146. /// Compares file name with the archive representation
  147. /// </summary>
  148. /// <param name="fileName">the file name to check for</param>
  149. /// <returns>True if the archive version of the file is older than <paramref name="fileName"/></returns>
  150. public abstract bool IsOutdated(string fileName);
  151. /// <summary>
  152. /// Gets all of the file names stored in this archive
  153. /// </summary>
  154. /// <returns>An enumerable of filenames stored in this archive.</returns>
  155. public abstract Collection<string> GetFiles();
  156. /// <summary>
  157. /// The path where this archive is stored.
  158. /// </summary>
  159. public string ArchivePath
  160. {
  161. get
  162. {
  163. return this._archivePath;
  164. }
  165. protected set
  166. {
  167. this._archivePath = value;
  168. }
  169. }
  170. /// <summary>
  171. /// Raise the FileChanged event.
  172. /// </summary>
  173. /// <param name="e"></param>
  174. protected virtual void OnFileChanged(FileEventRaisedArgs e) {
  175. EventHandler<FileEventRaisedArgs> handler = FileChanged;
  176. if(handler != null) {
  177. handler(this, e);
  178. }
  179. }
  180. /// <summary>
  181. /// Convenience function for logging exceptions upon task failure.
  182. /// </summary>
  183. /// <param name="task"></param>
  184. protected void LogExceptions(Task task) {
  185. task.ContinueWith(t => {
  186. foreach(var exception in t.Exception.InnerExceptions) {
  187. // logger.Error(exception);
  188. Console.Error.WriteLine(exception);
  189. }
  190. }, TaskContinuationOptions.OnlyOnFaulted);
  191. }
  192. /// <summary>
  193. /// Disposes of this object
  194. /// </summary>
  195. public virtual void Dispose() {
  196. _taskManager.Dispose();
  197. FileChanged = null;
  198. }
  199. }
  200. }