Skip to content

Commit

Permalink
Fixed component in subclass exception. This was happening because the…
Browse files Browse the repository at this point in the history
… subclass visitor gets all the mappings repeatedly to see which matches, and this doesn't work with our current design. Redesigned components to recreate the mapping on every call to GetMapping (as it should work really!). This needs to be ported to the other mappings.
  • Loading branch information
jagregory committed Aug 4, 2009
1 parent 1115655 commit 3109c19
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 29 deletions.
Expand Up @@ -40,7 +40,7 @@ public abstract class BaseModelFixture

protected ModelTester<SubclassMap<T>, SubclassMapping> SubclassMapForSubclass<T>()
{
return new ModelTester<SubclassMap<T>, SubclassMapping>(() => new SubclassMap<T>(), x => (SubclassMapping)x.GetSubclassMapping(new SubclassMapping()));
return new ModelTester<SubclassMap<T>, SubclassMapping>(() => new SubclassMap<T>(), x => (SubclassMapping)((IIndeterminateSubclassMappingProvider)x).GetSubclassMapping(new SubclassMapping()));
}

protected ModelTester<JoinedSubClassPart<T>, JoinedSubclassMapping> JoinedSubclass<T>()
Expand All @@ -50,7 +50,7 @@ public abstract class BaseModelFixture

protected ModelTester<SubclassMap<T>, JoinedSubclassMapping> SubclassMapForJoinedSubclass<T>()
{
return new ModelTester<SubclassMap<T>, JoinedSubclassMapping>(() => new SubclassMap<T>(), x => (JoinedSubclassMapping)x.GetSubclassMapping(new JoinedSubclassMapping()));
return new ModelTester<SubclassMap<T>, JoinedSubclassMapping>(() => new SubclassMap<T>(), x => (JoinedSubclassMapping)((IIndeterminateSubclassMappingProvider)x).GetSubclassMapping(new JoinedSubclassMapping()));
}

protected ModelTester<ComponentPart<T>, ComponentMapping> Component<T>()
Expand Down
@@ -1,4 +1,6 @@
using System;
using System.Linq;
using FluentNHibernate.Mapping;
using FluentNHibernate.Testing.DomainModel;
using FluentNHibernate.Testing.DomainModel.Mapping;
using NUnit.Framework;
Expand All @@ -16,6 +18,44 @@ public void ComponentShouldAddToModelComponentsCollection()
.ModelShouldMatch(x => x.Components.Count().ShouldEqual(1));
}

[Test]
public void ComponentWithPropertiesShouldAddToModelComponentsCollection()
{
var classMap = new ClassMap<Parent>();

classMap.Id(x => x.Id);

var subclassMap = new SubclassMap<Child>();

subclassMap.Component(x => x.Component, c => c.Map(x => x.Name));

var model = new PersistenceModel();

model.Add(classMap);
model.Add(subclassMap);

model.BuildMappings()
.First()
.Classes.First()
.Subclasses.First()
.Components.Count().ShouldEqual(1);
}

private class Parent
{
public int Id { get; set; }
}

private class Child : Parent
{
public Component Component { get; set; }
}

private class Component
{
public string Name { get; set; }
}

[Test]
public void DynamicComponentShouldAddToModelComponentsCollection()
{
Expand Down
25 changes: 19 additions & 6 deletions src/FluentNHibernate/Mapping/ComponentPart.cs
@@ -1,27 +1,40 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using FluentNHibernate.MappingModel;
using FluentNHibernate.MappingModel.ClassBased;

namespace FluentNHibernate.Mapping
{
public class ComponentPart<T> : ComponentPartBase<T>
{
private readonly Type entity;
private readonly AccessStrategyBuilder<ComponentPart<T>> access;
private readonly AttributeStore<ComponentMapping> attributes;

public ComponentPart(Type entity, PropertyInfo property)
: this(new ComponentMapping { ContainingEntityType = entity }, property.Name)
{ }
: this(entity, property.Name, new AttributeStore())
{}

private ComponentPart(ComponentMapping mapping, string propertyName)
: base(mapping, propertyName)
private ComponentPart(Type entity, string propertyName, AttributeStore underlyingStore)
: base(underlyingStore, propertyName)
{
access = new AccessStrategyBuilder<ComponentPart<T>>(this, value => mapping.Access = value);
attributes = new AttributeStore<ComponentMapping>(underlyingStore);
access = new AccessStrategyBuilder<ComponentPart<T>>(this, value => attributes.Set(x => x.Access, value));
this.entity = entity;

Insert();
Update();
}

protected override IComponentMapping CreateComponentMappingRoot(AttributeStore store)
{
return new ComponentMapping(store)
{
ContainingEntityType = entity
};
}

/// <summary>
/// Set the access and naming strategy for this component.
/// </summary>
Expand Down Expand Up @@ -65,7 +78,7 @@ public new ComponentPart<T> Update()

public ComponentPart<T> LazyLoad()
{
mapping.Lazy = nextBool;
attributes.Set(x => x.Lazy, nextBool);
nextBool = true;
return this;
}
Expand Down
28 changes: 16 additions & 12 deletions src/FluentNHibernate/Mapping/ComponentPartBase.cs
Expand Up @@ -12,18 +12,22 @@ public abstract class ComponentPartBase<T> : ClasslikeMapBase<T>, IComponentMapp
{
private readonly string propertyName;
private readonly AccessStrategyBuilder<ComponentPartBase<T>> access;
protected ComponentMappingBase mapping;
protected bool nextBool = true;
private readonly AttributeStore<ComponentMappingBase> attributes;

protected ComponentPartBase(ComponentMappingBase mapping, string propertyName)
protected ComponentPartBase(AttributeStore underlyingStore, string propertyName)
{
this.mapping = mapping;
access = new AccessStrategyBuilder<ComponentPartBase<T>>(this, value => mapping.Access = value);
attributes = new AttributeStore<ComponentMappingBase>(underlyingStore);
access = new AccessStrategyBuilder<ComponentPartBase<T>>(this, value => attributes.Set(x => x.Access, value));
this.propertyName = propertyName;
}

protected abstract IComponentMapping CreateComponentMappingRoot(AttributeStore store);

IComponentMapping IComponentMappingProvider.GetComponentMapping()
{
var mapping = CreateComponentMappingRoot(attributes.CloneInner());

mapping.Name = propertyName;

foreach (var property in properties)
Expand Down Expand Up @@ -62,11 +66,11 @@ public ComponentPartBase<T> ParentReference(Expression<Func<T, object>> exp)

private ComponentPartBase<T> ParentReference(PropertyInfo property)
{
mapping.Parent = new ParentMapping
attributes.Set(x => x.Parent, new ParentMapping
{
Name = property.Name,
ContainingEntityType = typeof(T)
};
});

return this;
}
Expand All @@ -82,37 +86,37 @@ public ComponentPartBase<T> Not

public ComponentPartBase<T> ReadOnly()
{
mapping.Insert = !nextBool;
mapping.Update = !nextBool;
attributes.Set(x => x.Insert, !nextBool);
attributes.Set(x => x.Update, !nextBool);
nextBool = true;

return this;
}

public ComponentPartBase<T> Insert()
{
mapping.Insert = nextBool;
attributes.Set(x => x.Insert, nextBool);
nextBool = true;
return this;
}

public ComponentPartBase<T> Update()
{
mapping.Update = nextBool;
attributes.Set(x => x.Update, nextBool);
nextBool = true;
return this;
}

public ComponentPartBase<T> Unique()
{
mapping.Unique = nextBool;
attributes.Set(x => x.Unique, nextBool);
nextBool = true;
return this;
}

public ComponentPartBase<T> OptimisticLock()
{
mapping.OptimisticLock = nextBool;
attributes.Set(x => x.OptimisticLock, nextBool);
nextBool = true;
return this;
}
Expand Down
21 changes: 16 additions & 5 deletions src/FluentNHibernate/Mapping/DynamicComponentPart.cs
@@ -1,24 +1,35 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using FluentNHibernate.MappingModel;
using FluentNHibernate.MappingModel.ClassBased;

namespace FluentNHibernate.Mapping
{
public class DynamicComponentPart<T> : ComponentPartBase<T>
{
private readonly Type entity;
private readonly AccessStrategyBuilder<DynamicComponentPart<T>> access;
private readonly AttributeStore<DynamicComponentMapping> attributes;

public DynamicComponentPart(Type entity, PropertyInfo property)
: this(new DynamicComponentMapping { ContainingEntityType = entity }, property.Name)
: this(entity, property.Name, new AttributeStore())
{}

private DynamicComponentPart(DynamicComponentMapping mapping, string propertyName)
: base(mapping, propertyName)
private DynamicComponentPart(Type entity, string propertyName, AttributeStore underlyingStore)
: base(underlyingStore, propertyName)
{
access = new AccessStrategyBuilder<DynamicComponentPart<T>>(this, value => mapping.Access = value);
this.entity = entity;
attributes = new AttributeStore<DynamicComponentMapping>(underlyingStore);
access = new AccessStrategyBuilder<DynamicComponentPart<T>>(this, value => attributes.Set(x => x.Access, value));
}

this.mapping = mapping;
protected override IComponentMapping CreateComponentMappingRoot(AttributeStore store)
{
return new DynamicComponentMapping(store)
{
ContainingEntityType = entity
};
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/FluentNHibernate/Mapping/SubclassMap.cs
Expand Up @@ -25,7 +25,7 @@ public SubclassMap<T> Not
}
}

public ISubclassMapping GetSubclassMapping(ISubclassMapping mapping)
ISubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(ISubclassMapping mapping)
{
GenerateNestedSubclasses(mapping);

Expand Down
Expand Up @@ -11,7 +11,7 @@ public ComponentMapping()
: this(new AttributeStore())
{}

private ComponentMapping(AttributeStore store)
public ComponentMapping(AttributeStore store)
: base(store)
{
attributes = new AttributeStore<ComponentMapping>(store);
Expand Down
Expand Up @@ -11,7 +11,7 @@ public DynamicComponentMapping()
: this(new AttributeStore())
{ }

private DynamicComponentMapping(AttributeStore store)
public DynamicComponentMapping(AttributeStore store)
: base(store)
{
attributes = new AttributeStore<DynamicComponentMapping>(store);
Expand Down
Expand Up @@ -13,7 +13,7 @@ public interface IComponentMapping
bool Update { get; set; }
string Access { get; set; }
Type ContainingEntityType { get; }
string Name { get; }
string Name { get; set; }
PropertyInfo PropertyInfo { get; }
Type Type { get; }
bool Lazy { get; }
Expand All @@ -25,5 +25,11 @@ public interface IComponentMapping
IEnumerable<IComponentMapping> Components { get; }
IEnumerable<OneToOneMapping> OneToOnes { get; }
IEnumerable<AnyMapping> Anys { get; }
void AddProperty(PropertyMapping mapping);
void AddComponent(IComponentMapping mapping);
void AddOneToOne(OneToOneMapping mapping);
void AddCollection(ICollectionMapping mapping);
void AddReference(ManyToOneMapping mapping);
void AddAny(AnyMapping mapping);
}
}
Expand Up @@ -9,6 +9,7 @@ public interface ISubclassMapping : IMappingBase
string Name { get; set; }
Type Type { get; }
IEnumerable<ISubclassMapping> Subclasses { get; }
IEnumerable<IComponentMapping> Components { get; }
void OverrideAttributes(AttributeStore store);
void AddProperty(PropertyMapping mapping);
void AddComponent(IComponentMapping mapping);
Expand Down

0 comments on commit 3109c19

Please sign in to comment.