gt: 		DataSource ds = Mockito.mock(DataSource.class);
context: /*
   * JBoss, Home of Professional Open Source.
   * See the COPYRIGHT.txt file distributed with this work for information
   * regarding copyright ownership.  Some portions may be licensed
   * to Red Hat, Inc. under one or more contributor license agreements.
   * 
   * 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; either
   * version 2.1 of the License, or (at your option) any later version.
   * 
   * 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.
   * 
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301 USA.
   */
  
  package org.teiid.jdbc;
  
  import static org.junit.Assert.*;
  
  import java.io.FileInputStream;
  import java.sql.Connection;
  import java.sql.DatabaseMetaData;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Map;
  import java.util.Properties;
  
  import javax.sql.DataSource;
  
  import org.junit.After;
  import org.junit.Before;
  import org.junit.Test;
  import org.mockito.Mockito;
  import org.teiid.adminapi.impl.ModelMetaData;
  import org.teiid.core.types.DataTypeManager;
  import org.teiid.core.util.SimpleMock;
  import org.teiid.core.util.UnitTestUtil;
  import org.teiid.deployers.VDBRepository;
  import org.teiid.metadata.Column;
  import org.teiid.metadata.DuplicateRecordException;
  import org.teiid.metadata.ForeignKey;
  import org.teiid.metadata.FunctionMethod;
  import org.teiid.metadata.MetadataFactory;
  import org.teiid.metadata.MetadataStore;
  import org.teiid.metadata.Procedure;
  import org.teiid.metadata.ProcedureParameter;
  import org.teiid.metadata.Table;
  import org.teiid.query.metadata.NativeMetadataRepository;
  import org.teiid.query.parser.QueryParser;
  import org.teiid.translator.ExecutionFactory;
  import org.teiid.translator.TranslatorException;
  import org.teiid.translator.jdbc.oracle.OracleExecutionFactory;
  import org.teiid.translator.jdbc.teiid.TeiidExecutionFactory;
  
  /**
   */
  @SuppressWarnings("nls")
  public class TestDynamicImportedMetaData {
  
  	public static final class BadMetadata {
  		public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
  			throw new SQLException();
  		}
  	}
  
  	private FakeServer server;
  	
  	@Before public void setup() {
  		this.server = new FakeServer(true);
  	}
  	
  	@After public void tearDown() {
  		this.server.stop();
  	}
  
  	private MetadataFactory getMetadata(Properties importProperties, Connection conn)
  			throws TranslatorException {
  		MetadataFactory mf = createMetadataFactory("test", importProperties);
      	
      	TeiidExecutionFactory tef = new TeiidExecutionFactory();
      	tef.getMetadata(mf, conn);
      	return mf;
  	}
  
  	private MetadataFactory createMetadataFactory(String schema, Properties importProperties) {
  		VDBRepository vdbRepository = new VDBRepository();
      	return new MetadataFactory("vdb", 1, schema, vdbRepository.getRuntimeTypeMap(), importProperties, null);
  	}
  	
  	@Test public void testUniqueReferencedKey() throws Exception {
  		server.deployVDB("vdb", UnitTestUtil.getTestDataPath() + "/keys.vdb");
      	Connection conn = server.createConnection("jdbc:teiid:vdb"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.importKeys", "true");
      	importProperties.setProperty("importer.schemaPattern", "x");
      	MetadataFactory mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("TEST").getTables().get("VDB.X.A");
      	List<ForeignKey> fks = t.getForeignKeys();
      	assertEquals(1, fks.size());
      	assertNotNull(fks.get(0).getPrimaryKey());
  	}
  	
      @Test public void testProcImport() throws Exception {
      	server.deployVDB("vdb", UnitTestUtil.getTestDataPath() + "/TestCase3473/test.vdb");
      	Connection conn = server.createConnection("jdbc:teiid:vdb"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.importProcedures", Boolean.TRUE.toString());
      	MetadataFactory mf = getMetadata(importProperties, conn);
      	Procedure p = mf.asMetadataStore().getSchemas().get("TEST").getProcedures().get("VDB.SYS.GETXMLSCHEMAS");
      	assertEquals(1, p.getResultSet().getColumns().size());
      }
      
      @Test public void testExcludes() throws Exception {
      	server.deployVDB("vdb", UnitTestUtil.getTestDataPath() + "/TestCase3473/test.vdb");
      	Connection conn = server.createConnection("jdbc:teiid:vdb"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.importProcedures", Boolean.TRUE.toString());
      	importProperties.setProperty("importer.excludeTables", "VDB\\.SYS.*");
      	importProperties.setProperty("importer.excludeProcedures", "VDB\\..*");
      	MetadataFactory mf = getMetadata(importProperties, conn);
      	assertEquals(String.valueOf(mf.asMetadataStore().getSchemas().get("TEST").getTables()), 17, mf.asMetadataStore().getSchemas().get("TEST").getTables().size());
      	assertEquals(0, mf.asMetadataStore().getSchemas().get("TEST").getProcedures().size());
      }
          
      @Test public void testDuplicateException() throws Exception {
      	MetadataFactory mf = createMetadataFactory("x", new Properties());
      	MetadataFactory mf1 = createMetadataFactory("y", new Properties());
      	
      	Table dup = mf.addTable("dup");
      	Table dup1 = mf1.addTable("dup");
      	
      	mf.addColumn("x", DataTypeManager.DefaultDataTypes.STRING, dup);
      	mf1.addColumn("x", DataTypeManager.DefaultDataTypes.STRING, dup1);
      	
      	MetadataStore ms = mf.asMetadataStore();
      	ms.addSchema(mf1.asMetadataStore().getSchemas().values().iterator().next());
      	
      	server.deployVDB("test", ms);
      	Connection conn = server.createConnection("jdbc:teiid:test"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	
      	mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("TEST").getTables().get("TEST.X.DUP");
      	assertEquals("\"test\".\"x\".\"dup\"", t.getNameInSource());
  
      	importProperties.setProperty("importer.useFullSchemaName", Boolean.FALSE.toString());
      	try {
      		getMetadata(importProperties, conn);
      		fail();
      	} catch (DuplicateRecordException e) {
      		
      	}
      }
      
      @Test public void testUseCatalog() throws Exception {
      	MetadataFactory mf = createMetadataFactory("x", new Properties());
      	
      	Table dup = mf.addTable("dup");
      	
      	mf.addColumn("x", DataTypeManager.DefaultDataTypes.STRING, dup);
      	
      	MetadataStore ms = mf.asMetadataStore();
      	
      	server.deployVDB("test", ms);
      	Connection conn = server.createConnection("jdbc:teiid:test"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.useCatalogName", Boolean.FALSE.toString());
      	mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("TEST").getTables().get("X.DUP");
      	assertEquals("\"x\".\"dup\"", t.getNameInSource());
      }
      
      @Test public void testUseQualified() throws Exception {
      	MetadataFactory mf = createMetadataFactory("x", new Properties());
      	
      	Table dup = mf.addTable("dup");
      	
      	mf.addColumn("x", DataTypeManager.DefaultDataTypes.STRING, dup);
      	
      	MetadataStore ms = mf.asMetadataStore();
      	
      	server.deployVDB("test", ms);
      	Connection conn = server.createConnection("jdbc:teiid:test"); //$NON-NLS-1$
      	
      	//neither the name nor name in source should be qualified
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.useQualifiedName", Boolean.FALSE.toString());
      	
      	mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("TEST").getTables().get("DUP");
      	assertEquals("\"dup\"", t.getNameInSource());
      }
      
      @Test
      public void testDDLMetadata() throws Exception {
      	String ddl = "CREATE FOREIGN PROCEDURE getTextFiles(IN pathAndPattern varchar) RETURNS (file clob, filpath string) OPTIONS(UUID 'uuid')";
      	MetadataFactory mf = createMetadataFactory("MarketData", new Properties());
      	QueryParser.getQueryParser().parseDDL(mf, ddl);
      	MetadataStore ms = mf.asMetadataStore();
      
      	String ddl2 = "CREATE VIEW stock (symbol string, price bigdecimal) OPTIONS (UUID 'uuid')" +
      			"AS select stock.* from (call MarketData.getTextFiles('*.txt')) f, " +
      			"TEXTTABLE(f.file COLUMNS symbol string, price bigdecimal HEADER) stock;";    	
      	MetadataFactory m2 = createMetadataFactory("portfolio", new Properties());
  
      	QueryParser.getQueryParser().parseDDL(m2, ddl2);
      	m2.getSchema().setPhysical(false);
      	m2.mergeInto(ms);
      	
      	server.deployVDB("test", ms);
      	Connection conn =  server.createConnection("jdbc:teiid:test"); //$NON-NLS-1$
      	Properties props = new Properties();
      	props.setProperty("importer.importProcedures", Boolean.TRUE.toString());
      	MetadataStore store = getMetadata(props, conn).asMetadataStore();
      	
      	Procedure p = store.getSchema("test").getProcedure("test.MarketData.getTextFiles");
      	assertNotNull(p);
      	
      	ProcedureParameter pp = p.getParameters().get(0);
      	assertEquals("pathAndPattern", pp.getName());
      	assertEquals(ProcedureParameter.Type.In, pp.getType());
      	//assertEquals("string", pp.getDatatype().getName());
      	
      	Table t = store.getSchema("test").getTable("test.portfolio.stock");
      	assertNotNull(t);
  		
      	List<Column> columns = t.getColumns();
      	assertEquals(2, columns.size());
      	assertEquals("symbol", columns.get(0).getName());
      	assertEquals("price", columns.get(1).getName());
      }    
      
      @Test public void testImportFunction() throws Exception {
      	MetadataFactory mf = createMetadataFactory("x", new Properties());
      	
      	Table dup = mf.addTable("dup");
      	
      	mf.addColumn("x", DataTypeManager.DefaultDataTypes.STRING, dup);
      	
      	MetadataStore ms = mf.asMetadataStore();
      	
      	server.deployVDB("test", ms);
      	Connection conn = server.createConnection("jdbc:teiid:test"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty(NativeMetadataRepository.IMPORT_PUSHDOWN_FUNCTIONS, Boolean.TRUE.toString());
      	
      	mf = createMetadataFactory("test", importProperties);
      	NativeMetadataRepository nmr = new NativeMetadataRepository();
      	OracleExecutionFactory oef = new OracleExecutionFactory();
      	oef.start();
      	DataSource ds = Mockito.mock(DataSource.class);
      	    	
      	Mockito.stub(ds.getConnection()).toReturn(conn);
      	
      	nmr.loadMetadata(mf, oef, ds);
      	
      	Map<String, FunctionMethod> functions = mf.asMetadataStore().getSchemas().get("TEST").getFunctions();
      	
      	assertEquals(14, functions.size());
      }
      
      @Test public void testIgnorePkIndex() throws Exception {
      	MetadataFactory mf = createMetadataFactory("x", new Properties());
      	
      	Table dup = mf.addTable("x");
      	
      	mf.addColumn("x", DataTypeManager.DefaultDataTypes.STRING, dup);
      	mf.addPrimaryKey("foo", Arrays.asList("x"), dup);
      	
      	MetadataStore ms = mf.asMetadataStore();
      	
      	server.deployVDB("test", ms);
      	
      	//cheat and add the index after deployment
      	mf.addIndex("foo", false, Arrays.asList("x"), dup);
      	
      	Connection conn = server.createConnection("jdbc:teiid:test"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.importKeys", Boolean.TRUE.toString());
      	importProperties.setProperty("importer.importIndexes", Boolean.TRUE.toString());
      	mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("TEST").getTables().get("test.X.X");
      	assertNotNull(t.getPrimaryKey());
      	assertEquals(0, t.getUniqueKeys().size());
      	assertEquals(0, t.getIndexes().size());
      }
      
      @Test public void testDroppedFk() throws Exception {
      	ModelMetaData mmd = new ModelMetaData();
      	mmd.addSourceMetadata("ddl", "create foreign table x (y integer primary key);"
      			+ "create foreign table z (y integer, foreign key (y) references x)");
      	mmd.setName("foo");
      	mmd.addSourceMapping("x", "x", "x");
      	server.addTranslator("x", new ExecutionFactory());
  		server.deployVDB("vdb", mmd);
      	Connection conn = server.createConnection("jdbc:teiid:vdb"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.importKeys", "true");
      	//only import z and not the referenced table x
      	importProperties.setProperty("importer.tableNamePattern", "z");
      	MetadataFactory mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("test").getTables().get("vdb.foo.z");
      	List<ForeignKey> fks = t.getForeignKeys();
      	assertEquals(0, fks.size());
  	}
      
      @Test public void testMultipleFK() throws Exception {
      	ModelMetaData mmd = new ModelMetaData();
      	mmd.addSourceMetadata("ddl", "create foreign table x (y integer, z integer, primary key (y, z));"
      			+ "create foreign table z (y integer, z integer, y1 integer, z1 integer, foreign key (y, z) references x (y, z), foreign key (y1, z1) references x (y, z))");
      	mmd.setName("foo");
      	mmd.addSourceMapping("x", "x", "x");
      	server.addTranslator("x", new ExecutionFactory());
  		server.deployVDB("vdb", mmd);
      	Connection conn = server.createConnection("jdbc:teiid:vdb"); //$NON-NLS-1$
      	
      	Properties importProperties = new Properties();
      	importProperties.setProperty("importer.importKeys", "true");
      	MetadataFactory mf = getMetadata(importProperties, conn);
      	Table t = mf.asMetadataStore().getSchemas().get("test").getTables().get("vdb.foo.z");
      	List<ForeignKey> fks = t.getForeignKeys();
      	assertEquals(2, fks.size());
  	}
      
      @Test public void testMultiSource() throws Exception {
      	ModelMetaData mmd = new ModelMetaData();
      	mmd.addSourceMetadata("ddl", "create foreign table x (y integer primary key);");
      	mmd.setName("foo");
      	mmd.addSourceMapping("x", "x", "x");
      	server.addTranslator("x", new ExecutionFactory());
  		server.deployVDB("vdb", mmd);
  		TeiidExecutionFactory tef = new TeiidExecutionFactory() {
  			@Override
  			public void closeConnection(Connection connection,
  					DataSource factory) {
  			}
  		};
  		tef.setSupportsDirectQueryProcedure(true);
  		tef.start();
  		server.addTranslator("teiid", tef);
  