
org.reactivecommons.async.starter.props.GenericAsyncPropsDomain Maven / Gradle / Ivy
Show all versions of async-commons-starter Show documentation
package org.reactivecommons.async.starter.props;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.reactivecommons.async.starter.exceptions.InvalidConfigurationException;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN;
@Getter
@Setter
public class GenericAsyncPropsDomain, P> extends HashMap {
private Class asyncPropsClass;
private Class propsClass;
public GenericAsyncPropsDomain(String defaultAppName,
P defaultProperties,
GenericAsyncPropsDomainProperties configured,
SecretFiller secretFiller,
Class asyncPropsClass,
Class propsClass) {
super(configured);
this.propsClass = propsClass;
this.asyncPropsClass = asyncPropsClass;
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
this.computeIfAbsent(DEFAULT_DOMAIN, k -> {
T defaultApp = AsyncPropsDomainBuilder.instantiate(asyncPropsClass);
defaultApp.setConnectionProperties(mapper.convertValue(defaultProperties, propsClass));
return defaultApp;
});
super.forEach((key, value) -> { // To ensure that each domain has an appName
if (value.getAppName() == null) {
if (defaultAppName == null || defaultAppName.isEmpty()) {
throw new InvalidConfigurationException("defaultAppName does not has value and domain " + key
+ " has not set the property appName. please use respective property or " +
" spring.application.name property or withDefaultAppName in builder");
}
value.setAppName(defaultAppName);
}
if (value.getConnectionProperties() == null) {
if (defaultProperties == null) {
throw new InvalidConfigurationException("Domain " + key + " could not be instantiated because no" +
" properties found, please use withDefaultProperties or define the" +
"default " + key + " domain with properties explicitly");
}
value.setConnectionProperties(mapper.convertValue(defaultProperties, propsClass));
}
if (secretFiller != null) {
secretFiller.fillWithSecret(key, value);
}
fillCustoms(value);
});
}
protected void fillCustoms(T asyncProps) {
// To be overridden called after the default properties are set
}
public T getProps(String domain) {
T props = get(domain);
if (props == null) {
throw new InvalidConfigurationException("Domain " + domain + " id not defined");
}
return props;
}
// Static builder strategy
public static <
T extends GenericAsyncProps
,
P,
X extends GenericAsyncPropsDomainProperties,
R extends GenericAsyncPropsDomain>
AsyncPropsDomainBuilder builder(Class propsClass,
Class asyncPropsDomainClass,
Constructor returnType) {
return new AsyncPropsDomainBuilder<>(propsClass, asyncPropsDomainClass, returnType);
}
public static class AsyncPropsDomainBuilder<
T extends GenericAsyncProps,
P,
X extends GenericAsyncPropsDomainProperties,
R extends GenericAsyncPropsDomain> {
private final Class propsClass;
private final Class asyncPropsDomainClass;
private final Constructor returnType;
private String defaultAppName;
private final HashMap domains = new HashMap<>();
private P defaultProperties;
private SecretFiller secretFiller;
public AsyncPropsDomainBuilder(Class
propsClass, Class asyncPropsDomainClass,
Constructor returnType) {
this.propsClass = propsClass;
this.asyncPropsDomainClass = asyncPropsDomainClass;
this.returnType = returnType;
}
public AsyncPropsDomainBuilder withDefaultProperties(P defaultProperties) {
this.defaultProperties = defaultProperties;
return this;
}
public AsyncPropsDomainBuilder withDefaultAppName(String defaultAppName) {
this.defaultAppName = defaultAppName;
return this;
}
public AsyncPropsDomainBuilder withSecretFiller(SecretFiller secretFiller) {
this.secretFiller = secretFiller;
return this;
}
public AsyncPropsDomainBuilder withDomain(String domain, T props) {
domains.put(domain, props);
return this;
}
@SneakyThrows
public R build() {
X domainProperties = instantiate(asyncPropsDomainClass, domains);
if (defaultProperties == null) {
defaultProperties = instantiate(propsClass);
}
return returnType.newInstance(defaultAppName, defaultProperties, domainProperties, secretFiller);
}
@SneakyThrows
private static X instantiate(Class xClass) {
return xClass.getDeclaredConstructor().newInstance();
}
@SneakyThrows
private static X instantiate(Class xClass, Map, ?> arg) {
return xClass.getDeclaredConstructor(Map.class).newInstance(arg);
}
}
public interface SecretFiller {
void fillWithSecret(String domain, GenericAsyncProps
props);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
GenericAsyncPropsDomain, ?> that = (GenericAsyncPropsDomain, ?>) o;
return Objects.equals(asyncPropsClass, that.asyncPropsClass) && Objects.equals(propsClass, that.propsClass);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), asyncPropsClass, propsClass);
}
}