示例#1
0
/**
 * Provides a filtered, sorted view over the available EPSG coordinate reference systems.
 *
 * @author Gabriel Roldan - OpenGeo
 * @author Andrea Aime - OpenGeo
 */
public class SRSProvider extends GeoServerDataProvider<SRSProvider.SRS> {

  private static final long serialVersionUID = 3731647638872356912L;

  /**
   * Spots integral numbers
   *
   * @see #buildCodeList()
   */
  private static Pattern NUMERIC = Pattern.compile("\\d+");

  /**
   * A lightweight bean to carry over the code and description of a {@link
   * CoordinateReferenceSystem}
   *
   * @author Gabriel Roldan - OpenGeo
   */
  public static class SRS implements Serializable, Comparable<SRS> {

    private static final long serialVersionUID = -4155644876049747585L;

    private String code;

    private transient String description;

    public SRS(String code) {
      this.code = code;
    }

    public String getCode() {
      return code;
    }

    public String getDescription() {
      // lazy loading of description
      if (description == null) {
        // grab the description
        String desc = "-";
        try {
          // REVISIT: as far as I know the EPSG names are not localized? anyway, if
          // they're revisit to use the page locale
          // description = CRS.getAuthorityFactory(true).getDescriptionText("EPSG:" +
          // code)
          // .toString(getLocale()).toUpperCase();
          desc = CRS.getAuthorityFactory(true).getDescriptionText("EPSG:" + code).toString();
        } catch (Exception e) {
          // no problem
        }
        description = desc;
      }
      return description;
    }

    @Override
    public boolean equals(Object o) {
      return code.equals(((SRS) o).code);
    }

    @Override
    public int hashCode() {
      return 17 * code.hashCode();
    }

    public int compareTo(SRS o) {
      return code.compareTo(o.code);
    }
  }

  /** custom geoserver crs factory which loads codes from epsg.properties file in data directory */
  private static CRSAuthorityFactory customFactory =
      ReferencingFactoryFinder.getCRSAuthorityFactory(
          "EPSG", new Hints(Hints.CRS_AUTHORITY_FACTORY, GeoserverCustomWKTFactory.class));

  public static final Property<SRS> CODE =
      new BeanProperty<SRS>("code", "code") {

        private static final long serialVersionUID = -1638823520421390286L;

        @Override
        public Comparator<SRS> getComparator() {
          return new CodeComparator();
        }
      };

  public static final Property<SRS> DESCRIPTION =
      new BeanProperty<SRS>("description", "description") {

        private static final long serialVersionUID = 3549074714488486991L;

        @Override
        public Comparator<SRS> getComparator() {
          return new Comparator<SRS>() {

            public int compare(SRS o1, SRS o2) {
              return String.CASE_INSENSITIVE_ORDER.compare(
                  o1.getDescription(), o2.getDescription());
            }
          };
        }
      };

  @SuppressWarnings("unchecked")
  private static final ArrayList<Property<SRS>> PROPERTIES =
      new ArrayList<Property<SRS>>(Arrays.asList(CODE, DESCRIPTION));

  private List<SRS> items;

  @Override
  protected List<SRS> getItems() {
    if (items == null) {
      synchronized (SRSProvider.class) {
        if (items == null) {
          items = buildCodeList();
        }
      }
    }
    return items;
  }

  @Override
  protected List<Property<SRS>> getProperties() {
    return PROPERTIES;
  }

  static List<SRS> buildCodeList() {
    long t = System.currentTimeMillis();
    Set<String> codes = CRS.getSupportedCodes("EPSG");

    try {
      codes.addAll(customFactory.getAuthorityCodes(CoordinateReferenceSystem.class));
    } catch (FactoryException e) {
      LOGGER.log(Level.WARNING, "Error occurred while trying to gather custom CRS codes", e);
    }

    // make a set with each code
    Set<SRS> idSet = new HashSet<SRS>();
    for (String code : codes) {
      // make sure we're using just the non prefix part
      String id = code.substring(code.indexOf(':') + 1);
      // avoid WGS84DD and eventual friends, as we're still not able to handle them,
      // if they are chosen exceptions arises everywhere
      if (NUMERIC.matcher(id).matches()) {
        idSet.add(new SRS(id));
      }
    }

    List<SRS> srsList = new ArrayList<SRS>(idSet);
    Collections.sort(srsList, new CodeComparator()); // sort to get them in order
    return srsList;
  }

  /**
   * Compares the codes so that most of the codes ger compared as numbers, but unfortunately some
   * non numeric ones can sneak in...
   *
   * @author Andrea Aime - TOPP
   */
  private static class CodeComparator implements Comparator<SRS> {

    public int compare(SRS srs1, SRS srs2) {
      String s1 = srs1.getCode();
      String s2 = srs2.getCode();
      Integer c1 = null, c2 = null;
      try {
        c1 = Integer.parseInt(s1);
      } catch (NumberFormatException e) {
        //
      }
      try {
        c2 = Integer.parseInt(s2);
      } catch (NumberFormatException e) {
        //
      }
      if (c1 == null) {
        if (c2 == null) return s1.compareTo(s2);
        else return -1;
      } else {
        if (c2 == null) return 1;
        else return c1 - c2;
      }
    }
  }
}
 /** Returns a factory of the given type. */
 private static final <T extends AbstractAuthorityFactory> T getFactory(final Class<T> type) {
   return type.cast(
       ReferencingFactoryFinder.getCRSAuthorityFactory(
           "EPSG", new Hints(Hints.CRS_AUTHORITY_FACTORY, type)));
 }
  public static CoordinateReferenceSystem getCRS(MapProjection projection, Datum datum) {
    CoordinateReferenceSystem result = WGS84;

    try {
      final MapTransform mapTransform = projection.getMapTransform();
      if (mapTransform.getDescriptor() instanceof IdentityTransformDescriptor) {
        // 1. Identity map projection
        if (Datum.ITRF_97.equals(datum)) {
          result = ITRF97;
        } else if (Datum.WGS_72.equals(datum)) {
          result = WGS72;
        }
      } else if (projection instanceof UTMProjection && !Datum.ITRF_97.equals(datum)) {
        // 2. UTM map projections
        final UTMProjection utmProjection = (UTMProjection) projection;
        final int zone = utmProjection.getZone();

        if (zone >= 1 && zone <= 60) {
          final CRSAuthorityFactory factory =
              ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null);
          if (utmProjection.isNorth()) {
            if (Datum.WGS_72.equals(datum)) {
              final int WGS72_UTM_zone_N_BASE = 32200;
              result = factory.createProjectedCRS("EPSG:" + (WGS72_UTM_zone_N_BASE + zone));
            } else if (Datum.WGS_84.equals(datum)) {
              final int WGS84_UTM_zone_N_BASE = 32600;
              result = factory.createProjectedCRS("EPSG:" + (WGS84_UTM_zone_N_BASE + zone));
            }
          } else {
            if (Datum.WGS_72.equals(datum)) {
              final int WGS72_UTM_zone_S_BASE = 32300;
              result = factory.createProjectedCRS("EPSG:" + (WGS72_UTM_zone_S_BASE + zone));
            } else if (Datum.WGS_84.equals(datum)) {
              final int WGS84_UTM_zone_S_BASE = 32700;
              result = factory.createProjectedCRS("EPSG:" + (WGS84_UTM_zone_S_BASE + zone));
            }
          }
        }
      } else if (Datum.ITRF_97.equals(datum)) {
        // 3. Other map projections
        final String crsName = "ITRF 97 / " + mapTransform.getDescriptor().getName();
        final MathTransform mathTransform = getMathTransform(mapTransform);
        if (mathTransform != null) {
          result =
              new DefaultProjectedCRS(crsName, ITRF97, mathTransform, DefaultCartesianCS.PROJECTED);
        }
      } else if (Datum.WGS_72.equals(datum)) {
        final String crsName = "WGS 72 / " + mapTransform.getDescriptor().getName();
        final MathTransform mathTransform = getMathTransform(mapTransform);
        if (mathTransform != null) {
          result =
              new DefaultProjectedCRS(crsName, WGS72, mathTransform, DefaultCartesianCS.PROJECTED);
        }
      } else if (Datum.WGS_84.equals(datum)) {
        final String crsName = "WGS 84 / " + mapTransform.getDescriptor().getName();
        final MathTransform mathTransform = getMathTransform(mapTransform);
        if (mathTransform != null) {
          result =
              new DefaultProjectedCRS(crsName, WGS84, mathTransform, DefaultCartesianCS.PROJECTED);
        }
      }
    } catch (FactoryException e) {
      // ignore
    }

    return result;
  }