Skip to content

Commit

Permalink
Experimental HasMap functionality on Classlike.
Browse files Browse the repository at this point in the history
  • Loading branch information
Stuart Childs committed May 14, 2009
1 parent d782f8c commit 67d4a50
Show file tree
Hide file tree
Showing 13 changed files with 438 additions and 1 deletion.
@@ -0,0 +1,17 @@
using FluentNHibernate.Mapping;

namespace FluentNHibernate.Conventions.Defaults
{
public class HasMapCollectionNameConvention : IMapConvention
{
public bool Accept(IMapCollectionPart target)
{
return string.IsNullOrEmpty(target.CollectionColumnName);
}

public void Apply(IMapCollectionPart target)
{
target.WithCollectionColumn(target.ValueType.Name + "_id");
}
}
}
@@ -0,0 +1,17 @@
using FluentNHibernate.Mapping;

namespace FluentNHibernate.Conventions.Defaults
{
public class HasMapIndexNameConvention : IMapConvention
{
public bool Accept(IMapCollectionPart target)
{
return string.IsNullOrEmpty(target.IndexColumnName);
}

public void Apply(IMapCollectionPart target)
{
target.WithIndexColumn(target.IndexType.Name + "_id");
}
}
}
@@ -0,0 +1,17 @@
using FluentNHibernate.Mapping;

namespace FluentNHibernate.Conventions.Defaults
{
class HasMapTableNameConvention : IMapConvention
{
public bool Accept(IMapCollectionPart target)
{
return string.IsNullOrEmpty(target.TableName);
}

public void Apply(IMapCollectionPart target)
{
target.WithTableName(target.EntityType.Name + "To" + target.ValueType.Name);
}
}
}
@@ -0,0 +1,35 @@
using FluentNHibernate.Mapping;

namespace FluentNHibernate.Conventions.Discovery
{
/// <summary>
/// Discovers any <see cref="IJoinedSubclassConvention"/> implementations and applies them to
/// an <see cref="IJoinedSubclass"/> instance.
/// </summary>
public class HasMapDiscoveryConvention : IMappingPartConvention
{
private readonly IConventionFinder conventionFinder;

public HasMapDiscoveryConvention(IConventionFinder conventionFinder)
{
this.conventionFinder = conventionFinder;
}

public bool Accept(IMappingPart target)
{
return (target is IMapCollectionPart);
}

public void Apply(IMappingPart target)
{
var conventions = conventionFinder.Find<IMapConvention>();
var join = (IMapCollectionPart)target;

foreach (var convention in conventions)
{
if (convention.Accept(join))
convention.Apply(join);
}
}
}
}
13 changes: 12 additions & 1 deletion src/FluentNHibernate/Conventions/ForeignKeyConvention.cs
Expand Up @@ -4,7 +4,7 @@

namespace FluentNHibernate.Conventions
{
public abstract class ForeignKeyConvention : IReferenceConvention, IHasManyConvention, IHasManyToManyConvention
public abstract class ForeignKeyConvention : IReferenceConvention, IHasManyConvention, IHasManyToManyConvention, IMapConvention
{
private bool acceptParent = true;
private bool acceptChild = true;
Expand Down Expand Up @@ -48,5 +48,16 @@ public void Apply(IManyToManyPart target)
if (acceptChild && target.ChildType != null)
target.WithChildKeyColumn(GetKeyName(null, target.ChildType));
}

public bool Accept(IMapCollectionPart target)
{
return target.KeyColumnNames.List().Count == 0;
}

public void Apply(IMapCollectionPart target)
{
target.KeyColumnNames.Clear();
target.KeyColumnNames.Add(GetKeyName(null, target.EntityType));
}
}
}
8 changes: 8 additions & 0 deletions src/FluentNHibernate/Conventions/IMapConvention.cs
@@ -0,0 +1,8 @@
using FluentNHibernate.Mapping;

namespace FluentNHibernate.Conventions
{
public interface IMapConvention : IConvention<IMapCollectionPart>
{
}
}
9 changes: 9 additions & 0 deletions src/FluentNHibernate/FluentNHibernate.csproj
Expand Up @@ -110,6 +110,9 @@
<Compile Include="Cfg\SetupConventionFinder.cs" />
<Compile Include="Conventions\ConventionsCollection.cs" />
<Compile Include="Conventions\Defaults\DefaultForeignKeyConvention.cs" />
<Compile Include="Conventions\Defaults\HasMapCollectionNameConvention.cs" />
<Compile Include="Conventions\Defaults\HasMapIndexNameConvention.cs" />
<Compile Include="Conventions\Defaults\HasMapTableNameConvention.cs" />
<Compile Include="Conventions\Discovery\BaseMappingPartDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\ClassDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\ClassMappingPartDiscoveryConvention.cs" />
Expand All @@ -120,6 +123,7 @@
<Compile Include="Conventions\Discovery\DynamicComponentMappingPartDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\HasManyDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\HasManyToManyDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\HasMapDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\HasOneDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\IdDiscoveryConvention.cs" />
<Compile Include="Conventions\Discovery\JoinDiscoveryConvention.cs" />
Expand Down Expand Up @@ -176,6 +180,7 @@
<Compile Include="Conventions\Helpers\Table.cs" />
<Compile Include="Conventions\Helpers\Builders\VersionConventionBuilder.cs" />
<Compile Include="Conventions\IJoinedSubclassConvention.cs" />
<Compile Include="Conventions\IMapConvention.cs" />
<Compile Include="Conventions\ISubclassConvention.cs" />
<Compile Include="Conventions\MultipleAttribute.cs" />
<Compile Include="Data\Entity.cs" />
Expand Down Expand Up @@ -269,12 +274,16 @@
<Compile Include="Mapping\IDiscriminatorPart.cs" />
<Compile Include="Mapping\IDynamicComponent.cs" />
<Compile Include="Mapping\IHasAttributes.cs" />
<Compile Include="Mapping\IIndexMapping.cs" />
<Compile Include="Mapping\IJoinedSubclass.cs" />
<Compile Include="Mapping\IMapCollectionPart.cs" />
<Compile Include="Mapping\IMappingPart.cs" />
<Compile Include="Mapping\IndexMappingBase.cs" />
<Compile Include="Mapping\INotFoundExpression.cs" />
<Compile Include="Mapping\InvalidPrefixException.cs" />
<Compile Include="Mapping\IRelationship.cs" />
<Compile Include="Mapping\ISubclass.cs" />
<Compile Include="Mapping\MapCollectionPart.cs" />
<Compile Include="Mapping\MappingPartComparer.cs" />
<Compile Include="Mapping\Prefix.cs" />
<Compile Include="Utils\XmlExtensions.cs" />
Expand Down
35 changes: 35 additions & 0 deletions src/FluentNHibernate/Mapping/ClasslikeMapBase.cs
Expand Up @@ -268,6 +268,36 @@ public ManyToManyPart<TChild> HasManyToMany<TChild>(Expression<Func<T, object>>
return MapHasManyToMany<TChild, object>(expression);
}

public MapCollectionPart<TIndex, TValue> HasMap<TIndex, TValue>(Expression<Func<T, IDictionary<TIndex, TValue>>> expression)
{
return MapHasMap<TIndex, TValue, IDictionary<TIndex, TValue>>(expression);
}

private MapCollectionPart<TIndex, TValue> MapHasMap<TIndex, TValue, TReturn>(Expression<Func<T, TReturn>> expression)
{
return ReflectionHelper.IsMethodExpression(expression)
? HasMap<TIndex, TValue>(ReflectionHelper.GetMethod(expression))
: HasMap<TIndex, TValue>(ReflectionHelper.GetProperty(expression));
}

public MapCollectionPart<TIndex, TValue> HasMap<TIndex, TValue>(MethodInfo method)
{
var part = new MapCollectionPart<TIndex, TValue>(EntityType, method);

AddPart(part);

return part;
}

public MapCollectionPart<TIndex, TValue> HasMap<TIndex, TValue>(PropertyInfo property)
{
var part = new MapCollectionPart<TIndex, TValue>(EntityType, property);

AddPart(part);

return part;
}

public VersionPart Version(Expression<Func<T, object>> expression)
{
return Version(ReflectionHelper.GetProperty(expression));
Expand Down Expand Up @@ -371,6 +401,11 @@ IProperty IClasslike.Map<TEntity>(Expression<Func<TEntity, object>> expression)
return HasManyToMany<TChild>(ReflectionHelper.GetProperty(expression));
}

IMapCollectionPart IClasslike.HasMap<TEntity, TIndex, TChild>(Expression<Func<TEntity, IDictionary<TIndex, TChild>>> expression)
{
return HasMap<TIndex, TChild>(ReflectionHelper.GetProperty(expression));
}

#endregion
}
}
2 changes: 2 additions & 0 deletions src/FluentNHibernate/Mapping/IClasslike.cs
Expand Up @@ -58,6 +58,8 @@ public interface IClasslike
/// <returns>many-to-many part</returns>
IManyToManyPart HasManyToMany<TEntity, TChild>(Expression<Func<TEntity, IEnumerable<TChild>>> expression);

IMapCollectionPart HasMap<TEntity, TIndex, TChild>(Expression<Func<TEntity, IDictionary<TIndex, TChild>>> expression);

IVersion Version<T>(Expression<Func<T, object>> expression);
}
}
16 changes: 16 additions & 0 deletions src/FluentNHibernate/Mapping/IIndexMapping.cs
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace FluentNHibernate.Mapping
{
public interface IIndexMapping
{
IIndexMapping WithColumn(string columnName);
IIndexMapping WithType<TIndex>();
IIndexMapping WithType(Type type);
void WriteIndexElement(XmlElement element);
}
}
21 changes: 21 additions & 0 deletions src/FluentNHibernate/Mapping/IMapCollectionPart.cs
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FluentNHibernate.Mapping
{
public interface IMapCollectionPart : IMappingPart
{
Type EntityType { get; }
Type IndexType { get; }
Type ValueType { get; }
string TableName { get; }
string IndexColumnName { get; }
string CollectionColumnName { get; }
IMapCollectionPart WithTableName(string name);
IMapCollectionPart WithIndexColumn(string name);
IMapCollectionPart WithCollectionColumn(string name);
IColumnNameCollection KeyColumnNames { get; }
}
}
59 changes: 59 additions & 0 deletions src/FluentNHibernate/Mapping/IndexMappingBase.cs
@@ -0,0 +1,59 @@
using System;
using System.Xml;
using FluentNHibernate.Utils;

namespace FluentNHibernate.Mapping
{
public class IndexMappingBase : IIndexMapping
{
protected Cache<string, string> properties = new Cache<string, string>();
protected string indexElementName;
protected string indexType;

public IndexMappingBase()
: this("type", "index")
{

}

public IndexMappingBase(string indexType, string indexElementName)
{
this.indexType = indexType;
this.indexElementName = indexElementName;
}

#region IIndexMapping Members

public IIndexMapping WithColumn(string columnName)
{
properties.Store("column", columnName);
return this;
}

public IIndexMapping WithType<TIndex>()
{
return WithType(typeof(TIndex));
}

public IIndexMapping WithType(Type type)
{
properties.Store(indexType, (indexType == "type") ? type.Name : type.AssemblyQualifiedName);
return this;
}

public void WriteIndexElement(XmlElement collectionElement)
{
var indexElement = collectionElement.AddElement(indexElementName);
indexElement.WithProperties(properties);
}

public static IIndexMapping GetIndexMappingTypeFor<TIndex>()
{
return (typeof(TIndex).IsPrimitive || typeof(TIndex) == typeof(string))
? new IndexMappingBase()
: new IndexMappingBase("class", "index-many-to-many");
}

#endregion
}
}

0 comments on commit 67d4a50

Please sign in to comment.