/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2009, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.geometry.jts; import java.util.Set; import org.apache.sis.referencing.CRS; import org.geotoolkit.referencing.IdentifiedObjects; import org.opengis.util.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.opengis.metadata.Identifier; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * Utility class that can generate a SRID from a Coordinate Reference System. * this ability is needed since JTS geometry only handle a integer id for crs. * * @author Johann Sorel (Geomatys) * @module */ public final class SRIDGenerator { public enum Version{ V1( (byte)1 ); final byte code; Version(final byte code){ this.code = code; } }; private static final String AUTHORITY_CRS = "CRS"; private static final String AUTHORITY_EPSG = "EPSG"; private SRIDGenerator() { } /** * Generate a unique int number for a knowned coordinate reference system. * The first 4 bits of the result integer are holding the authority code. * The remaining bits hold the code number of the crs within the authority. * * exemple : version = COMPACT_V1 * first 4 bits = 0 > EPSG * first 4 bits = 1 > CRS * * return int , 0 if no srid could be generated because the crs has no identifiers. */ public static int toSRID(final CoordinateReferenceSystem crs, final Version version){ final Set<Identifier> ids = crs.getIdentifiers(); if(ids.isEmpty()){ return 0; // throw new IllegalArgumentException("CoordinateReferenceSystem has not identifier, impossible to compact it."); } final Identifier id = ids.iterator().next(); final String authority = id.getCodeSpace(); final int code = Integer.valueOf(id.getCode()); final int authorityCode; if(version == Version.V1){ if(AUTHORITY_EPSG.equalsIgnoreCase(authority)){ authorityCode = 0; }else if(AUTHORITY_CRS.equalsIgnoreCase(authority)){ authorityCode = 1; }else{ throw new IllegalArgumentException("unknowed authority : " + authority); } int compact = (authorityCode << 28) | code ; return compact; } throw new IllegalArgumentException("unknowed compact version : " + version); } /** * Generate a unique int number for a knowed coordinate reference system. * @param srs : String presenting the crs code. * exemple : EPSG:4326 or CRS:84 */ public static int toSRID(final String srs, final Version version){ final int index = srs.lastIndexOf(':'); if(index <= 0){ throw new IllegalArgumentException("CRS code doesnt match pattern Authority:Code : " + srs ); } final String authority = srs.substring(0, index); int code = Integer.parseInt(srs.substring(index+1, srs.length())); final int authorityCode; if(version == Version.V1){ if(AUTHORITY_EPSG.equalsIgnoreCase(authority)){ authorityCode = 0; }else if(AUTHORITY_CRS.equalsIgnoreCase(authority)){ authorityCode = 1; }else{ try { CoordinateReferenceSystem crs = CRS.forCode(srs); Integer epsgCode = IdentifiedObjects.lookupEpsgCode(crs, true); if (epsgCode != null) { authorityCode = 0; code = epsgCode; } else { throw new IllegalArgumentException("unknowed authority : " + authority); } } catch (NoSuchAuthorityCodeException ex) { throw new IllegalArgumentException("unknowed authority : " + srs); } catch (FactoryException ex) { throw new IllegalArgumentException("unknowed authority : " + srs); } } int compact = (authorityCode << 28) | code ; return compact; } throw new IllegalArgumentException("unknowed compact version : " + version); } /** * Read a byte array and extract the srid. * buffer must have a size of 5. * buffer[offset+0] hold the compact version number * buffer[offset+1] to buffer[offset+4] hold the SRID number */ public static int toSRID(final byte[] buffer, final int offset){ if(buffer[offset] == Version.V1.code){ return toInt(buffer, offset+1); } throw new IllegalArgumentException("unknowed compact version : " + buffer[offset]); } /** * Read a byte array and extract an integer value from * the first 4 bytes, buffer[offset+0] to buffer[offset+3]. */ public static int toInt(final byte[] buffer, final int offset){ int compact = ((int)(buffer[offset]) & 0xFF) << 24; compact |= ((int)(buffer[offset+1]) & 0xFF) << 16; compact |= ((int)(buffer[offset+2]) & 0xFF) << 8; compact |= ((int)(buffer[offset+3]) & 0xFF); return compact; } /** * Read an integer SRID, and knowing it's compact version * extract the real SRS value. */ public static String toSRS(final int srid, final Version version){ if(version == Version.V1){ final int authorityCode = srid >>> 28; final String authority; if(authorityCode == 0){ authority = AUTHORITY_EPSG; }else if(authorityCode == 1){ authority = AUTHORITY_CRS; }else{ throw new IllegalArgumentException("unknowed authority : " + authorityCode); } final int code = srid & 0xFFFFFFF; return new StringBuilder(authority).append(':').append(code).toString(); } throw new IllegalArgumentException("unknowed compact version : " + version); } /** * Read a byte array and extract the srs. * buffer must have a size of 5. * buffer[offset+0] hold the compact version number * buffer[offset+1] to buffer[offset+4] hold the SRID number */ public static String toSRS(final byte[] buffer, final int offset){ if(buffer[offset] == Version.V1.code){ final int srid = toInt(buffer, offset+1); return toSRS(srid, Version.V1); } throw new IllegalArgumentException("unknowed compact version : " + buffer[0]); } /** * Write a CRS in a byte[] of lenght 5. * the result byte array holds the compact version and the srid. */ public static byte[] toBytes(final CoordinateReferenceSystem crs, final Version version){ final int srid = toSRID(crs, version); return toBytes(srid, version); } /** * Write an srid in a byte[] of lenght 5. * the result byte array holds the compact version and the srid. */ public static byte[] toBytes(final int srid, final Version version){ final byte[] buffer = new byte[5]; buffer[0] = version.code; toBytes(srid, buffer, 1); return buffer; } /** * Write an int in a byte array. * 4 bytes will be used, from buffer[offset+0] to buffer[offset+3]. */ public static byte[] toBytes(final int compact, final byte[] buffer, final int offset){ buffer[offset ] = (byte)(compact >>> 24); buffer[offset+1] = (byte)(compact >>> 16); buffer[offset+2] = (byte)(compact >>> 8); buffer[offset+3] = (byte) compact; return buffer; } }