/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Serializers;
namespace MongoDB.Bson
{
///
/// Represents a BSON array that is not materialized until you start using it.
///
[BsonSerializer(typeof(MaterializedOnDemandBsonArraySerializer))]
public abstract class MaterializedOnDemandBsonArray : BsonArray, IDisposable
{
// private fields
private bool _disposed;
private bool _isMaterialized;
// constructors
///
/// Initializes a new instance of the class.
///
protected MaterializedOnDemandBsonArray()
{
}
// public properties
///
/// Gets or sets the total number of elements the internal data structure can hold without resizing.
///
public override int Capacity
{
get
{
EnsureIsMaterialized();
return base.Capacity;
}
set
{
EnsureIsMaterialized();
base.Capacity = value;
}
}
///
/// Gets the count of array elements.
///
public override int Count
{
get
{
EnsureIsMaterialized();
return base.Count;
}
}
///
/// Gets a value indicating whether this instance is disposed.
///
///
/// true if this instance is disposed; otherwise, false .
///
public bool IsDisposed
{
get { return _disposed; }
}
///
/// Gets a value indicating whether this instance is materialized.
///
///
/// true if this instance is materialized; otherwise, false .
///
public bool IsMaterialized
{
get { return _isMaterialized; }
}
///
/// Gets the array elements as raw values (see BsonValue.RawValue).
///
[Obsolete("Use ToArray to ToList instead.")]
public override IEnumerable RawValues
{
get
{
EnsureIsMaterialized();
return base.RawValues;
}
}
///
/// Gets the array elements.
///
public override IEnumerable Values
{
get
{
EnsureIsMaterialized();
return base.Values;
}
}
// public indexers
///
/// Gets or sets a value by position.
///
/// The position.
/// The value.
public override BsonValue this[int index]
{
get
{
EnsureIsMaterialized();
return base[index];
}
set
{
EnsureIsMaterialized();
base[index] = value;
}
}
// public methods
///
/// Adds an element to the array.
///
/// The value to add to the array.
/// The array (so method calls can be chained).
public override BsonArray Add(BsonValue value)
{
EnsureIsMaterialized();
return base.Add(value);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Adds multiple elements to the array.
///
/// A list of values to add to the array.
/// The array (so method calls can be chained).
public override BsonArray AddRange(IEnumerable values)
{
EnsureIsMaterialized();
return base.AddRange(values);
}
///
/// Clears the array.
///
public override void Clear()
{
EnsureIsMaterialized();
base.Clear();
}
///
/// Creates a shallow clone of the array (see also DeepClone).
///
///
/// A shallow clone of the array.
///
public override BsonValue Clone()
{
EnsureIsMaterialized();
return base.Clone();
}
///
/// Compares the array to another array.
///
/// The other array.
/// A 32-bit signed integer that indicates whether this array is less than, equal to, or greather than the other.
public override int CompareTo(BsonArray other)
{
EnsureIsMaterialized();
return base.CompareTo(other);
}
///
/// Compares the array to another BsonValue.
///
/// The other BsonValue.
/// A 32-bit signed integer that indicates whether this array is less than, equal to, or greather than the other BsonValue.
public override int CompareTo(BsonValue other)
{
EnsureIsMaterialized();
return base.CompareTo(other);
}
///
/// Tests whether the array contains a value.
///
/// The value to test for.
/// True if the array contains the value.
public override bool Contains(BsonValue value)
{
EnsureIsMaterialized();
return base.Contains(value);
}
///
/// Copies elements from this array to another array.
///
/// The other array.
/// The zero based index of the other array at which to start copying.
public override void CopyTo(BsonValue[] array, int arrayIndex)
{
EnsureIsMaterialized();
base.CopyTo(array, arrayIndex);
}
///
/// Copies elements from this array to another array as raw values (see BsonValue.RawValue).
///
/// The other array.
/// The zero based index of the other array at which to start copying.
[Obsolete("Use ToArray or ToList instead.")]
public override void CopyTo(object[] array, int arrayIndex)
{
EnsureIsMaterialized();
base.CopyTo(array, arrayIndex);
}
///
/// Creates a deep clone of the array (see also Clone).
///
///
/// A deep clone of the array.
///
public override BsonValue DeepClone()
{
EnsureIsMaterialized();
return base.DeepClone();
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Determines whether the specified , is equal to this instance.
///
/// The to compare with this instance.
///
/// true if the specified is equal to this instance; otherwise, false .
///
public override bool Equals(object obj)
{
EnsureIsMaterialized();
return base.Equals(obj);
}
///
/// Gets an enumerator that can enumerate the elements of the array.
///
/// An enumerator.
public override IEnumerator GetEnumerator()
{
EnsureIsMaterialized();
return base.GetEnumerator();
}
///
/// Gets the hash code.
///
/// The hash code.
public override int GetHashCode()
{
EnsureIsMaterialized();
return base.GetHashCode();
}
///
/// Gets the index of a value in the array.
///
/// The value to search for.
/// The zero based index of the value (or -1 if not found).
public override int IndexOf(BsonValue value)
{
EnsureIsMaterialized();
return base.IndexOf(value);
}
///
/// Gets the index of a value in the array.
///
/// The value to search for.
/// The zero based index at which to start the search.
/// The zero based index of the value (or -1 if not found).
public override int IndexOf(BsonValue value, int index)
{
EnsureIsMaterialized();
return base.IndexOf(value, index);
}
///
/// Gets the index of a value in the array.
///
/// The value to search for.
/// The zero based index at which to start the search.
/// The number of elements to search.
/// The zero based index of the value (or -1 if not found).
public override int IndexOf(BsonValue value, int index, int count)
{
EnsureIsMaterialized();
return base.IndexOf(value, index, count);
}
///
/// Inserts a new value into the array.
///
/// The zero based index at which to insert the new value.
/// The new value.
public override void Insert(int index, BsonValue value)
{
EnsureIsMaterialized();
base.Insert(index, value);
}
///
/// Removes the first occurrence of a value from the array.
///
/// The value to remove.
/// True if the value was removed.
public override bool Remove(BsonValue value)
{
EnsureIsMaterialized();
return base.Remove(value);
}
///
/// Removes an element from the array.
///
/// The zero based index of the element to remove.
public override void RemoveAt(int index)
{
EnsureIsMaterialized();
base.RemoveAt(index);
}
///
/// Converts the BsonArray to an array of BsonValues.
///
/// An array of BsonValues.
public override BsonValue[] ToArray()
{
EnsureIsMaterialized();
return base.ToArray();
}
///
/// Converts the BsonArray to a list of BsonValues.
///
/// A list of BsonValues.
public override List ToList()
{
EnsureIsMaterialized();
return base.ToList();
}
///
/// Returns a string representation of the array.
///
/// A string representation of the array.
public override string ToString()
{
EnsureIsMaterialized();
return base.ToString();
}
// protected methods
///
/// Releases unmanaged and - optionally - managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
_disposed = true;
}
///
/// Materializes the BsonArray.
///
/// The materialized elements.
protected abstract IEnumerable Materialize();
///
/// Informs subclasses that the Materialize process completed so they can free any resources related to the unmaterialized state.
///
protected abstract void MaterializeCompleted();
///
/// Throws if disposed.
///
///
protected void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
// private methods
private void EnsureIsMaterialized()
{
ThrowIfDisposed();
if (!_isMaterialized)
{
var values = Materialize();
try
{
_isMaterialized = true;
base.AddRange(values);
MaterializeCompleted();
}
catch
{
base.Clear();
_isMaterialized = false;
throw;
}
}
}
internal class MaterializedOnDemandBsonArraySerializer : AbstractClassSerializer
{
}
}
}