package org.deri.grefine.reconcile.rdf; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.util.List; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.deri.grefine.reconcile.model.AbstractReconciliationService; import org.deri.grefine.reconcile.model.ReconciliationCandidate; import org.deri.grefine.reconcile.model.ReconciliationRequest; import org.deri.grefine.reconcile.model.ReconciliationResponse; import org.deri.grefine.reconcile.model.SearchResultItem; import org.deri.grefine.reconcile.rdf.endpoints.QueryEndpoint; import org.deri.grefine.reconcile.rdf.factories.PreviewResourceCannedQuery; import org.json.JSONException; import org.json.JSONWriter; import com.google.common.collect.ImmutableList; import com.google.common.collect.Multimap; /** * @author fadmaa * also implements reconcile so that it differentiate between reconcile request without type ==> gussType Request and those with types ==> reconcile */ public class RdfReconciliationService extends AbstractReconciliationService{ protected ImmutableList<String> searchPropertyUris; protected QueryEndpoint queryEndpoint; /** * the limit used when guessing types... this depends on the data that are queried */ protected final int limitForSuggestion; protected final double matchThreshold; // protected final String labelPropertyUri; protected PreviewResourceCannedQuery previewResourceCannedQuery; /** * @param searchPropertyUris list of property URIs that will be used for full text search and for retrieving items name (i.e. displayed label) * @param freemarkerConfig */ public RdfReconciliationService(String id, String name, ImmutableList<String> searchPropertyUris, QueryEndpoint queryEndpoint, double matchThreshold){ super(id,name); this.searchPropertyUris = searchPropertyUris; this.queryEndpoint = queryEndpoint; //TODO hard-coded value this.limitForSuggestion = LIMIT_FOR_SUGGESTION; this.matchThreshold = matchThreshold; try{ //TODO hard-coded for now.. accept as parameter if you need services to use different properties for perviewing InputStream in = this.getClass().getResourceAsStream("/files/preview_properties.properties"); this.previewResourceCannedQuery = new PreviewResourceCannedQuery(in); }catch (IOException e) { } } public RdfReconciliationService(String id, String name, QueryEndpoint queryEndpoint, double matchThreshold){ this(id,name,ImmutableList.of(RDFS_LABEL),queryEndpoint,matchThreshold); } @Override public ReconciliationResponse reconcile(ReconciliationRequest request) { List<ReconciliationCandidate> candidates = queryEndpoint.reconcileEntities(request, searchPropertyUris, matchThreshold); return wrapCandidates(candidates); } @Override public ImmutableList<SearchResultItem> suggestType(String prefix) { return this.queryEndpoint.suggestType(prefix, limitForSuggestion); } @Override public ImmutableList<SearchResultItem> suggestProperty(String prefix) { return this.queryEndpoint.suggestProperty(prefix, limitForSuggestion); } @Override public ImmutableList<SearchResultItem> suggestProperty(String prefix, String subjectTypeUri) { return this.queryEndpoint.suggestProperty(prefix, subjectTypeUri, limitForSuggestion); } @Override public String getPreviewHtmlForType(String typeUri) throws Exception { List<SearchResultItem> sampleInstances = this.queryEndpoint.getSampleInstances(typeUri, searchPropertyUris,LIMIT_FOR_INSTANCES_SAMPLE); VelocityContext context = new VelocityContext(); context.put("typeUri", typeUri); context.put("instances", sampleInstances); return getHtmlFromTemplate("templates/type_preview.vt", context); } @Override public String getPreviewHtmlForProperty(String propertyUri) throws Exception { List<String[]> sampleInstances = this.queryEndpoint.getSampleValuesOfProperty(propertyUri, LIMIT_FOR_PROPERTY_VALUES_SAMPLE); VelocityContext context = new VelocityContext(); context.put("propertyUri", propertyUri); context.put("instances", sampleInstances); return getHtmlFromTemplate("templates/property_preview.vt", context); } @Override public String getPreviewHtmlForResource(String resourceUri) throws Exception{ //Multimap<String, String> propertiesMap = this.queryEndpoint.getResourcePropertiesMap(resourceUri,LIMIT_FOR_RESOURCE_PREVIEW); Multimap<String, String> propertiesMap = this.queryEndpoint.getResourcePropertiesMap(previewResourceCannedQuery, resourceUri); VelocityContext context = new VelocityContext(); context.put("resourceUri", resourceUri); context.put("propertiesMap", propertiesMap); return getHtmlFromTemplate("templates/resource_preview.vt", context); } @Override public ImmutableList<SearchResultItem> suggestEntity(String prefix) { return this.queryEndpoint.searchForEntities(prefix, searchPropertyUris, limitForSuggestion); } @Override public void writeAsJson(JSONWriter writer,boolean saveMode)throws JSONException { writer.object(); writer.key("type"); writer.value("rdf"); writer.key("id");writer.value(this.getId()); writer.key("name");writer.value(this.getName()); writer.key("matchThreshold");writer.value(this.matchThreshold); writer.key("searchPropertyUris"); writer.array(); for(String uri:this.searchPropertyUris){ writer.value(uri); } writer.endArray(); writer.key("endpoint"); this.queryEndpoint.write(writer); writer.endObject(); } @Override public void save(FileOutputStream out) throws IOException{ queryEndpoint.save(this.getId(),out); } @Override public void initialize(FileInputStream in){ queryEndpoint.initialize(in); } protected String getHtmlFromTemplate(String templatePath, VelocityContext context) throws Exception{ StringWriter writer = new StringWriter(); InputStream in = this.getClass().getClassLoader().getResourceAsStream(templatePath); VelocityEngine templateEngine = new VelocityEngine(); templateEngine.init(); templateEngine.evaluate(context, writer, "rdf-reconcile-extension", new InputStreamReader(in)); writer.close(); String html = writer.toString(); return html; } private ReconciliationResponse wrapCandidates(List<ReconciliationCandidate> candidates){ ReconciliationResponse response = new ReconciliationResponse(); response.setResults(candidates); return response; } private static final int LIMIT_FOR_INSTANCES_SAMPLE = 5; private static final int LIMIT_FOR_PROPERTY_VALUES_SAMPLE = 5; //private static final int LIMIT_FOR_RESOURCE_PREVIEW = 15; private static final int LIMIT_FOR_SUGGESTION = 40; private static final String RDFS_LABEL = "http://www.w3.org/2000/01/rdf-schema#label"; }