/**
* 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.jooby.querydsl;
import static java.util.Objects.requireNonNull;
import static javaslang.API.Case;
import static javaslang.API.Match;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.jooby.Env;
import org.jooby.Env.ServiceKey;
import org.jooby.jdbc.Jdbc;
import com.google.inject.Binder;
import com.querydsl.sql.Configuration;
import com.querydsl.sql.DB2Templates;
import com.querydsl.sql.FirebirdTemplates;
import com.querydsl.sql.H2Templates;
import com.querydsl.sql.HSQLDBTemplates;
import com.querydsl.sql.MySQLTemplates;
import com.querydsl.sql.OracleTemplates;
import com.querydsl.sql.PostgreSQLTemplates;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.SQLTemplates;
import com.querydsl.sql.SQLiteTemplates;
import com.typesafe.config.Config;
/**
* <h1>queryDSL</h1>
*
* <p>
* SQL abstraction provided by <a href="http://www.querydsl.com">QueryDSL</a> using plain JDBC
* underneath.
* </p>
*
* <p>
* This module depends on {@link Jdbc} module, make sure you read the doc of the {@link Jdbc}
* module before using this module.
* </p>
*
* <h2>usage</h2>
*
* <pre>
* import org.jooby.querydsl.QueryDSL;
*
* {
* use(new QueryDSL());
*
* get("/my-api", req {@literal ->} {
* SQLQueryFactory queryFactory = req.require(SQLQueryFactory.class);
* // Do something with the database
* ...
* });
* }
* </pre>
*
* <h2>dialects</h2>
* <p>
* Dialect is detected automatically and usually you don't need to do anything. But if the default
* dialect detector doesn't work and/or you have a custom dialect:
* </p>
*
* <pre>
* {
* use(new QueryDSL().with(new MyCustomTemplates());
* }
* </pre>
*
* <h2>multiple databases</h2>
*
* <pre>
* import org.jooby.querydsl.QueryDSL;
*
* {
* use(new QueryDSL("db.main"));
* use(new QueryDSL("db.aux"));
*
* get("/my-api", req {@literal ->} {
* SQLQueryFactory queryFactory = req.require("db.main", SQLQueryFactory.class);
* // Do something with the database
* });
* }
* </pre>
*
* <h2>advanced configuration</h2>
* <p>
* This module builds QueryDSL SQLQueryFactories on top of a default {@link Configuration} object, a
* {@link SQLTemplates} instance and a {@link javax.sql.DataSource} from the {@link Jdbc} module.
* </p>
* <p>
* Advanced configuration can be added by invoking the {@link #doWith(BiConsumer)} method, adding
* your own settings to the configuration.
* </p>
*
* <pre>
* {
* use(new QueryDSL().doWith(conf {@literal ->} {
* conf.set(...);
* });
* }
* </pre>
*
* <h2>code generation</h2>
* <p>
* This module does not provide code generation for DB mapping classes. To learn how to create
* QueryDSL mapping classes using Maven, please consult the
* <a href="http://www.querydsl.com/static/querydsl/latest/reference/html_single/#d0e725">QueryDSL
* documentation.</a>
* </p>
*
* @since 1.0.0.CR
* @author sjackel
*/
public class QueryDSL extends Jdbc {
private Function<String, SQLTemplates> templates = QueryDSL::toSQLTemplates;
/**
* Creates a new {@link QueryDSL} module
*
* @param name Database name
*/
public QueryDSL(final String name) {
super(name);
}
/**
* Creates a new {@link QueryDSL} module
*/
public QueryDSL() {
}
@Override
public void configure(final Env env, final Config conf, final Binder binder) {
super.configure(env, conf, binder, (name, ds) -> {
SQLTemplates templates = this.templates.apply(dbtype.orElse("unknown"));
Configuration querydslconf = new Configuration(templates);
callback(querydslconf, conf);
SQLQueryFactory sqfp = new SQLQueryFactory(querydslconf, ds);
ServiceKey serviceKey = env.serviceKey();
serviceKey.generate(SQLTemplates.class, name, k -> binder.bind(k).toInstance(templates));
serviceKey.generate(Configuration.class, name, k -> binder.bind(k).toInstance(querydslconf));
serviceKey.generate(SQLQueryFactory.class, name, k -> binder.bind(k).toInstance(sqfp));
});
}
public QueryDSL with(final SQLTemplates templates) {
requireNonNull(templates, "SQL templates needs to be defined");
this.templates = t -> templates;
return this;
}
static SQLTemplates toSQLTemplates(final String type) {
return Match(type).option(
Case("db2", DB2Templates::new),
Case("mysql", MySQLTemplates::new),
Case("mariadb", MySQLTemplates::new),
Case("h2", H2Templates::new),
Case("hsqldb", HSQLDBTemplates::new),
Case("pgsql", PostgreSQLTemplates::new),
Case("postgresql", PostgreSQLTemplates::new),
Case("sqlite", SQLiteTemplates::new),
Case("oracle", OracleTemplates::new),
Case("firebirdsql", FirebirdTemplates::new))
.getOrElseThrow(() -> new IllegalStateException("Unsupported database: " + type));
}
}