// Copyright © 2016 HSL <https://www.hsl.fi> // This program is dual-licensed under the EUPL v1.2 and AGPLv3 licenses. package fi.hsl.parkandride.config; import com.querydsl.sql.SQLExceptionTranslator; import com.querydsl.sql.SQLTemplates; import com.querydsl.sql.postgresql.PostgreSQLQueryFactory; import com.querydsl.sql.spatial.GeoDBTemplates; import com.querydsl.sql.spatial.PGGeometryType; import com.querydsl.sql.spatial.PostGISTemplates; import com.querydsl.sql.types.DateTimeType; import com.querydsl.sql.types.EnumByNameType; import fi.hsl.parkandride.FeatureProfile; import fi.hsl.parkandride.back.H2GeometryType; import fi.hsl.parkandride.back.LiipiSQLExceptionTranslator; import fi.hsl.parkandride.back.TimeType; import fi.hsl.parkandride.core.back.PhoneType; import fi.hsl.parkandride.core.domain.*; import org.geolatte.geom.Point; import org.geolatte.geom.Polygon; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.transaction.PlatformTransactionManager; import javax.inject.Inject; import javax.inject.Provider; import javax.sql.DataSource; import java.sql.Connection; @Configuration public class JdbcConfiguration { private static final Logger log = LoggerFactory.getLogger(JdbcConfiguration.class); @Configuration @Profile({FeatureProfile.H2}) public static class H2 { public H2() { log.info("USING H2"); } @Bean public SQLTemplates sqlTemplates() { return new GeoDBTemplates(); } } @Configuration @Profile(FeatureProfile.PSQL) public static class Postgresql { public Postgresql() { log.info("USING POSTGRESQL"); } @Bean public SQLTemplates sqlTemplates() { return new PostGISTemplates(); } } @Inject SQLTemplates sqlTemplates; @Inject DataSource dataSource; @Bean public PostgreSQLQueryFactory queryFactory(com.querydsl.sql.Configuration configuration) { return new PostgreSQLQueryFactory(configuration, connectionProvider()); } @Bean public Provider<Connection> connectionProvider() { return () -> { Connection conn = DataSourceUtils.getConnection(dataSource); if (!DataSourceUtils.isConnectionTransactional(conn, dataSource)) { throw new RuntimeException("Connection should be transactional"); } return conn; }; } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource); } @Bean @Profile(FeatureProfile.PSQL) public com.querydsl.sql.Configuration querydslConfigurationPsql() { com.querydsl.sql.Configuration conf = querydslConfiguration(); conf.register("FACILITY", "LOCATION", new PGGeometryType<>(Polygon.class)); conf.register("PORT", "LOCATION", new PGGeometryType<>(Point.class)); conf.register("HUB", "LOCATION", new PGGeometryType<>(Point.class)); conf.register("REGION", "AREA", new PGGeometryType<>(Polygon.class)); return conf; } @Bean @Profile({FeatureProfile.H2}) public com.querydsl.sql.Configuration querydslConfigurationH2() { com.querydsl.sql.Configuration conf = querydslConfiguration(); conf.register("FACILITY", "LOCATION", new H2GeometryType<>(Polygon.class)); conf.register("PORT", "LOCATION", new H2GeometryType<>(Point.class)); conf.register("HUB", "LOCATION", new H2GeometryType<>(Point.class)); conf.register("REGION", "AREA", new H2GeometryType<>(Polygon.class)); return conf; } private com.querydsl.sql.Configuration querydslConfiguration() { com.querydsl.sql.Configuration conf = new com.querydsl.sql.Configuration(sqlTemplates); conf.setExceptionTranslator(sqlExceptionTranslator()); conf.register(new TimeType()); conf.register("PRICING", "CAPACITY_TYPE", new EnumByNameType<>(CapacityType.class)); conf.register("PRICING", "USAGE", new EnumByNameType<>(Usage.class)); conf.register("PRICING", "DAY_TYPE", new EnumByNameType<>(DayType.class)); conf.register("PRICING", "FROM_TIME", new TimeType()); conf.register("PRICING", "UNTIL_TIME", new TimeType()); conf.register("UNAVAILABLE_CAPACITY", "CAPACITY_TYPE", new EnumByNameType<>(CapacityType.class)); conf.register("UNAVAILABLE_CAPACITY", "USAGE", new EnumByNameType<>(Usage.class)); conf.register("UNAVAILABLE_CAPACITY_HISTORY", "CAPACITY_TYPE", new EnumByNameType<>(CapacityType.class)); conf.register("UNAVAILABLE_CAPACITY_HISTORY", "USAGE", new EnumByNameType<>(Usage.class)); conf.register("CAPACITY_TYPE", "NAME", new EnumByNameType<>(CapacityType.class)); conf.register("USAGE", "NAME", new EnumByNameType<>(Usage.class)); conf.register("CONTACT", "PHONE", new PhoneType()); conf.register("APP_USER", "ROLE", new EnumByNameType<>(Role.class)); conf.register("FACILITY", "STATUS", new EnumByNameType<>(FacilityStatus.class)); conf.register("FACILITY", "PRICING_METHOD", new EnumByNameType<>(PricingMethod.class)); conf.register("FACILITY_UTILIZATION", "CAPACITY_TYPE", new EnumByNameType<>(CapacityType.class)); conf.register("FACILITY_UTILIZATION", "USAGE", new EnumByNameType<>(Usage.class)); conf.register("FACILITY_PREDICTION", "CAPACITY_TYPE", new EnumByNameType<>(CapacityType.class)); conf.register("FACILITY_PREDICTION", "USAGE", new EnumByNameType<>(Usage.class)); conf.register("FACILITY_SERVICE", "SERVICE", new EnumByNameType<>(Service.class)); conf.register("FACILITY_STATUS_HISTORY", "STATUS", new EnumByNameType<>(FacilityStatus.class)); conf.register("FACILITY_PAYMENT_METHOD", "PAYMENT_METHOD", new EnumByNameType<>(PaymentMethod.class)); conf.register("PREDICTOR", "CAPACITY_TYPE", new EnumByNameType<>(CapacityType.class)); conf.register("PREDICTOR", "USAGE", new EnumByNameType<>(Usage.class)); conf.register(new DateTimeType()); return conf; } private SQLExceptionTranslator sqlExceptionTranslator() { return new LiipiSQLExceptionTranslator(); } }