|
From: <fab...@us...> - 2008-09-29 22:46:41
|
Revision: 3807
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=3807&view=rev
Author: fabiomaulo
Date: 2008-09-29 22:46:17 +0000 (Mon, 29 Sep 2008)
Log Message:
-----------
Fix NH-1173 new feature Generic Ordered Set support (by Sean Carpenter)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Mapping/Set.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Type/GenericOrderedSetType.cs
trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/
trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/A.cs
trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/B.cs
trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.cs
trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.hbm.xml
Modified: trunk/nhibernate/src/NHibernate/Mapping/Set.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Mapping/Set.cs 2008-09-29 22:14:24 UTC (rev 3806)
+++ trunk/nhibernate/src/NHibernate/Mapping/Set.cs 2008-09-29 22:46:17 UTC (rev 3807)
@@ -34,8 +34,7 @@
}
else if (HasOrder)
{
- throw new MappingException(
- "Cannot use order-by with generic set, no appropriate collection implementation is available");
+ return TypeFactory.GenericOrderedSet(Role, ReferencedPropertyName, this.GenericArguments[0]);
}
else
{
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2008-09-29 22:14:24 UTC (rev 3806)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2008-09-29 22:46:17 UTC (rev 3807)
@@ -1062,6 +1062,7 @@
<Compile Include="Type\CollectionType.cs" />
<Compile Include="Type\CustomCollectionType.cs" />
<Compile Include="Type\EmbeddedComponentType.cs" />
+ <Compile Include="Type\GenericOrderedSetType.cs" />
<Compile Include="Type\ICacheAssembler.cs" />
<Compile Include="Type\OrderedSetType.cs" />
<Compile Include="Type\OrderedMapType.cs" />
Added: trunk/nhibernate/src/NHibernate/Type/GenericOrderedSetType.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Type/GenericOrderedSetType.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Type/GenericOrderedSetType.cs 2008-09-29 22:46:17 UTC (rev 3807)
@@ -0,0 +1,31 @@
+using System;
+using Iesi.Collections.Generic;
+
+namespace NHibernate.Type
+{
+ /// <summary>
+ /// An <see cref="IType"/> that maps a sorted <see cref="ISet{T}"/> collection
+ /// to the database.
+ /// </summary>
+ [Serializable]
+ public class GenericOrderedSetType<T> : GenericSetType<T>
+ {
+ /// <summary>
+ /// Initializes a new instance of a <see cref="GenericOrderedSetType{T}"/> class for
+ /// a specific role.
+ /// </summary>
+ /// <param name="role">The role the persistent collection is in.</param>
+ /// <param name="propertyRef">The name of the property in the
+ /// owner object containing the collection ID, or <see langword="null" /> if it is
+ /// the primary key.</param>
+ public GenericOrderedSetType(string role, string propertyRef)
+ : base(role, propertyRef)
+ {
+ }
+
+ public override object Instantiate(int anticipatedSize)
+ {
+ return new OrderedSet<T>();
+ }
+ }
+}
Modified: trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2008-09-29 22:14:24 UTC (rev 3806)
+++ trunk/nhibernate/src/NHibernate/Type/TypeFactory.cs 2008-09-29 22:46:17 UTC (rev 3807)
@@ -33,8 +33,8 @@
PrecisionScale
}
- private static readonly char[] precisionScaleSplit = new char[] {'(', ')', ','};
- private static readonly char[] lengthSplit = new char[] {'(', ')'};
+ private static readonly char[] precisionScaleSplit = new char[] { '(', ')', ',' };
+ private static readonly char[] lengthSplit = new char[] { '(', ')' };
/*
* Maps the string representation of the type to the IType. The string
@@ -59,7 +59,7 @@
private static readonly IDictionary<string, IType> typeByTypeOfName =
new ThreadSafeDictionary<string, IType>(new Dictionary<string, IType>());
- private static readonly IDictionary<string, GetNullableTypeWithLength> getTypeDelegatesWithLength =
+ private static readonly IDictionary<string, GetNullableTypeWithLength> getTypeDelegatesWithLength =
new ThreadSafeDictionary<string, GetNullableTypeWithLength>(new Dictionary<string, GetNullableTypeWithLength>());
private static readonly IDictionary<string, GetNullableTypeWithPrecision> getTypeDelegatesWithPrecision =
@@ -241,7 +241,7 @@
// Use the basic name (such as String or String(255)) to get the
// instance of the IType object.
IType returnType;
- if (typeByTypeOfName.TryGetValue(name,out returnType))
+ if (typeByTypeOfName.TryGetValue(name, out returnType))
{
return returnType;
}
@@ -259,7 +259,7 @@
if (parsedName.Length < 4)
{
throw new ArgumentOutOfRangeException("TypeClassification.PrecisionScale", name,
- "It is not a valid Precision/Scale name");
+ "It is not a valid Precision/Scale name");
}
typeName = parsedName[0].Trim();
@@ -372,8 +372,8 @@
{
parsedTypeName = typeName.Split(lengthSplit);
}
- else
- parsedTypeName = typeClassification == TypeClassification.PrecisionScale ? typeName.Split(precisionScaleSplit) : new string[] {typeName};
+ else
+ parsedTypeName = typeClassification == TypeClassification.PrecisionScale ? typeName.Split(precisionScaleSplit) : new string[] { typeName };
System.Type typeClass;
@@ -392,7 +392,7 @@
{
try
{
- type = (IType) Activator.CreateInstance(typeClass);
+ type = (IType)Activator.CreateInstance(typeClass);
}
catch (Exception e)
{
@@ -439,11 +439,11 @@
private static Boolean IsNullableEnum(System.Type typeClass)
{
if (!typeClass.IsGenericType) return false;
- System.Type nullable = typeof (Nullable<>);
+ System.Type nullable = typeof(Nullable<>);
if (!nullable.Equals(typeClass.GetGenericTypeDefinition())) return false;
System.Type genericClass = typeClass.GetGenericArguments()[0];
- return genericClass.IsSubclassOf(typeof (Enum));
+ return genericClass.IsSubclassOf(typeof(Enum));
}
@@ -604,12 +604,12 @@
/// <summary>
/// A one-to-one association type for the given class and cascade style.
/// </summary>
- public static EntityType OneToOne(string persistentClass, ForeignKeyDirection foreignKeyType, string uniqueKeyPropertyName,
+ public static EntityType OneToOne(string persistentClass, ForeignKeyDirection foreignKeyType, string uniqueKeyPropertyName,
bool lazy, bool unwrapProxy, bool isEmbeddedInXML, string entityName, string propertyName)
{
return
new OneToOneType(persistentClass, foreignKeyType, uniqueKeyPropertyName, lazy, unwrapProxy, isEmbeddedInXML,
- entityName, propertyName);
+ entityName, propertyName);
}
/// <summary>
@@ -633,7 +633,7 @@
/// <summary>
/// A many-to-one association type for the given class and cascade style.
/// </summary>
- public static EntityType ManyToOne(string persistentClass, string uniqueKeyPropertyName, bool lazy, bool unwrapProxy,
+ public static EntityType ManyToOne(string persistentClass, string uniqueKeyPropertyName, bool lazy, bool unwrapProxy,
bool isEmbeddedInXML, bool ignoreNotFound)
{
return new ManyToOneType(persistentClass, uniqueKeyPropertyName, lazy, unwrapProxy, isEmbeddedInXML, ignoreNotFound);
@@ -796,15 +796,17 @@
return new OrderedSetType(role, propertyRef, embedded);
}
+
+
private static CollectionType CreateCollectionType(
System.Type genericCollectionType,
string role,
string propertyRef,
params System.Type[] typeArguments)
{
- return (CollectionType) Activator.CreateInstance(
- genericCollectionType.MakeGenericType(typeArguments),
- role, propertyRef);
+ return (CollectionType)Activator.CreateInstance(
+ genericCollectionType.MakeGenericType(typeArguments),
+ role, propertyRef);
}
private static CollectionType CreateSortedCollectionType(
@@ -814,11 +816,20 @@
object comparer,
params System.Type[] typeArguments)
{
- return (CollectionType) Activator.CreateInstance(
- genericCollectionType.MakeGenericType(typeArguments),
- role, propertyRef, comparer);
+ return (CollectionType)Activator.CreateInstance(
+ genericCollectionType.MakeGenericType(typeArguments),
+ role, propertyRef, comparer);
}
+ private static CollectionType CreateOrderedCollectionType(System.Type genericCollectionType,
+ string role,
+ string propertyRef,
+ params System.Type[] typeArguments)
+ {
+ return
+ (CollectionType)Activator.CreateInstance(genericCollectionType.MakeGenericType(typeArguments), role, propertyRef);
+ }
+
/// <summary>
/// Creates a new <see cref="CollectionType"/> for an
/// <see cref="System.Collections.Generic.IList{T}"/> with bag semantics.
@@ -901,24 +912,24 @@
/// A <see cref="MapType"/> for the specified role.
/// </returns>
public static CollectionType GenericMap(string role, string propertyRef, System.Type indexClass,
- System.Type elementClass)
+ System.Type elementClass)
{
return CreateCollectionType(typeof(GenericMapType<,>), role, propertyRef, indexClass, elementClass);
}
public static CollectionType GenericSortedList(string role, string propertyRef, object comparer,
- System.Type indexClass, System.Type elementClass)
+ System.Type indexClass, System.Type elementClass)
{
return
CreateSortedCollectionType(typeof(GenericSortedListType<,>), role, propertyRef, comparer, indexClass, elementClass);
}
public static CollectionType GenericSortedDictionary(string role, string propertyRef, object comparer,
- System.Type indexClass, System.Type elementClass)
+ System.Type indexClass, System.Type elementClass)
{
return
CreateSortedCollectionType(typeof(GenericSortedDictionaryType<,>), role, propertyRef, comparer, indexClass,
- elementClass);
+ elementClass);
}
/// <summary>
@@ -946,11 +957,26 @@
/// <param name="elementType">The type of the elements in the set.</param>
/// <returns>A <see cref="GenericSetType{T}" /> for the specified role.</returns>
public static CollectionType GenericSortedSet(string role, string propertyRef, object comparer,
- System.Type elementType)
+ System.Type elementType)
{
return CreateSortedCollectionType(typeof(GenericSortedSetType<>), role, propertyRef, comparer, elementType);
}
+ /// <summary>
+ /// Creates a new <see cref="CollectionType"/> for an ordered <see cref="Iesi.Collections.Generic.ISet{T}" />.
+ /// </summary>
+ /// <param name="role">The role the collection is in.</param>
+ /// <param name="propertyRef">The name of the property in the
+ /// owner object containing the collection ID, or <see langword="null" /> if it is
+ /// the primary key.</param>
+ /// <param name="elementType">The type of the elements in the set.</param>
+ /// <returns>A <see cref="GenericSetType{T}" /> for the specified role.</returns>
+ public static CollectionType GenericOrderedSet(string role, string propertyRef,
+ System.Type elementType)
+ {
+ return CreateOrderedCollectionType(typeof(GenericOrderedSetType<>), role, propertyRef, elementType);
+ }
+
/// <summary> Deep copy a series of values from one array to another... </summary>
/// <param name="values">The values to copy (the source) </param>
/// <param name="types">The value types </param>
@@ -1137,7 +1163,7 @@
/// <param name="copiedAlready">Represent a cache of already replaced state </param>
/// <returns> The replaced state </returns>
public static object[] Replace(object[] original, object[] target, IType[] types, ISessionImplementor session,
- object owner, IDictionary copiedAlready)
+ object owner, IDictionary copiedAlready)
{
object[] copied = new object[original.Length];
for (int i = 0; i < original.Length; i++)
@@ -1159,7 +1185,7 @@
/// <param name="copyCache">A map representing a cache of already replaced state </param>
/// <param name="foreignKeyDirection">FK directionality to be applied to the replacement </param>
/// <returns> The replaced state </returns>
- public static object[] Replace(object[] original, object[] target, IType[] types,
+ public static object[] Replace(object[] original, object[] target, IType[] types,
ISessionImplementor session, object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
{
object[] copied = new object[original.Length];
@@ -1192,7 +1218,7 @@
/// If the corresponding type is a component type, then apply <see cref="ReplaceAssociations"/>
/// across the component subtypes but do not replace the component value itself.
/// </remarks>
- public static object[] ReplaceAssociations(object[] original, object[] target, IType[] types,
+ public static object[] ReplaceAssociations(object[] original, object[] target, IType[] types,
ISessionImplementor session, object owner, IDictionary copyCache, ForeignKeyDirection foreignKeyDirection)
{
object[] copied = new object[original.Length];
@@ -1205,14 +1231,14 @@
else if (types[i].IsComponentType)
{
// need to extract the component values and check for subtype replacements...
- IAbstractComponentType componentType = (IAbstractComponentType) types[i];
+ IAbstractComponentType componentType = (IAbstractComponentType)types[i];
IType[] subtypes = componentType.Subtypes;
object[] origComponentValues = original[i] == null
- ? new object[subtypes.Length]
- : componentType.GetPropertyValues(original[i], session);
+ ? new object[subtypes.Length]
+ : componentType.GetPropertyValues(original[i], session);
object[] targetComponentValues = componentType.GetPropertyValues(target[i], session);
ReplaceAssociations(origComponentValues, targetComponentValues, subtypes, session, null, copyCache,
- foreignKeyDirection);
+ foreignKeyDirection);
copied[i] = target[i];
}
else if (!types[i].IsAssociationType)
@@ -1242,7 +1268,7 @@
CustomCollectionType result = new CustomCollectionType(typeClass, role, propertyRef, embedded);
if (typeParameters != null)
{
- InjectParameters(result.UserType, (IDictionary) typeParameters);
+ InjectParameters(result.UserType, (IDictionary)typeParameters);
}
return result;
}
@@ -1251,7 +1277,7 @@
{
if (type is IParameterizedType)
{
- ((IParameterizedType) type).SetParameterValues(parameters);
+ ((IParameterizedType)type).SetParameterValues(parameters);
}
else if (parameters != null && !(parameters.Count == 0))
{
Added: trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/A.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/A.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/A.cs 2008-09-29 22:46:17 UTC (rev 3807)
@@ -0,0 +1,19 @@
+using Iesi.Collections.Generic;
+
+namespace NHibernate.Test.GenericTest.OrderedSetGeneric
+{
+ public class A
+ {
+ private ISet<B> _items = new OrderedSet<B>();
+
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+
+ public virtual ISet<B> Items
+ {
+ get { return _items; }
+ set { _items = value; }
+ }
+ }
+}
Added: trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/B.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/B.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/B.cs 2008-09-29 22:46:17 UTC (rev 3807)
@@ -0,0 +1,13 @@
+namespace NHibernate.Test.GenericTest.OrderedSetGeneric
+{
+ public class B
+ {
+ public virtual int Id { get; set; }
+
+ public virtual int OrderBy { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual int AId { get; set; }
+ }
+}
Property changes on: trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/B.cs
___________________________________________________________________
Added: svn:mergeinfo
+
Added: trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.cs 2008-09-29 22:46:17 UTC (rev 3807)
@@ -0,0 +1,64 @@
+using System.Collections;
+using NUnit.Framework;
+
+namespace NHibernate.Test.GenericTest.OrderedSetGeneric
+{
+ [TestFixture]
+ public class OrderedSetFixture : TestCase
+ {
+ protected override IList Mappings
+ {
+ get { return new[] {"GenericTest.OrderedSetGeneric.OrderedSetFixture.hbm.xml"}; }
+ }
+
+ protected override string MappingsAssembly
+ {
+ get { return "NHibernate.Test"; }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (ISession s = OpenSession())
+ {
+ using (ITransaction tx = s.BeginTransaction())
+ {
+ s.Delete("from B");
+ s.Delete("from A");
+ tx.Commit();
+ }
+ }
+ }
+
+ [Test]
+ public void OrderedSetIsInOrder()
+ {
+ var names = new[] {"First B", "Second B"};
+ const int TheId = 100;
+
+ var a = new A {Name = "First", Id = TheId};
+
+ var b = new B {Name = names[1], OrderBy = 3, AId = TheId};
+ a.Items.Add(b);
+
+ var b2 = new B {Name = names[0], OrderBy = 1, AId = TheId};
+ a.Items.Add(b2);
+
+ ISession s = OpenSession();
+ s.Save(a);
+ s.Flush();
+ s.Close();
+
+ s = OpenSession();
+ var newA = s.Get<A>(a.Id);
+
+ Assert.AreEqual(2, newA.Items.Count);
+ int counter = 0;
+ foreach (B item in newA.Items)
+ {
+ Assert.AreEqual(names[counter], item.Name);
+ counter++;
+ }
+ s.Close();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/GenericTest/OrderedSetGeneric/OrderedSetFixture.hbm.xml 2008-09-29 22:46:17 UTC (rev 3807)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
+ assembly="NHibernate.Test"
+ namespace="NHibernate.Test.GenericTest.OrderedSetGeneric">
+
+ <class name="A" table="a" lazy="false">
+ <id name="Id" column="id">
+ <generator class="assigned" />
+ </id>
+ <property name="Name" column="aname" />
+ <set name="Items" cascade="save-update" order-by="OrderBy ASC">
+ <key column="aid"/>
+ <one-to-many class="B"/>
+ </set>
+ </class>
+
+ <class name="B" table="b">
+ <id name="Id" column="id">
+ <generator class="native" />
+ </id>
+ <property name="AId" column="aid" />
+ <property name="OrderBy" column="orderby" />
+ <property name="Name" column="aname" />
+ </class>
+</hibernate-mapping>
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2008-09-29 22:14:24 UTC (rev 3806)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2008-09-29 22:46:17 UTC (rev 3807)
@@ -257,6 +257,9 @@
<Compile Include="GenericTest\MapGeneric\B.cs" />
<Compile Include="GenericTest\MapGeneric\MapGenericFixture.cs" />
<Compile Include="GenericTest\Methods\Fixture.cs" />
+ <Compile Include="GenericTest\OrderedSetGeneric\A.cs" />
+ <Compile Include="GenericTest\OrderedSetGeneric\B.cs" />
+ <Compile Include="GenericTest\OrderedSetGeneric\OrderedSetFixture.cs" />
<Compile Include="GenericTest\Overall\A.cs" />
<Compile Include="GenericTest\Overall\Fixture.cs" />
<Compile Include="GenericTest\SetGeneric\A.cs" />
@@ -1478,6 +1481,7 @@
<EmbeddedResource Include="Cascade\JobBatch.hbm.xml" />
<EmbeddedResource Include="Deletetransient\Person.hbm.xml" />
<Content Include="DynamicEntity\package.html" />
+ <EmbeddedResource Include="GenericTest\OrderedSetGeneric\OrderedSetFixture.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH1293\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH1490\Mappings.hbm.xml" />
<EmbeddedResource Include="NHSpecificTest\NH1492\Mappings.hbm.xml" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|