PageRenderTime 3293ms CodeModel.GetById 2ms RepoModel.GetById 1ms app.codeStats 0ms

/Serenity.Services/RequestHandlers/IntegratedFeatures/Localization/LocalizationHandler.cs

https://gitlab.com/pgksunilkumar/Serenity
C# | 291 lines | 237 code | 54 blank | 0 comment | 45 complexity | 684fca627d3336c930c26413aeaa19e0 MD5 | raw file
  1. using Serenity.Services;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.Reflection;
  6. namespace Serenity.Data
  7. {
  8. public interface ILocalizationRowHandler
  9. {
  10. bool IsLocalized(Field field);
  11. }
  12. public class LocalizationRowHandler<TRow> : ILocalizationRowHandler
  13. where TRow: Row, IIdRow, new()
  14. {
  15. private static string schemaName;
  16. private static StaticInfo info;
  17. private class StaticInfo
  18. {
  19. public TRow rowInstance;
  20. public Row localRowInstance;
  21. public ILocalizationRow localRowInterface;
  22. public int rowFieldPrefixLength;
  23. public int localRowFieldPrefixLength;
  24. public IIdField mappedIdField;
  25. }
  26. static LocalizationRowHandler()
  27. {
  28. SchemaChangeSource.Observers += (schema, table) =>
  29. {
  30. if (schema == schemaName)
  31. info = null;
  32. };
  33. }
  34. static StaticInfo EnsureInfo()
  35. {
  36. var newInfo = info;
  37. if (newInfo != null)
  38. return newInfo;
  39. var localAttr = typeof(TRow).GetCustomAttribute<LocalizationRowAttribute>(false);
  40. if (localAttr == null || localAttr.LocalizationRow == null)
  41. throw new InvalidOperationException(String.Format("{0} row type has no localization row type defined!", typeof(TRow).Name));
  42. var localInstance = (Row)Activator.CreateInstance(localAttr.LocalizationRow);
  43. var localRow = localInstance as ILocalizationRow;
  44. if (localRow == null)
  45. throw new InvalidOperationException(String.Format("Localization table {0} doesn't implement ILocalizationRow interface!",
  46. localAttr.LocalizationRow.GetType().FullName, schemaName, typeof(TRow).Name));
  47. schemaName = RowRegistry.GetConnectionKey(localInstance);
  48. newInfo = new StaticInfo();
  49. newInfo.localRowInterface = localRow;
  50. newInfo.localRowInstance = localInstance;
  51. newInfo.rowInstance = new TRow();
  52. newInfo.rowFieldPrefixLength = PrefixHelper.DeterminePrefixLength(newInfo.rowInstance.EnumerateTableFields(), x => x.Name);
  53. newInfo.localRowFieldPrefixLength = PrefixHelper.DeterminePrefixLength(localInstance.EnumerateTableFields(), x => x.Name);
  54. newInfo.mappedIdField = (IIdField)((Row)localInstance).FindField(localAttr.MappedIdField ?? ((Field)new TRow().IdField).Name);
  55. if (newInfo.mappedIdField == null)
  56. throw new InvalidOperationException(String.Format("Can't locate localization table mapped ID field for {0}!",
  57. localInstance.Table));
  58. info = newInfo;
  59. return newInfo;
  60. }
  61. public static Field GetLocalizationMatch(Field field)
  62. {
  63. var info = EnsureInfo();
  64. if (!field.IsTableField())
  65. return null;
  66. var name = field.Name.Substring(info.rowFieldPrefixLength);
  67. name = ((Field)info.localRowInterface.IdField).Name.Substring(0, info.localRowFieldPrefixLength) + name;
  68. var match = info.localRowInstance.FindField(name);
  69. if (ReferenceEquals(null, match))
  70. return null;
  71. if (!match.IsTableField())
  72. return null;
  73. if (ReferenceEquals(match, info.localRowInterface.IdField) ||
  74. ReferenceEquals(match, info.localRowInterface.CultureIdField))
  75. return null;
  76. if (info.localRowInstance is IIsActiveRow &&
  77. ReferenceEquals(match, ((IIsActiveRow)info.localRowInstance).IsActiveField))
  78. return null;
  79. var logging = info.localRowInstance as ILoggingRow;
  80. if (logging != null && (
  81. ReferenceEquals(match, logging.InsertUserIdField) ||
  82. ReferenceEquals(match, logging.UpdateUserIdField) ||
  83. ReferenceEquals(match, logging.UpdateDateField) ||
  84. ReferenceEquals(match, logging.InsertDateField)))
  85. return null;
  86. return match;
  87. }
  88. public bool IsLocalized(Field field)
  89. {
  90. return !ReferenceEquals(null, GetLocalizationMatch(field));
  91. }
  92. private Int64? GetOldLocalizationRowId(IDbConnection connection, Int64 recordId, object cultureId)
  93. {
  94. var info = EnsureInfo();
  95. var row = info.localRowInstance.CreateNew();
  96. if (new SqlQuery()
  97. .From(row)
  98. .Select((Field)info.localRowInterface.IdField)
  99. .WhereEqual((Field)info.mappedIdField, recordId)
  100. .WhereEqual(info.localRowInterface.CultureIdField, cultureId)
  101. .GetFirst(connection))
  102. return info.localRowInterface.IdField[row];
  103. return null;
  104. }
  105. public void Update<TLocalRow>(IUnitOfWork uow, TRow row, object cultureId)
  106. where TLocalRow: Row, IIdRow, new()
  107. {
  108. Update(uow, row, cultureId,
  109. (r) => new SaveRequestHandler<TLocalRow>().Process(uow,
  110. new SaveRequest<TLocalRow>
  111. {
  112. Entity = (TLocalRow)r
  113. }, SaveRequestType.Create),
  114. (r) => new SaveRequestHandler<TLocalRow>().Process(uow,
  115. new SaveRequest<TLocalRow>
  116. {
  117. Entity = (TLocalRow)r
  118. }, SaveRequestType.Update),
  119. (id) => new DeleteRequestHandler<TLocalRow>().Process(uow, new DeleteRequest
  120. {
  121. EntityId = id
  122. }));
  123. }
  124. public void Update(IUnitOfWork uow, TRow row, object cultureId,
  125. Action<Row> create, Action<Row> update, Action<Int64> delete)
  126. {
  127. var info = EnsureInfo();
  128. var idField = ((IIdRow)row).IdField;
  129. var recordId = idField[row].Value;
  130. var oldId = GetOldLocalizationRowId(uow.Connection, recordId, cultureId);
  131. var localRow = info.localRowInstance.CreateNew();
  132. localRow.TrackAssignments = true;
  133. if (oldId != null)
  134. ((IIdRow)localRow).IdField[localRow] = oldId;
  135. if (oldId == null)
  136. {
  137. info.mappedIdField[localRow] = recordId;
  138. info.localRowInterface.CultureIdField.AsObject(localRow, cultureId);
  139. }
  140. bool anyNonEmpty = false;
  141. foreach (var field in row.GetFields())
  142. {
  143. if (ReferenceEquals(field, idField))
  144. continue;
  145. if (!row.IsAssigned(field))
  146. continue;
  147. var match = GetLocalizationMatch(field);
  148. if (ReferenceEquals(null, match))
  149. throw new ValidationError("CantLocalize", field.Name, String.Format("{0} alanı yerelleştirilemez!", field.Title));
  150. var value = field.AsObject(row);
  151. match.AsObject(localRow, value);
  152. if (value != null &&
  153. (!(value is string) || !(value as string).IsTrimmedEmpty()))
  154. {
  155. anyNonEmpty = true;
  156. }
  157. }
  158. if (oldId == null)
  159. {
  160. if (anyNonEmpty)
  161. create(localRow);
  162. }
  163. else
  164. {
  165. if (anyNonEmpty)
  166. update(localRow);
  167. else
  168. delete(oldId.Value);
  169. }
  170. }
  171. private Row GetOldLocalizationRow(IDbConnection connection, Int64 recordId, object cultureId)
  172. {
  173. var info = EnsureInfo();
  174. var row = info.localRowInstance.CreateNew();
  175. if (new SqlQuery()
  176. .From(row)
  177. .SelectTableFields()
  178. .WhereEqual((Field)info.mappedIdField, recordId)
  179. .WhereEqual(info.localRowInterface.CultureIdField, cultureId)
  180. .GetFirst(connection))
  181. return row;
  182. return null;
  183. }
  184. private List<Row> GetOldLocalizationRows(IDbConnection connection, Int64 recordId)
  185. {
  186. var info = EnsureInfo();
  187. var row = info.localRowInstance.CreateNew();
  188. return new SqlQuery()
  189. .From(row)
  190. .SelectTableFields()
  191. .WhereEqual((Field)info.mappedIdField, recordId)
  192. .List(connection, row);
  193. }
  194. public RetrieveLocalizationResponse<TRow> Retrieve(IDbConnection connection, RetrieveLocalizationRequest request)
  195. {
  196. request.CheckNotNull();
  197. if (request.EntityId == null)
  198. throw new ArgumentNullException("entityId");
  199. var recordId = Convert.ToInt64(request.EntityId);
  200. var localRows = GetOldLocalizationRows(connection, recordId);
  201. var response = new RetrieveLocalizationResponse<TRow>();
  202. response.Entities = new Dictionary<string, TRow>();
  203. if (localRows.IsEmptyOrNull())
  204. return response;
  205. TRow row = new TRow();
  206. var idField = ((IIdRow)row).IdField;
  207. var fields = new TRow().GetFields();
  208. var matches = new Field[fields.Count];
  209. for (var i = 0; i < fields.Count; i++)
  210. {
  211. var field = fields[i];
  212. if (ReferenceEquals(field, idField))
  213. continue;
  214. matches[i] = GetLocalizationMatch(field);
  215. }
  216. foreach (var localRow in localRows)
  217. {
  218. row = new TRow();
  219. row.TrackAssignments = true;
  220. row.IdField[row] = recordId;
  221. for (var i = 0; i < fields.Count; i++)
  222. {
  223. var match = matches[i];
  224. if (!ReferenceEquals(null, match))
  225. {
  226. var field = fields[i];
  227. var value = match.AsObject(localRow);
  228. field.AsObject(row, value);
  229. }
  230. }
  231. var culture = ((ILocalizationRow)localRow).CultureIdField.AsObject(localRow);
  232. response.Entities[culture == null ? "" : culture.ToString()] = row;
  233. }
  234. return response;
  235. }
  236. }
  237. }