<commit_before>/*
 * Copyright 2015 MarkLogic Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.marklogic.semantics.jena;

import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.NodeFactory;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.query.DatasetFactory;
import com.hp.hpl.jena.query.ReadWrite;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.shared.LockNone;
import com.hp.hpl.jena.sparql.core.DatasetGraph;
import com.hp.hpl.jena.sparql.core.DatasetGraphTriplesQuads;
import com.hp.hpl.jena.sparql.core.Quad;
import com.hp.hpl.jena.sparql.core.Transactional;
import com.hp.hpl.jena.update.GraphStore;
import com.marklogic.client.io.InputStreamHandle;
import com.marklogic.client.query.QueryDefinition;
import com.marklogic.client.semantics.GraphPermissions;
import com.marklogic.client.semantics.SPARQLBindings;
import com.marklogic.client.semantics.SPARQLQueryDefinition;
import com.marklogic.client.semantics.SPARQLRuleset;
import com.marklogic.semantics.jena.client.JenaDatabaseClient;
import com.marklogic.semantics.jena.client.QuadsIterator;
import com.marklogic.semantics.jena.client.WrappingIterator;

/**
 * A representation of MarkLogic's triple store as a DatasetGraph,
 * plus a few extra MarkLogic-specific features.  Use this class as you 
 * would any other DatasetGraph in a jena-based project.
 * If you know you are using a MarkLogicDatasetGraph, simply cast it
 * in order to use the MarkLogic-specific capabilities.
 */
public class MarkLogicDatasetGraph extends DatasetGraphTriplesQuads implements DatasetGraph, GraphStore, Transactional {

    public static final String DEFAULT_GRAPH_URI = "http://marklogic.com/semantics#default-graph";
	static Logger log = LoggerFactory.getLogger(MarkLogicDatasetGraph.class);
	
	private JenaDatabaseClient client;
	
	/*
     * An inferencing datasetGraph will add ruleset config to each query
     */
    private SPARQLRuleset[] rulesets;
    
    /*
     * Used to constrain of corpus of documents against which to make a Dataset 
     */
    private QueryDefinition constrainingQueryDefinition;
    private GraphPermissions updatePermissions;
    
    
	/**
	 * Creates a new MarkLogicDatasetGraph using the supplied DatabaseClient.  If this client can write to
	 * the database, then the DatasetGraph is initialized with a default graph.
	 * @param jenaClient specifies the connection to the MarkLogic server.  Obtain from DatabaseClientFactory.
	 */
	public MarkLogicDatasetGraph(JenaDatabaseClient jenaClient) {
		this.client = jenaClient;
	}

	/**
	 * @see com.hp.hpl.jena.sparql.core.DatasetGraph
	 */
	@Override
	public Iterator<Node> listGraphNodes() {
		log.debug("listing graphs ");
        checkIsOpen();
        sync();
		Iterator<String> graphNames = client.listGraphUris();
		return new WrappingIterator(graphNames);
	}
	
	/**
	 * MarkLogicDatasetGraph does not make use of locks.
	 * @return An instance of com.hp.hpl.jena.shared.LockNone
	 */
	@Override
	public Lock getLock() {
	    return new LockNone();
	}

    /**
     * @see com.hp.hpl.jena.sparql.core.DatasetGraph
     */
	@Override
	public void clear() {
        checkIsOpen();
		String query = "DROP SILENT ALL";
		SPARQLQueryDefinition qdef = client.newQueryDefinition(query);
		client.executeUpdate(qdef);
	}
	
	/**
	 * Maps Jena bindings defined by a variable name and a {@link com.hp.hpl.jena.graph.Node} to MarkLogic 
	 * {@link com.marklogic.client.semantics.SPARQLQueryDefinition} bindings.
	 * @param qdef A {@link com.marklogic.client.semantics.SPARQLQueryDefinition} to decorate with a binding.
	 * @param variableName Name of the variable
	 * @param objectNode An RDF node with the value of variableName.
	 * @return The query definition, with binding set.
	 */
	public static SPARQLQueryDefinition bindObject(SPARQLQueryDefinition qdef, String variableName, Node objectNode) {
		SPARQLBindings bindings = qdef.getBindings();
		if (objectNode.isURI()) {
			bindings.bind(variableName, objectNode.getURI());
		}
		else if (objectNode.isLiteral()) {
			if ( objectNode.getLiteralDatatype() != null) {
				try {
					String xsdType = objectNode.getLiteralDatatypeURI();
					String fragment = new URI(xsdType).getFragment();
					bindings.bind(variableName, objectNode.getLiteralLexicalForm(), fragment);
					log.debug("found " + xsdType);
				} catch (URISyntaxException e) {
					log.info("Is this an error");
				}
			} else if (!objectNode.getLiteralLanguage().equals("")) {
				String languageTag = objectNode.getLiteralLanguage();
				bindings.bind(variableName, objectNode.getLiteralLexicalForm(), Locale.forLanguageTag(languageTag));
			} else {
				// is this a hole, no type string?
				bindings.bind(variableName, objectNode.getLiteralLexicalForm(), "string");
			}
		}
		qdef.setBindings(bindings);
		return qdef;
	}

	 /*
     * @see com.hp.hpl.jena.sparql.core.DatasetGraphTriplesQuads Internally uses
     * a write cache to hold batches of quad updates.  @see sync()
     */
	@Override
	protected void addToDftGraph(Node s, Node p, Node o) {
        checkIsOpen();<commit_msg>Fix for introduction of RDFTypes in Java Client API<commit_after>/*
 * Copyright 2015 MarkLogic Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.marklogic.semantics.jena;

import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.NodeFactory;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.query.DatasetFactory;
import com.hp.hpl.jena.query.ReadWrite;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.shared.LockNone;
import com.hp.hpl.jena.sparql.core.DatasetGraph;
import com.hp.hpl.jena.sparql.core.DatasetGraphTriplesQuads;
import com.hp.hpl.jena.sparql.core.Quad;
import com.hp.hpl.jena.sparql.core.Transactional;
import com.hp.hpl.jena.update.GraphStore;
import com.marklogic.client.io.InputStreamHandle;
import com.marklogic.client.query.QueryDefinition;
import com.marklogic.client.semantics.GraphPermissions;
import com.marklogic.client.semantics.RDFTypes;
import com.marklogic.client.semantics.SPARQLBindings;
import com.marklogic.client.semantics.SPARQLQueryDefinition;
import com.marklogic.client.semantics.SPARQLRuleset;
import com.marklogic.semantics.jena.client.JenaDatabaseClient;
import com.marklogic.semantics.jena.client.QuadsIterator;
import com.marklogic.semantics.jena.client.WrappingIterator;

/**
 * A representation of MarkLogic's triple store as a DatasetGraph,
 * plus a few extra MarkLogic-specific features.  Use this class as you 
 * would any other DatasetGraph in a jena-based project.
 * If you know you are using a MarkLogicDatasetGraph, simply cast it
 * in order to use the MarkLogic-specific capabilities.
 */
public class MarkLogicDatasetGraph extends DatasetGraphTriplesQuads implements DatasetGraph, GraphStore, Transactional {

    public static final String DEFAULT_GRAPH_URI = "http://marklogic.com/semantics#default-graph";
	static Logger log = LoggerFactory.getLogger(MarkLogicDatasetGraph.class);
	
	private JenaDatabaseClient client;
	
	/*
     * An inferencing datasetGraph will add ruleset config to each query
     */
    private SPARQLRuleset[] rulesets;
    
    /*
     * Used to constrain of corpus of documents against which to make a Dataset 
     */
    private QueryDefinition constrainingQueryDefinition;
    private GraphPermissions updatePermissions;
    
    
	/**
	 * Creates a new MarkLogicDatasetGraph using the supplied DatabaseClient.  If this client can write to
	 * the database, then the DatasetGraph is initialized with a default graph.
	 * @param jenaClient specifies the connection to the MarkLogic server.  Obtain from DatabaseClientFactory.
	 */
	public MarkLogicDatasetGraph(JenaDatabaseClient jenaClient) {
		this.client = jenaClient;
	}

	/**
	 * @see com.hp.hpl.jena.sparql.core.DatasetGraph
	 */
	@Override
	public Iterator<Node> listGraphNodes() {
		log.debug("listing graphs ");
        checkIsOpen();
        sync();
		Iterator<String> graphNames = client.listGraphUris();
		return new WrappingIterator(graphNames);
	}
	
	/**
	 * MarkLogicDatasetGraph does not make use of locks.
	 * @return An instance of com.hp.hpl.jena.shared.LockNone
	 */
	@Override
	public Lock getLock() {
	    return new LockNone();
	}

    /**
     * @see com.hp.hpl.jena.sparql.core.DatasetGraph
     */
	@Override
	public void clear() {
        checkIsOpen();
		String query = "DROP SILENT ALL";
		SPARQLQueryDefinition qdef = client.newQueryDefinition(query);
		client.executeUpdate(qdef);
	}
	
	/**
	 * Maps Jena bindings defined by a variable name and a {@link com.hp.hpl.jena.graph.Node} to MarkLogic 
	 * {@link com.marklogic.client.semantics.SPARQLQueryDefinition} bindings.
	 * @param qdef A {@link com.marklogic.client.semantics.SPARQLQueryDefinition} to decorate with a binding.
	 * @param variableName Name of the variable
	 * @param objectNode An RDF node with the value of variableName.
	 * @return The query definition, with binding set.
	 */
	public static SPARQLQueryDefinition bindObject(SPARQLQueryDefinition qdef, String variableName, Node objectNode) {
		SPARQLBindings bindings = qdef.getBindings();
		if (objectNode.isURI()) {
			bindings.bind(variableName, objectNode.getURI());
		}
		else if (objectNode.isLiteral()) {
			if ( objectNode.getLiteralDatatype() != null) {
				try {
					String xsdType = objectNode.getLiteralDatatypeURI();
					String fragment = new URI(xsdType).getFragment();
					bindings.bind(variableName, objectNode.getLiteralLexicalForm(), RDFTypes.valueOf(fragment.toUpperCase()));
					log.debug("found " + xsdType);
				} catch (URISyntaxException e) {
					throw new MarkLogicJenaException("Unrecognized binding type.  Use XSD only.", e);
				}
			} else if (!objectNode.getLiteralLanguage().equals("")) {
				String languageTag = objectNode.getLiteralLanguage();
				bindings.bind(variableName, objectNode.getLiteralLexicalForm(), Locale.forLanguageTag(languageTag));
			} else {
				// is this a hole, no type string?
				bindings.bind(variableName, objectNode.getLiteralLexicalForm(), RDFTypes.STRING);
			}
		}
		qdef.setBindings(bindings);
		return qdef;
	}

	 /*
     * @see com.hp.hpl.jena.sparql.core.DatasetGraphTriplesQuads Internally uses
     * a write cache to hold batches of quad updates.  @see sync()
     */
	@Override
	protected void addToDftGraph(Node s, Node p, Node o) {
        checkIsOpen();
{'fraction_non_alphanumeric': 0.09807996010306708, 'fraction_numerical': 0.0016623722051367302, 'mean_word_length': 4.192921881743634, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, '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': '6747584', 'n_tokens_mistral': 3912, 'n_tokens_neox': 3668, 'n_words': 978}