PageRenderTime 39ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/FluentNHibernate/Mapping/AnyPart.cs

http://github.com/jagregory/fluent-nhibernate
C# | 231 lines | 175 code | 34 blank | 22 comment | 11 complexity | e117dd916cf94397247fb70fe171f276 MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-SA-3.0, Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using FluentNHibernate.Mapping.Providers;
  7. using FluentNHibernate.MappingModel;
  8. using FluentNHibernate.Utils;
  9. namespace FluentNHibernate.Mapping
  10. {
  11. /// <summary>
  12. /// Represents the "Any" mapping in NHibernate. It is impossible to specify a foreign key constraint for this kind of association. For more information
  13. /// please reference chapter 5.2.4 in the NHibernate online documentation
  14. /// </summary>
  15. public class AnyPart<T> : IAnyMappingProvider
  16. {
  17. private readonly AttributeStore attributes = new AttributeStore();
  18. private readonly Type entity;
  19. private readonly Member member;
  20. private readonly AccessStrategyBuilder<AnyPart<T>> access;
  21. private readonly CascadeExpression<AnyPart<T>> cascade;
  22. private readonly IList<string> typeColumns = new List<string>();
  23. private readonly IList<string> identifierColumns = new List<string>();
  24. private readonly IList<MetaValueMapping> metaValues = new List<MetaValueMapping>();
  25. private bool nextBool = true;
  26. bool idTypeSet;
  27. public AnyPart(Type entity, Member member)
  28. {
  29. this.entity = entity;
  30. this.member = member;
  31. access = new AccessStrategyBuilder<AnyPart<T>>(this, value => attributes.Set("Access", Layer.UserSupplied, value));
  32. cascade = new CascadeExpression<AnyPart<T>>(this, value => attributes.Set("Cascade", Layer.UserSupplied, value));
  33. SetDefaultAccess();
  34. }
  35. void SetDefaultAccess()
  36. {
  37. var resolvedAccess = MemberAccessResolver.Resolve(member);
  38. if (resolvedAccess == Mapping.Access.Property || resolvedAccess == Mapping.Access.Unset)
  39. return; // property is the default so we don't need to specify it
  40. attributes.Set("Access", Layer.Defaults, resolvedAccess.ToString());
  41. }
  42. /// <summary>
  43. /// Defines how NHibernate will access the object for persisting/hydrating (Defaults to Property)
  44. /// </summary>
  45. public AccessStrategyBuilder<AnyPart<T>> Access
  46. {
  47. get { return access; }
  48. }
  49. /// <summary>
  50. /// Cascade style (Defaults to none)
  51. /// </summary>
  52. public CascadeExpression<AnyPart<T>> Cascade
  53. {
  54. get { return cascade; }
  55. }
  56. public AnyPart<T> IdentityType(Expression<Func<T, object>> expression)
  57. {
  58. return IdentityType(expression.ToMember().PropertyType);
  59. }
  60. public AnyPart<T> IdentityType<TIdentity>()
  61. {
  62. return IdentityType(typeof(TIdentity));
  63. }
  64. public AnyPart<T> IdentityType(Type type)
  65. {
  66. attributes.Set("IdType", Layer.UserSupplied, type.AssemblyQualifiedName);
  67. idTypeSet = true;
  68. return this;
  69. }
  70. public AnyPart<T> EntityTypeColumn(string columnName)
  71. {
  72. typeColumns.Add(columnName);
  73. return this;
  74. }
  75. public AnyPart<T> EntityIdentifierColumn(string columnName)
  76. {
  77. identifierColumns.Add(columnName);
  78. return this;
  79. }
  80. public AnyPart<T> AddMetaValue<TModel>(string valueMap)
  81. {
  82. return AddMetaValue(typeof(TModel), valueMap);
  83. }
  84. public AnyPart<T> AddMetaValue(Type @class, string valueMap)
  85. {
  86. var metaValueMapping = new MetaValueMapping
  87. {
  88. ContainingEntityType = entity
  89. };
  90. metaValueMapping.Set(x => x.Class, Layer.Defaults, new TypeReference(@class));
  91. metaValueMapping.Set(x => x.Value, Layer.Defaults, valueMap);
  92. metaValues.Add(metaValueMapping);
  93. return this;
  94. }
  95. public AnyPart<T> Insert()
  96. {
  97. attributes.Set("Insert", Layer.UserSupplied, nextBool);
  98. nextBool = true;
  99. return this;
  100. }
  101. public AnyPart<T> Update()
  102. {
  103. attributes.Set("Update", Layer.UserSupplied, nextBool);
  104. nextBool = true;
  105. return this;
  106. }
  107. public AnyPart<T> ReadOnly()
  108. {
  109. attributes.Set("Insert", Layer.UserSupplied, !nextBool);
  110. attributes.Set("Update", Layer.UserSupplied, !nextBool);
  111. nextBool = true;
  112. return this;
  113. }
  114. public AnyPart<T> LazyLoad()
  115. {
  116. attributes.Set("Lazy", Layer.UserSupplied, nextBool);
  117. nextBool = true;
  118. return this;
  119. }
  120. public AnyPart<T> OptimisticLock()
  121. {
  122. attributes.Set("OptimisticLock", Layer.UserSupplied, nextBool);
  123. nextBool = true;
  124. return this;
  125. }
  126. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  127. public AnyPart<T> Not
  128. {
  129. get
  130. {
  131. nextBool = !nextBool;
  132. return this;
  133. }
  134. }
  135. AnyMapping IAnyMappingProvider.GetAnyMapping()
  136. {
  137. var mapping = new AnyMapping(attributes.Clone());
  138. if (typeColumns.Count() == 0)
  139. throw new InvalidOperationException("<any> mapping is not valid without specifying an Entity Type Column");
  140. if (identifierColumns.Count() == 0)
  141. throw new InvalidOperationException("<any> mapping is not valid without specifying an Entity Identifier Column");
  142. if (!idTypeSet)
  143. throw new InvalidOperationException("<any> mapping is not valid without specifying an IdType");
  144. mapping.ContainingEntityType = entity;
  145. mapping.Set(x => x.Name, Layer.Defaults, member.Name);
  146. if (!mapping.IsSpecified("MetaType"))
  147. {
  148. mapping.Set(x => x.MetaType, Layer.Defaults, new TypeReference(member.PropertyType));
  149. }
  150. if (metaValues.Count() > 0)
  151. {
  152. metaValues.Each(mapping.AddMetaValue);
  153. mapping.Set(x => x.MetaType, Layer.Defaults, new TypeReference(typeof(string)));
  154. }
  155. foreach (var column in typeColumns)
  156. {
  157. var columnMapping = new ColumnMapping();
  158. columnMapping.Set(x => x.Name, Layer.Defaults, column);
  159. mapping.AddTypeColumn(Layer.UserSupplied, columnMapping);
  160. }
  161. foreach (var column in identifierColumns)
  162. {
  163. var columnMapping = new ColumnMapping();
  164. columnMapping.Set(x => x.Name, Layer.Defaults, column);
  165. mapping.AddIdentifierColumn(Layer.UserSupplied, columnMapping);
  166. }
  167. return mapping;
  168. }
  169. /// <summary>
  170. /// Sets the meta-type value for this any mapping.
  171. /// </summary>
  172. /// <typeparam name="TMetaType">Meta type</typeparam>
  173. public AnyPart<T> MetaType<TMetaType>()
  174. {
  175. attributes.Set("MetaType", Layer.UserSupplied, new TypeReference(typeof(TMetaType)));
  176. return this;
  177. }
  178. /// <summary>
  179. /// Sets the meta-type value for this any mapping.
  180. /// </summary>
  181. /// <param name="metaType">Meta type</param>
  182. public AnyPart<T> MetaType(string metaType)
  183. {
  184. attributes.Set("MetaType", Layer.UserSupplied, new TypeReference(metaType));
  185. return this;
  186. }
  187. /// <summary>
  188. /// Sets the meta-type value for this any mapping.
  189. /// </summary>
  190. /// <param name="metaType">Meta type</param>
  191. public AnyPart<T> MetaType(Type metaType)
  192. {
  193. attributes.Set("MetaType", Layer.UserSupplied, new TypeReference(metaType));
  194. return this;
  195. }
  196. }
  197. }