PageRenderTime 35ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/Raven.Abstractions/Spatial/ShapeConverter.cs

http://github.com/ayende/ravendb
C# | 116 lines | 96 code | 17 blank | 3 comment | 44 complexity | 375a212fba12ce0bf70f49729413038f MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Apache-2.0, BSD-3-Clause, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. using Raven.Abstractions.Linq;
  8. using Raven.Imports.Newtonsoft.Json.Linq;
  9. using Raven.Json.Linq;
  10. namespace Raven.Abstractions.Spatial
  11. {
  12. /// <summary>
  13. /// Converts shape objects to strings, if they are not already a string
  14. /// </summary>
  15. public class ShapeConverter
  16. {
  17. private static readonly GeoJsonWktConverter GeoJsonConverter = new GeoJsonWktConverter();
  18. private static readonly Regex RegexX = new Regex("^(?:X|Longitude|Lng|Lon|Long)$", RegexOptions.IgnoreCase);
  19. private static readonly Regex RegexY = new Regex("^(?:Y|Latitude|Lat)$", RegexOptions.IgnoreCase);
  20. public virtual bool TryConvert(object value, out string result)
  21. {
  22. var s = value as string;
  23. if (s != null)
  24. {
  25. result = s;
  26. return true;
  27. }
  28. var jValue = value as RavenJValue;
  29. if (jValue != null && jValue.Type == JTokenType.String)
  30. {
  31. result = (string)jValue.Value;
  32. return true;
  33. }
  34. var enumerable = value as IEnumerable;
  35. if (enumerable != null)
  36. {
  37. var list = enumerable.Cast<object>().ToList();
  38. if (list.Count > 1 && list.All(IsNumber))
  39. {
  40. result = MakePoint(GetDouble(list[0]), GetDouble(list[1]));
  41. return true;
  42. }
  43. var keyValues = list.OfType<KeyValuePair<object, object>>()
  44. .Where(x => IsNumber(x.Value))
  45. .ToDictionary(x => x.Key.ToString(), x => x.Value);
  46. if (keyValues.Count == 0)
  47. {
  48. keyValues = list.OfType<KeyValuePair<string, RavenJToken>>()
  49. .Where(x => IsNumber(x.Value))
  50. .ToDictionary(x => x.Key, x => (object)x.Value);
  51. }
  52. if (keyValues.Count > 1)
  53. {
  54. var x1 = keyValues.Select(x => x.Key).FirstOrDefault(c => RegexX.IsMatch(c));
  55. var y1 = keyValues.Select(x => x.Key).FirstOrDefault(c => RegexY.IsMatch(c));
  56. if (x1 != null && y1 != null)
  57. {
  58. result = MakePoint(GetDouble(keyValues[x1]), GetDouble(keyValues[y1]));
  59. return true;
  60. }
  61. }
  62. }
  63. var djObj = value as IDynamicJsonObject;
  64. var jObj = djObj != null ? djObj.Inner : value as RavenJObject;
  65. if (jObj != null && GeoJsonConverter.TryConvert(jObj, out result))
  66. return true;
  67. result = default(string);
  68. return false;
  69. }
  70. private bool IsNumber(object obj)
  71. {
  72. var rValue = obj as RavenJValue;
  73. return obj is double
  74. || obj is float
  75. || obj is int
  76. || obj is decimal
  77. || obj is long
  78. || obj is short
  79. || rValue != null && (rValue.Type == JTokenType.Float || rValue.Type == JTokenType.Integer);
  80. }
  81. private double GetDouble(object obj)
  82. {
  83. if (obj is double || obj is float || obj is int || obj is long || obj is short || obj is decimal)
  84. return Convert.ToDouble(obj);
  85. var rValue = obj as RavenJValue;
  86. if (rValue != null && (rValue.Type == JTokenType.Float || rValue.Type == JTokenType.Integer))
  87. return Convert.ToDouble(rValue.Value);
  88. return 0d;
  89. }
  90. protected string MakePoint(double x, double y)
  91. {
  92. return string.Format(CultureInfo.InvariantCulture, "POINT ({0} {1})", x, y);
  93. }
  94. protected string MakeCircle(double x, double y, double radius)
  95. {
  96. return string.Format(CultureInfo.InvariantCulture, "Circle({0} {1} d={2})", x, y, radius);
  97. }
  98. }
  99. }