package charts.builder;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.reflections.Reflections;
import play.Logger;
import charts.Chart;
import charts.ChartType;
import charts.Region;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class DefaultChartBuilder implements ChartBuilder {
private static final ImmutableList<ChartTypeBuilder> builders = detectBuilders();
private final DataSourceFactory dataSourceFactory;
@Inject
public DefaultChartBuilder(DataSourceFactory dsf) {
this.dataSourceFactory = dsf;
}
@Override
public List<Chart> getCharts(String id, ChartType type,
List<Region> regions, Map<String, String> parameters) throws Exception {
DataSource datasource = dataSourceFactory.getDataSource(id);
return getCharts(datasource, type, regions, parameters);
}
private List<Chart> getCharts(DataSource datasource,
ChartType type,
List<Region> regions,
Map<String, String> parameters) {
final List<Chart> result = Lists.newLinkedList();
for (final ChartTypeBuilder builder : builders) {
try {
List<Chart> charts = builder.build(datasource, type, regions, parameters);
if(!charts.isEmpty()) {
result.addAll(charts);
}
} catch(Exception e) {
Logger.warn(String.format("caught exception while building charts (type %s," +
" regions %s, parameters %s)", type, regions, parameters), e);
}
}
// make sure charts are sorted by region
// https://github.com/uq-eresearch/aorra/issues/44
Collections.sort(result, new Comparator<Chart>() {
@Override
public int compare(Chart c1, Chart c2) {
return getRegion(c1).compareTo(getRegion(c2));
}
private Region getRegion(Chart c) {
return c.getDescription().getRegion();
}
});
return result;
}
public List<ChartTypeBuilder> builders() {
return builders;
}
private static ImmutableList<ChartTypeBuilder> detectBuilders() {
final ImmutableList.Builder<ChartTypeBuilder> b =
new ImmutableList.Builder<ChartTypeBuilder>();
for (Class<? extends ChartTypeBuilder> builderClass : new Reflections(
"charts.builder").getSubTypesOf(ChartTypeBuilder.class)) {
if (builderClass.isInterface())
continue;
if (Modifier.isAbstract(builderClass.getModifiers()))
continue;
try {
Logger.debug("Found chart builder: "+builderClass.getCanonicalName());
b.add(builderClass.newInstance());
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return b.build();
}
}