All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.backendless.persistence.GeoJSONParser Maven / Gradle / Ivy

The newest version!
package com.backendless.persistence;

import com.backendless.util.JSONUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class GeoJSONParser
{
  private final Class geomClass;
  private SpatialReferenceSystemEnum srs;


  public GeoJSONParser()
  {
    this( null, null );
  }

  public GeoJSONParser( SpatialReferenceSystemEnum srs )
  {
    this( srs, null );
  }

  public GeoJSONParser( String geomClassName )
  {
    this( null, geomClassName );
  }

  GeoJSONParser( SpatialReferenceSystemEnum srs, String geomClassName )
  {
    this.srs = srs;

    if( geomClassName != null )
    {
      try
      {
        @SuppressWarnings( "unchecked" )
        Class uncheckedClazz = (Class) Class.forName( geomClassName );
        this.geomClass = uncheckedClazz;
      }
      catch( ClassNotFoundException e )
      {
        throw new IllegalArgumentException( "'geomClassName' contains unknown class '" + geomClassName + "'." );
      }
    }
    else
      this.geomClass = null;
  }

  public Geometry read( String geoJson )
  {
    if( geoJson == null || geoJson.isEmpty() )
      return null;

    Map geoJsonMap;
    try
    {
      geoJsonMap = JSONUtil.getJsonConverter().readObject( geoJson, Map.class );
    }
    catch( Exception e )
    {
      throw new GeoJSONParserException( e );
    }

    return read( geoJsonMap );
  }

  @SuppressWarnings( "unchecked" )
  public Geometry read( Map geoJson )
  {
    String type = (String) geoJson.get( "type" );
    Object coordinatesObj = geoJson.get( "coordinates" );

    if( this.srs == null )
    {
      Integer srsId = (Integer) geoJson.get( "srsId" );
      if( srsId != null )
        this.srs = SpatialReferenceSystemEnum.valueBySRSId( srsId );
      else
        this.srs = SpatialReferenceSystemEnum.DEFAULT;
    }

    Object[] coordinates = null;

    if( coordinatesObj instanceof List )
      coordinates = ((List) coordinatesObj).toArray();
    else if( coordinatesObj != null )
      coordinates = (Object[]) coordinatesObj;

    if( type == null || coordinates == null )
      throw new GeoJSONParserException( "Both 'type' and 'coordinates' should be present in GeoJSON object." );

    if( this.geomClass == null || this.geomClass == Geometry.class || Point.class == this.geomClass || LineString.class == this.geomClass || Polygon.class == this.geomClass )
    {
      switch( type )
      {
        case Point.GEOJSON_TYPE:
          return constructPointFromCoordinates( coordinates );
        case LineString.GEOJSON_TYPE:
          return constructLineStringFromCoordinates( coordinates );
        case Polygon.GEOJSON_TYPE:
          return constructPolygonFromCoordinates( coordinates );
      }
    }
    else
      throw new GeoJSONParserException( "Unknown geometry class: '" + this.geomClass + "'" );

    throw new GeoJSONParserException( "Unknown geometry type: '" + type + "'" );
  }

  private Point constructPointFromCoordinates( Object[] coordinatePair )
  {
    return new Point( this.srs ).setX( ((Number) coordinatePair[ 0 ]).doubleValue() ).setY( ((Number) coordinatePair[ 1 ]).doubleValue() );
  }

  private LineString constructLineStringFromCoordinates( Object[] arrayOfCoordinatePairs )
  {
    ArrayList points = new ArrayList<>();

    Object[] coordinatePairNumbers;
    for( Object coordinatePairObj : arrayOfCoordinatePairs )
    {
      if( coordinatePairObj instanceof List )
        coordinatePairNumbers = ((List) coordinatePairObj).toArray();
      else
        coordinatePairNumbers = (Object[]) coordinatePairObj;

      points.add( new Point( this.srs ).setX( ((Number) coordinatePairNumbers[ 0 ]).doubleValue() ).setY( ((Number) coordinatePairNumbers[ 1 ]).doubleValue() ) );
    }

    return new LineString( points, this.srs );
  }

  private Polygon constructPolygonFromCoordinates( Object[] arrayOfCoordinateArrayPairs )
  {
    ArrayList lineStrings = new ArrayList<>();

    Object[] arrayOfCoordinatePairs;

    for( Object arrayOfCoordinatePairsObj : arrayOfCoordinateArrayPairs )
    {
      if( arrayOfCoordinatePairsObj instanceof List )
        arrayOfCoordinatePairs = ((List) arrayOfCoordinatePairsObj).toArray();
      else
        arrayOfCoordinatePairs = (Object[]) arrayOfCoordinatePairsObj;

      LineString lineString = constructLineStringFromCoordinates( arrayOfCoordinatePairs );
      lineStrings.add( lineString );
    }

    if( lineStrings.isEmpty() )
      throw new GeoJSONParserException( "Polygon's GeoJSON should contain at least one LineString." );

    LineString shell = lineStrings.get( 0 );
    List holes = lineStrings.subList( 1, lineStrings.size() );

    return new Polygon( shell, holes, srs );
  }

  public static class GeoJSONParserException extends RuntimeException
  {
    public GeoJSONParserException( String message )
    {
      super( message );
    }

    public GeoJSONParserException( String message, Throwable cause )
    {
      super( message, cause );
    }

    public GeoJSONParserException( Throwable cause )
    {
      super( cause );
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy