package com.example;

import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Maps;
import com.zaxxer.hikari.HikariConfig;

import io.dropwizard.db.ManagedDataSource;
import io.dropwizard.db.ManagedPooledDataSource;
import io.dropwizard.db.PooledDataSourceFactory;
import io.dropwizard.util.Duration;
import io.dropwizard.validation.MinDuration;

public class HikariDataSourceFactory implements PooledDataSourceFactory {
    @NotNull
    private String datasourceClassName = null;

    private String user = null;

    private String password = null;

    private boolean autoCommit = true;

    @NotNull
    private Map<String, String> properties = Maps.newLinkedHashMap();

    @Min(1)
    @JsonProperty
    private int minSize = 8;

    @Min(1)
    @JsonProperty
    private int maxSize = 16;

    @NotNull
    private String validationQuery = "/* Health Check */ SELECT 1";

    private boolean autoCommentsEnabled = true;

    @JsonProperty
    @Override
    public boolean isAutoCommentsEnabled() {
        return this.autoCommentsEnabled;
    }

    @JsonProperty
    public void setAutoCommentsEnabled(final boolean autoCommentsEnabled) {
        this.autoCommentsEnabled = autoCommentsEnabled;
    }

    @JsonProperty
    @Override
    public String getDriverClass() {
        return this.datasourceClassName;
    }

    @Override
    public String getUrl() {
        return "I'm not needed";
    }

    @JsonProperty
    public void setDatasourceClassName(final String datasourceClassName) {
        this.datasourceClassName = datasourceClassName;
    }

    @JsonProperty
    public String getUser() {
        return this.user;
    }

    @JsonProperty
    public void setUser(final String user) {
        this.user = user;
    }

    @JsonProperty
    public String getPassword() {
        return this.password;
    }

    @JsonProperty
    public void setPassword(final String password) {
        this.password = password;
    }

    @JsonProperty
    @Override
    public Map<String, String> getProperties() {
        return this.properties;
    }

    @JsonProperty
    public void setProperties(final Map<String, String> properties) {
        this.properties = properties;
    }

    @Override
    @JsonProperty
    public String getValidationQuery() {
        return this.validationQuery;
    }

    @Override
    @Deprecated
    @JsonIgnore
    public String getHealthCheckValidationQuery() {
        return this.getValidationQuery();
    }

    @Override
    @Deprecated
    @JsonIgnore
    public Optional<Duration> getHealthCheckValidationTimeout() {
        return this.getValidationQueryTimeout();
    }

    @JsonProperty
    public boolean isAutoCommit() {
        return autoCommit;
    }

    @JsonProperty
    public void setAutoCommit(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }

    @Override
    public void asSingleConnectionPool() {
        this.minSize = 1;
        this.maxSize = 1;
    }

    @Override
    public ManagedDataSource build(final MetricRegistry metricRegistry, final String name) {
        final Properties properties = new Properties();
        for (final Map.Entry<String, String> property : this.properties.entrySet()) {
            properties.setProperty(property.getKey(), property.getValue());
        }

        final HikariConfig config = new HikariConfig();
        config.setMetricRegistry(metricRegistry);
        config.setAutoCommit(autoCommit);
        config.setDataSourceProperties(properties);
        config.setDataSourceClassName(this.datasourceClassName);
        config.setMaximumPoolSize(this.maxSize);
        config.setMinimumIdle(this.minSize);
        config.setPoolName(name);
        config.setUsername(this.user);
        config.setPassword(this.user != null && this.password == null ? "" : this.password);
        return new HikariManagedPooledDataSource(config);
    }

    @Override
    @JsonProperty
    public java.util.Optional<Duration> getValidationQueryTimeout() {
        return Optional.of(Duration.minutes(1));
    }
}
@@ -81,26 +81,27 @@
 va.util.
-Properties
+OptionalInt
 ;%0Aimport
@@ -115,27 +115,18 @@
 til.
-concurrent.TimeUnit
+Properties
 ;%0A%0Ai
@@ -487,57 +487,8 @@
 ce;%0A
-import io.dropwizard.db.ManagedPooledDataSource;%0A
 impo
@@ -571,53 +571,8 @@
 ion;
-%0Aimport io.dropwizard.validation.MinDuration;
 %0A%0Apu
@@ -936,25 +936,33 @@
     private 
-i
+OptionalI
 nt minSize =
@@ -966,9 +966,27 @@
 e = 
-8
+OptionalInt.empty()
 ;%0A%0A 
@@ -3156,25 +3156,43 @@
 s.minSize = 
-1
+OptionalInt.empty()
 ;%0A        th
@@ -3788,21 +3788,16 @@
 assName(
-this.
 datasour
@@ -3844,21 +3844,16 @@
 oolSize(
-this.
 maxSize)
@@ -3858,31 +3858,50 @@
 e);%0A        
+minSize.ifPresent(
 config
-.
+::
 setMinimumId
@@ -3906,21 +3906,8 @@
 Idle
-(this.minSize
 );%0A 
@@ -3966,21 +3966,16 @@
 sername(
-this.
 user);%0A 
@@ -4000,21 +4000,16 @@
 assword(
-this.
 user != 
@@ -4016,21 +4016,16 @@
 null && 
-this.
 password
@@ -4040,21 +4040,16 @@
  ? %22%22 : 
-this.
 password

Allow absent minSize to default to maxSize