/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.data.ogr;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.data.DataSourceException;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.util.logging.Logging;
/**
* Implementation of the DataStore service provider interface for OGR.
*
* @author Andrea Aime, GeoSolution
*
*
*
* @source $URL$
* @version $Id$
*/
@SuppressWarnings("rawtypes")
public abstract class OGRDataStoreFactory implements DataStoreFactorySpi {
protected static Logger LOGGER = Logging.getLogger("org.geotools.data.ogr");
public static final Param OGR_NAME = new Param("DatasourceName", String.class,
"Name of the file, or data source to try and open", true);
public static final Param OGR_DRIVER_NAME = new Param(
"DriverName",
String.class,
"Name of the OGR driver to be used. Required to create a new data source, optional when opening an existing one",
false);
public static final Param NAMESPACEP = new Param("namespace", URI.class,
"uri to a the namespace", false); // not required
/**
* Caches opened data stores. TODO: is this beneficial or problematic? It's a static cache, so
* opening a lot of datastore (thousands, hundreds of thousands...) may become a memory problem.
* Plus OGR is not designed to be thread safe.
*/
private Map liveStores = new HashMap();
protected abstract OGR createOGR();
public boolean canProcess(Map params) {
boolean accept = false;
String ogrName = null;
String ogrDriver = null;
try {
ogrName = (String) OGR_NAME.lookUp(params);
} catch (IOException ioe) {
// yes, I am eating this
}
try {
ogrDriver = (String) OGR_DRIVER_NAME.lookUp(params);
} catch (IOException ioe) {
// yes, I am eating this
}
accept = canProcess(ogrName, ogrDriver);
return accept;
}
public DataStore createDataStore(Map params) throws IOException {
DataStore ds = null;
if (!liveStores.containsKey(params)) {
URL url = null;
try {
ds = createNewDataStore(params);
liveStores.put(params, ds);
} catch (MalformedURLException mue) {
throw new DataSourceException("Unable to attatch datastore to " + url, mue);
}
} else
ds = (DataStore) liveStores.get(params);
return ds;
}
/**
* Not implemented yet.
*
* @param params
*
* @throws IOException
*
* @throws IOException DOCUMENT ME!
* @throws UnsupportedOperationException
*/
public DataStore createNewDataStore(Map params) throws IOException {
DataStore ds = null;
String ogrName = (String) OGR_NAME.lookUp(params);
String ogrDriver = (String) OGR_DRIVER_NAME.lookUp(params);
URI namespace = (URI) NAMESPACEP.lookUp(params);
ds = new OGRDataStore(ogrName, ogrDriver, namespace, createOGR());
return ds;
}
public String getDisplayName() {
return "OGR";
}
/**
* Describes the type of data the datastore returned by this factory works with.
*
* @return String a human readable description of the type of restore supported by this
* datastore.
*/
public String getDescription() {
return "Uses OGR as a data source";
}
/**
* Test to see if this datastore is available, if it has all the appropriate libraries to
* construct a datastore.
*
* @return <tt>true</tt> if and only if this factory is available to create DataStores.
*
* @task REVISIT: I'm just adding this method to compile, maintainer should revisit to check for
* any libraries that may be necessary for datastore creations.
*/
public final boolean isAvailable() {
return isAvailable(true);
}
/**
* Performs the available test specifying how to handle errors.
* <p>
* Specifying true for <tt>handleError</tt> will cause any exceptions to be caught and logged,
* and return false
* </p>
*/
public final boolean isAvailable(boolean handleError) {
try {
return doIsAvailable();
} catch (Throwable t) {
if (handleError) {
LOGGER.log(Level.FINE, "Error initializing GDAL/OGR library", t);
return false;
}
else {
throw new RuntimeException(t);
}
}
}
/**
* Performs the actual test to see if the OGR library and this datastore is available.
* <p>
* Implemetnations of this method should not attempt to handle any fatal exceptions.
* </p>
*/
protected abstract boolean doIsAvailable() throws Throwable;
/**
* Describe parameters.
*
*
* @see org.geotools.data.DataStoreFactorySpi#getParametersInfo()
*/
public Param[] getParametersInfo() {
return new Param[] { OGR_NAME, OGR_DRIVER_NAME, NAMESPACEP };
}
/**
* Assume we can process an ogrName if the ogrName exists and can be opened, or if the specified
* driver does exist.
*
* @param ogrName
* @param driverName
* @return
*/
public boolean canProcess(String ogrName, String driverName) {
OGR ogr = createOGR();
Object dataset = ogr.OpenShared(ogrName, 0);
if (dataset != null) {
//OGRReleaseDataSource(dataset);
ogr.DataSourceRelease(dataset);
return true;
}
if (driverName != null) {
try {
Object driver = ogr.GetDriverByName(driverName);
if (driver != null) {
return true;
}
}
catch(Exception e) {
LOGGER.log(Level.FINE, "Error loading driver", e);
}
}
return false;
}
public Set<String> getAvailableDrivers() {
OGR ogr = createOGR();
int count = ogr.GetDriverCount();
Set<String> result = new HashSet<String>();
for (int i = 0; i < count; i++) {
Object driver = ogr.GetDriver(i);
String name = ogr.DriverGetName(driver);
result.add(name);
}
return result;
}
public Map getImplementationHints() {
return Collections.EMPTY_MAP;
}
}