/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.ui.crs;
import org.esa.snap.core.datamodel.GeoPos;
import org.geotools.factory.Hints;
import org.geotools.metadata.iso.citation.Citations;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.geotools.referencing.factory.FallbackAuthorityFactory;
import org.geotools.referencing.factory.wms.AutoCRSFactory;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeodeticCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author Marco Peters
* @author Marco Zühlke
* @since BEAM 4.7
*/
class CrsInfo implements Comparable<CrsInfo> {
private static final String AUTHORITY = "EPSG";
private final String crsCode;
private final CRSAuthorityFactory factory;
CrsInfo(String crsCode, CRSAuthorityFactory factory) {
this.crsCode = crsCode;
this.factory = factory;
}
public CoordinateReferenceSystem getCrs(GeoPos referencePos) throws FactoryException {
return factory.createCoordinateReferenceSystem(crsCode);
}
@Override
public int compareTo(CrsInfo o) {
return crsCode.compareTo(o.crsCode);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CrsInfo)) {
return false;
}
CrsInfo crsInfo = (CrsInfo) o;
return !(crsCode != null ? !crsCode.equals(crsInfo.crsCode) : crsInfo.crsCode != null);
}
@Override
public int hashCode() {
return crsCode != null ? crsCode.hashCode() : 0;
}
@Override
public String toString() {
String crsDescription = crsCode + " - ";
try {
crsDescription += factory.getDescriptionText(crsCode).toString();
} catch (Exception e) {
crsDescription += e.getLocalizedMessage();
}
return crsDescription;
}
public String getDescription() {
try {
return getCrs(null).toString();
} catch (FactoryException e) {
return e.getMessage();
}
}
private static class AutoCrsInfo extends CrsInfo {
AutoCrsInfo(String epsgCode, CRSAuthorityFactory factory) {
super(epsgCode, factory);
}
@Override
public CoordinateReferenceSystem getCrs(GeoPos referencePos) throws FactoryException {
if (referencePos == null) {
referencePos = new GeoPos(0, 0);
}
String code = String.format("%s,%s,%s", super.crsCode, referencePos.lon, referencePos.lat);
return super.factory.createCoordinateReferenceSystem(code);
}
@Override
public String toString() {
String crsDescription = super.crsCode + " - ";
try {
String code = super.crsCode + ",0,0";
crsDescription += super.factory.getDescriptionText(code).toString();
} catch (Exception e) {
crsDescription += e.getLocalizedMessage();
}
return crsDescription;
}
@Override
public String getDescription() {
return toString();
}
}
static List<CrsInfo> generateCRSList() {
// todo - (mp/mz) this method takes time (2 sec.) try to speed up
Hints hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, true);
Set<CRSAuthorityFactory> factories = ReferencingFactoryFinder.getCRSAuthorityFactories(hints);
final List<CRSAuthorityFactory> filtered = new ArrayList<CRSAuthorityFactory>();
for (final CRSAuthorityFactory factory : factories) {
if (Citations.identifierMatches(factory.getAuthority(), AUTHORITY)) {
filtered.add(factory);
}
}
CRSAuthorityFactory crsAuthorityFactory = FallbackAuthorityFactory.create(CRSAuthorityFactory.class, filtered);
Set<String> codes = new HashSet<String>();
List<CrsInfo> crsList = new ArrayList<CrsInfo>(1024);
retrieveCodes(codes, GeodeticCRS.class, crsAuthorityFactory);
retrieveCodes(codes, ProjectedCRS.class, crsAuthorityFactory);
for (String code : codes) {
final String authCode = String.format("%s:%s", AUTHORITY, code);
crsList.add(new CrsInfo(authCode, crsAuthorityFactory));
}
codes.clear();
AutoCRSFactory autoCRSFactory = new AutoCRSFactory();
retrieveCodes(codes, ProjectedCRS.class, autoCRSFactory);
for (String code : codes) {
final String authCode = String.format("AUTO:%s", code);
crsList.add(new AutoCrsInfo(authCode, autoCRSFactory));
}
Collections.sort(crsList);
return crsList;
}
private static void retrieveCodes(Set<String> codes, Class<? extends CoordinateReferenceSystem> crsType,
CRSAuthorityFactory factory) {
Set<String> localCodes;
try {
localCodes = factory.getAuthorityCodes(crsType);
} catch (FactoryException ignore) {
return;
}
codes.addAll(localCodes);
}
}