<commit_before>package org.nanopub;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.activation.MimetypesFileTypeMap;
import javax.xml.bind.DatatypeConverter;

import org.openrdf.OpenRDFException;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.ContextStatementImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFParser;
import org.openrdf.rio.Rio;
import org.openrdf.rio.helpers.RDFHandlerBase;

import com.google.common.collect.ImmutableSet;

/**
 * @author <NAME>
 * @author <NAME>
 */
public class NanopubImpl implements Nanopub, Serializable {

	private static final long serialVersionUID = -1514452524339132128L;

	private static final MimetypesFileTypeMap mimeMap = new MimetypesFileTypeMap();

	private URI nanopubUri;
	private URI headUri, assertionUri, provenanceUri, pubinfoUri;
	private Set<URI> assertionSubUris, provenanceSubUris, pubinfoSubUris;
	private Set<URI> graphUris;
	private Set<Statement> head, assertion, provenance, pubinfo;

	private List<Statement> statements = new ArrayList<>();
	private List<String> nsPrefixes = new ArrayList<>();
	private Map<String,String> ns = new HashMap<>();

	public NanopubImpl(Collection<Statement> statements, List<String> nsPrefixes, Map<String,String> ns) throws MalformedNanopubException {
		this.statements.addAll(statements);
		this.nsPrefixes.addAll(nsPrefixes);
		this.ns.putAll(ns);
		init();
	}

	public NanopubImpl(Collection<Statement> statements) throws MalformedNanopubException {
		this.statements.addAll(statements);
		init();
	}

	private static final String nanopubViaSPARQLQuery =
			"prefix np: <http://www.nanopub.org/nschema#> " +
			"prefix rdfg: <http://www.w3.org/2004/03/trix/rdfg-1/> " +
			"prefix this: <@> " +
			"select ?G ?S ?P ?O where { " +
			"  { " +
			"    graph ?G { this: a np:Nanopublication } " +
			"  } union { " +
			"    graph ?H { this: a np:Nanopublication } . " +
			"    graph ?H { { this: np:hasAssertion ?G } union { this: np:hasProvenance ?G } " +
			"        union { this: np:hasPublicationInfo ?G } } " +
			"  } union { " +
			"    graph ?H { this: a np:Nanopublication . ?G rdfg:subGraphOf ?I } . " +
			"    graph ?H { { this: np:hasAssertion ?I } union { this: np:hasProvenance ?I } " +
			"        union { this: np:hasPublicationInfo ?I } } " +
			"  } " +
			"  graph ?G { ?S ?P ?O } " +
			"}";

	public NanopubImpl(Repository repo, URI nanopubUri)
			throws MalformedNanopubException, RepositoryException {
		try {
			RepositoryConnection connection = repo.getConnection();
			try {
				String q = nanopubViaSPARQLQuery.replaceAll("@", nanopubUri.toString());
				TupleQuery tupleQuery = connection.prepareTupleQuery(QueryLanguage.SPARQL, q);
				TupleQueryResult result = tupleQuery.evaluate();
				try {
					while (result.hasNext()) {
						BindingSet bs = result.next();
						Resource g = (Resource) bs.getBinding("G").getValue();
						Resource s = (Resource) bs.getBinding("S").getValue();
						URI p = (URI) bs.getBinding("P").getValue();
						Value o = bs.getBinding("O").getValue();
						Statement st = new ContextStatementImpl(s, p, o, g);
						statements.add(st);
					}
				} finally {
					result.close();
				}
			} finally {
				connection.close();
			}
		} catch (MalformedQueryException ex) {
			ex.printStackTrace();
		} catch (QueryEvaluationException ex) {
			ex.printStackTrace();
		}
		init();
	}

	public NanopubImpl(File file, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		readStatements(new FileInputStream(file), format, "");
		init();
	}

	public NanopubImpl(File file) throws MalformedNanopubException, OpenRDFException, IOException {
		String n = file.getName();
		RDFFormat format = RDFFormat.forMIMEType(mimeMap.getContentType(n));
		if (format == null || !format.supportsContexts()) {
			format = RDFFormat.forFileName(n, RDFFormat.TRIG);
		}
		if (!format.supportsContexts()) {
			format = RDFFormat.TRIG;
		}
		readStatements(new FileInputStream(file), format, "");
		init();
	}

	public NanopubImpl(URL url, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		readStatements(url.openConnection().getInputStream(), format, "");
		init();
	}

	public NanopubImpl(URL url) throws MalformedNanopubException, OpenRDFException, IOException {
		URLConnection conn = url.openConnection();
		RDFFormat format = RDFFormat.forMIMEType(conn.getContentType());
		if (format == null || !format.supportsContexts()) {
			format = RDFFormat.forFileName(url.toString(), RDFFormat.TRIG);
		}
		if (!format.supportsContexts()) {
			format = RDFFormat.TRIG;
		}
		readStatements(conn.getInputStream(), format, "");
		init();
	}

	public NanopubImpl(InputStream in, RDFFormat format, String baseUri)
			throws MalformedNanopubException, OpenRDFException, IOException {
		readStatements(in, format, baseUri);
		init();
	}

	public NanopubImpl(InputStream in, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		this(in, format, "");
	}

	public NanopubImpl(String utf8, RDFFormat format, String baseUri)
			throws MalformedNanopubException, OpenRDFException, IOException {
		this(new ByteArrayInputStream(utf8.getBytes("UTF-8")), format, baseUri);
	}

	public NanopubImpl(String utf8, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		this(utf8, format, "");
	}

	// TODO Is the baseURI really needed? Shouldn't the input stream contain all needed data?
	private void readStatements(InputStream in, RDFFormat format, String baseUri)
			throws MalformedNanopubException, OpenRDFException, IOException {
		RDFParser p = Rio.createParser(format);
		p.setRDFHandler(new RDFHandlerBase() {

			@Override
			public void handleNamespace(String prefix, String uri) throws RDFHandlerException {<commit_msg>Be strict about undefined prefixes<commit_after>package org.nanopub;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.activation.MimetypesFileTypeMap;
import javax.xml.bind.DatatypeConverter;

import org.openrdf.OpenRDFException;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.ContextStatementImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFParser;
import org.openrdf.rio.Rio;
import org.openrdf.rio.helpers.RDFHandlerBase;
import org.openrdf.rio.helpers.RDFaParserSettings;

import com.google.common.collect.ImmutableSet;

/**
 * @author <NAME>
 * @author <NAME>
 */
public class NanopubImpl implements Nanopub, Serializable {

	private static final long serialVersionUID = -1514452524339132128L;

	private static final MimetypesFileTypeMap mimeMap = new MimetypesFileTypeMap();

	private URI nanopubUri;
	private URI headUri, assertionUri, provenanceUri, pubinfoUri;
	private Set<URI> assertionSubUris, provenanceSubUris, pubinfoSubUris;
	private Set<URI> graphUris;
	private Set<Statement> head, assertion, provenance, pubinfo;

	private List<Statement> statements = new ArrayList<>();
	private List<String> nsPrefixes = new ArrayList<>();
	private Map<String,String> ns = new HashMap<>();

	public NanopubImpl(Collection<Statement> statements, List<String> nsPrefixes, Map<String,String> ns) throws MalformedNanopubException {
		this.statements.addAll(statements);
		this.nsPrefixes.addAll(nsPrefixes);
		this.ns.putAll(ns);
		init();
	}

	public NanopubImpl(Collection<Statement> statements) throws MalformedNanopubException {
		this.statements.addAll(statements);
		init();
	}

	private static final String nanopubViaSPARQLQuery =
			"prefix np: <http://www.nanopub.org/nschema#> " +
			"prefix rdfg: <http://www.w3.org/2004/03/trix/rdfg-1/> " +
			"prefix this: <@> " +
			"select ?G ?S ?P ?O where { " +
			"  { " +
			"    graph ?G { this: a np:Nanopublication } " +
			"  } union { " +
			"    graph ?H { this: a np:Nanopublication } . " +
			"    graph ?H { { this: np:hasAssertion ?G } union { this: np:hasProvenance ?G } " +
			"        union { this: np:hasPublicationInfo ?G } } " +
			"  } union { " +
			"    graph ?H { this: a np:Nanopublication . ?G rdfg:subGraphOf ?I } . " +
			"    graph ?H { { this: np:hasAssertion ?I } union { this: np:hasProvenance ?I } " +
			"        union { this: np:hasPublicationInfo ?I } } " +
			"  } " +
			"  graph ?G { ?S ?P ?O } " +
			"}";

	public NanopubImpl(Repository repo, URI nanopubUri)
			throws MalformedNanopubException, RepositoryException {
		try {
			RepositoryConnection connection = repo.getConnection();
			try {
				String q = nanopubViaSPARQLQuery.replaceAll("@", nanopubUri.toString());
				TupleQuery tupleQuery = connection.prepareTupleQuery(QueryLanguage.SPARQL, q);
				TupleQueryResult result = tupleQuery.evaluate();
				try {
					while (result.hasNext()) {
						BindingSet bs = result.next();
						Resource g = (Resource) bs.getBinding("G").getValue();
						Resource s = (Resource) bs.getBinding("S").getValue();
						URI p = (URI) bs.getBinding("P").getValue();
						Value o = bs.getBinding("O").getValue();
						Statement st = new ContextStatementImpl(s, p, o, g);
						statements.add(st);
					}
				} finally {
					result.close();
				}
			} finally {
				connection.close();
			}
		} catch (MalformedQueryException ex) {
			ex.printStackTrace();
		} catch (QueryEvaluationException ex) {
			ex.printStackTrace();
		}
		init();
	}

	public NanopubImpl(File file, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		readStatements(new FileInputStream(file), format, "");
		init();
	}

	public NanopubImpl(File file) throws MalformedNanopubException, OpenRDFException, IOException {
		String n = file.getName();
		RDFFormat format = RDFFormat.forMIMEType(mimeMap.getContentType(n));
		if (format == null || !format.supportsContexts()) {
			format = RDFFormat.forFileName(n, RDFFormat.TRIG);
		}
		if (!format.supportsContexts()) {
			format = RDFFormat.TRIG;
		}
		readStatements(new FileInputStream(file), format, "");
		init();
	}

	public NanopubImpl(URL url, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		readStatements(url.openConnection().getInputStream(), format, "");
		init();
	}

	public NanopubImpl(URL url) throws MalformedNanopubException, OpenRDFException, IOException {
		URLConnection conn = url.openConnection();
		RDFFormat format = RDFFormat.forMIMEType(conn.getContentType());
		if (format == null || !format.supportsContexts()) {
			format = RDFFormat.forFileName(url.toString(), RDFFormat.TRIG);
		}
		if (!format.supportsContexts()) {
			format = RDFFormat.TRIG;
		}
		readStatements(conn.getInputStream(), format, "");
		init();
	}

	public NanopubImpl(InputStream in, RDFFormat format, String baseUri)
			throws MalformedNanopubException, OpenRDFException, IOException {
		readStatements(in, format, baseUri);
		init();
	}

	public NanopubImpl(InputStream in, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		this(in, format, "");
	}

	public NanopubImpl(String utf8, RDFFormat format, String baseUri)
			throws MalformedNanopubException, OpenRDFException, IOException {
		this(new ByteArrayInputStream(utf8.getBytes("UTF-8")), format, baseUri);
	}

	public NanopubImpl(String utf8, RDFFormat format)
			throws MalformedNanopubException, OpenRDFException, IOException {
		this(utf8, format, "");
	}

	// TODO Is the baseURI really needed? Shouldn't the input stream contain all needed data?
	private void readStatements(InputStream in, RDFFormat format, String baseUri)
			throws MalformedNanopubException, OpenRDFException, IOException {
		RDFParser p = Rio.createParser(format);
		p.getParserConfig().set(RDFaParserSettings.FAIL_ON_RDFA_UNDEFINED_PREFIXES, true);
		p.setRDFHandler(new RDFHandlerBase() {

			@Override
			public void handleNamespace(String prefix, String uri) throws RDFHandlerException {
{'fraction_non_alphanumeric': 0.1198583098387913, 'fraction_numerical': 0.004626617508855635, 'mean_word_length': 4.745016611295681, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1203685', 'n_tokens_mistral': 5006, 'n_tokens_neox': 4464, 'n_words': 954}