/* 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.Linq.Expressions;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.Linq.Translators;
namespace MongoDB.Driver
{
///
/// A rendered projection.
///
/// The type of the projection.
public sealed class RenderedProjectionDefinition
{
private readonly BsonDocument _projection;
private readonly IBsonSerializer _projectionSerializer;
///
/// Initializes a new instance of the class.
///
/// The document.
/// The projection serializer.
public RenderedProjectionDefinition(BsonDocument document, IBsonSerializer projectionSerializer)
{
_projection = document;
_projectionSerializer = Ensure.IsNotNull(projectionSerializer, nameof(projectionSerializer));
}
///
/// Gets the document.
///
public BsonDocument Document
{
get { return _projection; }
}
///
/// Gets the serializer.
///
public IBsonSerializer ProjectionSerializer
{
get { return _projectionSerializer; }
}
}
///
/// Base class for projections whose projection type is not yet known.
///
/// The type of the source.
public abstract class ProjectionDefinition
{
///
/// Renders the projection to a .
///
/// The source serializer.
/// The serializer registry.
/// A .
public abstract BsonDocument Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry);
///
/// Performs an implicit conversion from to .
///
/// The document.
///
/// The result of the conversion.
///
public static implicit operator ProjectionDefinition(BsonDocument document)
{
if (document == null)
{
return null;
}
return new BsonDocumentProjectionDefinition(document);
}
///
/// Performs an implicit conversion from to .
///
/// The JSON string.
///
/// The result of the conversion.
///
public static implicit operator ProjectionDefinition(string json)
{
if (json == null)
{
return null;
}
return new JsonProjectionDefinition(json);
}
}
///
/// Base class for projections.
///
/// The type of the source.
/// The type of the projection.
public abstract class ProjectionDefinition
{
///
/// Renders the projection to a .
///
/// The source serializer.
/// The serializer registry.
/// A .
public abstract RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry);
///
/// Performs an implicit conversion from to .
///
/// The document.
///
/// The result of the conversion.
///
public static implicit operator ProjectionDefinition(BsonDocument document)
{
if (document == null)
{
return null;
}
return new BsonDocumentProjectionDefinition(document);
}
///
/// Performs an implicit conversion from to .
///
/// The JSON string.
///
/// The result of the conversion.
///
public static implicit operator ProjectionDefinition(string json)
{
if (json == null)
{
return null;
}
return new JsonProjectionDefinition(json);
}
///
/// Performs an implicit conversion from to .
///
/// The projection.
///
/// The result of the conversion.
///
public static implicit operator ProjectionDefinition(ProjectionDefinition projection)
{
return new KnownResultTypeProjectionDefinitionAdapter(projection);
}
}
///
/// A based projection whose projection type is not yet known.
///
/// The type of the source.
public sealed class BsonDocumentProjectionDefinition : ProjectionDefinition
{
private readonly BsonDocument _document;
///
/// Initializes a new instance of the class.
///
/// The document.
public BsonDocumentProjectionDefinition(BsonDocument document)
{
_document = Ensure.IsNotNull(document, nameof(document));
}
///
/// Gets the document.
///
public BsonDocument Document
{
get { return _document; }
}
///
public override BsonDocument Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
return _document;
}
}
///
/// A based projection.
///
/// The type of the source.
/// The type of the projection.
public sealed class BsonDocumentProjectionDefinition : ProjectionDefinition
{
private readonly BsonDocument _document;
private readonly IBsonSerializer _projectionSerializer;
///
/// Initializes a new instance of the class.
///
/// The document.
/// The projection serializer.
public BsonDocumentProjectionDefinition(BsonDocument document, IBsonSerializer projectionSerializer = null)
{
_document = Ensure.IsNotNull(document, nameof(document));
_projectionSerializer = projectionSerializer;
}
///
/// Gets the document.
///
public BsonDocument Document
{
get { return _document; }
}
///
/// Gets the projection serializer.
///
public IBsonSerializer ProjectionSerializer
{
get { return _projectionSerializer; }
}
///
public override RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
return new RenderedProjectionDefinition(
_document,
_projectionSerializer ?? (sourceSerializer as IBsonSerializer) ?? serializerRegistry.GetSerializer());
}
}
///
/// A find based projection.
///
/// The type of the source.
/// The type of the projection.
public sealed class FindExpressionProjectionDefinition : ProjectionDefinition
{
private readonly Expression> _expression;
///
/// Initializes a new instance of the class.
///
/// The expression.
public FindExpressionProjectionDefinition(Expression> expression)
{
_expression = Ensure.IsNotNull(expression, nameof(expression));
}
///
/// Gets the expression.
///
public Expression> Expression
{
get { return _expression; }
}
///
public override RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
return FindProjectionTranslator.Translate(_expression, sourceSerializer, serializerRegistry);
}
}
///
/// A JSON based projection whose projection type is not yet known.
///
/// The type of the source.
public sealed class JsonProjectionDefinition : ProjectionDefinition
{
private readonly string _json;
///
/// Initializes a new instance of the class.
///
/// The json.
public JsonProjectionDefinition(string json)
{
_json = Ensure.IsNotNullOrEmpty(json, nameof(json));
}
///
/// Gets the json.
///
public string Json
{
get { return _json; }
}
///
public override BsonDocument Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
return BsonDocument.Parse(_json);
}
}
///
/// A JSON based projection.
///
/// The type of the source.
/// The type of the projection.
public sealed class JsonProjectionDefinition : ProjectionDefinition
{
private readonly string _json;
private readonly IBsonSerializer _projectionSerializer;
///
/// Initializes a new instance of the class.
///
/// The json.
/// The projection serializer.
public JsonProjectionDefinition(string json, IBsonSerializer projectionSerializer = null)
{
_json = Ensure.IsNotNullOrEmpty(json, nameof(json));
_projectionSerializer = projectionSerializer;
}
///
/// Gets the json.
///
public string Json
{
get { return _json; }
}
///
/// Gets the projection serializer.
///
public IBsonSerializer ProjectionSerializer
{
get { return _projectionSerializer; }
}
///
public override RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
return new RenderedProjectionDefinition(
BsonDocument.Parse(_json),
_projectionSerializer ?? (sourceSerializer as IBsonSerializer) ?? serializerRegistry.GetSerializer());
}
}
///
/// An based projection whose projection type is not yet known.
///
/// The type of the source.
public sealed class ObjectProjectionDefinition : ProjectionDefinition
{
private readonly object _obj;
///
/// Initializes a new instance of the class.
///
/// The object.
public ObjectProjectionDefinition(object obj)
{
_obj = Ensure.IsNotNull(obj, nameof(obj));
}
///
/// Gets the object.
///
public object Object
{
get { return _obj; }
}
///
public override BsonDocument Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
var serializer = serializerRegistry.GetSerializer(_obj.GetType());
return new BsonDocumentWrapper(_obj, serializer);
}
}
///
/// An based projection.
///
/// The type of the source.
/// The type of the projection.
public sealed class ObjectProjectionDefinition : ProjectionDefinition
{
private readonly object _obj;
private readonly IBsonSerializer _projectionSerializer;
///
/// Initializes a new instance of the class.
///
/// The object.
/// The projection serializer.
public ObjectProjectionDefinition(object obj, IBsonSerializer projectionSerializer = null)
{
_obj = Ensure.IsNotNull(obj, nameof(obj));
_projectionSerializer = projectionSerializer;
}
///
/// Gets the object.
///
public object Object
{
get { return _obj; }
}
///
/// Gets the projection serializer.
///
public IBsonSerializer ProjectionSerializer
{
get { return _projectionSerializer; }
}
///
public override RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
var serializer = serializerRegistry.GetSerializer(_obj.GetType());
return new RenderedProjectionDefinition(
new BsonDocumentWrapper(_obj, serializer),
_projectionSerializer ?? (sourceSerializer as IBsonSerializer) ?? serializerRegistry.GetSerializer());
}
}
internal sealed class KnownResultTypeProjectionDefinitionAdapter : ProjectionDefinition
{
private readonly ProjectionDefinition _projection;
private readonly IBsonSerializer _projectionSerializer;
public KnownResultTypeProjectionDefinitionAdapter(ProjectionDefinition projection, IBsonSerializer projectionSerializer = null)
{
_projection = Ensure.IsNotNull(projection, nameof(projection));
_projectionSerializer = projectionSerializer;
}
public ProjectionDefinition Projection
{
get { return _projection; }
}
public IBsonSerializer ResultSerializer
{
get { return _projectionSerializer; }
}
public override RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
var document = _projection.Render(sourceSerializer, serializerRegistry);
return new RenderedProjectionDefinition(
document,
_projectionSerializer ?? (sourceSerializer as IBsonSerializer) ?? serializerRegistry.GetSerializer());
}
}
///
/// A client side only projection that is implemented solely by deserializing using a different serializer.
///
/// The type of the source.
/// The type of the projection.
public sealed class ClientSideDeserializationProjectionDefinition : ProjectionDefinition
{
private readonly IBsonSerializer _projectionSerializer;
///
/// Initializes a new instance of the class.
///
/// The projection serializer.
public ClientSideDeserializationProjectionDefinition(IBsonSerializer projectionSerializer = null)
{
_projectionSerializer = projectionSerializer;
}
///
/// Gets the result serializer.
///
///
/// The result serializer.
///
public IBsonSerializer ResultSerializer
{
get { return _projectionSerializer; }
}
///
public override RenderedProjectionDefinition Render(IBsonSerializer sourceSerializer, IBsonSerializerRegistry serializerRegistry)
{
return new RenderedProjectionDefinition(
null,
_projectionSerializer ?? (sourceSerializer as IBsonSerializer) ?? serializerRegistry.GetSerializer());
}
}
}