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));
 }
Exemple #3
0
 /// <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);
 }
Exemple #4
0
 protected override void CompareCopyFill(SoundboxNode other)
 {
     base.CompareCopyFill(other);
     if (other is SoundboxFile file)
     {
         file.FileName         = this.FileName;
         file.AbsoluteFileName = this.AbsoluteFileName;
     }
 }
Exemple #5
0
        /// <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();
            }
        }
Exemple #6
0
 /// <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);
     }
 }
Exemple #7
0
 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);
         }
     }
 }
Exemple #8
0
 /// <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);
        }
Exemple #10
0
        /// <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();
            }
        }
Exemple #11
0
 /// <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);
         }
     }
 }
Exemple #12
0
 /// <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));
 }
Exemple #13
0
 /// <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));
 }
Exemple #14
0
 public void AddChild(SoundboxNode file)
 {
     this.Children.Add(file);
     file.ParentDirectory = this;
 }
Exemple #15
0
        /// <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();
            }
        }
Exemple #16
0
        /// <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();
            }
        }
Exemple #17
0
 /// <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));
 }
Exemple #18
0
 /// <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));
 }