using System.Collections.Concurrent; using Newtonsoft.Json.Linq; namespace WingServerCommon.Config.Parameters { public class ParameterDictionarySerializer { /// /// Deserialize json file to parameter /// /// File path or json string that will be deserialize /// str type, 0-file Path, 1-json string /// Parameter list. public static ConcurrentDictionary Deserialize(string str, int type = 0) { var content = ""; if (type == 0) { content = File.ReadAllText(str); } else { content = str; } //Decrypt text var configCrypter = new ConfigCrypter(); content = configCrypter.DecryptDES(content); var childrenList = JToken.Parse(content).Children(); var parameters = new ConcurrentDictionary(); foreach (var child in childrenList) { ParseTokenSetions(child, ref parameters); } return parameters; } private static void ParseTokenSetions(JToken children, ref ConcurrentDictionary dic) { var item = (JProperty)children; ParseToken(item.Name, item.Value.Children(), ref dic); } private static void ParseToken(string sectionName, JEnumerable childrenList, ref ConcurrentDictionary parameters) { foreach (var jToken in childrenList) { var item = (JProperty)jToken; if (item.Value is JArray jArray) { //TODO Do we have array parameter? continue; } if (item.Value is JObject jObject) { if (IsRangeParameter(jObject)) { var parameter = ParseRangeParameter(jObject, item.Name); parameter.Section = sectionName; var rangeKey = parameter.Section + "_" + parameter.Name; parameters.TryAdd(rangeKey, parameter); continue; } if (IsEnumParameter(jObject)) { var parameter = ParseEnumParameter(item.Name, jObject); parameter.Section = sectionName; var enumKey = parameter.Section + "_" + parameter.Name; parameters.TryAdd(enumKey, parameter); continue; } ParseToken(sectionName, jObject.Children(), ref parameters); } if (item.Value is JValue jValue) { var parameter = ParseBasicParameter(jValue, item.Name); parameter.Section = sectionName; var valueKey = parameter.Section + "_" + parameter.Name; parameters.TryAdd(valueKey, parameter); } } } private static bool IsEnumParameter(JObject jObject) { return jObject.Children().Any(m => ((JProperty)m).Name == "Source"); } private static bool IsRangeParameter(JObject jObject) { return jObject.Children().Any(m => ((JProperty)m).Name == "MaxValue"); } private static IParameter ParseEnumParameter(string name, JObject jObject) { var defaultValue = jObject["DefaultValue"]?.Value(); switch (defaultValue?.Type) { case JTokenType.String: return new EnumStringParameter { Name = name, Source = jObject["Source"].Values().ToList(), Value = defaultValue.Value() }; //TODO other types } throw new ArgumentException($"Invalid enum parameter {name}."); } private static IParameter ParseRangeParameter(JObject jObject, string key) { var max = jObject["MaxValue"].Value(); switch (max.Type) { case JTokenType.Integer: { if (max.Value() > int.MaxValue) { var defaultValue = jObject["DefaultValue"].Value(); var minValue = jObject["MinValue"].Value(); var maxValue = max.Value(); var longRangeValue = new RangeLongParameter { Name = key, Value = defaultValue, MaxValue = maxValue, MinValue = minValue }; } else { var defaultValue = jObject["DefaultValue"].Value(); var minValue = jObject["MinValue"].Value(); var maxValue = max.Value(); var intRangeValue = new RangeIntParameter { Name = key, Value = defaultValue, MaxValue = maxValue, MinValue = minValue }; } break; } } throw new ArgumentException($"Invalid range parameter with name {key}."); } private static IParameter ParseBasicParameter(JValue jValue, string key) { if (jValue.Type == JTokenType.Integer) { return new IntParameter { Name = key, Value = jValue.Value() }; } if (jValue.Type == JTokenType.Boolean) { return new BoolParameter { Name = key, Value = jValue.Value() }; } if (jValue.Type == JTokenType.String) { return new StringParameter { Name = key, Value = jValue.Value() }; } //TODO Implement FloatParameter //if (jValue.Type == JTokenType.Float) //{ // return new FloatParameter { Name = key, Value = jValue.Value() }; //} throw new ArgumentException($"Invalid jValue type {jValue.Type}"); } } }