package de.brightbyte.rdf;

import de.brightbyte.util.SpiTools;
import de.brightbyte.util.SystemUtils;

public class RdfPlatforms {
	
	public static interface SPI<T extends RdfPlatform> {
		public T newPlatform();
	}
	
	public static class GenericSPI<T extends RdfPlatform> implements SPI<T> {
		protected Class<T> platform;

		public GenericSPI(Class<T> platform) {
			if (platform==null) throw new NullPointerException();
			this.platform = platform;
		}

		public T newPlatform() {
			return SpiTools.instantiate(platform);
		}
	}
	
	private static SpiTools.ProviderRegistry<SPI> registry = new SpiTools.ProviderRegistry<SPI>(SPI.class, RdfPlatforms.class);
	
	static {
		SPI def = SpiTools.newDefaultSPI(RdfPlatforms.class, SPI.class, "de.brightbyte.rdf.aardfark.AardfarkPlatform$SPI");
		registry.registerProvider("default", def);
		
		SPI aardfark = SpiTools.newSPI(RdfPlatforms.class, SPI.class, "de.brightbyte.rdf.aardfark.AardfarkPlatform$SPI");
		registry.registerProvider("aardfark", aardfark);
				
		if (SystemUtils.isClassKnown("org.openrdf.model.ValueFactory", RdfPlatforms.class)) {
			SPI sesame = SpiTools.newSPI(RdfPlatforms.class, SPI.class, "de.brightbyte.rdf.sesame.SesamePlatform$SPI");
			registry.registerProvider("sesame", sesame);
		}
		
		if (SystemUtils.isClassKnown("com.hp.hpl.jena.graph.Graph", RdfPlatforms.class)) {
			SPI jena = SpiTools.newSPI(RdfPlatforms.class, SPI.class, "de.brightbyte.rdf.jena.JenaPlatform$SPI");
			registry.registerProvider("jena", jena);
		}
	}

	public static RdfPlatform newPlatform() {
		return newPlatform("default");
	}
	
	public static RdfPlatform newPlatform(String name) {
		SPI spi = registry.getProvider(name);
		if (spi==null) spi = registry.getProvider("default");
		return spi.newPlatform();
	}
	
	public static void registerProvider(String name, SPI spi) {
		registry.registerProvider(name, spi);
	}
	
	public static void registerProvider(String name, Class<? extends SPI<?>> sp) {
		registry.registerProvider(name, sp);
	}
	
	public static void registerProvider(String name, String sp) {
		registry.registerProvider(name, sp);
	}

	public static <T extends RdfPlatform> void registerPlatform(String name, Class<T> platformClass) {
		registerProvider(name, new GenericSPI<T>(platformClass));
	}
	
	
}
