private SpatialDataType GetDataTypeForKind(SpatialShapeKind kind)
        {
            SpatialDataType dataType;

            if (!this.shapeKindToEdmTypeMapping.TryGetValue(kind, out dataType))
            {
                dataType = (SpatialDataType)typeof(EdmDataTypes).GetProperty(kind.ToString(), true, true).GetValue(null, null);

                // add the clr type facet immediately so that return/parameter types have it as well
                dataType = dataType.WithPrimitiveClrType(this.ClrTypeResolver.GetClrType(dataType));

                // add to dictionary before recursing
                this.shapeKindToEdmTypeMapping[kind] = dataType;

                // properties
                foreach (var property in this.GetMemberPropertiesForKind(kind).ToList())
                {
                    dataType.Properties.Add(property);
                }

                // methods
                foreach (var method in this.GetMethodsForKind(kind).ToList())
                {
                    dataType.Methods.Add(method);
                }
            }

            return(dataType);
        }
        private IEnumerable <Function> GetMethodsForKind(SpatialShapeKind kind)
        {
            var parameterKind = kind.HasFacet(SpatialShapeFacets.Geography) ? SpatialShapeKind.Geography : SpatialShapeKind.Geometry;

            yield return(new Function("geo", "Distance")
            {
                ReturnType = EdmDataTypes.Double,
                Parameters = { new FunctionParameter("other", this.GetDataTypeForKind(parameterKind)) },
                Annotations = { new MemberInSpatialTypeAnnotation(false) }
            });
        }
 /// <summary>
 /// Returns the hint for the spatial shape kind.
 /// </summary>
 /// <param name="value">the spatial shape kind.</param>
 /// <returns>the hint for spatial shape kind.</returns>
 public static SpatialShapeKindHint SpatialShapeKind(SpatialShapeKind value)
 {
     return(new SpatialShapeKindHint(value));
 }
 /// <summary>
 /// Determines whether the specified kind has the given facet.
 /// </summary>
 /// <param name="kind">The shape kind.</param>
 /// <param name="facet">The facet to look for.</param>
 /// <returns>
 ///   <c>true</c> if the specified kind has the facet; otherwise, <c>false</c>.
 /// </returns>
 public static bool HasFacet(this SpatialShapeKind kind, SpatialShapeFacets facet)
 {
     return(0 != ((int)kind & (int)facet));
 }
        private IEnumerable <MemberProperty> GetMemberPropertiesForKind(SpatialShapeKind kind)
        {
            yield return(new MemberProperty("CoordinateSystem", CoordinateSystemDataType));

            yield return(new MemberProperty("IsEmpty", EdmDataTypes.Boolean));

            bool isGeography = kind.HasFacet(SpatialShapeFacets.Geography);

            if (!kind.HasFacet(SpatialShapeFacets.Collection))
            {
                // Point
                if (kind.HasFacet(SpatialShapeFacets.Point))
                {
                    if (isGeography)
                    {
                        yield return(new MemberProperty("Latitude", EdmDataTypes.Double.NotNullable()));

                        yield return(new MemberProperty("Longitude", EdmDataTypes.Double.NotNullable()));
                    }
                    else
                    {
                        yield return(new MemberProperty("X", EdmDataTypes.Double.NotNullable()));

                        yield return(new MemberProperty("Y", EdmDataTypes.Double.NotNullable()));
                    }

                    yield return(new MemberProperty("M", EdmDataTypes.Double.Nullable()));

                    yield return(new MemberProperty("Z", EdmDataTypes.Double.Nullable()));
                }
                else if (kind.HasFacet(SpatialShapeFacets.LineString))
                {
                    var elementKind = isGeography ? SpatialShapeKind.GeographyPoint : SpatialShapeKind.GeometryPoint;
                    yield return(new MemberProperty("Points", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind))));
                }
                else if (kind.HasFacet(SpatialShapeFacets.Polygon))
                {
                    var elementKind = isGeography ? SpatialShapeKind.GeographyLineString : SpatialShapeKind.GeometryLineString;
                    yield return(new MemberProperty("Rings", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind))));
                }
            }
            else
            {
                if (kind.HasFacet(SpatialShapeFacets.Point))
                {
                    // MultiPoint
                    var elementKind = isGeography ? SpatialShapeKind.GeographyPoint : SpatialShapeKind.GeometryPoint;
                    yield return(new MemberProperty("Points", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind))));
                }
                else if (kind.HasFacet(SpatialShapeFacets.LineString))
                {
                    // MultiLineString
                    var elementKind = isGeography ? SpatialShapeKind.GeographyLineString : SpatialShapeKind.GeometryLineString;
                    yield return(new MemberProperty("LineStrings", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind))));
                }
                else if (kind.HasFacet(SpatialShapeFacets.Polygon))
                {
                    // MultiPolygon
                    var elementKind = isGeography ? SpatialShapeKind.GeographyPolygon : SpatialShapeKind.GeometryPolygon;
                    yield return(new MemberProperty("Polygons", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind))));
                }
                else
                {
                    var propertyName = isGeography ? "Geographies" : "Geometries";
                    var elementKind  = isGeography ? SpatialShapeKind.Geography : SpatialShapeKind.Geometry;
                    yield return(new MemberProperty(propertyName, DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind))));
                }
            }
        }
        private SpatialDataType GetDataTypeForKind(SpatialShapeKind kind)
        {
            SpatialDataType dataType;
            if (!this.shapeKindToEdmTypeMapping.TryGetValue(kind, out dataType))
            {
                dataType = (SpatialDataType)typeof(EdmDataTypes).GetProperty(kind.ToString(), true, true).GetValue(null, null);

                // add the clr type facet immediately so that return/parameter types have it as well
                dataType = dataType.WithPrimitiveClrType(this.ClrTypeResolver.GetClrType(dataType));

                // add to dictionary before recursing
                this.shapeKindToEdmTypeMapping[kind] = dataType;

                // properties
                foreach (var property in this.GetMemberPropertiesForKind(kind).ToList())
                {
                    dataType.Properties.Add(property);
                }

                // methods
                foreach (var method in this.GetMethodsForKind(kind).ToList())
                {
                    dataType.Methods.Add(method);
                }
            }

            return dataType;
        }
        private IEnumerable<MemberProperty> GetMemberPropertiesForKind(SpatialShapeKind kind)
        {
            yield return new MemberProperty("CoordinateSystem", CoordinateSystemDataType);
            yield return new MemberProperty("IsEmpty", EdmDataTypes.Boolean);

            bool isGeography = kind.HasFacet(SpatialShapeFacets.Geography);
            if (!kind.HasFacet(SpatialShapeFacets.Collection))
            {
                // Point
                if (kind.HasFacet(SpatialShapeFacets.Point))
                {
                    if (isGeography)
                    {
                        yield return new MemberProperty("Latitude", EdmDataTypes.Double.NotNullable());
                        yield return new MemberProperty("Longitude", EdmDataTypes.Double.NotNullable());
                    }
                    else
                    {
                        yield return new MemberProperty("X", EdmDataTypes.Double.NotNullable());
                        yield return new MemberProperty("Y", EdmDataTypes.Double.NotNullable());
                    }

                    yield return new MemberProperty("M", EdmDataTypes.Double.Nullable());
                    yield return new MemberProperty("Z", EdmDataTypes.Double.Nullable());
                }
                else if (kind.HasFacet(SpatialShapeFacets.LineString))
                {
                    var elementKind = isGeography ? SpatialShapeKind.GeographyPoint : SpatialShapeKind.GeometryPoint;
                    yield return new MemberProperty("Points", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind)));
                }
                else if (kind.HasFacet(SpatialShapeFacets.Polygon))
                {
                    var elementKind = isGeography ? SpatialShapeKind.GeographyLineString : SpatialShapeKind.GeometryLineString;
                    yield return new MemberProperty("Rings", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind)));
                }
            }
            else
            {
                if (kind.HasFacet(SpatialShapeFacets.Point))
                {
                    // MultiPoint
                    var elementKind = isGeography ? SpatialShapeKind.GeographyPoint : SpatialShapeKind.GeometryPoint;
                    yield return new MemberProperty("Points", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind)));
                }
                else if (kind.HasFacet(SpatialShapeFacets.LineString))
                {
                    // MultiLineString
                    var elementKind = isGeography ? SpatialShapeKind.GeographyLineString : SpatialShapeKind.GeometryLineString;
                    yield return new MemberProperty("LineStrings", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind)));
                }
                else if (kind.HasFacet(SpatialShapeFacets.Polygon))
                {
                    // MultiPolygon
                    var elementKind = isGeography ? SpatialShapeKind.GeographyPolygon : SpatialShapeKind.GeometryPolygon;
                    yield return new MemberProperty("Polygons", DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind)));
                }
                else
                {
                    var propertyName = isGeography ? "Geographies" : "Geometries";
                    var elementKind = isGeography ? SpatialShapeKind.Geography : SpatialShapeKind.Geometry;
                    yield return new MemberProperty(propertyName, DataTypes.CollectionType.WithElementDataType(this.GetDataTypeForKind(elementKind)));
                }
            }
        }
 private IEnumerable<Function> GetMethodsForKind(SpatialShapeKind kind)
 {
     var parameterKind = kind.HasFacet(SpatialShapeFacets.Geography) ? SpatialShapeKind.Geography : SpatialShapeKind.Geometry;
     yield return new Function("geo", "Distance")
     {
         ReturnType = EdmDataTypes.Double,
         Parameters = { new FunctionParameter("other", this.GetDataTypeForKind(parameterKind)) },
         Annotations = { new MemberInSpatialTypeAnnotation(false) }
     };
 }