Skip to content

Commit

Permalink
Created a CouchDocumentConvention class to encapsulate the default co…
Browse files Browse the repository at this point in the history
…nventions. We also allow the user to override these conventions. We also did some refactoring and created a GuidIdentityGenerator.
  • Loading branch information
dragan committed Aug 28, 2010
1 parent 578535b commit 13d8305
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 26 deletions.
78 changes: 78 additions & 0 deletions src/SineSignal.Ottoman.Specs/CouchDocumentConventionSpecs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Reflection;

using NSubstitute;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using SineSignal.Ottoman.Specs.Framework;

using SineSignal.Ottoman;
using SineSignal.Ottoman.Generators;

namespace SineSignal.Ottoman.Specs
{
public class CouchDocumentConventionSpecs
{
public class When_retrieving_the_identity_property_info_for_a_given_type : ConcernFor<CouchDocumentConvention>
{
private string defaultIdentityName;
private Employee entity;
private PropertyInfo identityProperty;

protected override void Given()
{
defaultIdentityName = "Id";
entity = new Employee { Id = Guid.NewGuid(), Name = "Bob", Login = "boblogin" };
}

public override CouchDocumentConvention CreateSystemUnderTest ()
{
return new CouchDocumentConvention();
}

protected override void When()
{
identityProperty = Sut.GetIdentityPropertyFor(entity.GetType());
}

[Test]
public void Should_be_able_to_get_identity_property_info_given_the_name_of_the_property()
{
Assert.That(identityProperty.Name, Is.EqualTo(defaultIdentityName));
}
}

public class When_generating_an_identity_value_for_a_given_identity_type : ConcernFor<CouchDocumentConvention>
{
private Employee entity;
private object generatedValue;

protected override void Given()
{
entity = new Employee { Name = "Bob", Login = "boblogin" };
}

public override CouchDocumentConvention CreateSystemUnderTest ()
{
return new CouchDocumentConvention();
}

protected override void When()
{
generatedValue = Sut.GenerateIdentityFor(entity.Id.GetType());
}

[Test]
public void Should_return_a_Guid_type()
{
Assert.That(generatedValue, Is.TypeOf(typeof(Guid)));
}

[Test]
public void Should_not_return_an_empty_Guid()
{
Assert.That((Guid)generatedValue, Is.Not.EqualTo(Guid.Empty));
}
}
}
}
24 changes: 12 additions & 12 deletions src/SineSignal.Ottoman.Specs/CouchDocumentSessionSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class When_storing_a_new_entity_into_the_session : ConcernFor<CouchDocume
private PropertyInfo identityProperty;
private Type identityType;
private Guid id;
private IDocumentConvention documentConvention;
private ICouchDocumentConvention documentConvention;
private ICouchDatabase couchDatabase;

protected override void Given()
Expand All @@ -33,12 +33,12 @@ protected override void Given()
identityType = identityProperty.PropertyType;
id = Guid.NewGuid();

documentConvention = Fake<IDocumentConvention>();
documentConvention = Fake<ICouchDocumentConvention>();
documentConvention.GetIdentityPropertyFor(entity1Type).Returns(identityProperty);
documentConvention.GenerateIdentityFor(identityType).Returns(id);

couchDatabase = Fake<ICouchDatabase>();
couchDatabase.DocumentConvention.Returns(documentConvention);
couchDatabase.CouchDocumentConvention.Returns(documentConvention);
}

public override CouchDocumentSession CreateSystemUnderTest()
Expand Down Expand Up @@ -83,7 +83,7 @@ public class When_storing_an_entity_with_an_id_already_assigned : ConcernFor<Cou
private Employee entity1;
private Type entity1Type;
private PropertyInfo identityProperty;
private IDocumentConvention documentConvention;
private ICouchDocumentConvention documentConvention;
private ICouchDatabase couchDatabase;

protected override void Given()
Expand All @@ -93,11 +93,11 @@ protected override void Given()
entity1Type = entity1.GetType();
identityProperty = entity1Type.GetProperty("Id");

documentConvention = Fake<IDocumentConvention>();
documentConvention = Fake<ICouchDocumentConvention>();
documentConvention.GetIdentityPropertyFor(entity1Type).Returns(identityProperty);

couchDatabase = Fake<ICouchDatabase>();
couchDatabase.DocumentConvention.Returns(documentConvention);
couchDatabase.CouchDocumentConvention.Returns(documentConvention);
}

public override CouchDocumentSession CreateSystemUnderTest()
Expand Down Expand Up @@ -144,7 +144,7 @@ public class When_attempting_to_store_a_different_entity_with_the_same_id_as_ano
private Type entity2Type;
private PropertyInfo identityProperty;
private NonUniqueEntityException thrownException;
private IDocumentConvention documentConvention;
private ICouchDocumentConvention documentConvention;
private ICouchDatabase couchDatabase;

protected override void Given()
Expand All @@ -155,11 +155,11 @@ protected override void Given()
entity2Type = entity2.GetType();
identityProperty = entity2Type.GetProperty("Id");

documentConvention = Fake<IDocumentConvention>();
documentConvention = Fake<ICouchDocumentConvention>();
documentConvention.GetIdentityPropertyFor(entity2Type).Returns(identityProperty);

couchDatabase = Fake<ICouchDatabase>();
couchDatabase.DocumentConvention.Returns(documentConvention);
couchDatabase.CouchDocumentConvention.Returns(documentConvention);
}

public override CouchDocumentSession CreateSystemUnderTest()
Expand Down Expand Up @@ -196,7 +196,7 @@ public class When_saving_changes_after_storing_a_new_entity : ConcernFor<CouchDo
private PropertyInfo identityProperty;
private Type identityType;
private Guid id;
private IDocumentConvention documentConvention;
private ICouchDocumentConvention documentConvention;
private BulkDocsResult[] bulkDocsResults;
private ICouchProxy couchProxy;
private ICouchDatabase couchDatabase;
Expand All @@ -209,7 +209,7 @@ protected override void Given()
identityType = identityProperty.PropertyType;
id = Guid.NewGuid();

documentConvention = Fake<IDocumentConvention>();
documentConvention = Fake<ICouchDocumentConvention>();
documentConvention.GetIdentityPropertyFor(entity1Type).Returns(identityProperty);
documentConvention.GenerateIdentityFor(identityType).Returns(id);

Expand All @@ -219,7 +219,7 @@ protected override void Given()
couchProxy.Execute<BulkDocsResult[]>(Arg.Any<BulkDocsCommand>()).Returns(bulkDocsResults);

couchDatabase = Fake<ICouchDatabase>();
couchDatabase.DocumentConvention.Returns(documentConvention);
couchDatabase.CouchDocumentConvention.Returns(documentConvention);
couchDatabase.Name.Returns("ottoman-test-database");
couchDatabase.CouchProxy.Returns(couchProxy);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<Compile Include="Serialization\JsonReaderSpecs\ReadingObjectsSpecs.cs" />
<Compile Include="Serialization\JsonReaderSpecs\ReadingArraySpecs.cs" />
<Compile Include="Serialization\JsonSerializerSpecs.cs" />
<Compile Include="CouchDocumentConventionSpecs.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SineSignal.Ottoman\SineSignal.Ottoman.csproj">
Expand Down
17 changes: 12 additions & 5 deletions src/SineSignal.Ottoman/CouchDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,24 @@ public ICouchProxy CouchProxy
get { return CouchClient.CouchProxy; }
}

public IDocumentConvention DocumentConvention
{
get { throw new NotImplementedException(); }
}
public ICouchDocumentConvention CouchDocumentConvention { get; private set; }

public string Name { get; private set; }

public CouchDatabase(CouchClient couchClient, string name)
public CouchDatabase(CouchClient couchClient, string name) : this(couchClient, name, new CouchDocumentConvention())
{
}

public CouchDatabase(CouchClient couchClient, string name, ICouchDocumentConvention couchDocumentConvention)
{
CouchClient = couchClient;
Name = name;
CouchDocumentConvention = couchDocumentConvention;
}

public ICouchDocumentSession OpenDocumentSession()
{
return new CouchDocumentSession(this);
}
}
}
51 changes: 51 additions & 0 deletions src/SineSignal.Ottoman/CouchDocumentConvention.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Reflection;

using SineSignal.Ottoman.Generators;

namespace SineSignal.Ottoman
{
public class CouchDocumentConvention : ICouchDocumentConvention
{
private static IDictionary<Type, object> identityGenerators = InitializeIdentityGenerators();

public virtual PropertyInfo GetIdentityPropertyFor(Type entityType)
{
return entityType.GetProperty("Id");
}

public object GenerateIdentityFor(Type identityType)
{
object generatedValue = null;

if (identityType == typeof(Guid))
{
generatedValue = GetIdentityGeneratorFor<Guid>(identityType).Generate();
}

return generatedValue;
}

private static IDictionary<Type, object> InitializeIdentityGenerators()
{
IDictionary<Type, object> identityGenerators = new Dictionary<Type, object>();

identityGenerators.Add(typeof(Guid), new GuidIdentityGenerator());

return identityGenerators;
}

private static IIdentityGenerator<T> GetIdentityGeneratorFor<T>(Type type)
{
object generator;

if (identityGenerators.TryGetValue(type, out generator))
{
return generator as IIdentityGenerator<T>;
}

return null;
}
}
}
11 changes: 5 additions & 6 deletions src/SineSignal.Ottoman/CouchDocumentSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public CouchDocumentSession(ICouchDatabase couchDatabase)
public void Store(object entity)
{
Type entityType = entity.GetType();
PropertyInfo identityProperty = CouchDatabase.DocumentConvention.GetIdentityPropertyFor(entityType);
PropertyInfo identityProperty = CouchDatabase.CouchDocumentConvention.GetIdentityPropertyFor(entityType);

object id = null;
if (identityProperty != null)
Expand All @@ -34,7 +34,7 @@ public void Store(object entity)

if (id == null)
{
id = CouchDatabase.DocumentConvention.GenerateIdentityFor(identityProperty.PropertyType);
id = CouchDatabase.CouchDocumentConvention.GenerateIdentityFor(identityProperty.PropertyType);
identityProperty.SetValue(entity, id, null);
}
}
Expand Down Expand Up @@ -69,7 +69,7 @@ public void SaveChanges()
var docs = new List<CouchDocument>();
foreach (object entity in IdentityMap.Values)
{
PropertyInfo identityProperty = CouchDatabase.DocumentConvention.GetIdentityPropertyFor(entity.GetType());
PropertyInfo identityProperty = CouchDatabase.CouchDocumentConvention.GetIdentityPropertyFor(entity.GetType());
var couchDocument = new CouchDocument(entity, identityProperty);
docs.Add(couchDocument);
}
Expand All @@ -90,10 +90,9 @@ private static object GetIdentityValueFor(object entity, PropertyInfo identityPr
object id = identityProperty.GetValue(entity, null);

Type propertyType = identityProperty.PropertyType;
if (propertyType == typeof(Guid))
if (propertyType == typeof(Guid) && (Guid)id == Guid.Empty)
{
if ((Guid)id == Guid.Empty)
id = null;
id = null;
}

return id;
Expand Down
12 changes: 12 additions & 0 deletions src/SineSignal.Ottoman/Generators/GuidIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace SineSignal.Ottoman.Generators
{
public class GuidIdentityGenerator : IIdentityGenerator<Guid>
{
public Guid Generate()
{
return Guid.NewGuid();
}
}
}
9 changes: 9 additions & 0 deletions src/SineSignal.Ottoman/Generators/IIdentityGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace SineSignal.Ottoman.Generators
{
public interface IIdentityGenerator<T>
{
T Generate();
}
}
3 changes: 2 additions & 1 deletion src/SineSignal.Ottoman/ICouchDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ namespace SineSignal.Ottoman
public interface ICouchDatabase
{
ICouchProxy CouchProxy { get; }
IDocumentConvention DocumentConvention { get; }
ICouchDocumentConvention CouchDocumentConvention { get; }
string Name { get; }
ICouchDocumentSession OpenDocumentSession();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace SineSignal.Ottoman
{
public interface IDocumentConvention
public interface ICouchDocumentConvention
{
PropertyInfo GetIdentityPropertyFor(Type entityType);
object GenerateIdentityFor(Type identityType);
Expand Down
6 changes: 5 additions & 1 deletion src/SineSignal.Ottoman/SineSignal.Ottoman.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="CouchDocumentSession.cs" />
<Compile Include="IDocumentConvention.cs" />
<Compile Include="Exceptions\NonUniqueEntityException.cs" />
<Compile Include="Http\HttpClient.cs" />
<Compile Include="Http\HttpRequest.cs" />
Expand Down Expand Up @@ -70,6 +69,10 @@
<Compile Include="Exceptions\CannotGetDatabaseException.cs" />
<Compile Include="Exceptions\CouchException.cs" />
<Compile Include="Exceptions\UnexpectedHttpResponseException.cs" />
<Compile Include="ICouchDocumentConvention.cs" />
<Compile Include="Generators\IIdentityGenerator.cs" />
<Compile Include="Generators\GuidIdentityGenerator.cs" />
<Compile Include="CouchDocumentConvention.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
Expand All @@ -81,5 +84,6 @@
<Folder Include="Http\" />
<Folder Include="Commands\" />
<Folder Include="Serialization\" />
<Folder Include="Generators\" />
</ItemGroup>
</Project>

0 comments on commit 13d8305

Please sign in to comment.