org.eclipse.rdf4j.lucene.spin.LuceneSpinSail Maven / Gradle / Ivy
/**
* Copyright (c) 2017 Eclipse RDF4J contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.eclipse.rdf4j.lucene.spin;
import static org.eclipse.rdf4j.sail.lucene.LuceneSail.INDEXEDFIELDS;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.rdf4j.common.annotation.Experimental;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.sail.NotifyingSailConnection;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.sail.evaluation.TupleFunctionEvaluationMode;
import org.eclipse.rdf4j.sail.helpers.NotifyingSailWrapper;
import org.eclipse.rdf4j.sail.lucene.LuceneSail;
import org.eclipse.rdf4j.sail.lucene.SearchIndex;
import org.eclipse.rdf4j.sail.lucene.SearchIndexQueryContextInitializer;
import org.eclipse.rdf4j.sail.lucene.util.SearchIndexUtils;
import org.eclipse.rdf4j.sail.spin.SpinSail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Activates support of {@link SearchIndex} feature inside {@link SpinSail} and manages the index during statements
* adding/removing. Technically this sail binds {@link SearchIndex} using .addQueryContextInitializer and wraps
* connection from baseSail by wrapped which modify SearchIndex.
*
* @author jacek grzebyta
*
* @deprecated since 3.0. The experimental LuceneSpinSail is scheduled to be removed by the next major release.
*/
@Deprecated
@Experimental
public class LuceneSpinSail extends NotifyingSailWrapper {
private final Logger log = LoggerFactory.getLogger(LuceneSpinSail.class);
private SearchIndex si;
private Properties parameters = new Properties();
private Set indexedFields;
private Map indexedFieldsMapping;
public LuceneSpinSail() {
}
public LuceneSpinSail(SpinSail baseSail) {
super(baseSail);
}
public Properties getParameters() {
return parameters;
}
/**
* Replaces existing parameters.
*
* By default parameters field is instantiated in constructor. Using this method replaces the existing field. If you
* wish only add missing parameters use {@link #addAbsentParameters(java.util.Properties)}.
*
*
* @param parameters
*/
public void setParameters(Properties parameters) {
this.parameters = parameters;
}
/**
* Add only absent parameters from argument.
*
* @see Properties#putIfAbsent(java.lang.Object, java.lang.Object)
* @param parameters
*/
public void addAbsentParameters(Properties parameters) {
parameters.forEach((Object k, Object v) -> {
LuceneSpinSail.this.parameters.putIfAbsent(k, v);
});
}
/**
* Creates absolute path to Lucene Index. If the properties contains no absolute path to lucene index than it is
* created here. The generic pattern of lisp-like pseudocode in that case is:
*
* (Paths/get (absolute datadir) + (or (getProperty parameters LuceneSail/LUCENE_DIR_KEY) "index/"))
*
*
* @return
*/
private Path getAbsoluteLuceneIndexDir() {
Path parametersIndexDir = Paths.get(parameters.getProperty(LuceneSail.LUCENE_DIR_KEY, "index/"));
if (!parametersIndexDir.isAbsolute()) {
parametersIndexDir = Paths.get(getDataDir().getAbsolutePath()).resolve(parametersIndexDir);
}
return parametersIndexDir;
}
/**
* @throws SailException
*/
@Override
public void initialize() throws SailException {
// Add support for indexed fields
if (parameters.containsKey(INDEXEDFIELDS)) {
String indexedfieldsString = parameters.getProperty(INDEXEDFIELDS);
Properties prop = new Properties();
try (Reader reader = new StringReader(indexedfieldsString)) {
prop.load(reader);
} catch (IOException e) {
throw new SailException("Could read " + INDEXEDFIELDS + ": " + indexedfieldsString, e);
}
ValueFactory vf = getValueFactory();
indexedFields = new HashSet<>();
indexedFieldsMapping = new HashMap<>();
for (Object key : prop.keySet()) {
String keyStr = key.toString();
if (keyStr.startsWith("index.")) {
indexedFields.add(vf.createIRI(prop.getProperty(keyStr)));
} else {
indexedFieldsMapping.put(vf.createIRI(keyStr), vf.createIRI(prop.getProperty(keyStr)));
}
}
}
((SpinSail) getBaseSail()).setEvaluationMode(TupleFunctionEvaluationMode.TRIPLE_SOURCE);
parameters.setProperty(LuceneSail.INDEX_CLASS_KEY,
getParameters().getProperty(LuceneSail.INDEX_CLASS_KEY, LuceneSail.DEFAULT_INDEX_CLASS));
Path indexLocation = getAbsoluteLuceneIndexDir();
log.debug("index location: {}", indexLocation);
Properties newParameters = (Properties) this.parameters.clone();
newParameters.setProperty(LuceneSail.LUCENE_DIR_KEY, indexLocation.toString());
try {
si = SearchIndexUtils.createSearchIndex(newParameters);
// bind index to SpinSail
((SpinSail) getBaseSail()).addQueryContextInitializer(new SearchIndexQueryContextInitializer(si));
} catch (Exception ex) {
log.warn("error occured during set up of the search index. It might affect functionality.");
throw new SailException(ex);
}
super.initialize();
}
/**
* @return sail connection
* @throws SailException
*/
@Override
public NotifyingSailConnection getConnection() throws SailException {
if (si == null) {
throw new SailException("Index is not created");
}
// the connection from the super is created only when the index exists
return new LuceneSpinSailConnection(super.getConnection(), si, this);
}
/**
* Copy of {@link LuceneSail#mapStatement(org.eclipse.rdf4j.model.Statement) }
*
* @param statement
* @return
*/
public Statement mapStatement(Statement statement) {
IRI p = statement.getPredicate();
boolean predicateChanged = false;
Map nextIndexedFieldsMapping = indexedFieldsMapping;
if (nextIndexedFieldsMapping != null) {
IRI res = nextIndexedFieldsMapping.get(p);
if (res != null) {
p = res;
predicateChanged = true;
}
}
Set nextIndexedFields = indexedFields;
if (nextIndexedFields != null && !nextIndexedFields.contains(p)) {
return null;
}
if (predicateChanged) {
return getValueFactory().createStatement(statement.getSubject(), p, statement.getObject(),
statement.getContext());
} else {
return statement;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy