package won.matcher.solr.index;
import com.github.jsonldjava.core.JsonLdError;
import com.github.jsonldjava.core.JsonLdOptions;
import com.github.jsonldjava.core.JsonLdProcessor;
import com.github.jsonldjava.utils.JsonUtils;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import won.matcher.service.common.service.http.HttpService;
import won.matcher.solr.config.SolrMatcherConfig;
import won.protocol.model.Coordinate;
import won.protocol.model.NeedContentPropertyType;
import won.protocol.util.DefaultNeedModelWrapper;
import won.protocol.util.NeedModelWrapper;
import won.protocol.vocabulary.WON;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;
/**
* Created by hfriedrich on 03.08.2016.
*/
@Component
@Scope("prototype")
public class NeedIndexer {
private final Logger log = LoggerFactory.getLogger(getClass());
public static final String SOLR_IS_LOCATION_COORDINATES_FIELD = "is_need_location";
public static final String SOLR_SEEKS_LOCATION_COORDINATES_FIELD = "seeks_need_location";
public static final String SOLR_SEEKS_SEEKS_LOCATION_COORDINATES_FIELD = "seeksSeeks_need_location";
// SPARQL query to contruct a need object out of the dataset, use all graphs that reference "won:Need"
private static final String NEED_INDEX_QUERY =
"prefix won: <http://purl.org/webofneeds/model#> construct { ?a ?b ?c .} where { " +
"GRAPH ?graph { ?need a won:Need. ?a ?b ?c. } }";
@Autowired
private SolrMatcherConfig config;
@Autowired
private HttpService httpService;
public void index(Dataset dataset) throws IOException, JsonLdError {
// serialize the need Dataset to jsonld
Query query = QueryFactory.create(NEED_INDEX_QUERY);
QueryExecution qexec = QueryExecutionFactory.create(query, dataset);
Model needModel = qexec.execConstruct();
// normalize the need model for solr indexing
NeedModelWrapper needModelWrapper = new NeedModelWrapper(needModel, null);
String needUri = needModelWrapper.getNeedUri();
needModel = needModelWrapper.normalizeNeedModel();
// check if test index should be used for need
boolean usedForTesting = needModelWrapper.hasFlag(WON.USED_FOR_TESTING);
indexNeedModel(needModel, needUri, usedForTesting);
}
public void indexNeedModel(Model needModel, String id, boolean useTestCore) throws IOException, JsonLdError {
// create the json from rdf model
StringWriter sw = new StringWriter();
RDFDataMgr.write(sw, needModel, Lang.JSONLD);
String jsonld = sw.toString();
Object jsonObject = JsonUtils.fromString(jsonld);
Object frame = JsonUtils.fromString(" {\"@type\": \"" + WON.NEED + "\"} ");
JsonLdOptions options = new JsonLdOptions();
Map<String, Object> framed = JsonLdProcessor.frame(jsonObject, frame, options);
// add the uri of the need as id field to avoid multiple adding of needs but instead allow updates
framed.put("id", id);
// add latitude and longitude values in one field for Solr spatial queries
DefaultNeedModelWrapper needModelWrapper = new DefaultNeedModelWrapper(needModel, null);
for (Resource contentNode : needModelWrapper.getContentNodes(NeedContentPropertyType.IS)) {
Coordinate coordinate = needModelWrapper.getLocationCoordinate(contentNode);
if (coordinate != null) {
framed.put(SOLR_IS_LOCATION_COORDINATES_FIELD, String.valueOf(coordinate.getLatitude()) + "," + String.valueOf(coordinate.getLongitude()));
}
}
for (Resource contentNode : needModelWrapper.getContentNodes(NeedContentPropertyType.SEEKS)) {
Coordinate coordinate = needModelWrapper.getLocationCoordinate(contentNode);
if (coordinate != null) {
framed.put(SOLR_SEEKS_LOCATION_COORDINATES_FIELD, String.valueOf(coordinate.getLatitude()) + "," + String.valueOf(coordinate.getLongitude()));
}
}
for (Resource contentNode : needModelWrapper.getContentNodes(NeedContentPropertyType.SEEKS_SEEKS)) {
Coordinate coordinate = needModelWrapper.getLocationCoordinate(contentNode);
if (coordinate != null) {
framed.put(SOLR_SEEKS_SEEKS_LOCATION_COORDINATES_FIELD, String.valueOf(coordinate.getLatitude()) + "," + String.valueOf(coordinate.getLongitude()));
}
}
// write the final json string
sw = new StringWriter();
JsonUtils.writePrettyPrint(sw, framed);
String needJson = sw.toString();
// post the need to the solr index
String indexUri = config.getSolrEndpointUri(useTestCore);
indexUri += "update/json/docs";
if (config.isCommitIndexedNeedImmediately()) {
indexUri += "?commit=" + config.isCommitIndexedNeedImmediately();
}
log.debug("Post needto solr index. \n Solr URI: {} \n Need (JSON): {}", indexUri, needJson);
httpService.postJsonRequest(indexUri, needJson);
}
}