public Task Update(SoundboxNode file) { GetSoundsCollection().Update(file); //TODO interface commit Database.Checkpoint(); return(Task.FromResult(true)); }
public Task Delete(SoundboxNode file) { DeleteRecursive(GetSoundsCollection(), file); //TODO interface commit Database.Checkpoint(); return(Task.FromResult(true)); }
/// <summary> /// Returns true if the given node is the root directory. Thus it may not be edited/moved/deleted. /// </summary> /// <param name="file"></param> /// <returns></returns> protected bool IsRootDirectory(SoundboxNode file) { if (file is SoundboxDirectory directory) { return(directory.IsRootDirectory()); } return(false); }
protected override void CompareCopyFill(SoundboxNode other) { base.CompareCopyFill(other); if (other is SoundboxFile file) { file.FileName = this.FileName; file.AbsoluteFileName = this.AbsoluteFileName; } }
/// <summary> /// Deletes a file or directory. If <paramref name="file"/> is a directory, then its entire content is deleted as well. /// </summary> /// <param name="file"></param> /// <returns></returns> public async Task <FileResult> Delete(SoundboxNode file) { file = GetCleanFile(file); if (file == null) { return(new FileResult(BaseResultStatus.INVALID_PARAMETER)); } if (IsRootDirectory(file)) { return(new FileResult(FileResultStatus.ILLEGAL_FILE_EDIT_DENIED_ROOT)); } try { DatabaseLock.EnterWriteLock(); //save previous watermark for event Guid previousWatermark = GetRootWatermark(); Guid newWatermark = Guid.NewGuid(); //remove from cache file.ParentDirectory.Children.Remove(file); NodesCache.Remove(file.ID); //do not remove the parent from the file: need it for the client event //remove from disk DeleteRecursive(file); //delete from database //TODO async Database.Delete(file); //update cache and database watermarks (this will call Update for parent) SetWatermark(file, newWatermark); //update our clients GetHub().OnFileEvent(new SoundboxFileChangeEvent() { Event = SoundboxFileChangeEvent.Type.DELETED, File = FlattenForEvent(file), PreviousWatermark = previousWatermark }); return(new FileResult(BaseResultStatus.OK, file, previousWatermark)); } catch (Exception ex) { Log(ex); return(new FileResult(BaseResultStatus.INTERNAL_SERVER_ERROR)); } finally { DatabaseLock.ExitWriteLock(); } }
/// <summary> /// Sets the given watermark on all ancestors of a file (and the file itself if it represents a directory). This is required when the given file changed. /// </summary> /// <param name="file"></param> /// <param name="watermark"></param> protected void SetWatermark(SoundboxNode file, Guid watermark) { if (file is SoundboxDirectory) { SetWatermark(file as SoundboxDirectory, watermark); } else { SetWatermark(file.ParentDirectory, watermark); } }
protected override void CompareCopyFill(SoundboxNode other) { base.CompareCopyFill(other); if (other is SoundboxDirectory directory) { directory.Watermark = this.Watermark; if (this.Children?.Count > 0) { directory.Children = new List <SoundboxNode>(this.Children); } } }
/// <summary> /// /// </summary> /// <param name="status"></param> /// <param name="file"></param> /// <param name="previousWatermark"></param> /// <param name="fromDirectory"> /// See <see cref="SoundboxFileMoveEvent.FromDirectory"/> /// </param> public FileResult(ResultStatus status, SoundboxNode file, Guid?previousWatermark, SoundboxDirectory fromDirectory = null) : base(status) { if (file != null) { File = file.Flatten(true); } PreviousWatermark = previousWatermark; if (fromDirectory != null) { FromDirectory = fromDirectory.Flatten() as SoundboxDirectory; } }
/// <summary> /// Deletes the given file and all its descendants if it is a <see cref="SoundboxDirectory"/>. /// </summary> /// <param name="file"></param> protected void DeleteRecursive(ILiteCollection <SoundboxNode> collection, SoundboxNode file) { if (file is SoundboxDirectory directory) { //is directory: recursively delete all content foreach (var child in directory.Children) { DeleteRecursive(collection, child); } } collection.Delete(file.ID); }
/// <summary> /// Adds the given new file to our in-memory data structures and to our database. Updates all clients on success. /// </summary> /// <param name="newFile"></param> /// <param name="parent"></param> private FileResult UploadOnNewFile(SoundboxNode newFile, SoundboxDirectory parent) { try { DatabaseLock.EnterWriteLock(); //save previous watermark for event Guid previousWatermark = GetRootWatermark(); Guid newWatermark = Guid.NewGuid(); //add to cache parent.AddChild(newFile); NodesCache[newFile.ID] = newFile; //add to database //TODO async Database.Insert(newFile); //update cache and database watermarks (this will call Update for parent) SetWatermark(newFile, newWatermark); //update our clients GetHub().OnFileEvent(new SoundboxFileChangeEvent() { Event = SoundboxFileChangeEvent.Type.ADDED, File = FlattenForEvent(newFile), PreviousWatermark = previousWatermark }); if (newFile is Sound sound) { SpeechRecognition_OnSoundChanged(sound, null); } return(new FileResult(BaseResultStatus.OK, newFile, previousWatermark)); } finally { DatabaseLock.ExitWriteLock(); } }
/// <summary> /// Deletes the given node from disk. /// Deletes the node itself it is a <see cref="SoundboxFile"/>. /// Deletes all its content recursively if it is a <see cref="SoundboxDirectory"/>. /// </summary> /// <param name="node"></param> protected void DeleteRecursive(SoundboxNode node) { if (node is SoundboxFile file) { try { File.Delete(GetAbsoluteFileName(file)); } catch (Exception ex) { Log(ex); //continue deleting } } else if (node is SoundboxDirectory directory) { foreach (var child in directory.Children) { DeleteRecursive(child); } } }
/// <summary> /// Edits the given file. Currently these attributes are affected:<list type="bullet"> /// <item><see cref="SoundboxNode.Name"/></item> /// <item><see cref="SoundboxNode.Tags"/></item> /// <item><see cref="Sound.VoiceActivation"/></item> /// </list> /// </summary> /// <param name="file"></param> /// <returns></returns> public Task <FileResult> Edit(SoundboxNode file) { return(GetSoundbox().Edit(file)); }
/// <summary> /// Moves a file to a new directory. There is no <see cref="Edit(SoundboxNode)"/> performed on the given file.<br/> /// If the given directory is null then the root directory is used. /// </summary> /// <param name="file"></param> /// <param name="directory"></param> /// <returns></returns> public Task <FileResult> Move(SoundboxNode file, SoundboxDirectory directory) { return(GetSoundbox().Move(file, directory)); }
public void AddChild(SoundboxNode file) { this.Children.Add(file); file.ParentDirectory = this; }
/// <summary> /// Moves a file to a new directory without performing an <see cref="Edit(SoundboxNode)"/>. /// </summary> /// <param name="file"></param> /// <param name="directory"> /// Null: uses the root directory instead. /// </param> /// <returns></returns> public async Task <FileResult> Move(SoundboxNode file, SoundboxDirectory directory) { file = GetCleanFile(file); if (file == null) { return(new FileResult(BaseResultStatus.INVALID_PARAMETER)); } if (IsRootDirectory(file)) { return(new FileResult(FileResultStatus.ILLEGAL_FILE_EDIT_DENIED_ROOT)); } if (directory == null) { directory = GetRootDirectory(); } else { directory = GetCleanFile(directory); if (directory == null) { return(new FileResult(BaseResultStatus.INVALID_PARAMETER)); } } if (file == directory) { //not possible return(new FileResult(FileResultStatus.MOVE_TARGET_INVALID)); } if (file.ParentDirectory == directory) { //no change return(new FileResult(BaseResultStatus.OK_NO_CHANGE)); } try { DatabaseLock.EnterWriteLock(); //save previous watermark for event Guid previousWatermark = GetRootWatermark(); Guid newWatermark = Guid.NewGuid(); //move in cache SoundboxDirectory oldParent = file.ParentDirectory; oldParent.Children.Remove(file); directory.AddChild(file); //update file in database if (!(file is SoundboxDirectory)) { //TODO async Database.Update(file); } //else: is updated anyways in SetWatermak //update cache and database watermarks (this will call Update for parent) SetWatermark(file, newWatermark); SetWatermark(oldParent, newWatermark); //update our clients GetHub().OnFileEvent(new SoundboxFileMoveEvent() { Event = SoundboxFileChangeEvent.Type.MOVED, File = FlattenForEvent(file), FromDirectory = oldParent, PreviousWatermark = previousWatermark }); return(new FileResult(BaseResultStatus.OK, file, previousWatermark, oldParent)); } catch (Exception ex) { Log(ex); return(new FileResult(BaseResultStatus.INTERNAL_SERVER_ERROR)); } finally { DatabaseLock.ExitWriteLock(); } }
/// <summary> /// Edits the given file. These attributes are modified:<list type="bullet"> /// <item><see cref="SoundboxNode.Name"/></item> /// <item><see cref="SoundboxNode.Tags"/></item> /// <item><see cref="Sound.VoiceActivation"/></item> /// </list> /// </summary> /// <param name="file"></param> /// <returns></returns> public async Task <FileResult> Edit(SoundboxNode file) { SoundboxNode localFile = GetCleanFile(file); if (localFile == null) { return(new FileResult(BaseResultStatus.INVALID_PARAMETER)); } if (IsRootDirectory(localFile)) { return(new FileResult(FileResultStatus.ILLEGAL_FILE_EDIT_DENIED_ROOT)); } if (!CheckUploadDisplayName(file.Name)) { return(new FileResult(FileResultStatus.INVALID_FILE_NAME)); } //TODO check unique name in directory try { DatabaseLock.EnterWriteLock(); //save previous watermark for event Guid previousWatermark = GetRootWatermark(); Guid newWatermark = Guid.NewGuid(); //make a copy of our local file for comparison var localCopy = localFile.CompareCopy(); //modify our local file localFile.Name = file.Name; localFile.Tags = file.Tags; if (localFile is ISoundboxPlayable localPlayable && file is ISoundboxPlayable playable) { localPlayable.VoiceActivation = playable.VoiceActivation; } //modify in database //TODO async Database.Update(localFile); //update cache and database watermarks (this will call Update for parent) SetWatermark(localFile, newWatermark); //update our clients GetHub().OnFileEvent(new SoundboxFileChangeEvent() { Event = SoundboxFileChangeEvent.Type.MODIFIED, File = FlattenForEvent(localFile), PreviousWatermark = previousWatermark }); if (localFile is Sound newSound && localCopy is Sound oldSound) { SpeechRecognition_OnSoundChanged(newSound, oldSound); } return(new FileResult(BaseResultStatus.OK, localFile, previousWatermark)); } catch (Exception ex) { Log(ex); return(new FileResult(BaseResultStatus.INTERNAL_SERVER_ERROR)); } finally { DatabaseLock.ExitWriteLock(); } }
/// <summary> /// Deletes the given sound or directory. When a directory is passed then all content is deleted recursively. /// </summary> /// <param name="file"></param> /// <returns></returns> public Task <FileResult> Delete(SoundboxNode file) { return(GetSoundbox().Delete(file)); }
/// <summary> /// <see cref="SoundboxNode.Flatten"/>s the given node but preserves its <see cref="SoundboxNode.ParentDirectory"/> (in a flattened state). /// This the form we send out as events when the file tree changes. /// </summary> /// <param name="file"></param> /// <returns></returns> protected SoundboxNode FlattenForEvent(SoundboxNode file) { return(file.Flatten(true)); }