001: /**
002: * Objective Database Abstraction Layer (ODAL)
003: * Copyright (c) 2004, The ODAL Development Group
004: * All rights reserved.
005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
006: *
007: * Distributable under LGPL license.
008: * See terms of license at gnu.org.
009: */package com.completex.objective.components.persistency.meta.impl;
010:
011: import com.completex.objective.components.log.Log;
012: import com.completex.objective.components.persistency.AbstractParameters;
013: import com.completex.objective.components.persistency.BasicManagedQueryFactory;
014: import com.completex.objective.components.persistency.BasicQuery;
015: import com.completex.objective.components.persistency.Call;
016: import com.completex.objective.components.persistency.ColumnType;
017: import com.completex.objective.components.persistency.JavaToMetaType;
018: import com.completex.objective.components.persistency.MetaColumn;
019: import com.completex.objective.components.persistency.MetaTable;
020: import com.completex.objective.components.persistency.Persistency2;
021: import com.completex.objective.components.persistency.Query;
022: import com.completex.objective.components.persistency.QueryFactoryBase;
023: import com.completex.objective.components.persistency.core.ResultSetIterator;
024: import com.completex.objective.components.persistency.meta.MetaModel;
025: import com.completex.objective.components.persistency.meta.ModelLoader;
026: import com.completex.objective.components.persistency.transact.Transaction;
027:
028: import java.sql.PreparedStatement;
029: import java.sql.ResultSet;
030: import java.sql.ResultSetMetaData;
031: import java.sql.SQLException;
032: import java.util.ArrayList;
033: import java.util.HashSet;
034: import java.util.Iterator;
035: import java.util.LinkedHashMap;
036: import java.util.List;
037: import java.util.Map;
038:
039: /**
040: * @author Gennady Krizhevsky
041: */
042: public class QueryModelLoaderImpl extends AbstractDatabaseModelLoader
043: implements ModelLoader {
044:
045: protected static final int MOKE_COLUMN_SIZE = 20;
046: protected static final int MOKE_DECIMAL_DIGITS = 1;
047: private Persistency2 persistency;
048: private BasicManagedQueryFactory[] factories;
049: private TableNames tableNames;
050: private JavaToMetaType javaToMetaType;
051: private Log logger = Log.NULL_LOGGER;
052:
053: public QueryModelLoaderImpl(Persistency2 persistency,
054: BasicManagedQueryFactory[] factories,
055: TableNames tableNames, String filterPattern,
056: JavaToMetaType javaToMetaType, Log logger) {
057: super (filterPattern);
058: this .persistency = persistency;
059: this .factories = factories;
060: this .tableNames = tableNames;
061: this .javaToMetaType = javaToMetaType;
062: this .logger = logger;
063: setup(factories, persistency);
064: }
065:
066: public static BasicManagedQueryFactory instantiateFactory(
067: String factoryClassName) {
068: BasicManagedQueryFactory factory;
069: try {
070: factory = (BasicManagedQueryFactory) Class.forName(
071: factoryClassName).newInstance();
072: } catch (Exception e) {
073: throw new IllegalArgumentException(
074: "Cannot instantiate query factory by class name ["
075: + factoryClassName + "]");
076: }
077: return factory;
078: }
079:
080: private void setup(BasicManagedQueryFactory[] factories,
081: Persistency2 persistency) {
082: for (int i = 0; i < factories.length; i++) {
083: BasicManagedQueryFactory factory = factories[i];
084: QueryFactoryBase delegateFactory = BasicManagedQueryFactory.SupportedDelegates
085: .selectDelegate(factory, persistency);
086: factories[i].setDelegate(delegateFactory);
087: }
088: }
089:
090: public MetaModel load(MetaModel model) throws Exception {
091: debug("QueryModelLoaderImpl.load:: enter");
092: if (model == null) {
093: model = new MetaModel(filterPattern);
094: }
095: HashSet seenNames = new HashSet();
096: Transaction transaction = persistency.getTransactionManager()
097: .begin();
098: ResultSet columnsResultSet = null;
099: debug("model = " + model);
100: try {
101: for (int i = 0; i < factories.length; i++) {
102: BasicManagedQueryFactory factory = factories[i];
103: BasicQuery query = prepareQuery(factory, seenNames);
104: String tableName = query.getName();
105: if (!model.isTableAllowed(tableName)) {
106: continue;
107: }
108: // debug("Loading meta data for tableName: " + tableName);
109: MetaTable table = defineTable(model, tableName);
110: if (table == null) {
111: continue;
112: }
113:
114: PreparedStatement statement;
115: AbstractParameters parameters;
116: if (query instanceof Query) {
117: Query castQuery = ((Query) query);
118: statement = persistency.prepareStatement(
119: transaction, castQuery, new StringBuffer());
120: parameters = castQuery.getParameters();
121: } else if (query instanceof Call) {
122: Call castCall = ((Call) query);
123: statement = persistency.prepareCall(transaction,
124: castCall, new StringBuffer());
125: parameters = castCall.getParameters();
126: } else {
127: throw new IllegalArgumentException(
128: "Unsupported query type " + query);
129: }
130:
131: TableCounters tableCounters = new TableCounters();
132: ResultSetIterator resultSetIterator = persistency
133: .resultSetIterator(statement, parameters);
134: int index = 0;
135: try {
136: while (resultSetIterator.next()) {
137: columnsResultSet = resultSetIterator
138: .getResultSet();
139: boolean containsCount = tableCounters
140: .containsCount(table.getTableName());
141: String alias = null;
142: if (tableNames != null
143: && tableNames
144: .hasAlias(tableName, index)) {
145: alias = tableNames.getAlias(tableName,
146: index);
147: table = defineTable(model, alias);
148: }
149: if (containsCount) {
150: if (alias == null) {
151: alias = makeNewTableName(tableCounters,
152: tableName);
153: table = defineTable(model, alias);
154: }
155: }
156: processOne(columnsResultSet, model, table);
157: tableCounters.increaseCount(tableName);
158: index++;
159: }
160: } finally {
161: closeRs(columnsResultSet);
162: }
163: }
164: } catch (SQLException e) {
165: throw new Exception("Cannot get database meta-data", e);
166: } finally {
167:
168: try {
169: persistency.getTransactionManager().rollback(
170: transaction);
171: } catch (SQLException e) {
172: // Do nothing
173: }
174: debug("QueryModelLoaderImpl.load:: exit");
175: }
176: return model;
177: }
178:
179: private String makeNewTableName(TableCounters tableCounters,
180: String tableName) {
181: int count = tableCounters.getCount(tableName);
182: return tableName + "_" + count;
183: }
184:
185: private void processOne(ResultSet columnsResultSet,
186: MetaModel model, MetaTable table) throws SQLException {
187: ResultSetMetaData rsMetaColsInfo = columnsResultSet
188: .getMetaData();
189:
190: for (int k = 1; k <= rsMetaColsInfo.getColumnCount(); k++) {
191: String columnName = rsMetaColsInfo.getColumnName(k);
192:
193: debug("Columns col " + "name ["
194: + rsMetaColsInfo.getColumnName(k)
195: + "]; isAutoIncrement ["
196: + rsMetaColsInfo.isAutoIncrement(k) + "]");
197: boolean required = rsMetaColsInfo.isNullable(k) == ResultSetMetaData.columnNoNulls;
198: ColumnInfo columnInfo = new ColumnInfo(columnName,
199: rsMetaColsInfo.isAutoIncrement(k), rsMetaColsInfo
200: .getColumnType(k), rsMetaColsInfo
201: .getColumnTypeName(k));
202: debug(columnInfo.toString());
203:
204: MetaColumn column = defineColumn(model, table, columnName,
205: columnInfo.jdbcType, columnType(String
206: .valueOf(columnInfo.jdbcType),
207: MOKE_COLUMN_SIZE, MOKE_DECIMAL_DIGITS,
208: required), "Y", null, null,
209: MOKE_COLUMN_SIZE, MOKE_DECIMAL_DIGITS, columnInfo);
210: column.setColumnIndex(k);
211: }
212: }
213:
214: protected void debug(String message) {
215: logger.debug(message);
216: }
217:
218: protected void info(String message) {
219: logger.info(message);
220: }
221:
222: protected ColumnType columnType(String dataType, int columnSize,
223: int decimalDigits, boolean required) {
224: return javaToMetaType.dataType(dataType, columnSize,
225: decimalDigits, required);
226: }
227:
228: public void setJavaToMetaType(JavaToMetaType javaToMetaType) {
229: this .javaToMetaType = javaToMetaType;
230: }
231:
232: //
233: // Util classes:
234: //
235: protected static class TableCounters {
236:
237: private LinkedHashMap tableCounters = new LinkedHashMap();
238:
239: public int getCount(String tableName) {
240: Integer count = (Integer) tableCounters.get(tableName);
241: return count == null ? 0 : count.intValue();
242: }
243:
244: public int increaseCount(String tableName) {
245: int count = getCount(tableName);
246: count++;
247: tableCounters.put(tableName, new Integer(count));
248: return count;
249: }
250:
251: public boolean containsCount(String tableName) {
252: return tableCounters.containsKey(tableName);
253: }
254: }
255:
256: /**
257: *
258: */
259: public static class TableNames {
260: private Map tableNames;
261:
262: public TableNames(Map tableNames) {
263: parse(tableNames);
264: }
265:
266: public void parse(Map tableNames) {
267: this .tableNames = tableNames;
268:
269: for (Iterator it = this .tableNames.entrySet().iterator(); it
270: .hasNext();) {
271: Map.Entry entry = (Map.Entry) it.next();
272: List aliasesList = (List) entry.getValue();
273: String[] aliases = getAliases(aliasesList);
274: entry.setValue(aliases);
275: }
276: }
277:
278: public int size(String tableName) {
279: return getAliases(tableName).length;
280: }
281:
282: private String[] getAliases(String tableName) {
283: Object values = tableNames.get(tableName);
284: return values == null ? new String[0] : (String[]) values;
285: }
286:
287: private String[] getAliases(List names) {
288: String[] aliases;
289: if (names != null) {
290: ArrayList list = new ArrayList(names.size());
291: list.addAll(names);
292: aliases = (String[]) list.toArray(new String[list
293: .size()]);
294: } else {
295: aliases = new String[0];
296: }
297: return aliases;
298: }
299:
300: public String getAlias(String tableName, int index) {
301: String[] aliases = getAliases(tableName);
302: return aliases[index];
303: }
304:
305: public boolean hasAlias(String tableName, int index) {
306: return index < size(tableName);
307: }
308: }
309:
310: }
|