001: package org.geotools.data.sql;
002:
003: import java.io.IOException;
004: import java.util.HashMap;
005: import java.util.Iterator;
006: import java.util.Map;
007: import java.util.logging.Logger;
008:
009: import net.sf.jsqlparser.statement.select.PlainSelect;
010: import net.sf.jsqlparser.statement.select.SelectBody;
011: import net.sf.jsqlparser.statement.select.Union;
012:
013: /**
014: * Utility class to help DataStoreFactories for
015: * {@linkplain org.geotools.data.sql.SqlDataStore}s register the views provided
016: * in a <code>java.util.Map</code> in the call to the factory's
017: * <code>createDataStore(Map)</code> method.
018: * <p>
019: * Due to the non hierarchical nature of a Map, it is no so easy to provide a
020: * variable number of arguments on it for the same keyword, since they're
021: * usually read from a .properties file.
022: * <p>
023: * </p>
024: * This class helps to minimize the work needed to provide such a mapping of
025: * various SQL views to an in-process feature type by defining the following
026: * structure for a Map<String,String> passed to createDataStore. Example
027: * .properties file:
028: *
029: * <pre><code>
030: * dbtype=...
031: * <usual datastore's parameters>...
032: * sqlView.1.typeName = ViewType1
033: * sqlView.1.sqlQuery = select gid, the_geom, table2.someField \
034: * from table1, table2 \
035: * where table1.gid = table2.table1_id
036: *
037: * sqlView.2.typeName = ViewType2
038: * sqlView.2.sqlQuery = select ...
039: * </code></pre>
040: *
041: * This way, this class' utility method
042: * {@linkplain #registerSqlViews(SqlDataStore, Map)} will receive a
043: * {@linkplain org.geotools.data.sql.SqlDataStore} and the Map of datastore
044: * factory parameters and call
045: * {@linkplain org.geotools.data.sql.SqlDataStore#registerView(String, String)}
046: * for each pair of <code>sqlView.N.typeName, sqlView.N.sqlQuery</code>
047: * </p>
048: *
049: * @author Gabriel Roldan, Axios Engineering
050: */
051: public class ViewRegisteringFactoryHelper {
052: private static final Logger LOGGER = org.geotools.util.logging.Logging
053: .getLogger(ViewRegisteringFactoryHelper.class.getPackage()
054: .getName());
055:
056: private ViewRegisteringFactoryHelper() {
057: // no-op
058: }
059:
060: /**
061: * Registers the sql views provided in <code>params</code> on the
062: * SqlDataStore <code>dataStore</code>
063: *
064: * @param dataStore
065: * @param params
066: * @throws IOException
067: */
068: public static void registerSqlViews(SqlDataStore dataStore,
069: Map params) throws IOException {
070: Map cleanedUp = cleanUpViewDefinitions(params);
071: for (Iterator it = cleanedUp.entrySet().iterator(); it
072: .hasNext();) {
073: Map.Entry entry = (Map.Entry) it.next();
074: String typeName = (String) entry.getKey();
075: String sqlQuery = (String) entry.getValue();
076:
077: LOGGER.finer("registering view " + typeName);
078: LOGGER.finest("sql query is '" + sqlQuery + "'");
079:
080: SelectBody selectBody = SqlParser.parse(sqlQuery);
081: if (selectBody instanceof Union) {
082: dataStore.registerView(typeName, (Union) selectBody);
083: } else if (selectBody instanceof PlainSelect) {
084: dataStore.registerView(typeName,
085: (PlainSelect) selectBody);
086: } else {
087: throw new IllegalStateException(selectBody.getClass()
088: .getName());
089: }
090:
091: //dataStore.registerView(typeName, sqlQuery);
092:
093: }
094: }
095:
096: /**
097: * Looks up the set of "surrogate.XYZ" keys
098: * in <code>params</code> and returns a cleaned up map of XYZ/value.
099: *
100: * @param params
101: * @return
102: */
103: static Map cleanUpSurrogateParams(Map params) {
104: Map cleanedUpParams = new HashMap();
105: for (Iterator it = params.keySet().iterator(); it.hasNext();) {
106: final String key = (String) it.next();
107: if (!key.startsWith("surrogate.")) {
108: continue;
109: }
110:
111: String clean = key.substring("surrogate.".length());
112: cleanedUpParams.put(clean, params.get(key));
113: }
114: return cleanedUpParams;
115: }
116:
117: /**
118: * Looks up the set of "sqlView.N.typeName" and "sqlView.N.sqlQuery" keys
119: * in <code>params</code> and returns a cleaned up map of typeName/query.
120: *
121: * @param params
122: * @return
123: */
124: public static Map cleanUpViewDefinitions(Map params) {
125: Map cleanedUpViews = new HashMap();
126: for (Iterator it = params.keySet().iterator(); it.hasNext();) {
127: String key = (String) it.next();
128: if (!key.startsWith("sqlView.")) {
129: continue;
130: }
131: if (!key.endsWith(".typeName")) {
132: continue;
133: }
134:
135: String typeName = (String) params.get(key);
136:
137: String viewId = key.substring("sqlView.".length(), key
138: .indexOf(".typeName"));
139:
140: String queryKey = "sqlView." + viewId + ".sqlQuery";
141:
142: String query = (String) params.get(queryKey);
143: if (query == null) {
144: throw new IllegalArgumentException(
145: "No SQL query definition provided for type name "
146: + typeName);
147: }
148: cleanedUpViews.put(typeName, query);
149: }
150: return cleanedUpViews;
151: }
152:
153: }
|