/*
* RDFUtility.java
*
* Created on August 7, 2007, 10:24 AM
*
* Description: Provides RDF store utilities.
*
* Copyright (C) August 7, 2007 Stephen L. Reed.
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.texai.kb.persistence;
import java.io.BufferedWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import javax.xml.bind.DatatypeConverter;
import net.jcip.annotations.NotThreadSafe;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.LazyLoader;
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.ValueFactory;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.model.vocabulary.XMLSchema;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryConnection;
import org.texai.kb.Constants;
import org.texai.kb.persistence.lazy.LazyList;
import org.texai.kb.persistence.lazy.LazySet;
import org.texai.util.StringUtils;
import org.texai.util.TexaiException;
/** Provides RDF store utilities.
*
* @author reed
*/
@NotThreadSafe
public final class RDFUtility {
/** the Sesame value factory */
private final ValueFactory valueFactory = new ValueFactoryImpl();
/** the knowledge base access object */
private final KBAccess kbAccess;
/** Creates a new instance of RDFUtility.
*
* @param rdfEntityManager the entity manager
*/
public RDFUtility(final RDFEntityManager rdfEntityManager) {
//preconditions
assert rdfEntityManager != null : "rdfEntityManager must not be null";
kbAccess = new KBAccess(rdfEntityManager);
}
public static class ResourceComparator implements Comparator<Resource> {
/** Constructs a new ResourceComparator instance. */
public ResourceComparator() {
}
/** Compares the two given URIs.
*
* @param resource1 the first given resource
* @param resource2 the second given resource
* @return -1 if resource1 is less than resource2, 0 if they are equal, otherwise return +1
*/
@Override
public int compare(final Resource resource1, final Resource resource2) {
//preconditions
assert resource1 != null : "resource1 must not be null";
assert resource2 != null : "resource2 must not be null";
return resource1.toString().compareTo(resource2.toString());
}
}
/** Returns whether the given object is a URI that represents a logical variable.
*
* @param value the given object
* @return whether the given object is a URI that represents a logical variable
*/
public static boolean isVariableURI(final Value value) {
return value instanceof URI && ((URI) value).getLocalName().startsWith("?");
}
/** Returns whether the given object is a URI that represents an instance term, i.e. the name ends in a digit.
*
* @param value the given object
* @return whether the given object is a URI that represents an instance term, i.e. the name ends in a digit
*/
public static boolean isInstanceURI(final Value value) {
if (value instanceof URI) {
final String termName = ((URI) value).getLocalName();
return Character.isUpperCase(termName.charAt(0))
&& Character.isDigit(termName.charAt(termName.length() - 1));
} else {
return false;
}
}
/** Gets a default property URI for the persistent field.
*
* @param className the name of the persistent class containing the field
* @param fieldName the field name
* @param fieldType the field type
* @return a default property URI
*/
public static URI getDefaultPropertyURI(
final String className,
final String fieldName,
final Class<?> fieldType) {
//Preconditions
assert fieldName != null : "fieldName must not be null";
assert !fieldName.isEmpty() : "fieldName must not be empty";
// changed to longer, more storage-inefficient, full class name in order to eliminate namespace collisions
//final String className = StringUtils.getLowerCasePredicateName(field.getDeclaringClass().getSimpleName());
String uriString = Constants.TEXAI_NAMESPACE + className + "_" + StringUtils.capitalize(fieldName);
if (List.class.isAssignableFrom(fieldType) || fieldType.isArray()) {
// list or array
uriString = uriString + "_list";
} else if (Set.class.isAssignableFrom(fieldType)) {
// set
if (uriString.endsWith("s")) {
uriString = uriString.substring(0, uriString.length() - 1);
}
}
return new URIImpl(uriString);
}
/** Returns the class name as embedded in the id that is generated by default for a persistent object.
*
* @param id the persistent object id
* @return the class name
*/
public static String getDefaultClassFromId(final URI id) {
//Preconditions
assert id != null : "id must not be null";
return getDefaultClassFromIdString(id.toString());
}
/** Returns the class name as embedded in the id that is generated by default for a persistent object.
*
* @param idString the persistent object URI as a string
* @return the class name
*/
public static String getDefaultClassFromIdString(final String idString) {
//Preconditions
assert idString != null : "idString must not be null";
assert !idString.isEmpty() : "idString must not be empty";
int index = idString.lastIndexOf('/');
if (index == -1) {
return "";
}
final String localName = idString.substring(index + 1);
index = localName.indexOf('_');
if (index > -1) {
return localName.substring(0, index);
} else {
return "";
}
}
/** Sorts the given collection of statements.
*
* @param statements the given collection of statements
* @return the sorted list of statements
*/
public static List<Statement> sortStatements(final Collection<Statement> statements) {
//preconditions
assert statements != null : "statements must not be null";
final List<Statement> sortedStatements = new ArrayList<>(statements);
final StatementComparator statementComparator = new StatementComparator();
Collections.sort(sortedStatements, statementComparator);
return sortedStatements;
}
/** Provides a statement comparator. */
public static class StatementComparator implements Comparator<Statement> {
/** Constructs a new StatementComparator instance. */
public StatementComparator() {
}
/** Compares the two given statements.
*
* @param statement1 the first given statement
* @param statement2 the second given statement
* @return -1 if statement1 is less than statement2, 0 if they are equal, otherwise return +1
*/
@Override
public int compare(final Statement statement1, final Statement statement2) {
//preconditions
assert statement1 != null : "statement1 must not be null";
assert statement2 != null : "statement2 must not be null";
return statement1.toString().compareTo(statement2.toString());
}
}
/** Provides a turtle statement comparator. */
public static class TurtleStatementComparator implements Comparator<Statement> {
/** Constructs a new StatementComparator instance. */
public TurtleStatementComparator() {
}
/** Compares the two given statements.
*
* @param statement1 the first given statement
* @param statement2 the second given statement
* @return -1 if statement1 is less than statement2, 0 if they are equal, otherwise return +1
*/
@Override
public int compare(final Statement statement1, final Statement statement2) {
//preconditions
assert statement1 != null : "statement1 must not be null";
assert statement2 != null : "statement2 must not be null";
return formatStatementAsTurtle(statement1).compareTo(formatStatementAsTurtle(statement2));
}
}
/** Formats the given statements.
*
* @param statements the statements
* @return the formatted statement in which namespaces are represented by prefixes
*/
public static String formatStatements(final Collection<Statement> statements) {
//preconditions
assert statements != null : "statements must not be null";
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("{");
boolean isFirst = true;
final Iterator<Statement> statements_iter = statements.iterator();
while (statements_iter.hasNext()) {
if (isFirst) {
isFirst = false;
} else {
stringBuilder.append(", ");
}
stringBuilder.append(formatStatement(statements_iter.next()));
}
stringBuilder.append("}");
return stringBuilder.toString();
}
/** Formats an RDF statement.
*
* @param statement the statement
* @return the formatted statement in which namespaces are represented by prefixes
*/
public static String formatStatement(final Statement statement) {
//preconditions
assert statement != null : "statement must not be null";
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("(");
if (statement.getSubject() instanceof URI) {
stringBuilder.append(formatResource((URI) statement.getSubject()));
} else {
stringBuilder.append(statement.getSubject().toString());
}
stringBuilder.append(" ");
stringBuilder.append(formatResource(statement.getPredicate()));
stringBuilder.append(" ");
if (statement.getObject() instanceof URI) {
stringBuilder.append(formatResource((URI) statement.getObject()));
} else {
stringBuilder.append(statement.getObject().toString());
}
if (statement.getContext() != null) {
stringBuilder.append(" [");
stringBuilder.append(formatResource((URI) statement.getContext()));
stringBuilder.append("]");
}
stringBuilder.append(")");
return stringBuilder.toString();
}
/** Formats an RDF statement as Turtle, extended from the specification to support context.
* See http://www.w3.org/TeamSubmission/turtle/ .
*
* @param statement the statement
* @return the formatted statement in which namespaces are represented by prefixes
*/
public static String formatStatementAsTurtle(final Statement statement) {
//preconditions
assert statement != null : "statement must not be null";
final StringBuilder stringBuilder = new StringBuilder();
if (statement.getSubject() instanceof URI) {
stringBuilder.append(formatURIAsTurtle((URI) statement.getSubject()));
} else {
stringBuilder.append(statement.getSubject().toString());
}
stringBuilder.append(" ");
stringBuilder.append(formatURIAsTurtle(statement.getPredicate()));
stringBuilder.append(" ");
if (statement.getObject() instanceof URI) {
stringBuilder.append(formatURIAsTurtle((URI) statement.getObject()));
} else {
stringBuilder.append(statement.getObject().toString());
}
if (statement.getContext() != null) {
stringBuilder.append(" in ");
stringBuilder.append(formatURIAsTurtle((URI) statement.getContext()));
}
stringBuilder.append(" .");
return stringBuilder.toString();
}
/** Formats an RDF statement as XML Turtle.
*
* @param statement the statement
* @return the formatted statement in which namespaces are represented by prefixes
*/
public static String formatStatementAsXMLTurtle(final Statement statement) {
//preconditions
assert statement != null : "statement must not be null";
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<turtle><![CDATA[");
stringBuilder.append(formatStatementAsTurtle(statement));
stringBuilder.append("]]></turtle>");
return stringBuilder.toString();
}
/** Formats the given resources with common namespaces.
*
* @param resources the given URI or BNode
* @return the formatted URI
*/
public static String formatResources(final Collection<? extends Resource> resources) {
//preconditions
assert resources != null : "resources must not be null";
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('{');
boolean isFirst = true;
for (final Resource resource : resources) {
if (isFirst) {
isFirst = false;
} else {
stringBuilder.append(", ");
}
stringBuilder.append(formatResource(resource));
}
stringBuilder.append('}');
return stringBuilder.toString();
}
/** Formats the given resources with common namespaces after sortng them.
*
* @param resources the given URI or BNode
* @return the formatted URI
*/
public static String formatSortedResources(final Collection<? extends Resource> resources) {
//preconditions
assert resources != null : "resources must not be null";
final List<Resource> sortedResources = new ArrayList<>(resources);
Collections.sort(sortedResources, new ResourceComparator());
return formatResources(sortedResources);
}
/** Formats the given resource with common namespaces.
*
* @param resource the given URI or BNode
* @return the formatted URI
*/
public static String formatResource(final Resource resource) {
//preconditions
assert resource != null : "resource must not be null";
final String formattedResource;
if (resource instanceof URI) {
final URI uri = (URI) resource;
final String namespace = uri.getNamespace();
switch (namespace) {
case Constants.XSD_NAMESPACE:
formattedResource = "xsd:" + uri.getLocalName();
break;
case Constants.RDF_NAMESPACE:
formattedResource = "rdf:" + uri.getLocalName();
break;
case Constants.RDFS_NAMESPACE:
formattedResource = "rdfs:" + uri.getLocalName();
break;
case Constants.OWL_NAMESPACE:
formattedResource = "owl:" + uri.getLocalName();
break;
case Constants.CYC_NAMESPACE:
formattedResource = "cyc:" + uri.getLocalName();
break;
case Constants.TEXAI_NAMESPACE:
formattedResource = "texai:" + uri.getLocalName();
break;
default:
formattedResource = uri.toString();
break;
}
} else {
formattedResource = resource.toString();
}
//Postconditions
assert formattedResource != null : "formattedResource must not be null";
assert !formattedResource.isEmpty() : "formattedResource must not be empty";
return formattedResource;
}
/** Formats the given URI with common namespaces.
*
* @param value the given URI or BNode
* @return the formatted URI
*/
public static String formatValue(final Value value) {
//preconditions
assert value != null : "value must not be null";
final String formattedValue;
if (value instanceof Resource) {
formattedValue = formatResource((Resource) value);
} else {
formattedValue = value.toString();
}
//Postconditions
assert formattedValue != null : "formattedValue must not be null";
assert !formattedValue.isEmpty() : "formattedValue must not be empty";
return formattedValue;
}
/** Formats the given URI with common namespaces. See http://www.w3.org/TeamSubmission/turtle/ .
*
* @param uri the given URI
* @return the formatted URI
*/
public static String formatURIAsTurtle(final URI uri) {
//preconditions
assert uri != null : "uri must not be null";
final StringBuilder stringBuilder = new StringBuilder();
final String namespace = uri.getNamespace();
switch (namespace) {
case Constants.XSD_NAMESPACE:
stringBuilder.append("xsd:");
stringBuilder.append(uri.getLocalName());
break;
case Constants.RDF_NAMESPACE:
stringBuilder.append("rdf:");
stringBuilder.append(uri.getLocalName());
break;
case Constants.RDFS_NAMESPACE:
stringBuilder.append("rdfs:");
stringBuilder.append(uri.getLocalName());
break;
case Constants.OWL_NAMESPACE:
stringBuilder.append("owl:");
stringBuilder.append(uri.getLocalName());
break;
case Constants.CYC_NAMESPACE:
stringBuilder.append("cyc:");
stringBuilder.append(uri.getLocalName());
break;
case Constants.TEXAI_NAMESPACE:
if (uri.getLocalName().startsWith("?")) {
stringBuilder.append(uri.getLocalName());
} else {
stringBuilder.append("texai:");
stringBuilder.append(uri.getLocalName());
}
break;
default:
stringBuilder.append(uri.toString());
break;
}
return stringBuilder.toString();
}
/** Returns the namespace for the given namespace alias.
*
* @param namespaceAlias the given namespace alias
* @return the namespace for the given namespace alias, or null if not found
*/
public static String decodeNamespace(final String namespaceAlias) {
//preconditions
assert namespaceAlias != null : "namespaceAlias must not be null";
assert !namespaceAlias.isEmpty() : "namespaceAlias must not be empty";
switch (namespaceAlias) {
case "rdf":
return Constants.RDF_NAMESPACE;
case "rdfs":
return Constants.RDFS_NAMESPACE;
case "owl":
return Constants.OWL_NAMESPACE;
case "cyc":
return Constants.CYC_NAMESPACE;
case "texai":
return Constants.TEXAI_NAMESPACE;
default:
return null;
}
}
/** Returns a URI from the given string that may include an alias prefix.
*
* @param uriString the given string
* @return a URI
*/
public static URI makeURIFromAlias(final String uriString) {
//preconditions
assert uriString != null : "uriString must not be null";
assert !uriString.isEmpty() : "uriString must not be empty";
final int index = uriString.indexOf(':');
if (index == -1 || uriString.endsWith(":")) {
throw new TexaiException("invalid URI string " + uriString);
}
final String namespaceAlias = uriString.substring(0, index);
final String namespace = decodeNamespace(namespaceAlias);
if (namespace == null) {
return new URIImpl(uriString);
} else {
return new URIImpl(namespace + uriString.substring(index + 1));
}
}
/** Asserts the defining statements for a new RDF class. This method is useful in the case where a new RDF class is required
* but no direct instances of the RDF class will ever be instantiated as Java objects.
*
* @param repositoryName the repository name
* @param classURI the RDF class URI
* @param comment the RDF class comment
* @param typeURIs the RDF class typeURIs
* @param subClassOfURIs the RDF classes for which this RDF class is a subclass
* @param writer the export output writer, or null when objects are ordinarily persisted to the given RDF quad store
*/
public void defineRDFClass(
final String repositoryName,
final URI classURI,
final String comment,
final List<URI> typeURIs,
final List<URI> subClassOfURIs,
final BufferedWriter writer) {
//preconditions
assert repositoryName != null : "repositoryName must not be null";
assert !repositoryName.isEmpty() : "repositoryName must not be empty";
assert classURI != null : "classURI must not be null";
assert comment != null : "comment must not be null";
assert !comment.isEmpty() : "comment must not be empty";
assert typeURIs != null : "typeURIs must not be null";
assert !typeURIs.isEmpty() : "typeURIs must not be empty"; // NOPMD
assert subClassOfURIs != null : "subClassOfURIs must not be null";
assert !subClassOfURIs.isEmpty() : "typeURIs must not be empty";
kbAccess.defineRDFClass(
repositoryName,
classURI, comment,
typeURIs,
subClassOfURIs,
writer);
}
/** Asserts the defining statements for a new RDF individual. This method is useful in the case where a new RDF individual is required
* but no corresponding Java class has been created.
*
* @param repositoryName the repository name
* @param individualURI the individual URI
* @param comment the RDF individual comment
* @param typeURIs the RDF class typeURIs
* @param writer the export output writer, or null when objects are ordinarily persisted to the given RDF quad store
*/
public void defineRDFIndividual(
final String repositoryName,
final URI individualURI,
final String comment,
final List<URI> typeURIs,
final BufferedWriter writer) {
//preconditions
assert repositoryName != null : "repositoryName must not be null";
assert !repositoryName.isEmpty() : "repositoryName must not be empty";
assert individualURI != null : "classURI must not be null";
assert comment != null : "comment must not be null";
assert !comment.isEmpty() : "comment must not be empty";
assert typeURIs != null : "typeURIs must not be null";
assert !typeURIs.isEmpty() : "typeURIs must not be empty"; // NOPMD
kbAccess.defineRDFIndividual(
repositoryName,
individualURI,
comment,
typeURIs,
writer);
}
/** Asserts the defining statements for a new RDF context.
*
* @param repositoryName the repository name
* @param contextURI the RDF context URI
* @param comment the RDF class comment
* @param typeURIs the RDF context typeURIs
* @param genlMtURIs the RDF contexts for which this RDF context is a specialization
* @param writer the export output writer, or null when objects are ordinarily persisted to the given RDF quad store
*/
public void defineRDFContext(
final String repositoryName,
final URI contextURI,
final String comment,
final List<URI> typeURIs,
final List<URI> genlMtURIs,
final BufferedWriter writer) {
//preconditions
assert repositoryName != null : "repositoryName must not be null";
assert !repositoryName.isEmpty() : "repositoryName must not be empty";
assert contextURI != null : "contextURI must not be null";
assert comment != null : "comment must not be null";
assert !comment.isEmpty() : "comment must not be empty";
assert typeURIs != null : "typeURIs must not be null";
assert genlMtURIs != null : "genlMtURIs must not be null";
kbAccess.defineRDFContext(
repositoryName,
contextURI,
comment,
typeURIs,
genlMtURIs,
writer);
}
/** Asserts that the two given classes are disjoint.
*
* @param repositoryName the repository name
* @param classURI1 the first given class
* @param classURI2 the second given class
* @param writer the export output writer, or null when objects are ordinarily persisted to the given RDF quad store
*/
public void assertDisjoint(
final String repositoryName,
final URI classURI1,
final URI classURI2,
final BufferedWriter writer) {
//preconditions
assert repositoryName != null : "repositoryName must not be null";
assert !repositoryName.isEmpty() : "repositoryName must not be empty";
assert classURI1 != null : "classURI1 must not be null";
assert classURI2 != null : "classURI2 must not be null";
kbAccess.assertDisjoint(
repositoryName,
classURI1,
classURI2,
writer);
}
/**
* Asserts the defining statements for a new RDF predicate.
*
* @param repositoryName the repository name
* @param predicateURI the RDF predicate
* @param comment the RDF predicate comment
* @param typeURIs the RDF predicate typeURIs
* @param subPropertyOfs the RDF predicates for which this RDF predicate is a subproperty
* @param domainURI the type of the RDF subject that can be used with this predicate
* @param rangeURI the type of the RDF object that can be used with this predicate
* @param writer the export output writer, or null when objects are ordinarily persisted to the given RDF quad store
*/
public void defineRDFPredicate(
final String repositoryName,
final URI predicateURI,
final String comment,
final List<URI> typeURIs,
final List<URI> subPropertyOfs,
final URI domainURI,
final URI rangeURI,
final BufferedWriter writer) {
//preconditions
assert repositoryName != null : "repositoryName must not be null";
assert !repositoryName.isEmpty() : "repositoryName must not be empty";
assert predicateURI != null : "predicateURI must not be null";
assert typeURIs != null : "typeURIs must not be null";
assert !typeURIs.isEmpty() : "typeURIs must not be empty";
assert subPropertyOfs != null : "subPropertyOfs must not be null";
assert !subPropertyOfs.isEmpty() : "typeURIs must not be empty";
assert domainURI != null : "domainURI must not be null";
assert rangeURI != null : "rangeURI must not be null";
kbAccess.defineRDFPredicate(
repositoryName,
predicateURI,
comment,
typeURIs,
subPropertyOfs,
domainURI,
rangeURI,
writer);
}
/** Renames the given URI.
*
* @param repositoryName the repository name
* @param oldURI the old URI
* @param newURI the new URI
*/
public void renameURI(
final String repositoryName,
final URI oldURI,
final URI newURI) {
//preconditions
assert repositoryName != null : "repositoryName must not be null";
assert !repositoryName.isEmpty() : "repositoryName must not be empty";
assert oldURI != null : "oldURI must not be null";
assert newURI != null : "newURI must not be null";
kbAccess.renameURI(
repositoryName,
oldURI,
newURI);
}
/** Returns the lazy loaded object represented by the given proxy and as a side effect loads the object
* into its instance field. If the given object is not a proxy then it is returned directly. Ordinarily,
* proxy objects are automatically loaded whenever any of their methods, except toString(), are called.
* However there may be situations in which they are assigned to another field. Unless they are initialized
* they will not be persisted.
*
* @param proxyObject the given proxy object
* @return the lazy loaded object represented by the given proxy and as a side effect loads the object
* into its instance field. If the given object is not a proxy then it is returned directly.
*/
public Object initializeProxyObject(final Object proxyObject) {
//preconditions
assert proxyObject != null : "proxyObject must not be null";
if (proxyObject instanceof LazySet) {
// load the set and return it
return ((LazySet) proxyObject).getLoadedSet();
} else if (proxyObject instanceof LazyList) {
// load the list and return it
return ((LazyList) proxyObject).getLoadedList();
} else if (proxyObject instanceof Factory) {
final LazyLoader rdfEntityLazyLoader = (LazyLoader) ((Factory) proxyObject).getCallback(0);
try {
// load the proxied object and return it
return rdfEntityLazyLoader.loadObject();
} catch (final Exception ex) {
throw new TexaiException(ex);
}
} else {
// not a proxy
return proxyObject;
}
}
/** Returns a literal value corresponding to the given date.
*
* @param date the given date
* @return a literal value corresponding to the given date
*/
public Literal getLiteralForDate(final Date date) {
//preconditions
assert date != null : "date must not be null";
final Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
return getLiteralForCalendar(calendar);
}
/** Returns a literal value corresponding to the given calendar object.
*
* @param calendar the calendar object
* @return a literal value corresponding to the given calendar object
*/
public Literal getLiteralForCalendar(final Calendar calendar) {
//preconditions
assert calendar != null : "calendar must not be null";
return valueFactory.createLiteral(DatatypeConverter.printDateTime(calendar), XMLSchema.DATETIME);
}
/** Gets the set of values, given the subject, property and context.
*
* @param subject the statment subject
* @param predicate the predicate, i.e. the RDF property
* @param context the context
* @param repositoryConnection the repository connection
* @return the set of object values
*/
public static Set<Value> getObjectsGivenSubjectAndPredicate(
final Resource subject,
final Resource predicate,
final Resource context,
final RepositoryConnection repositoryConnection) {
//preconditions
assert subject != null : "subject must not be null";
assert predicate != null : "predicate must not be null";
assert repositoryConnection != null : "repositoryConnection must not be null";
final Set<Value> values = new HashSet<>();
try {
// get the persisted map entry key RDF value
final TupleQuery objectsTupleQuery = repositoryConnection.prepareTupleQuery(
QueryLanguage.SERQL,
"SELECT o, c FROM CONTEXT c {s} p {o}");
objectsTupleQuery.setBinding("s", subject);
objectsTupleQuery.setBinding("p", predicate);
objectsTupleQuery.setBinding("c", context);
final TupleQueryResult tupleQueryResult = objectsTupleQuery.evaluate();
while (tupleQueryResult.hasNext()) {
values.add(tupleQueryResult.next().getBinding("o").getValue());
}
tupleQueryResult.close();
} catch (final OpenRDFException ex) {
throw new TexaiException(ex);
}
return values;
}
/** Gets the single value, given the subject, property and context.
*
* @param subject the statement subject
* @param predicate the predicate, i.e. the RDF property
* @param context the context
* @param repositoryConnection the repository connection
* @return the single value, or null if not found
*/
public static Value getObjectGivenSubjectAndPredicate(
final Resource subject,
final Resource predicate,
final Resource context,
final RepositoryConnection repositoryConnection) {
//preconditions
assert subject != null : "subject must not be null";
assert predicate != null : "predicate must not be null";
assert repositoryConnection != null : "repositoryConnection must not be null";
final Value value;
try {
// get the persisted map entry key RDF value
final TupleQuery objectsTupleQuery = repositoryConnection.prepareTupleQuery(
QueryLanguage.SERQL,
"SELECT o, c FROM CONTEXT c {s} p {o}");
objectsTupleQuery.setBinding("s", subject);
objectsTupleQuery.setBinding("p", predicate);
objectsTupleQuery.setBinding("c", context);
final TupleQueryResult tupleQueryResult = objectsTupleQuery.evaluate();
if (tupleQueryResult.hasNext()) {
value = tupleQueryResult.next().getBinding("o").getValue();
} else {
value = null;
}
tupleQueryResult.close();
} catch (final OpenRDFException ex) {
throw new TexaiException(ex);
}
return value;
}
/** Returns whether the given string has an invalid character that would prevent loading the RDF statement.
*
* @param string the given string
* @return
*/
public static boolean hasInvalidCharacter(final String string) {
//Preconditions
assert string != null : "string must not be null";
for (final char ch : string.toCharArray()) {
if (ch == '\u211d'
|| ch == '\ufb05'
|| ch == '\ufb06') {
return true;
}
}
return false;
}
}