Skip to content

Commit

Permalink
[ issue #28 ] RDF faceting (facet fields)
Browse files Browse the repository at this point in the history
  • Loading branch information
agazzarini committed Mar 7, 2015
1 parent dcb60bd commit 1f99afb
Show file tree
Hide file tree
Showing 14 changed files with 383 additions and 49 deletions.
3 changes: 3 additions & 0 deletions solrdf/src/main/java/org/gazzax/labs/solrdf/Names.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ public interface Names {
String QUERY = "query";

String HTTP_REQUEST_KEY = "httpRequest";
String SOLR_REQUEST = "solr.request";
String SOLR_RESPONSE = "solr.response";
String HYBRID_MODE = "hybrid.mode";
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class DeepPagingIterator extends UnmodifiableIterator<Triple> {

private final SolrIndexSearcher searcher;
final SolrIndexSearcher.QueryCommand queryCommand;
final GraphEventListener listener;
private DocList page;

private CursorMark nextCursorMark;
Expand Down Expand Up @@ -91,11 +92,14 @@ public boolean hasNext() {
@Override
public Triple next() {
try {
final Document document = searcher.doc(iterator().nextDoc(), TRIPLE_FIELDS);
return Triple.create(
final int nextDocId = iterator().nextDoc();
final Document document = searcher.doc(nextDocId, TRIPLE_FIELDS);
final Triple triple = Triple.create(
NTriples.asURIorBlankNode((String) document.get(Field.S)),
NTriples.asURI((String) document.get(Field.P)),
NTriples.asNode((String) document.get(Field.O)));
listener.afterTripleHasBeenBuilt(triple, nextDocId);
return triple;
} catch (final IOException exception) {
throw new RuntimeException(exception);
}
Expand Down Expand Up @@ -140,11 +144,12 @@ public Triple next() {
* @param queryCommand the query command that will be submitted.static
* @param sort the sort specs.
*/
DeepPagingIterator(final SolrIndexSearcher searcher, final SolrIndexSearcher.QueryCommand queryCommand, final SortSpec sort) {
DeepPagingIterator(final SolrIndexSearcher searcher, final SolrIndexSearcher.QueryCommand queryCommand, final SortSpec sort, final GraphEventListener listener) {
this.searcher = searcher;
this.queryCommand = queryCommand;
this.sentCursorMark = new CursorMark(searcher.getSchema(), sort);
this.queryCommand.setCursorMark(sentCursorMark);
this.listener = listener;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.gazzax.labs.solrdf.graph;

import com.hp.hpl.jena.graph.Triple;

public interface GraphEventListener {
public void afterTripleHasBeenBuilt(Triple triple, int docId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class SolRDFDatasetGraph extends DatasetGraphCaching {
final SolrQueryResponse response;
final QParser qParser;

final GraphEventListener listener;

/**
* Builds a new Dataset graph with the given data.
*
Expand All @@ -41,9 +43,7 @@ public class SolRDFDatasetGraph extends DatasetGraphCaching {
public SolRDFDatasetGraph(
final SolrQueryRequest request,
final SolrQueryResponse response) {
this.request = request;
this.response = response;
this.qParser = null;
this(request, response, null, null);
}

/**
Expand All @@ -57,10 +57,12 @@ public SolRDFDatasetGraph(
public SolRDFDatasetGraph(
final SolrQueryRequest request,
final SolrQueryResponse response,
final QParser qParser) {
final QParser qParser,
final GraphEventListener listener) {
this.request = request;
this.response = response;
this.qParser = qParser;
this.listener = listener;
}

@Override
Expand All @@ -75,12 +77,12 @@ protected void _close() {

@Override
protected Graph _createNamedGraph(final Node graphNode) {
return SolRDFGraph.readableAndWritableGraph(graphNode, request, response, qParser);
return SolRDFGraph.readableAndWritableGraph(graphNode, request, response, qParser, listener);
}

@Override
protected Graph _createDefaultGraph() {
return SolRDFGraph.readableAndWritableGraph(null, request, response, qParser);
return SolRDFGraph.readableAndWritableGraph(null, request, response, qParser, listener);
}

@Override
Expand Down
18 changes: 12 additions & 6 deletions solrdf/src/main/java/org/gazzax/labs/solrdf/graph/SolRDFGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public final class SolRDFGraph extends GraphBase {

final int queryFetchSize;

final GraphEventListener listener;

/**
* Creates a Read / Write {@link Graph}.
*
Expand All @@ -76,8 +78,9 @@ public static SolRDFGraph readableAndWritableGraph(
final Node graphNode,
final SolrQueryRequest request,
final SolrQueryResponse response,
final QParser qParser) {
return new SolRDFGraph(graphNode, request, response, qParser, DEFAULT_QUERY_FETCH_SIZE);
final QParser qParser,
final GraphEventListener listener) {
return new SolRDFGraph(graphNode, request, response, qParser, DEFAULT_QUERY_FETCH_SIZE, listener);
}

/**
Expand All @@ -95,8 +98,9 @@ public static SolRDFGraph readableAndWritableGraph(
final SolrQueryRequest request,
final SolrQueryResponse response,
final QParser qParser,
final int fetchSize) {
return new SolRDFGraph(graphNode, request, response, qParser, fetchSize);
final int fetchSize,
final GraphEventListener listener) {
return new SolRDFGraph(graphNode, request, response, qParser, fetchSize, listener);
}

/**
Expand All @@ -113,7 +117,8 @@ private SolRDFGraph(
final SolrQueryRequest request,
final SolrQueryResponse response,
final QParser qparser,
final int fetchSize) {
final int fetchSize,
final GraphEventListener listener) {
this.graphNode = graphNode;
this.graphNodeStringified = (graphNode != null) ? asNtURI(graphNode) : null;
this.request = request;
Expand All @@ -123,6 +128,7 @@ private SolRDFGraph(
this.searcher = request.getSearcher();
this.qParser = qparser;
this.queryFetchSize = fetchSize;
this.listener = listener;
}

@Override
Expand Down Expand Up @@ -269,7 +275,7 @@ Iterator<Triple> query(final TripleMatch pattern) throws SyntaxError {

cmd.setFilterList(filters);

return new DeepPagingIterator(searcher, cmd, sortSpec);
return new DeepPagingIterator(searcher, cmd, sortSpec, listener);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void run() {
}
});

final DatasetGraph dataset = new SolRDFDatasetGraph(request, response, null);
final DatasetGraph dataset = new SolRDFDatasetGraph(request, response, null, null);
final Graph defaultGraph = dataset.getDefaultGraph();
while (iterator.hasNext()) {
defaultGraph.add(iterator.next());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package org.gazzax.labs.solrdf.response;

import static org.apache.solr.common.util.XML.escapeAttributeValue;
import static org.gazzax.labs.solrdf.Strings.isNotNullOrEmptyString;

import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.output.WriterOutputStream;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.response.XMLWriter;

import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.sparql.resultset.XMLOutput;

/**
* A subclass of {@link XMLWriter} for mixing up Solr and Jena results.
* Unfortunately something needs to be declared again here because, although it is not final,
* I assume the {@link XMLWriter} hasn't been thought with extensibility in mind.
*
* @author Andrea Gazzarini
* @since 1.0
*/
class CompoundXMLWriter extends XMLWriter {
protected static final char[] XML_PROCESSING_INSTR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".toCharArray();
protected static final char[] RESPONSE_ROOT_ELEMENT_START = ("<response>\n").toCharArray();
protected static final char[] RESPONSE_ROOT_ELEMENT_END = ("</response>").toCharArray();

protected static final char[] XML_STYLESHEET = "<?xml-stylesheet type=\"text/xsl\" href=\"".toCharArray();
protected static final char[] XML_STYLESHEET_END = "\"?>\n".toCharArray();

/**
* Builds a new {@link CompoundXMLWriter} with the given data.
*
* @param writer the output {@link Writer}.
* @param request the current {@link SolrQueryRequest}.
* @param response the current {@link SolrQueryResponse}.
*/
CompoundXMLWriter(
final Writer writer,
final SolrQueryRequest request,
final SolrQueryResponse response) {
super(writer, request, response);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void writeResponse() throws IOException {
writer.write(XML_PROCESSING_INSTR);

final String stylesheet = req.getParams().get("stylesheet");
if (isNotNullOrEmptyString(stylesheet)) {
writer.write(XML_STYLESHEET);

escapeAttributeValue(stylesheet, writer);

writer.write(XML_STYLESHEET_END);
}

writer.write(RESPONSE_ROOT_ELEMENT_START);

final NamedList<?> responseValues = rsp.getValues();
if (req.getParams().getBool(CommonParams.OMIT_HEADER, false)) {
responseValues.remove("responseHeader");
} else {
((NamedList)responseValues.get("responseHeader")).add("query", responseValues.remove("query"));
}

for (final Entry<String, ?> entry : responseValues) {
writeValue(entry.getKey(), entry.getValue(), responseValues);
}

writer.write(RESPONSE_ROOT_ELEMENT_END);
}

/**
* Writes out a given name / value pair.
* This is similar to {@link XMLWriter#writeVal(String, Object)}.
* This is needed because that similar method is not extensible and cannot be overriden
* (it is called recursively by other methods).
*
* @param name the name of the attribute.
* @param value the value of the attribute.
* @param data the complete set of response values.
* @throws IOException in case of I/O failure.
*/
public void writeValue(final String name, final Object value, final NamedList<?> data) throws IOException {
if (value == null) {
writeNull(name);
} else if (value instanceof ResultSet) {
final XMLOutput outputter = new XMLOutput(false);
outputter.format(new WriterOutputStream(writer), (ResultSet)value) ;
} else if (value instanceof String) {
writeStr(name, value.toString(), false);
} else if (value instanceof Number) {
if (value instanceof Integer || value instanceof Short || value instanceof Byte) {
writeInt(name, value.toString());
} else if (value instanceof Long) {
writeLong(name, value.toString());
} else if (value instanceof Float) {
writeFloat(name, ((Float) value).floatValue());
} else if (value instanceof Double) {
writeDouble(name, ((Double) value).doubleValue());
}
} else if (value instanceof Boolean) {
writeBool(name, value.toString());
} else if (value instanceof Date) {
writeDate(name, (Date) value);
} else if (value instanceof Map) {
writeMap(name, (Map<?,?>) value, false, true);
} else if (value instanceof NamedList) {
writeNamedList(name, (NamedList<?>) value);
} else if (value instanceof Iterable) {
writeArray(name, ((Iterable<?>) value).iterator());
} else if (value instanceof Object[]) {
writeArray(name, (Object[]) value);
} else if (value instanceof Iterator) {
writeArray(name, (Iterator<?>) value);
}
}
}
Loading

0 comments on commit 1f99afb

Please sign in to comment.