/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2003-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; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.geotools.data.DataAccessFactory.Param; import org.geotools.parameter.DefaultParameterDescriptor; import org.geotools.parameter.DefaultParameterDescriptorGroup; import org.geotools.parameter.FloatParameter; import org.geotools.parameter.Parameter; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterValue; /** * A best of toolkit for DataStoreFactory implementors. * <p> * Will also allow me to mess with the interface API without breaking every * last DataStoreFactorySpi out there. * </p> * <p> * The default implementations often hinge around the use of * getParameterInfo and the correct use of Param by your subclass. * </p> * <p> * You still have to implement a few methods: * </p> * <pre><code> * public DataSourceMetadataEnity createMetadata( Map params ) throws IOException { * String host = (String) HOST.lookUp(params); * String user = (String) USER.lookUp(params); * Integer port = (Integer) PORT.lookUp(params); * String database = (String) DATABASE.lookUp(params); * * String description = "Connection to "+getDisplayName()+" on "+host+" as "+user ; * return new DataSourceMetadataEnity( host+":"+port, database, description ); * }</code></pre> * * @author Jody Garnett, Refractions Research * * @source $URL$ */ public abstract class AbstractDataStoreFactory implements DataStoreFactorySpi { /** Default Implementation abuses the naming convention. * <p> * Will return <code>Foo</code> for * <code>org.geotools.data.foo.FooFactory</code>. * </p> * @return return display name based on class name */ public String getDisplayName() { String name = this.getClass().getName(); name = name.substring( name.lastIndexOf('.') ); if( name.endsWith("Factory")){ name = name.substring(0, name.length()-7); } else if( name.endsWith("FactorySpi")){ name = name.substring(0, name.length()-10); } return name; } /** * Default implementation verifies the Map against the Param information. * <p> * It will ensure that: * <ul> * <li>params is not null * <li>Everything is of the correct type (or upcovertable * to the correct type without Error) * <li>Required Parameters are present * </ul> * </p> * <p> * <p> * Why would you ever want to override this method? * If you want to check that a expected file exists and is a directory. * </p> * Overrride: * <pre><code> * public boolean canProcess( Map params ) { * if( !super.canProcess( params ) ){ * return false; // was not in agreement with getParametersInfo * } * // example check * File file = (File) DIRECTORY.lookup( params ); // DIRECTORY is a param * return file.exists() && file.isDirectory(); * } * </code></pre> * @param params * @return true if params is in agreement with getParametersInfo, override for additional checks. */ public boolean canProcess( Map params ) { if (params == null) { return false; } Param arrayParameters[] = getParametersInfo(); for (int i = 0; i < arrayParameters.length; i++) { Param param = arrayParameters[i]; Object value; if( !params.containsKey( param.key ) ){ if( param.required ){ return false; // missing required key! } else { continue; } } try { value = param.lookUp( params ); } catch (IOException e) { // could not upconvert/parse to expected type! // even if this parameter is not required // we are going to refuse to process // these params return false; } if( value == null ){ if (param.required) { return (false); } } else { if ( !param.type.isInstance( value )){ return false; // value was not of the required type } } } return true; } /** * Defaults to true, only a few datastores need to check for drivers. * * @return <code>true</code>, override to check for drivers etc... */ public boolean isAvailable() { return true; } public ParameterDescriptorGroup getParameters(){ Param params[] = getParametersInfo(); DefaultParameterDescriptor parameters[] = new DefaultParameterDescriptor[ params.length ]; for( int i=0; i<params.length; i++ ){ Param param = params[i]; parameters[i] = new ParamDescriptor( params[i] ); } Map properties = new HashMap(); properties.put( "name", getDisplayName() ); properties.put( "remarks", getDescription() ); return new DefaultParameterDescriptorGroup(properties, parameters); } /** * Returns the implementation hints. The default implementation returns en empty map. */ public Map<java.awt.RenderingHints.Key, ?> getImplementationHints() { return Collections.EMPTY_MAP; } } class ParamDescriptor extends DefaultParameterDescriptor { private static final long serialVersionUID = 1L; Param param; public ParamDescriptor(Param param) { super( DefaultParameterDescriptor.create(param.key, param.description, param.type, param.sample, param.required )); this.param = param; } public ParameterValue createValue() { if (Double.TYPE.equals( getValueClass())) { return new FloatParameter(this){ protected Object valueOf(String text) throws IOException { return param.handle( text ); } }; } return new Parameter(this){ protected Object valueOf(String text) throws IOException { return param.handle( text ); } }; } };