Quick.Config.pas 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. { ***************************************************************************
  2. Copyright (c) 2015-2018 Kike Pérez
  3. Unit : Quick.Config
  4. Description : Load/Save config from/to JSON file
  5. Author : Kike Pérez
  6. Version : 1.5
  7. Created : 26/01/2017
  8. Modified : 10/12/2018
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Config;
  22. interface
  23. {$i QuickLib.inc}
  24. uses
  25. Classes,
  26. SysUtils,
  27. Rtti,
  28. {$IFDEF FPC}
  29. fpjson,
  30. jsonparser,
  31. fpjsonrtti,
  32. Quick.Json.Serializer;
  33. {$ELSE}
  34. Quick.Json.Serializer,
  35. DBXJSON,
  36. System.JSON,
  37. Rest.Json.Types,
  38. Rest.Json;
  39. {$ENDIF}
  40. type
  41. TDateTimeZone = (tzLocal, tzUTC);
  42. IAppConfigProvider<T> = interface
  43. ['{D55B1EBF-47F6-478B-8F70-9444575CB825}']
  44. procedure Load(var cConfig : T);
  45. procedure Save(var cConfig : T);
  46. end;
  47. TSerializeProperty = (spPublic, spPublished);
  48. TAppConfigProviderBase<T : class> = class(TInterfacedObject,IAppConfigProvider<T>)
  49. private
  50. fCreateIfNotExists : Boolean;
  51. fSerializeLevel : TSerializeProperty;
  52. public
  53. constructor Create(var cConfig : T); virtual;
  54. property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
  55. property SerializeLevel : TSerializeProperty read fSerializeLevel write fSerializeLevel;
  56. function InitObject : T;
  57. procedure Load(var cConfig : T); virtual; abstract;
  58. procedure Save(var cConfig : T); virtual; abstract;
  59. end;
  60. TApplyConfigEvent = procedure of object;
  61. {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
  62. TAppConfig = class
  63. private
  64. {$IFDEF FPC}
  65. fOnApplyConfig : TApplyConfigEvent;
  66. fDateTimeZone: TDateTimeZone;
  67. fJsonIndent: Boolean;
  68. fLastSaved : TDateTime;
  69. {$ELSE}
  70. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  71. fOnApplyConfig : TApplyConfigEvent;
  72. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  73. fDateTimeZone: TDateTimeZone;
  74. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  75. fJsonIndent: Boolean;
  76. {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
  77. fLastSaved : TDateTime;
  78. {$ENDIF}
  79. public
  80. constructor Create; virtual;
  81. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  82. property OnApplyConfig : TApplyConfigEvent read fOnApplyConfig write fOnApplyConfig;
  83. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  84. property DateTimeZone : TDateTimeZone read fDateTimeZone write fDateTimeZone;
  85. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  86. property JsonIndent : Boolean read fJsonIndent write fJsonIndent;
  87. {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
  88. property LastSaved : TDateTime read fLastSaved write fLastSaved;
  89. procedure Apply;
  90. procedure DefaultValues; virtual;
  91. function ToJSON : string;
  92. procedure FromJSON(const json : string);
  93. end;
  94. {Usage: create a descend class from TAppConfig and add published properties to be loaded/saved
  95. TMyConfig = class(TAppConfig)
  96. private
  97. fName : string;
  98. fSurname : string;
  99. fStatus : Integer;
  100. published
  101. property Name : string read fName write fName;
  102. property SurName : string read fSurname write fSurname;
  103. property Status : Integer read fStatus write fStatus;
  104. end;
  105. AppConfigProvider := TAppConfigJsonProvider<TMyConfig>.Create(MyConfig);
  106. MyConfig.Name := 'John';
  107. }
  108. implementation
  109. { TAppConfigProviderBase }
  110. constructor TAppConfigProviderBase<T>.Create(var cConfig : T);
  111. begin
  112. fCreateIfNotExists := True;
  113. fSerializeLevel := spPublished;
  114. //create object with rtti
  115. if Assigned(cConfig) then cConfig.Free;
  116. cConfig := InitObject;
  117. end;
  118. function TAppConfigProviderBase<T>.InitObject : T;
  119. var
  120. AValue: TValue;
  121. ctx: TRttiContext;
  122. rType: TRttiType;
  123. AMethCreate: TRttiMethod;
  124. begin
  125. ctx := TRttiContext.Create;
  126. try
  127. rType := ctx.GetType(TypeInfo(T));
  128. for AMethCreate in rType.GetMethods do
  129. begin
  130. if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then
  131. begin
  132. {$IFDEF FPC}
  133. Result := T(GetClass(T.ClassName).Create);
  134. {$ELSE}
  135. AValue := AMethCreate.Invoke(rType.AsInstance.AsInstance.MetaclassType,[]);
  136. Result := AValue.AsType<T>;
  137. {$ENDIF}
  138. Break;
  139. end;
  140. end;
  141. finally
  142. ctx.Free;
  143. end;
  144. end;
  145. { TAppConfig }
  146. constructor TAppConfig.Create;
  147. begin
  148. fDateTimeZone := TDateTimeZone.tzLocal;
  149. fJsonIndent := True;
  150. fLastSaved := 0;
  151. end;
  152. procedure TAppConfig.Apply;
  153. begin
  154. if Assigned(fOnApplyConfig) then fOnApplyConfig;
  155. end;
  156. procedure TAppConfig.DefaultValues;
  157. begin
  158. //inherit to set default values if no config exists before
  159. end;
  160. function TAppConfig.ToJSON : string;
  161. var
  162. Serializer : TJsonSerializer;
  163. begin
  164. Result := '';
  165. try
  166. serializer := TJsonSerializer.Create(slPublishedProperty);
  167. try
  168. Result := serializer.ObjectToJSON(Self,True);
  169. finally
  170. serializer.Free;
  171. end;
  172. except
  173. on e : Exception do raise Exception.Create(e.Message);
  174. end;
  175. end;
  176. procedure TAppConfig.FromJSON(const json : string);
  177. var
  178. Serializer : TJsonSerializer;
  179. begin
  180. try
  181. serializer := TJsonSerializer.Create(slPublishedProperty);
  182. try
  183. {$IF NOT DEFINED(FPC) AND DEFINED(ANDROID)}
  184. serializer.JsonToObject(Self,json);
  185. {$ELSE}
  186. Self := TAppConfig(serializer.JsonToObject(Self,json));
  187. {$ENDIF}
  188. finally
  189. serializer.Free;
  190. end;
  191. except
  192. on e : Exception do raise Exception.Create(e.Message);
  193. end;
  194. end;
  195. end.