package com.levigo.samplelib; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.levigo.samplelib.SampleHostInstance.SampleHostModule; import com.levigo.samplelib.api.SampleLibraryContext; import com.levigo.samplelib.descriptors.CategoryDescriptor; import com.levigo.samplelib.descriptors.LevigoSampleSystem; import com.levigo.samplelib.descriptors.LevigoSamples; import com.levigo.samplelib.descriptors.RequireSampleHostDescriptor; import com.levigo.samplelib.descriptors.RequirementDescriptor; import com.levigo.samplelib.descriptors.SampleDescriptor; import com.levigo.samplelib.descriptors.SampleHostDescriptor; import com.levigo.samplelib.util.TreeWalker; public class SampleManager { private static final Logger LOG = Logger.getLogger(SampleManager.class.getName()); private static final class CategoryDescriptorDebugTreeWalker extends TreeWalker<CategoryDescriptor> { private final Logger log; public CategoryDescriptorDebugTreeWalker(Logger log) { super(); this.log = log; } @Override protected Iterable<CategoryDescriptor> loadChildren(CategoryDescriptor parent, TraversalContext context) { return parent.getChildren() != null ? parent.getChildren() : TreeWalker.<CategoryDescriptor> empty(); } @Override protected void process(CategoryDescriptor obj, TraversalContext context) { StringBuilder b = new StringBuilder(); for (int i = 0; i < context.getDepth(); i++) b.append(" "); b.append(obj.getId()); log.fine(b.toString()); } } // FIXME should that really be static?` private static final Injector ROOT_INJECTOR = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(SampleLibraryContext.class).toInstance(new SampleLibraryContext()); } }); private Category categories; private List<SampleHostInstance> hostInstances; public SampleManager() { super(); // load the category tree // LevigoSampleHosts.read(is) hostInstances = new ArrayList<SampleHostInstance>(); load("META-INF/levigo-sample-system.xml", new Processor<Void, InputStream>() { @Override public Void process(InputStream in) throws Exception { final LevigoSampleSystem system = LevigoSampleSystem.read(in); for (final SampleHostDescriptor shd : system.getSampleHosts()) { hostInstances.add(new SampleHostInstance(shd, new SampleHostModule(shd))); } return null; } }); final List<Category> allCategories = new ArrayList<Category>(); List<SampleInstance> tmp = load("META-INF/levigo-samples.xml", new Processor<List<SampleInstance>, InputStream>() { final List<SampleInstance> sds = new ArrayList<SampleInstance>(); @Override public List<SampleInstance> process(InputStream in) throws Exception { LevigoSamples samples = LevigoSamples.read(in); // FIXME category collision for (CategoryDescriptor desc : samples.getCategories()) { if (LOG.isLoggable(Level.FINE)) new CategoryDescriptorDebugTreeWalker(LOG).walk(desc); allCategories.add(Category.create(desc)); } for (SampleDescriptor desc : samples.getSamples()) { sds.add(new SampleInstance(SampleManager.this, desc)); } return sds; } }); if (tmp == null) tmp = new ArrayList<SampleInstance>(); samples = tmp; categories = new RootCategory(allCategories); for (SampleInstance si : samples) { categories.install(si); } } @SuppressWarnings({ "unchecked", "rawtypes" }) public Object createSampleInstance(SampleDescriptor sd) { final Class clazz = sd.getSampleClass(); List<AbstractModule> modules = new ArrayList<AbstractModule>(2); for (RequirementDescriptor rd : sd.getRequirements()) { if (rd instanceof RequireSampleHostDescriptor) { for (SampleHostInstance shi : hostInstances) { if (shi.getDescriptor().getId().equals(((RequireSampleHostDescriptor) rd).getName())) modules.add(shi.getSampleHostModule()); } } } final Injector injector = ROOT_INJECTOR.createChildInjector(modules); System.err.println(injector); return injector.getInstance(clazz); } private final class RootCategory extends Category { private RootCategory(List<Category> children) { super("ROOT", "Samples", "", children); } public boolean install(SampleInstance sample) { if (!super.install(sample)) { // the root category is some kind of "Fallback" samples.add(sample); } return true; } } interface Processor<R, P> { R process(P in) throws Exception; } private final List<SampleInstance> samples; public List<SampleInstance> getSamples() { return samples; } private <R> R load(final String resourceName, final Processor<R, InputStream> processor) { Enumeration<URL> resources; try { resources = getClass().getClassLoader().getResources(resourceName); } catch (IOException e1) { e1.printStackTrace(); return null; } R res = null; while (resources.hasMoreElements()) { URL url = resources.nextElement(); try { final InputStream is = url.openStream(); res = processor.process(is); } catch (Exception e) { // FIXME better exception handling! e.printStackTrace(); } } return res; } public Category getCategories() { return categories; } }