PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/sandbox/simondud/Envers.NET.Spring/Envers.NET.SLN/Envers.NET/Envers/Configuration/RevisionInfoConfiguration.cs

https://bitbucket.org/dabide/nhcontrib
C# | 240 lines | 185 code | 41 blank | 14 comment | 31 complexity | a2c71649bbbce6b40a219d7a5b491836 MD5 | raw file
Possible License(s): BSD-3-Clause, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Apache-2.0, LGPL-3.0, LGPL-2.1
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using NHibernate;
  6. using NHibernate.Envers.Entities;
  7. using NHibernate.Envers.Configuration.Metadata;
  8. using System.Xml;
  9. using System.Reflection;
  10. using NHibernate.Mapping;
  11. using NHibernate.Envers.RevisionInfo;
  12. using NHibernate.Type;
  13. using NHibernate.SqlTypes;
  14. using NHibernate.Envers.Compatibility;
  15. namespace NHibernate.Envers.Configuration
  16. {
  17. /**
  18. * @author Simon Duduica, port of Envers omonyme class by Adam Warski (adam at warski dot org)
  19. */
  20. public class RevisionInfoConfiguration {
  21. private String revisionInfoEntityName;
  22. private PropertyData revisionInfoIdData;
  23. private PropertyData revisionInfoTimestampData;
  24. private IType revisionInfoTimestampType;
  25. private String revisionPropType;
  26. private String revisionPropSqlType;
  27. public RevisionInfoConfiguration() {
  28. revisionInfoEntityName = "NHibernate.Envers.DefaultRevisionEntity, Envers.NET";
  29. revisionInfoIdData = new PropertyData("id", "id", "field", ModificationStore._NULL);
  30. revisionInfoTimestampData = new PropertyData("RevisionDate", "RevisionDate", "field", ModificationStore._NULL);
  31. revisionInfoTimestampType = new DateTimeType(); //ORIG: LongType();
  32. revisionPropType = "integer";
  33. }
  34. private XmlDocument generateDefaultRevisionInfoXmlMapping() {
  35. XmlDocument document = new XmlDocument();//ORIG: DocumentHelper.createDocument();
  36. XmlElement class_mapping = MetadataTools.CreateEntity(document, new AuditTableData(null, null, null, null), null);
  37. class_mapping.SetAttribute("name", revisionInfoEntityName);
  38. class_mapping.SetAttribute("table", "REVINFO");
  39. XmlElement idProperty = MetadataTools.AddNativelyGeneratedId(document,class_mapping, revisionInfoIdData.Name,
  40. revisionPropType);
  41. //ORIG: MetadataTools.addColumn(idProperty, "REV", -1, 0, 0, null);
  42. XmlElement col = idProperty.OwnerDocument.CreateElement("column");
  43. col.SetAttribute("name", "REV");
  44. //idProperty should have a "generator" node otherwise sth. is wrong.
  45. idProperty.InsertBefore(col, idProperty.GetElementsByTagName("generator")[0]);
  46. XmlElement timestampProperty = MetadataTools.AddProperty(class_mapping, revisionInfoTimestampData.Name,
  47. revisionInfoTimestampType.Name, true, false);
  48. MetadataTools.AddColumn(timestampProperty, "REVTSTMP", -1, 0, 0, SqlTypeFactory.DateTime.ToString());
  49. return document;
  50. }
  51. private XmlElement generateRevisionInfoRelationMapping() {
  52. XmlDocument document = new XmlDocument();
  53. XmlElement rev_rel_mapping = document.CreateElement("key-many-to-one");
  54. rev_rel_mapping.SetAttribute("type", revisionPropType);
  55. rev_rel_mapping.SetAttribute("class", revisionInfoEntityName);
  56. if (revisionPropSqlType != null) {
  57. // Putting a fake name to make Hibernate happy. It will be replaced later anyway.
  58. MetadataTools.AddColumn(rev_rel_mapping, "*" , -1, 0, 0, revisionPropSqlType);
  59. }
  60. return rev_rel_mapping;
  61. }
  62. private void searchForRevisionInfoCfgInProperties(System.Type t, ref bool revisionNumberFound,
  63. ref bool revisionTimestampFound, String accessType) {
  64. foreach (PropertyInfo property in t.GetProperties()) {
  65. //RevisionNumber revisionNumber = property.getAnnotation(RevisionNumber.class);
  66. RevisionNumberAttribute revisionNumber = (RevisionNumberAttribute)Attribute.GetCustomAttribute(property, typeof(RevisionNumberAttribute));
  67. RevisionTimestampAttribute revisionTimestamp = (RevisionTimestampAttribute)Attribute.GetCustomAttribute(property, typeof(RevisionTimestampAttribute));
  68. if (revisionNumber != null) {
  69. if (revisionNumberFound) {
  70. throw new MappingException("Only one property may have the attribute [RevisionNumber]!");
  71. }
  72. System.Type revNrType = property.PropertyType;
  73. if (revNrType.Equals( typeof(int)) || revNrType.Equals( typeof(Int16)) || revNrType.Equals( typeof(Int32)) || revNrType.Equals( typeof(Int64))) {
  74. revisionInfoIdData = new PropertyData(property.Name, property.Name, accessType, ModificationStore._NULL);
  75. revisionNumberFound = true;
  76. } else if (revNrType.Equals(typeof(long))) {
  77. revisionInfoIdData = new PropertyData(property.Name, property.Name, accessType, ModificationStore._NULL);
  78. revisionNumberFound = true;
  79. // The default is integer
  80. revisionPropType = "long";
  81. } else {
  82. throw new MappingException("The field decorated with [RevisionNumberAttribute] must be of type " +
  83. "int, Int16, Int32, Int64 or long");
  84. }
  85. // Getting the @Column definition of the revision number property, to later use that info to
  86. // generate the same mapping for the relation from an audit table's revision number to the
  87. // revision entity revision number.
  88. ColumnAttribute revisionPropColumn = (ColumnAttribute)Attribute.GetCustomAttribute(property,typeof(ColumnAttribute));
  89. if (revisionPropColumn != null) {
  90. revisionPropSqlType = revisionPropColumn.columnDefinition;
  91. }
  92. }
  93. if (revisionTimestamp != null) {
  94. if (revisionTimestampFound) {
  95. throw new MappingException("Only one property may be decorated with [RevisionTimestampAttribute]!");
  96. }
  97. System.Type revisionTimestampType = property.GetType();
  98. if (typeof(DateTime).Equals(revisionTimestampType)) {
  99. revisionInfoTimestampData = new PropertyData(property.Name, property.Name, accessType, ModificationStore._NULL);
  100. revisionTimestampFound = true;
  101. } else {
  102. throw new MappingException("The field decorated with @RevisionTimestamp must be of type DateTime");
  103. }
  104. }
  105. }
  106. }
  107. private void searchForRevisionInfoCfg(System.Type t, ref bool revisionNumberFound, ref bool revisionTimestampFound) {
  108. System.Type superT = t.BaseType;
  109. if (!typeof(System.Object).Equals(t)) {
  110. searchForRevisionInfoCfg(superT, ref revisionNumberFound, ref revisionTimestampFound);
  111. }
  112. searchForRevisionInfoCfgInProperties(t, ref revisionNumberFound, ref revisionTimestampFound,
  113. "field");
  114. searchForRevisionInfoCfgInProperties(t, ref revisionNumberFound, ref revisionTimestampFound,
  115. "property");
  116. }
  117. //@SuppressWarnings({"unchecked"})
  118. public RevisionInfoConfigurationResult configure(NHibernate.Cfg.Configuration cfg) {
  119. ICollection<PersistentClass> classes = cfg.ClassMappings;
  120. bool revisionEntityFound = false;
  121. IRevisionInfoGenerator revisionInfoGenerator = null;
  122. System.Type revisionInfoClass = null;
  123. foreach (PersistentClass pc in classes) {
  124. System.Type clazz;
  125. try {
  126. clazz = System.Type.GetType(pc.ClassName, true);
  127. } catch (System.Exception e) {
  128. throw new MappingException(e);
  129. }
  130. RevisionEntityAttribute revisionEntity = (RevisionEntityAttribute)Attribute.GetCustomAttribute( clazz, typeof(RevisionEntityAttribute));
  131. if (revisionEntity != null) {
  132. if (revisionEntityFound) {
  133. throw new MappingException("Only one entity may be decorated with [RevisionEntity]!");
  134. }
  135. // Checking if custom revision entity isn't audited
  136. if (Attribute.GetCustomAttribute( clazz, typeof(AuditedAttribute)) != null) {
  137. throw new MappingException("An entity decorated with [RevisionEntity] cannot be audited!");
  138. }
  139. revisionEntityFound = true;
  140. bool revisionNumberFound = false;
  141. bool revisionTimestampFound = false;
  142. searchForRevisionInfoCfg(clazz, ref revisionNumberFound, ref revisionTimestampFound);
  143. if (!revisionNumberFound) {
  144. throw new MappingException("An entity decorated with [RevisionEntity] must have a field decorated " +
  145. "with [RevisionNumber]!");
  146. }
  147. if (!revisionTimestampFound) {
  148. throw new MappingException("An entity decorated with [RevisionEntity] must have a field decorated " +
  149. "with [RevisionTimestamp]!");
  150. }
  151. revisionInfoEntityName = pc.EntityName;
  152. revisionInfoClass = pc.MappedClass;
  153. revisionInfoTimestampType = pc.GetProperty(revisionInfoTimestampData.Name).Type;
  154. revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
  155. /*revisionEntity.value, */revisionInfoTimestampData/*, isTimestampAsDate()*/);
  156. }
  157. }
  158. // In case of a custom revision info generator, the mapping will be null.
  159. XmlDocument revisionInfoXmlMapping = null;
  160. if (revisionInfoGenerator == null) {
  161. revisionInfoClass = typeof(DefaultRevisionEntity);
  162. revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
  163. revisionInfoTimestampData);
  164. revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
  165. }
  166. return new RevisionInfoConfigurationResult(
  167. revisionInfoGenerator, revisionInfoXmlMapping,
  168. new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.Name,
  169. revisionInfoTimestampData.Name),
  170. generateRevisionInfoRelationMapping(),
  171. new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName);
  172. }
  173. private bool isTimestampAsDate() {
  174. String typename = revisionInfoTimestampType.Name;
  175. return "date".Equals(typename) || "time".Equals(typename) || "RevisionDate".Equals(typename);
  176. }
  177. }
  178. public class RevisionInfoConfigurationResult {
  179. public IRevisionInfoGenerator RevisionInfoGenerator { get; private set; }
  180. public XmlDocument RevisionInfoXmlMapping { get; private set; }
  181. public RevisionInfoQueryCreator RevisionInfoQueryCreator { get; private set; }
  182. public XmlElement RevisionInfoRelationMapping { get; private set; }
  183. public RevisionInfoNumberReader RevisionInfoNumberReader { get; private set; }
  184. public String RevisionInfoEntityName { get; private set; }
  185. public RevisionInfoConfigurationResult(IRevisionInfoGenerator revisionInfoGenerator,
  186. XmlDocument revisionInfoXmlMapping,
  187. RevisionInfoQueryCreator revisionInfoQueryCreator,
  188. XmlElement revisionInfoRelationMapping,
  189. RevisionInfoNumberReader revisionInfoNumberReader,
  190. String revisionInfoEntityName) {
  191. this.RevisionInfoGenerator = revisionInfoGenerator;
  192. this.RevisionInfoXmlMapping = revisionInfoXmlMapping;
  193. this.RevisionInfoQueryCreator = revisionInfoQueryCreator;
  194. this.RevisionInfoRelationMapping = revisionInfoRelationMapping;
  195. this.RevisionInfoNumberReader = revisionInfoNumberReader;
  196. this.RevisionInfoEntityName = revisionInfoEntityName;
  197. }
  198. }
  199. }