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