/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.modelgenerator.xml.model; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.teiid.designer.modelgenerator.xml.wizards.StateManager; import org.teiid.designer.schema.tools.NameUtil; import org.teiid.designer.schema.tools.model.schema.Column; import org.teiid.designer.schema.tools.model.schema.QName; import org.teiid.designer.schema.tools.model.schema.Relationship; import org.teiid.designer.schema.tools.model.schema.SchemaModel; import org.teiid.designer.schema.tools.model.schema.SchemaObject; import org.teiid.designer.schema.tools.model.schema.Type; import org.teiid.designer.schema.tools.model.schema.impl.SchemaModelImpl; import org.teiid.designer.schema.tools.processing.SchemaUtil; /** * @since 8.0 */ public class DatabaseMetaDataImpl extends DatabaseMetaDataBase { private static final String ELEMENT_TABLETYPE = "ELEMENT"; //$NON-NLS-1$ private static final String RELATIONSHIP_TABLETYPE = "RELATIONSHIP"; //$NON-NLS-1$ private static final String[] tableTypes = new String[] {ELEMENT_TABLETYPE, RELATIONSHIP_TABLETYPE}; private StateManager stateManager; private UserSettings userSettings; private List catalogsResultsetData; private List columnsResultsetData; private Map columnsByTableName; private List crossReferencesResultsetData; private Map crossReferencesByBothTableNames; private Map crossReferencesByPrimaryTableName; private Map crossReferencesByForeignTableName; private List primaryKeysResultsetData; private Map primaryKeysByTableName; private List tablesResultsetData; private Map tablesByTableName; private List tableTypesResultsetData; private Map tableNameInSourceMap; private Map columnNameInSourceMap; private Map primaryKeyNameInSourceMap; private Map foreignKeyNameInSourceMap; private Map tableSimpleNameMap; private Map columnSimpleNameMap; private Map primaryKeySimpleNameMap; private Map foreignKeySimpleNameMap; private Object syncObject; private SchemaModel schemaModel; private HashSet knownCatalogs; /** * */ public DatabaseMetaDataImpl( StateManager manager, UserSettings userSettings, Connection connection, Object syncObject ) { super(connection); this.stateManager = manager; this.syncObject = syncObject; this.userSettings = userSettings; } public void changed() { synchronized (syncObject) { initialize(); } } private void ensureInitialized() { } private void initialize() { tableTypesResultsetData = new ArrayList(); catalogsResultsetData = new ArrayList(); columnsResultsetData = new ArrayList(); columnsByTableName = new HashMap(); crossReferencesResultsetData = new ArrayList(); crossReferencesByBothTableNames = new HashMap(); crossReferencesByPrimaryTableName = new HashMap(); crossReferencesByForeignTableName = new HashMap(); primaryKeysResultsetData = new ArrayList(); primaryKeysByTableName = new HashMap(); tablesResultsetData = new ArrayList(); tablesByTableName = new HashMap(); tableNameInSourceMap = new HashMap(); columnNameInSourceMap = new HashMap(); primaryKeyNameInSourceMap = new HashMap(); foreignKeyNameInSourceMap = new HashMap(); tableSimpleNameMap = new HashMap(); columnSimpleNameMap = new HashMap(); primaryKeySimpleNameMap = new HashMap(); foreignKeySimpleNameMap = new HashMap(); knownCatalogs = new HashSet(); schemaModel = stateManager.getProcessedModel(); createMetadataForTableTypes(); createMetadataForCatalogs(); createMetadataForRequestTable(); createMetadataForTables(); if (exportSQL) { exportMetaData(); } } private void createMetadataForTables() { for (Iterator iter = schemaModel.getElements().iterator(); iter.hasNext();) { Object o = iter.next(); SchemaObject table = (SchemaObject)o; createMetadataForTable(table); } } private void createMetadataForRequestTable() { if (userSettings.getSourceType() == StateManager.SOURCE_ACS || userSettings.getSourceType() == StateManager.SOURCE_HTTP_PARAMS || userSettings.getSourceType() == StateManager.SOURCE_HTTP_REQUEST_DOC) { QName qname = stateManager.getRequestResponseTable(); addTable(qname.getNamespace(), qname.getLName(), ELEMENT_TABLETYPE); addTableNameToMap(qname.getNamespace(), userSettings.getRequestResponseTableXpath(), qname.getLName()); } } protected void createMetadataForCatalogs() { catalogsResultsetData = new ArrayList(); List catalogs = stateManager.getCatalogs(); for (int i = 0; i < catalogs.size(); ++i) { String catalog = (String)catalogs.get(i); if (catalog == null || catalog.length() == 0) { continue; } createMetadataForCatalog(catalog); } createMetadataForCatalog(StateManager.globalNamespace); } public static boolean exportSQL = true; public static String[] getTableTypeNames() { return tableTypes; } private void createMetadataForTableTypes() { List row; String tableType; for (int i = 0; i < getTableTypeNames().length; i++) { tableType = getTableTypeNames()[i]; row = new ArrayList(); row.add(tableType); tableTypesResultsetData.add(row); } } private void createMetadataForCatalog( String catalog ) { if (!knownCatalogs.contains(catalog)) { knownCatalogs.add(catalog); List row = new ArrayList(); row.add(catalog); catalogsResultsetData.add(row); } } private void createMetadataForTable( SchemaObject table ) { addTableForTable(table); int pkIndex; pkIndex = 1; for (Iterator colIter = table.getAttributes().iterator(); colIter.hasNext();) { Object oCol = colIter.next(); Column column = (Column)oCol; addColumnForTable(table, column); if (column.isPrimaryKey()) { addPrimaryKeyForTable(table, column, pkIndex++); } } for (Iterator relIter = table.getChildren().iterator(); relIter.hasNext();) { Object oTableRelationship = relIter.next(); Relationship tableRelationship = (Relationship)oTableRelationship; String key = tableRelationship.getChild().getSimpleName() + ':' + tableRelationship.getChild().getNamespace(); int representation = ((SchemaModelImpl)schemaModel).getRelationToParent(key); switch (representation) { case Relationship.RELATIONSHIP_TABLE: createMetadataForRelationshipTable(tableRelationship); break; case Relationship.KEY_IN_CHILD: createMetadataForKeyInChild(tableRelationship); break; case Relationship.KEY_IN_PARENT_SINGLE: createMetadataForKeyInParent(tableRelationship); break; case Relationship.KEY_IN_PARENT_MULTIPLE: createMetadataForKeyInParent(tableRelationship); break; case Relationship.MERGE_IN_PARENT_SINGLE: // The columns were alread yadded to the parent break; case Relationship.MERGE_IN_PARENT_MULTIPLE: // The columns were alread yadded to the parent break; default: break; } } } private void createMetadataForKeyInChild( Relationship tableRelationship ) { int pkIndex; pkIndex = 1; for (Iterator colIter = tableRelationship.getParent().getAttributes().iterator(); colIter.hasNext();) { Object oCol = colIter.next(); Column column = (Column)oCol; if (column.isPrimaryKey()) { addColumnForKeyInChild(tableRelationship, column); addForeignKeyForKeyInChild(tableRelationship, column, pkIndex); ++pkIndex; } } } private void createMetadataForKeyInParent( Relationship tableRelationship ) { int pkIndex; int maxOccurs = tableRelationship.getMaxOccurs(); for (int iOccurrence = 1; iOccurrence <= maxOccurs; iOccurrence++) { pkIndex = 1; int iOccurenceParam = maxOccurs > 1 ? iOccurrence : -1; for (Iterator colIter = tableRelationship.getChild().getAttributes().iterator(); colIter.hasNext();) { Object oCol = colIter.next(); Column column = (Column)oCol; if (column.isPrimaryKey()) { addColumnForKeyInParent(tableRelationship, column, iOccurenceParam); addForeignKeyForKeyInParent(tableRelationship, column, pkIndex, iOccurenceParam); ++pkIndex; } } } } private void createMetadataForRelationshipTable( Relationship tableRelationship ) { int pkIndex; addTableForParent(tableRelationship); pkIndex = 1; int fkIndex; SchemaObject child = tableRelationship.getChild(); SchemaObject parent = tableRelationship.getParent(); fkIndex = 1; for (Iterator colIter = parent.getAttributes().iterator(); colIter.hasNext();) { Object oCol = colIter.next(); Column column = (Column)oCol; if (column.isPrimaryKey()) { addColumnForRelationshipTable(tableRelationship, column, false); addPrimaryKeyForRelationshipTable(tableRelationship, column, false, pkIndex++); addForeignKeyForRelationshipTable(tableRelationship, column, false, fkIndex++); } } fkIndex = 1; boolean selfReference = (parent == child); for (Iterator colIter = child.getAttributes().iterator(); colIter.hasNext();) { Object oCol = colIter.next(); Column column = (Column)oCol; if (column.isPrimaryKey()) { addColumnForRelationshipTable(tableRelationship, column, selfReference); addPrimaryKeyForRelationshipTable(tableRelationship, column, selfReference, pkIndex++); addForeignKeyForRelationshipTable(tableRelationship, column, selfReference, fkIndex++); } } } private String getColumnSimpleName( final String name, String namespace, String tableName ) { String[] array = new String[] {namespace, tableName, name}; List list = Arrays.asList(array); return (String)columnNameInSourceMap.get(list); } public String getPrimaryKeyNameInSource( final String name, String namespace ) { synchronized (syncObject) { String[] array = new String[] {namespace, name}; List list = Arrays.asList(array); return (String)primaryKeySimpleNameMap.get(list); } } public String getForeignKeyNameInSource( final String name, String namespace ) { synchronized (syncObject) { String[] array = new String[] {namespace, name}; List list = Arrays.asList(array); return (String)foreignKeySimpleNameMap.get(list); } } public String getTableNameInSource( final String name, String namespace ) { synchronized (syncObject) { String[] array = new String[] {namespace, name}; List list = Arrays.asList(array); return (String)tableSimpleNameMap.get(list); } } public String getColumnNameInSource( final String name, String namespace, String tableName ) { synchronized (syncObject) { String[] array = new String[] {namespace, tableName, name}; List list = Arrays.asList(array); return (String)columnSimpleNameMap.get(list); } } private void addTableNameToMap( String catalog, String name, String simpleName ) { String[] array; List list; array = new String[] {catalog, name}; list = Arrays.asList(array); tableNameInSourceMap.put(list, simpleName); array = new String[] {catalog, simpleName}; list = Arrays.asList(array); tableSimpleNameMap.put(list, name); } private void addColumnNameToMap( String catalog, String tableName, String columnName, String simpleName, String tableSimpleName ) { String[] array; List list; array = new String[] {catalog, tableName, columnName}; list = Arrays.asList(array); columnNameInSourceMap.put(list, simpleName); array = new String[] {catalog, tableSimpleName, simpleName}; list = Arrays.asList(array); columnSimpleNameMap.put(list, columnName); } private void addPrimaryKeyNameToMap( String catalog, String primaryKeyName, String simpleName ) { String[] array; List list; array = new String[] {catalog, primaryKeyName}; list = Arrays.asList(array); primaryKeyNameInSourceMap.put(list, simpleName); array = new String[] {catalog, simpleName}; list = Arrays.asList(array); primaryKeySimpleNameMap.put(list, primaryKeyName); } private void addForeignKeyNameToMap( String catalog, String foreignKeyName, String simpleName ) { String[] array; List list; array = new String[] {catalog, foreignKeyName}; list = Arrays.asList(array); foreignKeyNameInSourceMap.put(list, simpleName); array = new String[] {catalog, simpleName}; list = Arrays.asList(array); foreignKeySimpleNameMap.put(list, foreignKeyName); } private void addTableForTable( SchemaObject table ) { String catalog = stateManager.getCatalog(table); createMetadataForCatalog(catalog); String name = table.getInputXPath(); String simpleName = NameUtil.normalizeName(table.getSimpleName()); addTable(catalog, simpleName, ELEMENT_TABLETYPE); addTableNameToMap(catalog, name, simpleName); } private void addColumnForTable( SchemaObject table, Column column ) { String catalog = stateManager.getCatalog(table); String tableName = table.getInputXPath(); String columnName = column.getXpath(); String simpleName = NameUtil.normalizeName(column.getSimpleName()); // Simple element types (xsd:String) that are referenced by several // elements are sometimes turned into schemaModel. In this event a column // with the name text is created to hold the data. We only want to // retain that name if it is never rolled up. If it is rolled up, // then it should assume the table name. Length indicates a rollup. // ElementImpl:Author Column:text becomes Column:Author. // TODO: We can still be burned by text matching, we need a legitimate indicator here. int sepLength = UserSettings.getMergedChildSep().length(); if (simpleName.endsWith("text") && simpleName.length() > 4 + sepLength) { //$NON-NLS-1$ // Strip the length of "text" and the length of the user defined separator. simpleName = simpleName.substring(0, simpleName.length() - 4 - sepLength); } String simpleTableName = NameUtil.normalizeName(table.getSimpleName()); addColumn(catalog, simpleTableName, simpleName, column); addColumnNameToMap(catalog, tableName, columnName, simpleName, simpleTableName); } private void addPrimaryKeyForTable( SchemaObject table, Column column, int pkIndex ) { String catalog = stateManager.getCatalog(table); String tableName = table.getInputXPath(); String simpleTableName = NameUtil.normalizeName(table.getSimpleName()); String columnName = column.getXpath(); String primaryKeyName = "pk_" + tableName; //$NON-NLS-1$ String simpleName = "pk" + NameUtil.normalizeName(table.getSimpleName()); //$NON-NLS-1$ addPrimaryKey(pkIndex, catalog, simpleTableName, columnName, simpleName); addPrimaryKeyNameToMap(catalog, primaryKeyName, simpleName); } private String getRelationshipCatalog( Relationship tableRelationship ) { return stateManager.getCatalog(tableRelationship.getChild()); } private String getRelationshipTableName( Relationship tableRelationship ) { String parent = tableRelationship.getParent().getInputXPath(); String childRel = tableRelationship.getChildRelativeXpath(); return parent + "/" + childRel; //$NON-NLS-1$ } private String getRelationshipTableSimpleName( Relationship tableRelationship ) { return NameUtil.normalizeName(tableRelationship.getChild().getSimpleName()) + "_rel_" //$NON-NLS-1$ + NameUtil.normalizeName(tableRelationship.getParent().getSimpleName()); } private String getRelationshipColumnName( Relationship tableRelationship, Column column, boolean selfReferenceChild ) { SchemaObject child = tableRelationship.getChild(); SchemaObject parent = tableRelationship.getParent(); SchemaObject table = column.getTable(); String xpath; String columnXpath = column.getXpath(); boolean useChild; if (parent == child) { useChild = selfReferenceChild; } else { useChild = (table == child); } if (useChild) { xpath = columnXpath; } else { String parentRelativeXpath = tableRelationship.getParentRelativeXpath(); xpath = parentRelativeXpath + "/" + columnXpath; //$NON-NLS-1$ } return xpath; } private String getRelationshipSimpleColumnName( Column column, boolean selfReferenceChild ) { SchemaObject table = column.getTable(); StringBuffer retval = new StringBuffer(); if (selfReferenceChild) { retval.append("child_"); //$NON-NLS-1$ } retval.append(NameUtil.normalizeName(table.getSimpleName())); retval.append('_'); retval.append(NameUtil.normalizeName(column.getSimpleName())); return retval.toString(); } private void addTableForParent( Relationship tableRelationship ) { String catalog = getRelationshipCatalog(tableRelationship); String name = getRelationshipTableName(tableRelationship); String simpleName = getRelationshipTableSimpleName(tableRelationship); addTable(catalog, simpleName, RELATIONSHIP_TABLETYPE); addTableNameToMap(catalog, name, simpleName); } private void addTable( String catalog, String name, String tableType ) { List row = new ArrayList(); row = new ArrayList(); row.add(catalog); row.add(null); row.add(name); row.add(tableType); row.add(null); row.add(null); row.add(null); row.add(null); row.add(null); row.add(null); tablesResultsetData.add(row); QName qname = SchemaUtil.getQName(catalog, name); addToMapOfLists(tablesByTableName, qname, row); } private void addColumnForRelationshipTable( Relationship tableRelationship, Column column, boolean selfReferenceChild ) { String catalog = getRelationshipCatalog(tableRelationship); String columnName = getRelationshipColumnName(tableRelationship, column, selfReferenceChild); String simpleName = getRelationshipSimpleColumnName(column, selfReferenceChild); String tableName = getRelationshipTableName(tableRelationship); String simpleTableName = getRelationshipTableSimpleName(tableRelationship); addColumn(catalog, simpleTableName, simpleName, column); addColumnNameToMap(catalog, tableName, columnName, simpleName, simpleTableName); } private void addColumnForKeyInChild( Relationship tableRelationship, Column column ) { String catalog = stateManager.getCatalog(tableRelationship.getChild()); String columnName = tableRelationship.getParentRelativeXpath() + "/" + column.getXpath(); //$NON-NLS-1$ String simpleName = NameUtil.normalizeName(tableRelationship.getParent().getSimpleName()) + "_" //$NON-NLS-1$ + NameUtil.normalizeName(column.getSimpleName()); String tableName = tableRelationship.getParent().getInputXPath() + "/" + tableRelationship.getChildRelativeXpath(); //$NON-NLS-1$ String simpleTableName = NameUtil.normalizeName(tableRelationship.getChild().getSimpleName()); addColumn(catalog, simpleTableName, simpleName, column); addColumnNameToMap(catalog, tableName, columnName, simpleName, simpleTableName); } private void addForeignKeyForKeyInChild( Relationship tableRelationship, Column column, int fkIndex ) { // The importer contains the foreign key. The importer is the child table. // The exporter contains the primary key. The exporter is the parent table. String importerCatalog = stateManager.getCatalog(tableRelationship.getChild()); String importerColumnName = tableRelationship.getParentRelativeXpath() + "/" + column.getXpath(); //$NON-NLS-1$ String importerTableName = tableRelationship.getParent().getInputXPath() + "/" //$NON-NLS-1$ + tableRelationship.getChildRelativeXpath(); String importerTableSimpleName = NameUtil.normalizeName(tableRelationship.getChild().getSimpleName()); String exporterCatalog = stateManager.getCatalog(tableRelationship.getParent()); String exporterColumnName = column.getXpath(); String exporterTableName = tableRelationship.getParent().getInputXPath(); String exporterTableSimpleName = NameUtil.normalizeName(tableRelationship.getParent().getSimpleName()); String primaryKeyName = "pk_" + exporterTableName; //$NON-NLS-1$ String foreignKeyName = "fk_" + importerTableName + "_" + exporterTableName; //$NON-NLS-1$ //$NON-NLS-2$ String simpleName = "fk_" + importerTableSimpleName + "_" + exporterTableSimpleName; //$NON-NLS-1$ //$NON-NLS-2$ addCrossReference(fkIndex, importerCatalog, importerColumnName, importerTableSimpleName, exporterCatalog, exporterColumnName, exporterTableSimpleName, primaryKeyName, simpleName); addForeignKeyNameToMap(exporterCatalog, foreignKeyName, simpleName); } private void addCrossReference( int index, String importerCatalog, String importerColumnName, String importerTableName, String exporterCatalog, String exporterColumnName, String exporterTableName, String primaryKeyName, String name ) { List row = new ArrayList(); row.add(exporterCatalog); row.add(null); row.add(exporterTableName); row.add(exporterColumnName); row.add(importerCatalog); row.add(null); row.add(importerTableName); row.add(importerColumnName); row.add(new Integer(index)); row.add(new Integer(importedKeyNoAction)); row.add(new Integer(importedKeyNoAction)); row.add(name); row.add(primaryKeyName); row.add(new Integer(importedKeyInitiallyDeferred)); crossReferencesResultsetData.add(row); QName primaryQname = SchemaUtil.getQName(exporterCatalog, exporterTableName); addToMapOfLists(crossReferencesByPrimaryTableName, primaryQname, row); QName foreignQname = SchemaUtil.getQName(importerCatalog, importerTableName); addToMapOfLists(crossReferencesByForeignTableName, foreignQname, row); Pair pair = new Pair(primaryQname, foreignQname); addToMapOfLists(crossReferencesByBothTableNames, pair, row); } private void addColumnForKeyInParent( Relationship tableRelationship, Column column, int repetition ) { String catalog = stateManager.getCatalog(tableRelationship.getParent()); String columnName; String simpleName; String columnNameElementPart = tableRelationship.getChildRelativeXpath(); String columnNameAttributePart = "/" + column.getXpath(); //$NON-NLS-1$ String simpleNameElementPart = NameUtil.normalizeName(tableRelationship.getChild().getSimpleName()); String simpleNameAttributePart = NameUtil.normalizeName(column.getSimpleName()); if (repetition >= 0) { columnName = columnNameElementPart + "[" + repetition + "]" + columnNameAttributePart; //$NON-NLS-1$//$NON-NLS-2$ simpleName = simpleNameElementPart + repetition + "_" + simpleNameAttributePart; //$NON-NLS-1$ } else { columnName = columnNameElementPart + columnNameAttributePart; simpleName = simpleNameElementPart + "_" + simpleNameAttributePart; //$NON-NLS-1$ } String tableName = tableRelationship.getParent().getInputXPath(); String simpleTableName = NameUtil.normalizeName(tableRelationship.getParent().getSimpleName()); addColumn(catalog, simpleTableName, simpleName, column); addColumnNameToMap(catalog, tableName, columnName, simpleName, simpleTableName); } private void addColumn( String catalog, String tableName, String columnName, Type type ) { /* * Each column description has the following columns: 1. TABLE_CAT String => table catalog (may be null) 2. TABLE_SCHEM String => table schema (may be null) 3. TABLE_NAME String => table name 4. COLUMN_NAME String => column name 5. DATA_TYPE int => SQL type from java.sql.Types 6. TYPE_NAME String => Data source dependent type name, for a UDT the type name is fully qualified 7. COLUMN_SIZE int => column size. For char or date types this is the maximum number of characters, for numeric or decimal types this is precision. 8. BUFFER_LENGTH is not used. 9. DECIMAL_DIGITS int => the number of fractional digits 10. NUM_PREC_RADIX int => Radix (typically either 10 or 2) 11. NULLABLE int => is NULL allowed. * columnNoNulls - might not allow NULL values * columnNullable - definitely allows NULL values * columnNullableUnknown - nullability unknown 12. REMARKS String => comment describing column (may be null) 13. COLUMN_DEF String => default value (may be null) 14. SQL_DATA_TYPE int => unused 15. SQL_DATETIME_SUB int => unused 16. CHAR_OCTET_LENGTH int => for char types the maximum number of bytes in the column 17. ORDINAL_POSITION int => index of column in table (starting at 1) 18. IS_NULLABLE String => "NO" means column definitely does not allow NULL values; "YES" means the column might allow NULL values. An empty string means nobody knows. 19. SCOPE_CATLOG String => catalog of table that is the scope of a reference attribute (null if DATA_TYPE isn't REF) 20. SCOPE_SCHEMA String => schema of table that is the scope of a reference attribute (null if the DATA_TYPE isn't REF) 21. SCOPE_TABLE String => table name that this the scope of a reference attribute (null if the DATA_TYPE isn't REF) 22. SOURCE_DATA_TYPE short => source type of a distinct type or user-generated ref type, SQL type from java.sql.Types (null if DATA_TYPE isn't DISTINCT or user-generated REF) */ XSDSimpleTypeDefinition sourceType = type.getType(); List validFacets = sourceType.getValidFacets(); String typeName = null; String baseTypeName = sourceType.getBaseTypeDefinition().getName(); if (baseTypeName!=null && baseTypeName.equals("anySimpleType")) { //$NON-NLS-1$ typeName = sourceType.getRootTypeDefinition().getName(); } else { typeName = sourceType.getBaseTypeDefinition().getName(); } int actualLength = 255; int actualFractionalDigits = 0; boolean lengthDone = false; if (validFacets.contains("length") && sourceType.getLengthFacet() != null) {//$NON-NLS-1$ actualLength = sourceType.getLengthFacet().getValue(); lengthDone = true; } if (!lengthDone && validFacets.contains("maxLength") && sourceType.getMaxLengthFacet() != null) {//$NON-NLS-1$ actualLength = sourceType.getMaxLengthFacet().getValue(); lengthDone = true; } if (!lengthDone && validFacets.contains("totalDigits") && sourceType.getTotalDigitsFacet() != null) {//$NON-NLS-1$ actualLength = sourceType.getTotalDigitsFacet().getValue(); } else if (!lengthDone && validFacets.contains("totalDigits")) { //$NON-NLS-1$ actualLength = 20; // the type is decimal or one of its derivatives // but no facet specifying digits is found assign value. // TODO: pick more appropriate value based on derived type } if (validFacets.contains("fractionDigits") && sourceType.getFractionDigitsFacet() != null) {//$NON-NLS-1$ actualFractionalDigits = sourceType.getFractionDigitsFacet().getValue(); } List row = new ArrayList(); row.add(catalog); // 1 row.add(null); // 2 row.add(tableName); // 3 row.add(columnName); // 4 if (this.userSettings.isUseSchemaTypes()) { row.add(new Integer(getSQLtype(typeName))); // 5 row.add(typeName); // 6 } else { row.add(new Integer(getSQLtype("string"))); // 5 //$NON-NLS-1$ row.add(String.class.getName()); // 6 } row.add(new Integer(actualLength)); // 7: row.add(""); // 8 //$NON-NLS-1$ row.add(new Integer(actualFractionalDigits)); // 9 row.add(new Integer(10)); // 10 row.add(new Integer(columnNullableUnknown)); // 11 row.add(""); // 12 //$NON-NLS-1$ row.add(""); // 13 //$NON-NLS-1$ row.add(""); // 14 //$NON-NLS-1$ row.add(""); // 15 //$NON-NLS-1$ String bType = type.getBaseType(); if (bType!=null && bType.equals("string")) { //$NON-NLS-1$ row.add(new Integer(actualLength * 2)); // 16 } else { row.add(new Integer(0)); // 16 } row.add(""); // 17 //$NON-NLS-1$ row.add(""); // 18 //$NON-NLS-1$ row.add(""); // 19 //$NON-NLS-1$ row.add(""); // 20 //$NON-NLS-1$ row.add(""); // 21 //$NON-NLS-1$ row.add(""); // 22 //$NON-NLS-1$ columnsResultsetData.add(row); QName qname = SchemaUtil.getQName(catalog, tableName); addToMapOfLists(columnsByTableName, qname, row); } private int getSQLtype( String schemaTypeName ) { int retval = Types.VARCHAR; if(schemaTypeName==null) return retval; // trim off NS prefix if present String lschemaTypeName = null; int idx = schemaTypeName.indexOf(":"); //$NON-NLS-1$ if (idx != -1) { lschemaTypeName = new String(schemaTypeName.substring(idx)); } else { lschemaTypeName = schemaTypeName; } if (lschemaTypeName.equals("string")) { //$NON-NLS-1$ retval = Types.VARCHAR; } else if (lschemaTypeName.equals("boolean")) { //$NON-NLS-1$ retval = Types.BOOLEAN; } else if (lschemaTypeName.equals("decimal")) { //$NON-NLS-1$ retval = Types.DECIMAL; } else if (lschemaTypeName.equals("float")) { //$NON-NLS-1$ retval = Types.FLOAT; } else if (lschemaTypeName.equals("double")) { //$NON-NLS-1$ retval = Types.DOUBLE; } else if (lschemaTypeName.equals("duration")) { //$NON-NLS-1$ retval = Types.TIMESTAMP; } else if (lschemaTypeName.equals("dateTime")) { //$NON-NLS-1$ retval = Types.TIMESTAMP; } else if (lschemaTypeName.equals("integer")) { //$NON-NLS-1$ retval = Types.INTEGER; } else if (lschemaTypeName.equals("long") || lschemaTypeName.equals("nonPositiveInteger") //$NON-NLS-1$ //$NON-NLS-2$ || lschemaTypeName.equals("nonNegativeInteger")) { //$NON-NLS-1$ retval = Types.INTEGER; } else if (lschemaTypeName.equals("int") || lschemaTypeName.equals("positiveInteger") //$NON-NLS-1$ //$NON-NLS-2$ || lschemaTypeName.equals("negativeInteger") || lschemaTypeName.equals("unsignedLong")) { //$NON-NLS-1$ //$NON-NLS-2$ retval = Types.SMALLINT; } else if (lschemaTypeName.equals("short") || lschemaTypeName.equals("unsignedInt")) { //$NON-NLS-1$ //$NON-NLS-2$ retval = Types.TINYINT; } else if (lschemaTypeName.equals("byte") || lschemaTypeName.equals("unsignedShort") //$NON-NLS-1$ //$NON-NLS-2$ || lschemaTypeName.equals("unsignedByte")) { //$NON-NLS-1$ retval = Types.TINYINT; } else if (lschemaTypeName.equals("date")) { //$NON-NLS-1$ retval = Types.TIMESTAMP; } else if (lschemaTypeName.equals("time")) { //$NON-NLS-1$ retval = Types.TIMESTAMP; } else if (lschemaTypeName.equals("dateTime")) { //$NON-NLS-1$ retval = Types.TIMESTAMP; } else if (lschemaTypeName.equals("hexBinary")) { //$NON-NLS-1$ retval = Types.VARBINARY; } else if (lschemaTypeName.equals("base64Binary")) { //$NON-NLS-1$ retval = Types.VARBINARY; } else if (lschemaTypeName.equals("anyURI")) { //$NON-NLS-1$ retval = Types.VARCHAR; } else if (lschemaTypeName.equals("QNameImpl")) { //$NON-NLS-1$ retval = Types.VARCHAR; } else if (lschemaTypeName.equals("NOTATION")) { //$NON-NLS-1$ retval = Types.VARCHAR; } return retval; } private void addToMapOfLists( Map map, Object key, List row ) { Object olists = map.get(key); List lists = (List)olists; if (lists == null) { lists = new ArrayList(); map.put(key, lists); } lists.add(row); } private void addForeignKeyForKeyInParent( Relationship tableRelationship, Column column, int fkIndex, int repetition ) { // The importer contains the foreign key. The importer is the parent table. // The exporter contains the primary key. The exporter is the child table. String importerCatalog = stateManager.getCatalog(tableRelationship.getParent()); String importerColumnName; String columnNameElementPart = tableRelationship.getChildRelativeXpath(); String columnNameAttributePart = "/" + column.getXpath(); //$NON-NLS-1$ if (repetition >= 0) { importerColumnName = columnNameElementPart + "[" + repetition + "]" + columnNameAttributePart; //$NON-NLS-1$ //$NON-NLS-2$ } else { importerColumnName = columnNameElementPart + columnNameAttributePart; } String importerTableName = tableRelationship.getParent().getInputXPath(); String importerTableSimpleName = NameUtil.normalizeName(tableRelationship.getParent().getSimpleName()); String exporterCatalog = stateManager.getCatalog(tableRelationship.getChild()); String exporterColumnName = column.getXpath(); String exporterTableName = tableRelationship.getParent().getInputXPath() + "/" //$NON-NLS-1$ + tableRelationship.getChildRelativeXpath(); String exporterTableSimpleName = NameUtil.normalizeName(tableRelationship.getChild().getSimpleName()); String primaryKeyName = "pk_" + exporterTableName; //$NON-NLS-1$ String foreignKeyName = "fk_" + importerTableName + "_" + exporterTableName; //$NON-NLS-1$ //$NON-NLS-2$ if (repetition > 0) { foreignKeyName += repetition; } String simpleName = "fk_" + importerTableSimpleName + "_" + exporterTableSimpleName; //$NON-NLS-1$ //$NON-NLS-2$ if (repetition > 0) { simpleName += repetition; } addCrossReference(fkIndex, importerCatalog, importerColumnName, importerTableSimpleName, exporterCatalog, exporterColumnName, exporterTableSimpleName, primaryKeyName, simpleName); addForeignKeyNameToMap(exporterCatalog, foreignKeyName, simpleName); } private void addPrimaryKeyForRelationshipTable( Relationship tableRelationship, Column column, boolean selfReferenceChild, int pkIndex ) { String catalog = getRelationshipCatalog(tableRelationship); String tableName = getRelationshipTableName(tableRelationship); String simpleTableName = getRelationshipTableSimpleName(tableRelationship); String columnName = getRelationshipColumnName(tableRelationship, column, selfReferenceChild); String primaryKeyName = "pk_" + tableName; //$NON-NLS-1$ String simpleName = "pk_" + getRelationshipTableSimpleName(tableRelationship); //$NON-NLS-1$ addPrimaryKey(pkIndex, catalog, simpleTableName, columnName, simpleName); addPrimaryKeyNameToMap(catalog, primaryKeyName, simpleName); } private void addPrimaryKey( int pkIndex, String catalog, String tableName, String columnName, String keyName ) { List row = new ArrayList(); row.add(catalog); row.add(null); row.add(tableName); row.add(columnName); row.add(new Integer(pkIndex)); row.add(keyName); primaryKeysResultsetData.add(row); QName qname = SchemaUtil.getQName(catalog, tableName); addToMapOfLists(primaryKeysByTableName, qname, row); } private void addForeignKeyForRelationshipTable( Relationship tableRelationship, Column column, boolean selfReferenceChild, int fkIndex ) { // The importer contains the foreign key. The importer is the relationship table. // The exporter contains the primary key. The exporter can be the parent table or the child table (the column's table) String importerCatalog = getRelationshipCatalog(tableRelationship); String importerTableName = getRelationshipTableName(tableRelationship); String importerTableSimpleName = getRelationshipTableSimpleName(tableRelationship); String importerColumnName = getRelationshipColumnName(tableRelationship, column, selfReferenceChild); String exporterCatalog = stateManager.getCatalog(column.getTable()); String exporterTableName = column.getTable().getInputXPath(); String exporterTableSimpleName = NameUtil.normalizeName(column.getTable().getSimpleName()); String exporterColumnName = column.getXpath(); String primaryKeyName = "pk_" + exporterTableName; //$NON-NLS-1$ String fkPrefix = selfReferenceChild ? "fk_child_" : "fk_"; //$NON-NLS-1$ //$NON-NLS-2$ String foreignKeyName = fkPrefix + importerTableName + "_" + exporterTableName; //$NON-NLS-1$ String simpleName = fkPrefix + getRelationshipTableSimpleName(tableRelationship) + "_" //$NON-NLS-1$ + NameUtil.normalizeName(column.getTable().getSimpleName()); addCrossReference(fkIndex, importerCatalog, importerColumnName, importerTableSimpleName, exporterCatalog, exporterColumnName, exporterTableSimpleName, primaryKeyName, simpleName); addForeignKeyNameToMap(exporterCatalog, foreignKeyName, simpleName); } /** * @see java.sql.DatabaseMetaData#getCatalogs() */ @Override public ResultSet getCatalogs() { synchronized (syncObject) { ensureInitialized(); ResultSet retval = new MapResultSet(catalogsResultsetData, catalogsResultsetMetadata); return retval; } } /** * @see java.sql.DatabaseMetaData#getTableTypes() */ @Override public ResultSet getTableTypes() { synchronized (syncObject) { return new MapResultSet(tableTypesResultsetData, tableTypesResultsetMetadata); } } /** * @see java.sql.DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String) */ @Override public ResultSet getExportedKeys( String catalog, String schema, String table ) { synchronized (syncObject) { ensureInitialized(); QName qname = makeLookup(catalog, schema, table); List data; if (qname != null) { Object o = crossReferencesByPrimaryTableName.get(qname); data = (List)o; if (data == null) { data = new ArrayList(); } } else { data = new ArrayList(); for (Iterator iter = crossReferencesResultsetData.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object rowCatalog = row.get(0); Object rowTable = row.get(2); if (catalog != null && !catalog.equals(rowCatalog)) continue; if (table != null && !table.equals(rowTable)) continue; data.add(row); } } return new MapResultSet(data, crossReferencesResultsetMetadata); } } /** * @see java.sql.DatabaseMetaData#getImportedKeys(java.lang.String, java.lang.String, java.lang.String) */ @Override public ResultSet getImportedKeys( String catalog, String schema, String table ) { synchronized (syncObject) { ensureInitialized(); QName qname = makeLookup(catalog, schema, table); List data; if (qname != null) { Object o = crossReferencesByForeignTableName.get(qname); data = (List)o; if (data == null) { data = new ArrayList(); } } else { data = new ArrayList(); for (Iterator iter = crossReferencesResultsetData.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object rowCatalog = row.get(4); Object rowTable = row.get(6); if (catalog != null && !catalog.equals(rowCatalog)) continue; if (table != null && !table.equals(rowTable)) continue; data.add(row); } } return new MapResultSet(data, crossReferencesResultsetMetadata); } } private QName makeLookup( String catalog, String schema, String tableNamePattern ) { if (tableNamePattern == null || tableNamePattern.indexOf('%') > -1) { return null; } if (schema != null) { return null; } QName retval = SchemaUtil.getQName(catalog, tableNamePattern); return retval; } /** * @see java.sql.DatabaseMetaData#getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String) */ @Override public ResultSet getPrimaryKeys( String catalog, String schema, String tableNamePattern ) { synchronized (syncObject) { ensureInitialized(); List data; QName qname = makeLookup(catalog, schema, tableNamePattern); if (qname != null) { Object o = primaryKeysByTableName.get(qname); data = (List)o; if (data == null) { data = new ArrayList(); } } else { data = new ArrayList(); for (Iterator iter = primaryKeysResultsetData.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object rowCatalog = row.get(0); Object oRowTable = row.get(2); String rowTable = (String)oRowTable; if (catalog != null && !catalog.equals(rowCatalog)) continue; if (tableNamePattern != null && !patternMatch(tableNamePattern, rowTable)) continue; data.add(row); } } return new MapResultSet(data, primaryKeysResultsetMetadata); } } /** * @see java.sql.DatabaseMetaData#getColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ @Override public ResultSet getColumns( String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern ) { synchronized (syncObject) { ensureInitialized(); List dataForTable; QName qname = makeLookup(catalog, schemaPattern, tableNamePattern); if (qname != null) { Object o = columnsByTableName.get(qname); dataForTable = (List)o; } else { dataForTable = new ArrayList(); for (Iterator iter = columnsResultsetData.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object rowCatalog = row.get(0); Object oRowTable = row.get(2); String rowTable = (String)oRowTable; if (catalog != null && !catalog.equals(rowCatalog)) continue; if (tableNamePattern != null && !patternMatch(tableNamePattern, rowTable)) continue; dataForTable.add(row); } } List data; if (columnNamePattern == null || columnNamePattern.equals("%")) { //$NON-NLS-1$ data = dataForTable; } else { data = new ArrayList(); for (Iterator iter = dataForTable.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object oRowColumn = row.get(3); String rowColumn = (String)oRowColumn; if (!patternMatch(columnNamePattern, rowColumn)) continue; data.add(row); } } if (data == null) { data = new ArrayList(); } return new MapResultSet(data, columnsResultsetMetadata); } } private boolean patternMatch( String pattern, String test ) { if (pattern.equals("%")) { //$NON-NLS-1$ return true; } if (pattern.indexOf('%') == -1) { boolean retval = (pattern.equals(test)); return retval; } StringBuffer regex = new StringBuffer(); boolean insideQuote = false; for (int i = 0; i < pattern.length(); ++i) { char c = pattern.charAt(i); switch (c) { case '%': if (insideQuote) { regex.append("\\E"); //$NON-NLS-1$ insideQuote = false; } regex.append(".*"); //$NON-NLS-1$ break; case '_': if (insideQuote) { regex.append("\\E"); //$NON-NLS-1$ insideQuote = false; } regex.append('.'); break; default: if (!insideQuote) { regex.append("\\Q"); //$NON-NLS-1$ insideQuote = true; } regex.append(c); break; } } if (insideQuote) { regex.append("\\E"); //$NON-NLS-1$ insideQuote = false; } Pattern p = Pattern.compile(regex.toString()); Matcher m = p.matcher(test); boolean b = m.matches(); return b; } /** * @see java.sql.DatabaseMetaData#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) */ @Override public ResultSet getTables( String catalog, String schemaPattern, String tableNamePattern, String[] types ) { synchronized (syncObject) { ensureInitialized(); List typeList = types == null ? null : Arrays.asList(types); List dataForTable; QName qname = makeLookup(catalog, schemaPattern, tableNamePattern); if (qname != null) { Object o = tablesByTableName.get(qname); dataForTable = (List)o; if (dataForTable == null) { dataForTable = new ArrayList(); } } else { dataForTable = new ArrayList(); for (Iterator iter = tablesResultsetData.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object rowCatalog = row.get(0); Object oRowTable = row.get(2); String rowTable = (String)oRowTable; if (catalog != null && !catalog.equals(rowCatalog)) continue; if (tableNamePattern != null && !patternMatch(tableNamePattern, rowTable)) continue; dataForTable.add(row); } } List data; if (types == null) { data = dataForTable; } else { data = new ArrayList(); for (Iterator iter = dataForTable.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object oType = row.get(3); String type = (String)oType; if (!typeList.contains(type)) continue; data.add(row); } } return new MapResultSet(data, tablesResultsetMetadata); } } private static class Pair { public Object o1; public Object o2; public Pair( Object o1, Object o2 ) { this.o1 = o1; this.o2 = o2; int o1Hash = o1 == null ? 0 : o1.hashCode(); int o2Hash = o2 == null ? 0 : o2.hashCode(); hashCode = 17; hashCode = 37 * hashCode + o1Hash; hashCode = 37 * hashCode + o2Hash; } @Override public boolean equals( Object o ) { if (!(o instanceof Pair)) { return false; } Pair other = (Pair)o; if (o1 == null && other.o1 != null) { return false; } if (o1 != null && other.o1 == null) { return false; } if (o1 != null && !(o1.equals(other.o1))) { return false; } if (o2 == null && other.o2 != null) { return false; } if (o2 != null && other.o2 == null) { return false; } if (o2 != null && !(o2.equals(other.o2))) { return false; } return true; } int hashCode; @Override public int hashCode() { return hashCode; } } /** * @see java.sql.DatabaseMetaData#getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String, * java.lang.String, java.lang.String) */ @Override public ResultSet getCrossReference( String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable ) { synchronized (syncObject) { ensureInitialized(); QName primaryQname = makeLookup(primaryCatalog, primarySchema, primaryTable); QName foreignQname = makeLookup(foreignCatalog, foreignSchema, foreignTable); Pair pair; if (primaryQname == null || foreignQname == null) { pair = null; } else { pair = new Pair(primaryQname, foreignQname); } List data; if (pair != null) { Object o = crossReferencesByBothTableNames.get(pair); data = (List)o; if (data == null) { data = new ArrayList(); } } else { data = new ArrayList(); for (Iterator iter = crossReferencesResultsetData.iterator(); iter.hasNext();) { Object o = iter.next(); List row = (List)o; Object rowPkCatalog = row.get(0); Object rowPkTable = row.get(2); Object rowFkCatalog = row.get(4); Object rowFkTable = row.get(6); if (primaryCatalog != null && !primaryCatalog.equals(rowPkCatalog)) continue; if (primaryTable != null && !primaryTable.equals(rowPkTable)) continue; if (foreignCatalog != null && !foreignCatalog.equals(rowFkCatalog)) continue; if (foreignTable != null && !foreignTable.equals(rowFkTable)) continue; data.add(row); } } return new MapResultSet(data, crossReferencesResultsetMetadata); } } private void exportMetaData() { File file = null; Writer writer = null; try { file = File.createTempFile("xmlmetadata", ".sql"); //$NON-NLS-1$ //$NON-NLS-2$ writer = new FileWriter(file); ResultSet catalogset = getCatalogs(); while (catalogset.next()) { String catalog = catalogset.getString(1); ResultSet tableset = getTables(catalog, null, null, null); while (tableset.next()) { String tableName = tableset.getString(3); String tableNameInSource = this.getTableNameInSource(tableName, catalog); // CREATE TABLE [dbo].[AgeTable] ( // [Name] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , // [Age] [int] NULL // ) ON [PRIMARY] // GO writer.write("CREATE TABLE [" + tableName + "] (\n"); //$NON-NLS-1$ //$NON-NLS-2$ ResultSet columnset = getColumns(catalog, null, tableName, null); boolean first = true; while (columnset.next()) { if (first) { first = false; } else { writer.write(",\n"); //$NON-NLS-1$ } writer.write("\t[" + columnset.getString(4) + "] [varchar] NOT NULL"); //$NON-NLS-1$ //$NON-NLS-2$ } writer.write("\n) ON [PRIMARY]\nGO\n\n"); //$NON-NLS-1$ // ALTER TABLE [dbo].[AgeTable] ADD // CONSTRAINT [PK_AgeTable] PRIMARY KEY CLUSTERED // ( // [Name] // ) ON [PRIMARY] // GO ResultSet pkset = getPrimaryKeys(catalog, null, tableName); if (pkset.next()) { String pkName = pkset.getString(6); writer.write("ALTER TABLE [" + tableName + "] ADD \n"); //$NON-NLS-1$ //$NON-NLS-2$ writer.write("\tCONSTRAINT [" + pkName + "] PRIMARY KEY CLUSTERED (\n"); //$NON-NLS-1$ //$NON-NLS-2$ first = true; while (first || pkset.next()) { if (first) { first = false; } else { writer.write(",\n"); //$NON-NLS-1$ } String colNameInSource = pkset.getString(4); String colName = getColumnSimpleName(colNameInSource, catalog, tableNameInSource); writer.write("\t[" + colName + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } writer.write("\n) ON [PRIMARY]\nGO\n\n"); //$NON-NLS-1$ } } } catalogset = getCatalogs(); while (catalogset.next()) { String catalog = catalogset.getString(1); ResultSet tableset = getTables(catalog, null, null, null); while (tableset.next()) { String tableName = tableset.getString(3); String tableNameInSource = this.getTableNameInSource(tableName, catalog); // ALTER TABLE [dbo].[AgeTable] ADD // CONSTRAINT [FK_AgeTable_Person] FOREIGN KEY // ( // [Name] // ) REFERENCES [dbo].[Person] ( // [Name] // ) // GO ResultSet fkset = getImportedKeys(catalog, null, tableName); if (fkset.next()) { String fkName = fkset.getString(12); String exporterTableName = fkset.getString(3); writer.write("ALTER TABLE [" + tableName + "] ADD \n"); //$NON-NLS-1$ //$NON-NLS-2$ writer.write("\tCONSTRAINT [" + fkName + "] FOREIGN KEY (\n"); //$NON-NLS-1$ //$NON-NLS-2$ boolean first = true; while (first || fkset.next()) { if (first) { first = false; } else { writer.write(",\n"); //$NON-NLS-1$ } String importerColNameInSource = fkset.getString(8); String importerColName = getColumnSimpleName(importerColNameInSource, catalog, tableNameInSource); writer.write("\t[" + importerColName + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } writer.write("\n) REFERENCES " + exporterTableName + " (\n"); //$NON-NLS-1$ //$NON-NLS-2$ first = true; fkset.beforeFirst(); while (fkset.next()) { if (first) { first = false; } else { writer.write(",\n"); //$NON-NLS-1$ } String exporterColNameInSource = fkset.getString(4); String exporterColName = getColumnSimpleName(exporterColNameInSource, catalog, tableNameInSource); writer.write("\t[" + exporterColName + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } writer.write("\n)\nGO\n\n"); //$NON-NLS-1$ } } } } catch (Exception e) { StringWriter sw = new StringWriter(0); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); return; } finally { if (writer != null) { try { writer.flush(); writer.close(); } catch (Exception e) { StringWriter sw = new StringWriter(0); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); return; } } } } public Boolean isRequestOrResponseTable( QName qname ) { return stateManager.isRequestOrResponseTable(qname); } protected void catalogsChanged() { initialize(); } public Map getNamespacePrefixes( String name ) { return schemaModel.getNamespacePrefixes(); } public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { throw new SQLFeatureNotSupportedException(); } public boolean generatedKeyAlwaysReturned() throws SQLException { return false; } }