Permalink
Browse files

Merge branch 'load-feature' into development

  • Loading branch information...
2 parents d7701d3 + 736515f commit 961d8bfac6788d8b8131cb553852a2947cc0764a @dragan committed Dec 20, 2010
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Net;
using System.Reflection;
using NSubstitute;
@@ -252,12 +253,100 @@ public void Should_execute_bulk_docs_command_with_couch_proxy()
}));
}
}
+
+ public class When_loading_a_simple_entity : ConcernFor<CouchDocumentSession>
+ {
+ private Guid documentId;
+ private Employee entity1;
+ private Type entity1Type;
+ private PropertyInfo identityProperty;
+ private ICouchDocumentConvention documentConvention;
+ private ICouchProxy couchProxy;
+ private ICouchDatabase couchDatabase;
+
+ protected override void Given()
+ {
+ documentId = Guid.NewGuid();
+ entity1Type = typeof(Employee);
+ identityProperty = entity1Type.GetProperty("Id");
+
+ documentConvention = Fake<ICouchDocumentConvention>();
+ documentConvention.GetIdentityPropertyFor(entity1Type).Returns(identityProperty);
+
+ var couchDocument = new CouchDocument();
+ couchDocument.Add("_id", documentId.ToString());
+ couchDocument.Add("_rev", "123456");
+ couchDocument.Add("Type", entity1Type.Name);
+ couchDocument.Add("Name", "Bob");
+ couchDocument.Add("Login", "boblogin");
+
+ couchProxy = Fake<ICouchProxy>();
+ couchProxy.Execute<CouchDocument>(Arg.Any<GetDocumentCommand>()).Returns(couchDocument);
+
+ couchDatabase = Fake<ICouchDatabase>();
+ couchDatabase.Name.Returns("ottoman-test-database");
+ couchDatabase.CouchProxy.Returns(couchProxy);
+ couchDatabase.CouchDocumentConvention.Returns(documentConvention);
+ }
+
+ public override CouchDocumentSession CreateSystemUnderTest()
+ {
+ return new CouchDocumentSession(couchDatabase);
+ }
+
+ protected override void When()
+ {
+ entity1 = Sut.Load<Employee>(documentId.ToString());
+ }
+
+ [Test]
+ public void Should_execute_get_document_command_with_couch_proxy()
+ {
+ couchProxy.Received().Execute<CouchDocument>(Arg.Is<GetDocumentCommand>(c => {
+ return c.Route == couchDatabase.Name + "/" + documentId.ToString() &&
+ c.Operation == HttpMethod.Get &&
+ c.Message == null &&
+ c.SuccessStatusCode == HttpStatusCode.OK;
+ }));
+ }
+
+ [Test]
+ public void Should_call_get_identity_property()
+ {
+ documentConvention.Received().GetIdentityPropertyFor(entity1Type);
+ }
+
+ [Test]
+ public void Should_return_populated_entity()
+ {
+ Assert.That(entity1.Id, Is.EqualTo(documentId));
+ Assert.That(entity1.Name, Is.EqualTo("Bob"));
+ Assert.That(entity1.Login, Is.EqualTo("boblogin"));
+ }
+ }
}
public class Employee
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Login { get; set; }
+
+ public override bool Equals (object obj)
+ {
+ if (obj == null)
+ return false;
+
+ Employee employee = obj as Employee;
+ if (employee == null)
+ return false;
+
+ return (this.Id == employee.Id) && (this.Name == employee.Name) && (this.Login == employee.Login);
+ }
+
+ public override int GetHashCode ()
+ {
+ return Id.GetHashCode() ^ Name.GetHashCode() ^ Login.GetHashCode();
+ }
}
}
@@ -0,0 +1,35 @@
+using System;
+using System.Net;
+
+using SineSignal.Ottoman.Exceptions;
+using SineSignal.Ottoman.Http;
+
+namespace SineSignal.Ottoman.Commands
+{
+ internal class GetDocumentCommand : ICouchCommand
+ {
+ public string Route { get; private set; }
+ public string Operation { get; private set; }
+ public object Message { get; private set; }
+ public HttpStatusCode SuccessStatusCode { get; private set; }
+
+ private string DatabaseName { get; set; }
+ private string DocumentId { get; set; }
+
+ public GetDocumentCommand(string databaseName, string documentId)
+ {
+ DatabaseName = databaseName;
+ DocumentId = documentId;
+
+ Route = DatabaseName + "/" + DocumentId;
+ Operation = HttpMethod.Get;
+ Message = null;
+ SuccessStatusCode = HttpStatusCode.OK;
+ }
+
+ public void HandleError(string serverAddress, CommandErrorResult errorResult, UnexpectedHttpResponseException innerException)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
@@ -29,5 +29,42 @@ public static CouchDocument Dehydrate(object entity, PropertyInfo identityProper
return couchDocument;
}
+
+ public T Hydrate<T>(PropertyInfo identityProperty) where T : new()
+ {
+ var instance = new T();
+ var instanceType = instance.GetType();
+
+ foreach (KeyValuePair<string, object> pair in this)
+ {
+ if (pair.Key == "_rev")
+ continue;
+
+ if (pair.Key == "Type")
+ continue;
+
+ PropertyInfo property;
+
+ if (pair.Key == "_id")
+ {
+ property = instanceType.GetProperty(identityProperty.Name);
+ }
+ else
+ {
+ property = instanceType.GetProperty(pair.Key);
+ }
+
+ if (property.PropertyType == typeof(Guid))
+ {
+ property.SetValue(instance, new Guid(pair.Value.ToString()), null);
+ }
+ else
+ {
+ property.SetValue(instance, pair.Value, null);
+ }
+ }
+
+ return instance;
+ }
}
}
@@ -50,21 +50,24 @@ public void Store(object entity)
throw new NonUniqueEntityException("Attempted to associate a different entity with id '" + id + "'.");
}
- var entityMetadata = new EntityMetadata{ Key = id.ToString(), Revision = String.Empty, OriginalEntity = entity };
+ var entityMetadata = new EntityMetadata{ Key = id.ToString(), Revision = String.Empty };
EntityMetadataMap.Add(entity, entityMetadata);
IdentityMap[id.ToString()] = entity;
}
}
- public T Load<T>(string id)
+ public T Load<T>(string id) where T : new()
{
object existingEntity;
if(IdentityMap.TryGetValue(id, out existingEntity))
{
return (T)existingEntity;
}
- return default(T);
+ var getDocumentCommand = new GetDocumentCommand(CouchDatabase.Name, id);
+ CouchDocument couchDocument = CouchDatabase.CouchProxy.Execute<CouchDocument>(getDocumentCommand);
+
+ return StalkEntity<T>(couchDocument);
}
public void SaveChanges()
@@ -79,6 +82,9 @@ public void SaveChanges()
entities.Add(entity.Key);
}
+ if (docs.Count == 0 && entities.Count == 0)
+ return;
+
var bulkDocsMessage = new BulkDocsMessage(docs);
var bulkDocsCommand = new BulkDocsCommand(CouchDatabase.Name, bulkDocsMessage);
@@ -114,7 +120,25 @@ private static object GetIdentityValueFor(object entity, PropertyInfo identityPr
private bool IsEntityDirty(object entity, EntityMetadata entityMetadata)
{
- return true;
+ return entity.Equals(entityMetadata.OriginalEntity) == false;
+ }
+
+ private T StalkEntity<T>(CouchDocument couchDocument) where T : new()
+ {
+ PropertyInfo identityProperty = CouchDatabase.CouchDocumentConvention.GetIdentityPropertyFor(typeof(T));
+ T entity = couchDocument.Hydrate<T>(identityProperty);
+
+ EntityMetadata entityMetadata = new EntityMetadata
+ {
+ Key = couchDocument["_id"].ToString(),
+ Revision = couchDocument["_rev"].ToString(),
+ OriginalEntity = entity
+ };
+
+ EntityMetadataMap[entity] = entityMetadata;
+ IdentityMap[entityMetadata.Key] = entity;
+
+ return entity;
}
private class EntityMetadata
@@ -3,7 +3,7 @@ namespace SineSignal.Ottoman
public interface ICouchDocumentSession
{
void Store(object entity);
- T Load<T>(string id);
+ T Load<T>(string id) where T : new();
void SaveChanges();
}
}
@@ -76,6 +76,7 @@
<Compile Include="Exceptions\CannotConnectToServerException.cs" />
<Compile Include="Exceptions\CannotCreateDatabaseException.cs" />
<Compile Include="Exceptions\CannotDeleteDatabaseException.cs" />
+ <Compile Include="Commands\GetDocumentCommand.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />

0 comments on commit 961d8bf

Please sign in to comment.