/// <summary>
        /// Opens an existing file, or creates a new one, for both reading and writing.
        /// </summary>
        /// <param name="dataStorePath">The data store path specifying the file to open.</param>
        /// <returns>An <see cref="IBinaryStream"/> representing the file opened.</returns>
        public IBinaryStream ReadWriteBinary( string dataStorePath )
        {
            try
            {
                if( dataStorePath.NullOrEmpty()
                 || !DataStore.IsValidPath(dataStorePath) )
                    throw new ArgumentException("Invalid data store path!").StoreFileLine();

                lock( this.syncLock )
                {
                    // create parent
                    var parentNodes = this.GetOrCreateParentNodes(dataStorePath);

                    // get node
                    var nodeName = DataStore.GetNodeName(dataStorePath);
                    var node = parentNodes.FirstOrDefault(n => DataStore.Comparer.Equals(n.Name, nodeName));
                    if( node.NotNullReference() && !(node is IDataStoreValue) )
                        throw new FileNotFoundException("File system entry is not a file!").StoreFileLine();

                    // convert text to binary node
                    var textValue = node as IDataStoreTextValue;
                    if( textValue.NotNullReference() )
                    {
                        var str = textValue.Content.ToString();
                        var bytes = DataStore.DefaultEncoding.GetBytes(str);

                        var value = new DataStoreBinaryValue(DataStore.GetNodeName(dataStorePath), bytes);
                        this.SetValueForExistingParent(parentNodes, value);
                        node = value;
                    }

                    var binaryValue = node as IDataStoreBinaryValue;
                    if( binaryValue.NullReference() )
                    {
                        binaryValue = new DataStoreBinaryValue(DataStore.GetNodeName(dataStorePath));
                        this.SetValueForExistingParent(parentNodes, binaryValue);
                    }

                    return new DataStoreBinaryValueStream(binaryValue);
                }
            }
            catch( Exception ex )
            {
                ex.Store("dataStorePath", dataStorePath);
                throw;
            }
        }
        /// <summary>
        /// Releases any resources held by an open writer.
        /// </summary>
        /// <param name="writer">The writer of the value.</param>
        protected override void CloseWriter( IBinaryWriter writer )
        {
            var valueNode = new DataStoreBinaryValue(this.currentValueNodeName, this.memoryStream.ToArray());
            this.memoryStream.SetLength(0);

            this.AddChild(valueNode);
        }
        /// <summary>
        /// Creates a new empty file, and opens it for writing.
        /// </summary>
        /// <param name="dataStorePath">The data store path specifying the file to open.</param>
        /// <param name="overwriteIfExists"><c>true</c> to overwrite the file in case it already exists (like <see cref="System.IO.FileMode.Create"/>); or <c>false</c> to throw an exception (like <see cref="System.IO.FileMode.CreateNew"/>).</param>
        /// <returns>An <see cref="IBinaryWriter"/> representing the file opened.</returns>
        public IBinaryWriter CreateNewBinary( string dataStorePath, bool overwriteIfExists )
        {
            try
            {
                if( dataStorePath.NullOrEmpty()
                 || !DataStore.IsValidPath(dataStorePath) )
                    throw new ArgumentException("Invalid data store path!").StoreFileLine();

                lock( this.syncLock )
                {
                    // create parent
                    var parentNodes = this.GetOrCreateParentNodes(dataStorePath);

                    // get or create value
                    var binaryValue = this.GetNodeAt(dataStorePath) as IDataStoreBinaryValue;
                    if( binaryValue.NullReference() )
                    {
                        binaryValue = new DataStoreBinaryValue(DataStore.GetNodeName(dataStorePath));
                        this.SetValueForExistingParent(parentNodes, binaryValue);
                    }

                    return new DataStoreBinaryValueWriter(binaryValue);
                }
            }
            catch( Exception ex )
            {
                ex.Store("dataStorePath", dataStorePath);
                ex.Store("overwriteIfExists", overwriteIfExists);
                throw;
            }
        }