package com.revolsys.geometry.cs.esri; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystemException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import com.revolsys.geometry.cs.Authority; import com.revolsys.geometry.cs.CoordinateSystem; import com.revolsys.geometry.cs.CoordinateSystemParser; import com.revolsys.geometry.cs.CoordinateSystems; import com.revolsys.geometry.cs.GeographicCoordinateSystem; import com.revolsys.geometry.cs.ProjectedCoordinateSystem; import com.revolsys.geometry.cs.WktCsParser; import com.revolsys.geometry.model.GeometryFactory; import com.revolsys.io.StringWriter; import com.revolsys.logging.Logs; import com.revolsys.spring.resource.Resource; import com.revolsys.util.Exceptions; public class EsriCoordinateSystems { private static Map<CoordinateSystem, CoordinateSystem> coordinateSystems = new HashMap<>(); private static Map<Integer, CoordinateSystem> coordinateSystemsById = new HashMap<>(); private static Map<String, CoordinateSystem> coordinateSystemsByName = new HashMap<>(); static { final List<GeographicCoordinateSystem> geographicCoordinateSystems = CoordinateSystemParser .getGeographicCoordinateSystems("ESRI", EsriCoordinateSystems.class .getResourceAsStream("/com/revolsys/gis/cs/esri/geographicCoordinateSystem.txt")); for (final GeographicCoordinateSystem cs : geographicCoordinateSystems) { final int id = getCrsId(cs); coordinateSystemsById.put(id, cs); coordinateSystemsByName.put(cs.getCoordinateSystemName(), cs); coordinateSystems.put(cs, cs); } final List<ProjectedCoordinateSystem> projectedCoordinateSystems = CoordinateSystemParser .getProjectedCoordinateSystems(coordinateSystemsById, "ESRI", EsriCoordinateSystems.class .getResourceAsStream("/com/revolsys/gis/cs/esri/projectedCoordinateSystem.txt")); for (final ProjectedCoordinateSystem cs : projectedCoordinateSystems) { final int id = getCrsId(cs); coordinateSystemsById.put(id, cs); coordinateSystemsByName.put(cs.getCoordinateSystemName(), cs); coordinateSystems.put(cs, cs); } } public static CoordinateSystem getCoordinateSystem(final CoordinateSystem coordinateSystem) { if (coordinateSystem == null) { return null; } else { CoordinateSystem coordinateSystem2 = coordinateSystemsByName .get(coordinateSystem.getCoordinateSystemName()); if (coordinateSystem2 == null) { coordinateSystem2 = coordinateSystems.get(coordinateSystem); if (coordinateSystem2 == null) { return coordinateSystem; } } return coordinateSystem2; } } public static CoordinateSystem getCoordinateSystem(final int crsId) { final CoordinateSystem coordinateSystem = coordinateSystemsById.get(crsId); return coordinateSystem; } public static CoordinateSystem getCoordinateSystem(final Object source) { final Resource resource = Resource.getResource(source); if (resource == null) { return null; } else { try ( Reader reader = resource.newReader()) { final CoordinateSystem coordinateSystem = getCoordinateSystem(reader); return getCoordinateSystem(coordinateSystem); } catch (final IOException e) { throw Exceptions.wrap(e); } } } public static CoordinateSystem getCoordinateSystem(final Reader reader) { return new WktCsParser(reader).parse(); } public static CoordinateSystem getCoordinateSystem(final String wkt) { final WktCsParser parser = new WktCsParser(wkt); return getCoordinateSystem(parser); } public static CoordinateSystem getCoordinateSystem(final WktCsParser parser) { final CoordinateSystem coordinateSystem = parser.parse(); return getCoordinateSystem(coordinateSystem); } public static int getCrsId(final CoordinateSystem coordinateSystem) { final Authority authority = coordinateSystem.getAuthority(); if (authority != null) { final String name = authority.getName(); final String code = authority.getCode(); if (name.equals("ESRI")) { return Integer.parseInt(code); } } return 0; } public static GeometryFactory getGeometryFactory(final CoordinateSystem coordinateSystem) { if (coordinateSystem != null) { final int srid = EsriCoordinateSystems.getCrsId(coordinateSystem); if (srid > 0 && srid < 2000000) { return GeometryFactory.floating(srid, 2); } else { return GeometryFactory.floating(coordinateSystem, 2); } } return null; } public static GeometryFactory getGeometryFactory(final Reader reader) { try { final CoordinateSystem coordinateSystem = getCoordinateSystem(reader); return getGeometryFactory(coordinateSystem); } catch (final Exception e) { Logs.error(EsriCoordinateSystems.class, "Unable to load projection", e); return null; } } /** * Construct a new geometry factory from a .prj with the same base name as the resource if it exists. Returns null if the prj file does not exist. * @param resource * @return */ public static GeometryFactory getGeometryFactory(final Resource resource) { final Resource projResource = resource.newResourceChangeExtension("prj"); try { final CoordinateSystem coordinateSystem = getCoordinateSystem(projResource); return getGeometryFactory(coordinateSystem); } catch (final IllegalArgumentException e) { final Throwable cause = e.getCause(); if (cause instanceof FileNotFoundException) { } else if (cause instanceof FileSystemException) { } else { Logs.error(EsriCoordinateSystems.class, "Unable to load projection from " + projResource, e); } } catch (final Exception e) { Logs.error(EsriCoordinateSystems.class, "Unable to load projection from " + projResource, e); } return null; } public static GeometryFactory getGeometryFactory(final String wkt) { final CoordinateSystem coordinateSystem = getCoordinateSystem(wkt); return getGeometryFactory(coordinateSystem); } public static String toString(final GeometryFactory geometryFactory) { try ( StringWriter stringWriter = new StringWriter()) { writePrjFile(stringWriter, geometryFactory); return stringWriter.toString(); } } public static void writePrjFile(final Object target, final GeometryFactory geometryFactory) { final Resource resource = Resource.getResource(target); if (geometryFactory != null && resource != null) { final Resource prjResource = resource.newResourceChangeExtension("prj"); if (prjResource != null && geometryFactory.isHasCoordinateSystem()) { try ( final Writer writer = prjResource.newWriter(StandardCharsets.ISO_8859_1)) { writePrjFile(writer, geometryFactory); } catch (final Throwable e) { Logs.error(EsriCoordinateSystems.class, "Unable to create: " + resource, e); } } } } public static boolean writePrjFile(final Writer writer, final GeometryFactory geometryFactory) { if (geometryFactory != null) { final CoordinateSystem coordinateSystem = geometryFactory.getCoordinateSystem(); if (coordinateSystem != null) { final int srid = coordinateSystem.getCoordinateSystemId(); final CoordinateSystem esriCoordinateSystem = CoordinateSystems .getCoordinateSystem(new QName("ESRI", String.valueOf(srid))); if (esriCoordinateSystem == null) { EsriCsWktWriter.write(writer, coordinateSystem, -1); } else { EsriCsWktWriter.write(writer, esriCoordinateSystem, -1); } return true; } } return false; } }