Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.osgl.inject.ElementLoaderProvider Maven / Gradle / Ivy
package org.osgl.inject;
import org.osgl.$;
import org.osgl.inject.annotation.Filter;
import org.osgl.inject.annotation.LoadCollection;
import org.osgl.inject.annotation.MapKey;
import org.osgl.util.C;
import javax.inject.Provider;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A provider decorate that add element loading function decorator
* to underline provider
*/
abstract class ElementLoaderProvider implements Provider {
private static class FilterInfo extends $.Predicate {
final ElementFilter filter;
final Map options;
final $.Function predicate;
final BeanSpec containerSpec;
FilterInfo(ElementFilter filter, boolean reverse, Annotation anno, BeanSpec container) {
this.filter = filter;
this.options = $.evaluate(anno);
$.Function filterFunction = filter.filter(options, container);
this.predicate = reverse ? $.F.negate(filterFunction) : filterFunction;
this.containerSpec = container;
}
public boolean test(Object bean) {
return predicate.apply(bean);
}
}
private static class LoaderInfo extends FilterInfo implements Comparable {
LoaderInfo(ElementLoader loader, boolean reverse, Annotation anno, BeanSpec container) {
super(loader, reverse, anno, container);
}
ElementLoader loader() {
return (ElementLoader) filter;
}
@Override
public int compareTo(LoaderInfo o) {
return loader().priority() - o.loader().priority();
}
Iterable load(Genie genie) {
return loader().load(options, containerSpec, genie);
}
}
private static class CollectionLoaderProvider extends ElementLoaderProvider {
CollectionLoaderProvider(BeanSpec spec, Provider provider, Genie genie) {
super(spec, provider, genie);
}
@Override
protected void populate(T bean, Object element) {
bean.add(element);
}
}
private static class MapLoaderProvider extends ElementLoaderProvider {
String hint;
KeyExtractor keyExtractor;
MapLoaderProvider(BeanSpec spec, Provider provider, Genie genie) {
super(spec, provider, genie);
MapKey mapKey = spec.mapKey();
this.keyExtractor = genie.get(mapKey.extractor());
this.hint = mapKey.value();
}
@Override
protected void populate(T bean, Object element) {
bean.put(keyExtractor.keyOf(hint, element), element);
}
}
private final Provider realProvider;
private final LoaderInfo loader;
private final Set filters;
private final Genie genie;
private ElementLoaderProvider(BeanSpec spec, Provider provider, Genie genie) {
this.realProvider = provider;
C.List loaders = loaders(genie, spec).sorted();
this.loader = loaders.first();
List extends FilterInfo> tail = loaders.head(-1);
this.filters = C.set(filters(genie, spec).append(tail));
this.genie = genie;
}
@Override
public final T get() {
T bean = realProvider.get();
$.Predicate predicate = $.F.and(filters.toArray(new FilterInfo[filters.size()]));
for (Object element : loader.load(genie)) {
if (predicate.test(element)) {
populate(bean, element);
}
}
return bean;
}
protected abstract void populate(T bean, Object element);
static Provider decorate(BeanSpec spec, Provider provider, Genie genie) {
if (!spec.hasElementLoader()) {
return provider;
}
if (provider instanceof ElementLoaderProvider) {
return $.cast(provider);
}
if (spec.isMap()) {
return new MapLoaderProvider(spec, provider, genie);
}
return new CollectionLoaderProvider(spec, provider, genie);
}
private static C.List loaders(Genie genie, BeanSpec spec) {
C.List list = C.newList();
Set loaders = spec.loaders();
for (Annotation anno : loaders) {
Class extends Annotation> annoClass = anno.annotationType();
LoadCollection loaderTag = LoadCollection.class == annoClass ? ((LoadCollection) anno) : annoClass.getAnnotation(LoadCollection.class);
ElementLoader loader = genie.get(loaderTag.value());
list.add(new LoaderInfo(loader, loaderTag.reverseFilter(), anno, spec));
}
return list;
}
private static C.List filters(Genie genie, BeanSpec spec) {
C.List list = C.newList();
Set annotations = spec.filters();
for (Annotation anno : annotations) {
Class extends Annotation> annoClass = anno.annotationType();
Filter filterTag = (Filter.class == annoClass) ? (Filter) anno : annoClass.getAnnotation(Filter.class);
ElementFilter loader = genie.get(filterTag.value());
list.add(new FilterInfo(loader, filterTag.reverse(), anno, spec));
}
return list;
}
}