/* Copyright 2012-2013 Fabian Steeg, hbz. Licensed under the Eclipse Public License 1.0 */
package models;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
import org.lobid.lodmill.JsonLdConverter;
import org.lobid.lodmill.JsonLdConverter.Format;
import com.fasterxml.jackson.databind.JsonNode;
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 com.google.common.collect.ImmutableMap;
import com.hp.hpl.jena.shared.BadURIException;
import play.Logger;
import play.libs.Json;
/**
* Documents returned from the ElasticSearch index.
*
* @author Fabian Steeg (fsteeg)
*/
public class Document {
transient String matchedField;
private final String source;
private transient String id; // NOPMD
private Index index;
private String field;
/**
* @return The document ID.
*/
public String getId() {
return id;
}
/**
* @return The JSON source for this document as compact JSON-LD with an
* extracted, external context, or null if conversion failed.
*/
public String getSource() {
try {
final Pair<URL, String> localAndPublicContextUrls = index.context();
@SuppressWarnings("unchecked")
final Map<String, Object> compactJsonLd =
sourceAsCompactJsonLd((Map<String, Object>) JSONUtils
.fromURL(localAndPublicContextUrls.getLeft()));
compactJsonLd.put("@context", localAndPublicContextUrls.getRight());
compactJsonLd.put("primaryTopic", id);
final String result = JSONUtils.toString(compactJsonLd);
return this.field.isEmpty() ? result : findField(result);
} catch (JsonLdError | IOException e) {
e.printStackTrace();
return null;
}
}
private String findField(final String result) {
final List<JsonNode> fieldValues = Json.parse(result).findValues(field);
final JsonNode node =
fieldValues.size() == 1 && fieldValues.get(0).isArray() ? /**/
Json.toJson(fieldValues.get(0)) : Json.toJson(fieldValues);
return Json.stringify(node);
}
/**
* @return The JSON source for this document as compact JSON-LD with full
* properties (i.e. without a context), or null if conversion failed.
*/
public String getSourceWithFullProperties() {
try {
final Map<String, Object> jsonLd =
sourceAsCompactJsonLd(new HashMap<String, Object>());
jsonLd.put("http://xmlns.com/foaf/0.1/primaryTopic",
ImmutableMap.of("@id", id));
return JSONUtils.toString(jsonLd);
} catch (JsonLdError | IOException e) {
e.printStackTrace();
return null;
}
}
/**
* @return The JSON source for this document as it original resides in
* elasticsearch "_source" field.
*/
public String getEsSource() {
return source;
}
private Map<String, Object> sourceAsCompactJsonLd(
final Map<String, Object> contextObject) throws IOException, JsonLdError {
final Map<String, Object> jsonLd =
wrappedIntoGraphIfMissing(JsonLdProcessor.compact(
JSONUtils.fromString(source), contextObject, new JsonLdOptions()));
jsonLd.put("@id", id + "/about");
return jsonLd;
}
private static Map<String, Object> wrappedIntoGraphIfMissing(
final Map<String, Object> jsonLd) {
final String graphKey = "@graph";
final String contextKey = "@context";
if (!jsonLd.containsKey(graphKey)) {
final Map<String, Object> newJsonLd = new HashMap<>();
final Map<String, Object> graph = new HashMap<>();
newJsonLd.put(contextKey, jsonLd.get(contextKey));
jsonLd.remove(contextKey);
graph.putAll(jsonLd);
newJsonLd.put(graphKey, Arrays.asList(graph));
return newJsonLd;
}
return jsonLd;
}
/**
* @return The field that matched the query.
*/
public String getMatchedField() {
return matchedField;
}
/**
* @param id The document ID
* @param source The document JSON source
* @param index The index that this document is part of
* @param field The field to consider as this document's data (if empty, the
* complete source will be the document's content)
*/
public Document(final String id, final String source, final Index index,
final String field) { // NOPMD
this.id = id;
this.source = source;
this.index = index;
this.field = field;
}
/**
* @param format The RDF serialization format to represent this document as
* @return This documents, in the given RDF format
*/
public String as(final Format format) { // NOPMD
final JsonLdConverter converter = new JsonLdConverter(format);
final String json = getSourceWithFullProperties();
String result = "";
try {
result = converter.toRdf(json);
} catch (BadURIException x) {
Logger.error(x.getMessage(), x);
}
return result;
}
}