
com.github.nill14.utils.init.impl.ServiceRegistry Maven / Gradle / Ivy
package com.github.nill14.utils.init.impl;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.github.nill14.utils.init.api.ILazyPojo;
import com.github.nill14.utils.init.api.IPojoFactory;
import com.github.nill14.utils.init.api.IPojoInitializer;
import com.github.nill14.utils.init.api.IPropertyResolver;
import com.github.nill14.utils.init.api.IServiceRegistry;
import com.github.nill14.utils.init.api.IType;
import com.github.nill14.utils.init.inject.PojoInjectionDescriptor;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
/**
*
* The ServiceRegistry must not be serializable. Serializing the registry indicates a programming error.
*
*/
public class ServiceRegistry implements IServiceRegistry {
private final ConcurrentHashMap beans = new ConcurrentHashMap<>();
private final ConcurrentHashMap, Map> services = new ConcurrentHashMap<>();
private IPropertyResolver delegateResolver;
/**
*
* Not thread-safe
* @param delegateResolver The extra resolver which can provide the answer first.
*/
public void setDelegateResolver(IPropertyResolver delegateResolver) {
if(this.delegateResolver != null) {
throw new IllegalStateException("can be set only once");
}
this.delegateResolver = delegateResolver;
}
private String generateName(Class> type) {
return type.getTypeName();
}
@Override
public void addService(Class serviceBean) {
addService(generateName(serviceBean), serviceBean);
}
@Override
public void addService(String name, Class serviceBean) {
ILazyPojo lazyPojo = LazyPojo.forClass(serviceBean, annotationInitializer);
Object proxy = LazyJdkProxy.newProxy(lazyPojo);
Set> types = new PojoInjectionDescriptor(serviceBean).getDeclaredTypes();
types.forEach((type) -> addElement(type, name, proxy));
Object old = beans.put(name, proxy);
Preconditions.checkArgument(old == null, "Duplicate bean " + old);
}
@Override
public > void addServiceFactory(
Class iface, Class factoryBean) {
addServiceFactory(iface, generateName(iface), factoryBean);
}
@Override
public > void addServiceFactory(
Class iface, String name, Class factoryBean) {
ILazyPojo lazyPojo = LazyPojo.forFactory(iface, factoryBean, annotationInitializer);
Object proxy = LazyJdkProxy.newProxy(lazyPojo);
Set> types = new PojoInjectionDescriptor(iface).getDeclaredTypes();
types.forEach((type) -> addElement(type, name, proxy));
beans.put(name, proxy);
}
@Override
public S getService(Class iface) {
Optional optional = getOptionalService(iface);
return iface.cast(optional.get());
}
@Override
public S getService(Class iface, String name) {
S service = iface.cast(beans.get(name));
Objects.requireNonNull(service);
return service;
}
@Override
public Optional getOptionalService(Class iface) {
return getServices(iface).stream().findFirst();
}
@Override
public Optional getOptionalService(Class iface, String name) {
S service = iface.cast(beans.get(name));
return Optional.ofNullable(service);
}
private void addElement(Class> registrable, String name, Object proxy) {
Map map = services.computeIfAbsent(registrable, r -> new ConcurrentHashMap<>());
map.put(name, proxy);
}
@SuppressWarnings("unchecked")
@Override
public Collection getServices(Class registrable) {
Preconditions.checkNotNull(registrable);
Map map = (Map) services.getOrDefault(registrable, Collections.emptyMap());
if (map != null) {
return ImmutableList.copyOf(map.values());
} else {
return ImmutableList.of();
}
}
@Override
public void addSingleton(T serviceBean) {
addSingleton(Objects.toString(serviceBean), serviceBean);
}
@Override
public void addSingleton(String name, T serviceBean) {
Set> types = new PojoInjectionDescriptor(serviceBean.getClass()).getDeclaredTypes();
types.forEach((type) -> addElement(type, name, serviceBean));
beans.put(name, serviceBean);
}
public Collection> getBeans() {
Builder> builder = ImmutableList.builder();
builder.addAll(services.keySet());
// builder.addAll(providers.values())
return builder.build();
}
public Collection getBeanNames() {
return beans.keySet();
}
@SuppressWarnings("unchecked")
public Map getBeansOfType(Class type) {
return (Map) services.getOrDefault(type, Collections.emptyMap());
}
public Object getBean(String name) {
return beans.get(name);
}
private final IPropertyResolver resolver = new IPropertyResolver() {
private static final long serialVersionUID = 746185406164849945L;
@Override
public Object resolve(Object pojo, IType type) {
if (delegateResolver != null) {
Object resolve = delegateResolver.resolve(pojo, type);
if (resolve != null) {
return resolve;
}
}
Optional> optionalNamed = getOptionalService(type.getRawType(), type.getName());
if (optionalNamed.isPresent()) {
return optionalNamed.get();
}
if (type.isParametrized()) {
Class> rawType = type.getRawType();
Class> paramClass = type.getFirstParamClass();
if (Optional.class.isAssignableFrom(rawType)) {
Optional> optional = getOptionalService(paramClass);
return optional;
}
if (Collection.class.isAssignableFrom(rawType)) {
Collection> providers = getServices(paramClass);
if (Set.class.isAssignableFrom(rawType)) {
return ImmutableSet.copyOf(providers);
} else {
return ImmutableList.copyOf(providers);
}
}
}
Optional> optionalTyped = getOptionalService(type.getRawType());
if (optionalTyped.isPresent()) {
return optionalTyped.get();
}
return null;
}
};
public IPropertyResolver toResolver() {
return resolver;
}
private final IPojoInitializer
© 2015 - 2025 Weber Informatics LLC | Privacy Policy