/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.metamodel; import java.io.File; import java.io.InputStream; import java.net.URL; import java.sql.Connection; import java.util.Arrays; import java.util.Collection; import java.util.List; import javax.sql.DataSource; import org.apache.metamodel.cassandra.CassandraDataContext; import org.apache.metamodel.couchdb.CouchDbDataContext; import org.apache.metamodel.csv.CsvConfiguration; import org.apache.metamodel.csv.CsvDataContext; import org.apache.metamodel.elasticsearch.nativeclient.ElasticSearchDataContext; import org.apache.metamodel.elasticsearch.rest.ElasticSearchRestDataContext; import org.apache.metamodel.excel.ExcelConfiguration; import org.apache.metamodel.excel.ExcelDataContext; import org.apache.metamodel.fixedwidth.FixedWidthConfiguration; import org.apache.metamodel.fixedwidth.FixedWidthDataContext; import org.apache.metamodel.hbase.HBaseConfiguration; import org.apache.metamodel.hbase.HBaseDataContext; import org.apache.metamodel.jdbc.JdbcDataContext; import org.apache.metamodel.json.JsonDataContext; import org.apache.metamodel.mongodb.mongo3.MongoDbDataContext; import org.apache.metamodel.openoffice.OpenOfficeDataContext; import org.apache.metamodel.pojo.PojoDataContext; import org.apache.metamodel.pojo.TableDataProvider; import org.apache.metamodel.salesforce.SalesforceDataContext; import org.apache.metamodel.schema.TableType; import org.apache.metamodel.sugarcrm.SugarCrmDataContext; import org.apache.metamodel.util.FileHelper; import org.apache.metamodel.util.Resource; import org.apache.metamodel.util.SimpleTableDef; import org.apache.metamodel.xml.XmlDomDataContext; import org.ektorp.http.StdHttpClient.Builder; import org.elasticsearch.client.Client; import org.xml.sax.InputSource; import com.datastax.driver.core.Cluster; import com.google.common.base.Strings; import com.mongodb.MongoClient; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; import com.mongodb.client.MongoDatabase; import io.searchbox.client.JestClient; /** * A factory for DataContext objects. This class substantially easens the task * of creating and initializing DataContext objects and/or their strategies for * reading datastores. * * @see DataContext */ public class DataContextFactory { public static final char DEFAULT_CSV_SEPARATOR_CHAR = CsvConfiguration.DEFAULT_SEPARATOR_CHAR; public static final char DEFAULT_CSV_QUOTE_CHAR = CsvConfiguration.DEFAULT_QUOTE_CHAR; private DataContextFactory() { // Prevent instantiation } /** * Creates a composite DataContext based on a set of delegate DataContexts. * * Composite DataContexts enables cross-DataContext querying and unified * schema exploration * * @param delegates * an array/var-args of delegate DataContexts * @return a DataContext that matches the request */ public static DataContext createCompositeDataContext(DataContext... delegates) { return new CompositeDataContext(delegates); } /** * Creates a composite DataContext based on a set of delegate DataContexts. * * Composite DataContexts enables cross-DataContext querying and unified * schema exploration * * @param delegates * a collection of delegate DataContexts * @return a DataContext that matches the request */ public static DataContext createCompositeDataContext(Collection<DataContext> delegates) { return new CompositeDataContext(delegates); } /** * Creates a DataContext that connects to a Salesforce.com instance. * * @param username * the Salesforce username * @param password * the Salesforce password * @param securityToken * the Salesforce security token * @return a DataContext object that matches the request */ public static DataContext createSalesforceDataContext(String username, String password, String securityToken) { return new SalesforceDataContext(username, password, securityToken); } /** * Create a DataContext that connects to a SugarCRM system. * * @param baseUrl * the base URL of the system, e.g. http://localhost/sugarcrm * @param username * the SugarCRM username * @param password * the SugarCRM password * @param applicationName * the name of the application you are connecting with * @return a DataContext object that matches the request */ public static DataContext createSugarCrmDataContext(String baseUrl, String username, String password, String applicationName) { return new SugarCrmDataContext(baseUrl, username, password, applicationName); } /** * Creates a DataContext based on a CSV file * * @param file * a CSV file * @return a DataContext object that matches the request */ public static UpdateableDataContext createCsvDataContext(File file) { return createCsvDataContext(file, DEFAULT_CSV_SEPARATOR_CHAR, DEFAULT_CSV_QUOTE_CHAR); } /** * Creates a DataContext based on a JSON file */ public static DataContext createJsonDataContext(File file) { return new JsonDataContext(file); } /** * Creates a DataContext based on a CSV file * * @param file * a CSV file * @param separatorChar * the char to use for separating values * @param quoteChar * the char used for quoting values (typically if they include * the separator char) * @return a DataContext object that matches the request */ public static UpdateableDataContext createCsvDataContext(File file, char separatorChar, char quoteChar) { return createCsvDataContext(file, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING); } /** * Creates a DataContext based on a CSV file * * @param file * a CSV file * @param separatorChar * the char to use for separating values * @param quoteChar * the char used for quoting values (typically if they include * the separator char) * @param encoding * the character encoding of the file * @return a DataContext object that matches the request */ public static UpdateableDataContext createCsvDataContext(File file, char separatorChar, char quoteChar, String encoding) { final CsvConfiguration configuration = new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar, quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR); final CsvDataContext dc = new CsvDataContext(file, configuration); return dc; } /** * Creates a DataContext based on a CSV file * * @param file * a CSV file * @param configuration * the CSV configuration to use * @return a DataContext object that matches the request */ public static UpdateableDataContext createCsvDataContext(File file, CsvConfiguration configuration) { final CsvDataContext dc = new CsvDataContext(file, configuration); return dc; } /** * Creates a DataContext based on CSV-content through an input stream * * @param inputStream * the input stream to read from * @param separatorChar * the char to use for separating values * @param quoteChar * the char used for quoting values (typically if they include * the separator char) * @return a DataContext object that matches the request */ public static DataContext createCsvDataContext(InputStream inputStream, char separatorChar, char quoteChar) { return createCsvDataContext(inputStream, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING); } /** * Creates a DataContext based on CSV-content through an input stream * * @param inputStream * the input stream to read from * @param separatorChar * the char to use for separating values * @param quoteChar * the char used for quoting values (typically if they include * the separator char) * @return a DataContext object that matches the request */ public static DataContext createCsvDataContext(InputStream inputStream, char separatorChar, char quoteChar, String encoding) { final CsvConfiguration configuration = new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar, quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR); final CsvDataContext dc = new CsvDataContext(inputStream, configuration); return dc; } /** * Creates a DataContext based on CSV-content through an input stream * * @param inputStream * the input stream to read from * @param configuration * the CSV configuration to use * @return a DataContext object that matches the request */ public static DataContext createCsvDataContext(InputStream inputStream, CsvConfiguration configuration) { final CsvDataContext dc = new CsvDataContext(inputStream, configuration); return dc; } /** * Creates a DataContext based on a fixed width file. * * @param file * the file to read from. * @param fileEncoding * the character encoding of the file. * @param fixedValueWidth * the (fixed) width of values in the file. * @return a DataContext object that matches the request */ public static DataContext createFixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth) { return createFixedWidthDataContext(file, new FixedWidthConfiguration( FixedWidthConfiguration.DEFAULT_COLUMN_NAME_LINE, fileEncoding, fixedValueWidth)); } /** * Creates a DataContext based on a fixed width file. * * @param file * the file to read from. * @param configuration * the fixed width configuration to use * @return a DataContext object that matches the request */ public static DataContext createFixedWidthDataContext(File file, FixedWidthConfiguration configuration) { final FixedWidthDataContext dc = new FixedWidthDataContext(file, configuration); return dc; } /** * Creates a DataContext based on a fixed width file. * * @param resource * the resource to read from. * @param configuration * the fixed width configuration to use * @return a DataContext object that matches the request */ public static DataContext createFixedWidthDataContext(Resource resource, FixedWidthConfiguration configuration) { final FixedWidthDataContext dc = new FixedWidthDataContext(resource, configuration); return dc; } /** * Creates a DataContext based on a fixed width file. * * @param file * the file to read from. * @param fileEncoding * the character encoding of the file. * @param fixedValueWidth * the (fixed) width of values in the file. * @param headerLineNumber * the line number of the column headers. * @return a DataContext object that matches the request */ public static DataContext createFixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth, int headerLineNumber) { return createFixedWidthDataContext(file, new FixedWidthConfiguration( FixedWidthConfiguration.DEFAULT_COLUMN_NAME_LINE, fileEncoding, fixedValueWidth)); } /** * Creates a DataContet based on an Excel spreadsheet file * * @param file * an excel spreadsheet file * @param configuration * the configuration with metadata for reading the spreadsheet * @return a DataContext object that matches the request */ public static UpdateableDataContext createExcelDataContext(File file, ExcelConfiguration configuration) { return new ExcelDataContext(file, configuration); } /** * Creates a DataContext based on an Excel spreadsheet file * * @param file * an Excel spreadsheet file * @return a DataContext object that matches the request */ public static UpdateableDataContext createExcelDataContext(File file) { return createExcelDataContext(file, new ExcelConfiguration()); } /** * Creates a DataContext based on XML-content from an input source. * * Tables are created by examining the data in the XML file, NOT by reading * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but * also raises a risk that two XML files with the same format wont * nescesarily yield the same table model if some optional attributes or * tags are omitted in one of the files. * * @param inputSource * an input source feeding XML content * @param schemaName * the name to be used for the main schema * @param autoFlattenTables * a boolean indicating if MetaModel should flatten very simple * table structures (where tables only contain a single * data-carrying column) for greater usability of the generated * table-based model * @return a DataContext object that matches the request */ public static DataContext createXmlDataContext(InputSource inputSource, String schemaName, boolean autoFlattenTables) { XmlDomDataContext dc = new XmlDomDataContext(inputSource, schemaName, autoFlattenTables); return dc; } /** * Creates a DataContext based on XML-content from a File. * * Tables are created by examining the data in the XML file, NOT by reading * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but * also raises a risk that two XML files with the same format wont * nescesarily yield the same table model if some optional attributes or * tags are omitted in one of the files. * * @param file * the File to use for feeding XML content * @param autoFlattenTables * a boolean indicating if MetaModel should flatten very simple * table structures (where tables only contain a single * data-carrying column) for greater usability of the generated * table-based model * @return a DataContext object that matches the request */ public static DataContext createXmlDataContext(File file, boolean autoFlattenTables) { XmlDomDataContext dc = new XmlDomDataContext(file, autoFlattenTables); return dc; } /** * Creates a DataContext based on XML-content from a URL. * * Tables are created by examining the data in the XML file, NOT by reading * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but * also raises a risk that two XML files with the same format wont * nescesarily yield the same table model if some optional attributes or * tags are omitted in one of the files. * * @param url * the URL to use for feeding XML content * @param autoFlattenTables * a boolean indicating if MetaModel should flatten very simple * table structures (where tables only contain a single * data-carrying column) for greater usability of the generated * table-based model * @return a DataContext object that matches the request */ public static DataContext createXmlDataContext(URL url, boolean autoFlattenTables) { XmlDomDataContext dc = new XmlDomDataContext(url, autoFlattenTables); return dc; } /** * Creates a DataContext based on an OpenOffice.org database file. * * @param file * an OpenOffice.org database file * @return a DataContext object that matches the request */ public static DataContext createOpenOfficeDataContext(File file) { return new OpenOfficeDataContext(file); } /** * Creates a DataContext based on a JDBC connection * * @param connection * a JDBC connection * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(Connection connection) { return new JdbcDataContext(connection); } /** * Creates a DataContext based on a JDBC datasource * * @param ds * a JDBC datasource * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(DataSource ds) { return new JdbcDataContext(ds); } /** * Creates a DataContext based on a JDBC connection * * @param connection * a JDBC connection * @param catalogName * a catalog name to use * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(Connection connection, String catalogName) { return new JdbcDataContext(connection, TableType.DEFAULT_TABLE_TYPES, catalogName); } /** * Creates a DataContext based on a JDBC connection * * @param connection * a JDBC connection * @param tableTypes * the types of tables to include in the generated schemas * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(Connection connection, TableType... tableTypes) { return new JdbcDataContext(connection, tableTypes, null); } /** * Creates a DataContext based on a JDBC connection * * @param connection * a JDBC connection * @param catalogName * a catalog name to use * @param tableTypes * the types of tables to include in the generated schemas * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(Connection connection, String catalogName, TableType[] tableTypes) { return new JdbcDataContext(connection, tableTypes, catalogName); } /** * Creates a DataContext based on a JDBC datasource * * @param ds * a JDBC datasource * @param tableTypes * the types of tables to include in the generated schemas * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(DataSource ds, TableType... tableTypes) { return new JdbcDataContext(ds, tableTypes, null); } /** * Creates a DataContext based on a JDBC datasource * * @param ds * a JDBC datasource * @param catalogName * a catalog name to use * @param tableTypes * the types of tables to include in the generated schemas * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(DataSource ds, String catalogName, TableType[] tableTypes) { return new JdbcDataContext(ds, tableTypes, catalogName); } /** * Creates a DataContext based on a JDBC datasource * * @param ds * a JDBC datasource * @param catalogName * a catalog name to use * @return a DataContext object that matches the request */ public static UpdateableDataContext createJdbcDataContext(DataSource ds, String catalogName) { return new JdbcDataContext(ds, TableType.DEFAULT_TABLE_TYPES, catalogName); } /** * Creates a new MongoDB datacontext. * * @param hostname * The hostname of the MongoDB instance * @param port * the port of the MongoDB instance, or null if the default port * should be used. * @param databaseName * the name of the database * @param username * the username, or null if unauthenticated access should be used * @param password * the password, or null if unathenticated access should be used * @param tableDefs * an array of table definitions, or null if table definitions * should be autodetected. * @return a DataContext object that matches the request */ public static UpdateableDataContext createMongoDbDataContext(String hostname, Integer port, String databaseName, String username, char[] password, SimpleTableDef[] tableDefs) { try { final ServerAddress serverAddress; if (port == null) { serverAddress = new ServerAddress(hostname); } else { serverAddress = new ServerAddress(hostname, port); } final MongoClient mongoClient; final MongoDatabase mongoDb; if (Strings.isNullOrEmpty(username)) { mongoClient = new MongoClient(serverAddress); } else { final MongoCredential credential = MongoCredential.createCredential(username, databaseName, password); mongoClient = new MongoClient(serverAddress, Arrays.asList(credential)); } mongoDb = mongoClient.getDatabase(databaseName); if (tableDefs == null || tableDefs.length == 0) { return new MongoDbDataContext(mongoDb); } return new MongoDbDataContext(mongoDb, tableDefs); } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new IllegalStateException(e); } } /** * Creates a new MongoDB datacontext. * * @param hostname * The hostname of the MongoDB instance * @param port * the port of the MongoDB instance, or null if the default port * should be used. * @param databaseName * the name of the database * @param username * the username, or null if unauthenticated access should be used * @param password * the password, or null if unathenticated access should be used * @return a DataContext object that matches the request */ public static UpdateableDataContext createMongoDbDataContext(String hostname, Integer port, String databaseName, String username, char[] password) { return createMongoDbDataContext(hostname, port, databaseName, username, password, null); } /** * Creates a new CouchDB datacontext. * * @param hostname * The hostname of the CouchDB instance * @param port * the port of the CouchDB instance, or null if the default port * should be used. * @param username * the username, or null if unauthenticated access should be used * @param password * the password, or null if unathenticated access should be used * @return a DataContext object that matches the request */ public static UpdateableDataContext createCouchDbDataContext(String hostname, Integer port, String username, String password) { return createCouchDbDataContext(hostname, port, username, password, null); } /** * Creates a new CouchDB datacontext. * * @param hostname * The hostname of the CouchDB instance * @param port * the port of the CouchDB instance, or null if the default port * should be used. * @param username * the username, or null if unauthenticated access should be used * @param password * the password, or null if unathenticated access should be used * @param tableDefs * an array of table definitions, or null if table definitions * should be autodetected. * @return a DataContext object that matches the request */ public static UpdateableDataContext createCouchDbDataContext(String hostname, Integer port, String username, String password, SimpleTableDef[] tableDefs) { final Builder httpClientBuilder = new Builder(); httpClientBuilder.host(hostname); if (port != null) { httpClientBuilder.port(port); } if (username != null) { httpClientBuilder.username(username); } if (password != null) { httpClientBuilder.password(password); } // increased timeouts (20 sec) - metamodel typically does quite some // batching so it might take a bit of time to provide a connection. httpClientBuilder.connectionTimeout(20000); httpClientBuilder.socketTimeout(20000); if (tableDefs == null || tableDefs.length == 0) { return new CouchDbDataContext(httpClientBuilder); } return new CouchDbDataContext(httpClientBuilder, tableDefs); } /** * Creates a new JSON-based ElasticSearch datacontext. * @param client * The Jest client * @param indexName * The ElasticSearch index name * @return a DataContext object that matches the request */ public static UpdateableDataContext createElasticSearchDataContext(JestClient client, String indexName) { return new ElasticSearchRestDataContext(client, indexName); } /** * Creates a new ElasticSearch datacontext. * * @param client * The ElasticSearch client * @param indexName * The ElasticSearch index name * @return a DataContext object that matches the request */ public static UpdateableDataContext createElasticSearchDataContext(Client client, String indexName) { return new ElasticSearchDataContext(client, indexName); } /** * Creates a new Cassandra datacontext. * * @param cluster * The Cassandra client * @param keySpaceName * The Cassandra key space name * @return a DataContext object that matches the request */ public static DataContext createCassandraDataContext(Cluster cluster, String keySpaceName) { return new CassandraDataContext(cluster, keySpaceName); } /** * Creates a new HBase datacontext. * * @param configuration * {@code HBaseConfiguration} object containing detailed HBase * configuration properties. * * @return a DataContext object that matches the request */ public static DataContext createHBaseDataContext(HBaseConfiguration configuration){ return new HBaseDataContext(configuration); } /** * Creates a new HBase datacontext. * * @param configuration * {@code HBaseConfiguration} object containing detailed HBase * configuration properties. * * @param connection * A cluster connection encapsulating lower level individual * connections to actual servers and a connection to zookeeper. * * @return a DataContext object that matches the request */ public static DataContext createHBaseDataContext(HBaseConfiguration configuration,org.apache.hadoop.hbase.client.Connection connection) { return new HBaseDataContext(configuration, connection); } /** * Creates a new POJO data context that is empty but can be populated at * will. * * @return a DataContext object that matches the request * */ public static DataContext createPojoDataContext() { return new PojoDataContext(); } /** * Creates a new POJO data context based on the provided * {@link TableDataProvider}s. * * @param tables * list of tables * * @return DataContext object that matches the request */ public static DataContext createPojoDataContext(List<TableDataProvider<?>> tables) { return new PojoDataContext(tables); } /** * Creates a new POJO data context based on the provided * {@link TableDataProvider}s. * * @param schemaName * the name of the created schema * * @param tables * table information * * @return DataContext object that matches the request * */ public static DataContext createPojoDataContext(String schemaName,TableDataProvider<?>[] tables) { return new PojoDataContext(schemaName, tables); } /** * Creates a new POJO data context based on the provided * {@link TableDataProvider}s. * * @param schemaName * the name of the created schema * * @param tables * list of tables * * @return DataContext object that matches the request */ public static DataContext createPojoDataContext(String schemaName,List<TableDataProvider<?>> tables) { return new PojoDataContext(schemaName, tables); } }