package au.org.aurin.wif.io;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geotools.data.DataStore;
import org.geotools.data.Query;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.wfs.WFSDataStore;
import org.geotools.factory.Hints;
import org.geotools.feature.type.AttributeTypeImpl;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.Filter;
import org.opengis.geometry.BoundingBox;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
/**
* A representation of a geospatial dataset.
*
* @author Gerson Galang
*/
public class GeospatialDatasetImpl implements GeospatialDataset {
/** The logger. */
private static final Log LOGGER = LogFactory
.getLog(GeospatialDatasetImpl.class);
protected SimpleFeatureSource featureSource;
private final DataSource dataSource;
private final CRSAuthorityFactory crsFactory;
/**
* Construct a GeospatialDatasetImpl object.
* <p>
* The constructor for this class was given a friendly access to hide how it
* is implemented and to force users to only use the DataSourceFactory to get
* instances of the GeospatialDataset implementations.
* </p>
*
* @param featureSource
*/
GeospatialDatasetImpl(final DataSource dataSource,
final SimpleFeatureSource featureSource) {
this.dataSource = dataSource;
this.featureSource = featureSource;
final Hints hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER,
Boolean.TRUE);
crsFactory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", hints);
}
public SimpleFeatureSource getFeatureSource() {
return featureSource;
}
public String getName() {
return featureSource.getSchema().getTypeName();
}
public SimpleFeatureCollection getFeatures(final DatasetQueryParams params)
throws InvalidDataQueryParamsException, DatasetAccessException {
final String[] propertyNames = params.getPropertyNamesToReturn();
final Filter filter = params.getFilter();
final String srsName = params.getSrsName();
try {
final Query query = new Query(getName());
if (filter != null) {
query.setFilter(filter);
}
if (propertyNames != null && propertyNames.length > 0) {
query.setPropertyNames(propertyNames);
}
if (srsName != null) {
final CoordinateReferenceSystem crs = crsFactory
.createCoordinateReferenceSystem(srsName);
// TODO: do we really need to call both of these methods?
query.setCoordinateSystem(crs);
// query.setCoordinateSystemReproject(crs);
}
final DataStore dataStore = (DataStore) featureSource.getDataStore();
if (WfsUtil.isWfsDataStore(dataStore)) {
final WFSDataStore wfsDataStore = (WFSDataStore) dataStore;
if (WfsUtil.isWfsVersion1_0_0(wfsDataStore)) {
// TODO: need to rethink of how to support different versions of WFS
// again!!!
LOGGER.info("Using getFeature 1.0.0");
return ((AbstractGeospatialDataSource) getDataSource()).wfsWorkaround
.getFeatures_1_0_0(getName(), propertyNames,
params.getCQLFilterString(), srsName);
}
}
// use the new way of performing getFeatures for WFS 1.1 and above
return featureSource.getFeatures(query);
} catch (final IOException e) {
LOGGER.error("IOException was thrown while calling getFeatures!", e);
throw new DatasetAccessException(
e.getMessage(),
"A communication exception has occurred while trying to access the remote dataset. Please, try later or notify AURIN if the problem persists",
e);
} catch (final NoSuchAuthorityCodeException e) {
LOGGER.error(
"NoSuchAuthorityCodeException was thrown while calling getFeatures!",
e);
throw new InvalidDataQueryParamsException(e.getMessage(), e);
} catch (final FactoryException e) {
LOGGER.error("FactoryException was thrown while calling getFeatures!", e);
throw new DatasetAccessException(
e.getMessage(),
"An internal error occured when trying to access the dataset. Please, notify AURIN about this problem.",
e);
}
}
public BoundingBox getBoundingBox() {
try {
final BoundingBox bbox = featureSource.getBounds();
return bbox;
} catch (final IOException e) {
LOGGER.error("Error while getting the bounding box", e);
return null;
}
}
public CoordinateReferenceSystem getSRS() {
return featureSource.getSchema().getCoordinateReferenceSystem();
}
public List<DatasetAttribute> getAttributes() {
// convert the list of AttributeDescriptors into a list of DatasetAttributes
final List<DatasetAttribute> attributes = new ArrayList<DatasetAttribute>();
for (final AttributeDescriptor attrDescriptor : getAttributeDescriptors()) {
attributes.add(new DatasetAttribute(attrDescriptor.getLocalName(),
((AttributeTypeImpl) attrDescriptor.getType()).getBinding().getName()
.toString()));
}
return attributes;
}
public GeometryDescriptor getGeometryAttribute() {
return featureSource.getSchema().getGeometryDescriptor();
}
public List<AttributeDescriptor> getAttributeDescriptors() {
return featureSource.getSchema().getAttributeDescriptors();
}
public DataCollection getData(final DatasetQueryParams params)
throws InvalidDataQueryParamsException, DatasetAccessException {
return new DataCollection(getFeatures(params));
}
public DataSource getDataSource() {
return dataSource;
}
}