package com.taxonic.carml.util;

import java.io.InputStream;
import java.util.Set;
import java.util.function.Function;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.rio.RDFFormat;

import com.google.common.collect.ImmutableSet;
import com.taxonic.carml.model.TermType;
import com.taxonic.carml.model.TriplesMap;
import com.taxonic.carml.model.impl.TriplesMapImpl;
import com.taxonic.carml.rdf_mapper.impl.MappingCache;
import com.taxonic.carml.rdf_mapper.util.RdfObjectLoader;
import com.taxonic.carml.vocab.Rdf;
import com.taxonic.carml.vocab.Rdf.Rr;

public class RmlMappingLoader {
	
	private RmlConstantShorthandExpander shorthandExpander;
	
	public RmlMappingLoader(
		RmlConstantShorthandExpander shorthandExpander
	) {
		this.shorthandExpander = shorthandExpander;
	}

	public Set<TriplesMap> load(String resource, RDFFormat rdfFormat) {
		InputStream input = RmlMappingLoader.class.getClassLoader().getResourceAsStream(resource);		
		return load(input, rdfFormat);
	}
	
	public Set<TriplesMap> load(InputStream input, RDFFormat rdfFormat) {
		// TODO: PM do we really need IoUtils?
		Model originalModel = IoUtils.parse(input, rdfFormat);
		return
			ImmutableSet.<TriplesMap>copyOf(
				RdfObjectLoader.load(
					selectTriplesMaps, 
					TriplesMapImpl.class, 
					originalModel, 
					shorthandExpander,
					this::addTermTypes
				)
			);
	}
	
	private void addTermTypes(MappingCache cache) {
		class AddTermTypes {
			
			void add(IRI iri, TermType termType) {
				cache.addCachedMapping(iri, TermType.class, termType);
			}
			
			void run() {
				add(Rr.BlankNode, TermType.BLANK_NODE);
				add(Rr.IRI      , TermType.IRI       );
				add(Rr.Literal  , TermType.LITERAL   );
			}
		}
		new AddTermTypes().run();
	}
	
	public static RmlMappingLoader build() {
		return new RmlMappingLoader(
			new RmlConstantShorthandExpander()
		);
	}
	
	private static Function<Model, Set<Resource>> selectTriplesMaps = 
		model ->
			ImmutableSet.copyOf(
				model
				.filter(null, Rdf.Rml.logicalSource, null)
				.subjects()
			);
}

@@ -42,26 +42,109 @@
 ava.io.I
-nputStream
+OException;%0Aimport java.io.InputStream;%0Aimport java.nio.file.Files;%0Aimport java.nio.file.Path
 ;%0Aimport
@@ -351,16 +351,49 @@
 Format;%0A
+import org.jooq.lambda.Unchecked;
 %0Aimport 
@@ -1174,32 +1174,281 @@
 dfFormat);%0A%09%7D%0A%09%0A
+%09public Set%3CTriplesMap%3E load(Path pathToFile, RDFFormat rdfFormat) %7B%0A%09%09InputStream input;%0A%09%09try %7B%0A%09%09%09input = Files.newInputStream(pathToFile);%0A%09%09%7D catch (IOException e) %7B%0A%09%09%09throw new RuntimeException(e);%0A%09%09%7D%09%09%0A%09%09return load(input, rdfFormat);%0A%09%7D%0A%09%0A
 %09public Set%3CTrip

Add path loading option to RmlMappingLoader