/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2006-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.sql;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.Union;
/**
* Utility class to help DataStoreFactories for
* {@linkplain org.geotools.data.sql.SqlDataStore}s register the views provided
* in a <code>java.util.Map</code> in the call to the factory's
* <code>createDataStore(Map)</code> method.
* <p>
* Due to the non hierarchical nature of a Map, it is no so easy to provide a
* variable number of arguments on it for the same keyword, since they're
* usually read from a .properties file.
* <p>
* </p>
* This class helps to minimize the work needed to provide such a mapping of
* various SQL views to an in-process feature type by defining the following
* structure for a Map<String,String> passed to createDataStore. Example
* .properties file:
*
* <pre><code>
* dbtype=...
* <usual datastore's parameters>...
* sqlView.1.typeName = ViewType1
* sqlView.1.sqlQuery = select gid, the_geom, table2.someField \
* from table1, table2 \
* where table1.gid = table2.table1_id
*
* sqlView.2.typeName = ViewType2
* sqlView.2.sqlQuery = select ...
* </code></pre>
*
* This way, this class' utility method
* {@linkplain #registerSqlViews(SqlDataStore, Map)} will receive a
* {@linkplain org.geotools.data.sql.SqlDataStore} and the Map of datastore
* factory parameters and call
* {@linkplain org.geotools.data.sql.SqlDataStore#registerView(String, String)}
* for each pair of <code>sqlView.N.typeName, sqlView.N.sqlQuery</code>
* </p>
*
* @author Gabriel Roldan, Axios Engineering
*
* @source $URL$
*/
public class ViewRegisteringFactoryHelper {
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(ViewRegisteringFactoryHelper.class.getPackage()
.getName());
private ViewRegisteringFactoryHelper() {
// no-op
}
/**
* Registers the sql views provided in <code>params</code> on the
* SqlDataStore <code>dataStore</code>
*
* @param dataStore
* @param params
* @throws IOException
*/
public static void registerSqlViews(SqlDataStore dataStore, Map params)
throws IOException {
Map cleanedUp = cleanUpViewDefinitions(params);
for (Iterator it = cleanedUp.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String typeName = (String) entry.getKey();
String sqlQuery = (String) entry.getValue();
LOGGER.finer("registering view " + typeName);
LOGGER.finest("sql query is '" + sqlQuery + "'");
SelectBody selectBody = SqlParser.parse(sqlQuery);
if(selectBody instanceof Union){
dataStore.registerView(typeName, (Union)selectBody);
}else if(selectBody instanceof PlainSelect){
dataStore.registerView(typeName, (PlainSelect)selectBody);
}else{
throw new IllegalStateException(selectBody.getClass().getName());
}
//dataStore.registerView(typeName, sqlQuery);
}
}
/**
* Looks up the set of "surrogate.XYZ" keys
* in <code>params</code> and returns a cleaned up map of XYZ/value.
*
* @param params
* @return
*/
static Map cleanUpSurrogateParams(Map params) {
Map cleanedUpParams = new HashMap();
for (Iterator it = params.keySet().iterator(); it.hasNext();) {
final String key = (String) it.next();
if (!key.startsWith("surrogate.")) {
continue;
}
String clean = key.substring("surrogate.".length());
cleanedUpParams.put(clean, params.get(key));
}
return cleanedUpParams;
}
/**
* Looks up the set of "sqlView.N.typeName" and "sqlView.N.sqlQuery" keys
* in <code>params</code> and returns a cleaned up map of typeName/query.
*
* @param params
* @return
*/
public static Map cleanUpViewDefinitions(Map params) {
Map cleanedUpViews = new HashMap();
for (Iterator it = params.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
if (!key.startsWith("sqlView.")) {
continue;
}
if (!key.endsWith(".typeName")) {
continue;
}
String typeName = (String) params.get(key);
String viewId = key.substring("sqlView.".length(), key
.indexOf(".typeName"));
String queryKey = "sqlView." + viewId + ".sqlQuery";
String query = (String) params.get(queryKey);
if (query == null) {
throw new IllegalArgumentException(
"No SQL query definition provided for type name "
+ typeName);
}
cleanedUpViews.put(typeName, query);
}
return cleanedUpViews;
}
}