package org.deri.grefine.reconcile;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.deri.grefine.reconcile.model.ReconciliationRequest;
import org.deri.grefine.reconcile.model.ReconciliationResponse;
import org.deri.grefine.reconcile.model.ReconciliationService;
import org.deri.grefine.reconcile.model.SearchResultItem;
import org.deri.grefine.reconcile.rdf.RdfReconciliationService;
import org.deri.grefine.reconcile.rdf.endpoints.PlainSparqlQueryEndpoint;
import org.deri.grefine.reconcile.rdf.endpoints.QueryEndpoint;
import org.deri.grefine.reconcile.rdf.endpoints.QueryEndpointImpl;
import org.deri.grefine.reconcile.rdf.executors.DumpQueryExecutor;
import org.deri.grefine.reconcile.rdf.executors.QueryExecutor;
import org.deri.grefine.reconcile.rdf.executors.RemoteQueryExecutor;
import org.deri.grefine.reconcile.rdf.executors.VirtuosoRemoteQueryExecutor;
import org.deri.grefine.reconcile.rdf.factories.BigOwlImSparqlQueryFactory;
import org.deri.grefine.reconcile.rdf.factories.JenaTextSparqlQueryFactory;
import org.deri.grefine.reconcile.rdf.factories.PlainSparqlQueryFactory;
import org.deri.grefine.reconcile.rdf.factories.SparqlQueryFactory;
import org.deri.grefine.reconcile.rdf.factories.VirtuosoSparqlQueryFactory;
import org.deri.grefine.reconcile.sindice.SindiceService;
import org.deri.grefine.reconcile.util.GRefineJsonUtilities;
import org.deri.grefine.reconcile.util.PrefixManager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.json.JSONWriter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
public class ServiceRegistry {
private Map<String, ReconciliationService> services;
private GRefineJsonUtilities grefineJsonUtilities;
private PrefixManager prefixManager;
public ServiceRegistry(GRefineJsonUtilities jsonUtilities, PrefixManager prefixer) {
services = new HashMap<String, ReconciliationService>();
this.grefineJsonUtilities = jsonUtilities;
this.prefixManager = prefixer;
}
public void addService(ReconciliationService service){
this.services.put(service.getId(), service);
}
public ReconciliationService removeService(String id){
return this.services.remove(id);
}
public Set<String> getServiceIds(){
return new HashSet<String>(services.keySet());
}
public ReconciliationService getService(String id, FileInputStream in){
ReconciliationService service = services.get(id);
if(in!=null){
service.initialize(in);
}
return service;
}
public void addAndSaveService(ReconciliationService service, FileOutputStream out) throws IOException{
this.addService(service);
service.save(out);
}
public void save(FileOutputStream out) throws JSONException, IOException{
Writer writer = new OutputStreamWriter(out);
try {
JSONWriter jsonWriter = new JSONWriter(writer);
jsonWriter.object();
jsonWriter.key("services");
jsonWriter.array();
for(ReconciliationService service:this.services.values()){
service.writeAsJson(jsonWriter,true);
}
jsonWriter.endArray();
jsonWriter.endObject();
} finally {
writer.close();
}
}
public boolean hasService(String id){
return services.containsKey(id);
}
public String metadata(ReconciliationService service, String baseUrl,String callback){
return grefineJsonUtilities.getServiceMetadataAsJsonP(service, callback, baseUrl);
}
public String multiReconcile(ReconciliationService service, String queries) throws JsonParseException, JsonMappingException, IOException{
ImmutableMap<String, ReconciliationRequest> multiQueryRequest = grefineJsonUtilities.getMultipleRequest(queries);
ImmutableMap<String, ReconciliationResponse> multiResult = service.reconcile(multiQueryRequest);
String response = grefineJsonUtilities.getMultipleResponse(multiResult,prefixManager).toString();
return response;
}
public String suggestType(ReconciliationService service,String prefix,String callback) throws JsonGenerationException, JsonMappingException, IOException {
ImmutableList<SearchResultItem> results = service.suggestType(prefix);
return grefineJsonUtilities.getJsonP(callback, grefineJsonUtilities.jsonizeSearchResult(results, prefix));
}
public String previewType(ReconciliationService service,String typeId, String callback) throws Exception{
String html = service.getPreviewHtmlForType(typeId);
return grefineJsonUtilities.getJsonP(callback,grefineJsonUtilities.jsonizeHtml(html,typeId));
}
public String previewProperty(ReconciliationService service, String propertyId, String callback) throws Exception{
String html = service.getPreviewHtmlForProperty(propertyId);
return grefineJsonUtilities.getJsonP(callback,grefineJsonUtilities.jsonizeHtml(html,propertyId));
}
public String previewEntity(ReconciliationService service, String entityId, String callback) throws Exception{
String html = previewResource(service,entityId);
if(html==null){
return null;
}
return grefineJsonUtilities.getJsonP(callback,grefineJsonUtilities.jsonizeHtml(html,entityId));
}
public String suggestProperty(ReconciliationService service, String typeId, String prefix, String callback) throws JsonGenerationException, JsonMappingException, IOException {
ImmutableList<SearchResultItem> results;
if(typeId==null || typeId.isEmpty()){
results = service.suggestProperty(prefix);
}else{
results = service.suggestProperty(prefix,typeId);
}
return grefineJsonUtilities.getJsonP(callback, grefineJsonUtilities.jsonizeSearchResult(results, prefix));
}
public String suggestEntity(ReconciliationService service,String prefix, String callback) throws JsonGenerationException, JsonMappingException, IOException {
ImmutableList<SearchResultItem> results = service.suggestEntity(prefix);
return grefineJsonUtilities.getJsonP(callback, grefineJsonUtilities.jsonizeSearchResult(results, prefix));
}
public String previewResource(ReconciliationService service, String resourceId) throws Exception{
return service.getPreviewHtmlForResource(resourceId);
}
public String getHtmlOfResourcePreviewTemplate(String previewUrl, String resourceId)throws Exception{
String templatePath = "templates/resource_preview_template.vt";
StringWriter writer = new StringWriter();
VelocityContext context = new VelocityContext();
context.put("resourceUri", resourceId);
context.put("previewResourceUrl", previewUrl);
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;
}
public void loadFromFile(FileInputStream in) throws JSONException, IOException{
try {
JSONTokener tokener = new JSONTokener(new InputStreamReader(in));
JSONObject obj = (JSONObject) tokener.nextValue();
JSONArray services = obj.getJSONArray("services");
for(int i=0;i<services.length();i++){
JSONObject serviceObj = services.getJSONObject(i);
String type = serviceObj.getString("type");
ReconciliationService service;
if(type.equals("rdf")){
service = loadRdfServiceFromJSON(serviceObj);
}else if(type.equals("sindice")){
service = loadSindiceServiceFromJSON(serviceObj);
}else{
//unknown service ignore
continue;
}
this.services.put(service.getId(), service);
}
}finally {
in.close();
}
}
private ReconciliationService loadSindiceServiceFromJSON(JSONObject serviceObj) throws JSONException{
String serviceId = serviceObj.getString("id");
String name = serviceObj.getString("name");
String domain = null;
if(serviceObj.has("domain")){
domain = serviceObj.getString("domain");
}
return new SindiceService(serviceId, name, domain);
}
private RdfReconciliationService loadRdfServiceFromJSON(JSONObject serviceObj) throws JSONException{
String serviceId = serviceObj.getString("id");
List<String> searchPropertyUris = new ArrayList<String>();
JSONArray propertiesArray = serviceObj.getJSONArray("searchPropertyUris");
for(int i=0;i<propertiesArray.length();i++){
searchPropertyUris.add(propertiesArray.getString(i));
}
QueryEndpoint endpoint = loadEndpointFromJSON(serviceObj.getJSONObject("endpoint"));
return new RdfReconciliationService(serviceId, serviceObj.getString("name"),
ImmutableList.copyOf(searchPropertyUris), endpoint, serviceObj.getDouble("matchThreshold"));
}
private QueryEndpoint loadEndpointFromJSON(JSONObject endpointObj) throws JSONException{
String type = endpointObj.getString("type");
QueryExecutor executor = loadQueryExecutorFromJSON(endpointObj.getJSONObject("queryExecutor"));
SparqlQueryFactory factory = loadQueryFactoryFromJSON(endpointObj.getJSONObject("queryFactory"));
if(type.equals("plain")){
return new PlainSparqlQueryEndpoint((PlainSparqlQueryFactory)factory, executor);
}else{
//default
return new QueryEndpointImpl(factory, executor);
}
}
private QueryExecutor loadQueryExecutorFromJSON(JSONObject jsonObject) throws JSONException {
String type = jsonObject.getString("type");
if(type.equals("dump")){
if(jsonObject.has("propertyUri")){
return new DumpQueryExecutor(jsonObject.getString("propertyUri"));
}else{
return new DumpQueryExecutor();
}
}else{
String url = jsonObject.getString("sparql-url");
String graph = null;
if(jsonObject.has("default-graph-uri")){
graph = jsonObject.getString("default-graph-uri");
}
if(type.equals("remote-virtuoso")){
return new VirtuosoRemoteQueryExecutor(url, graph);
}else{
//plain
return new RemoteQueryExecutor(url, graph);
}
}
}
private SparqlQueryFactory loadQueryFactoryFromJSON(JSONObject factoryObj) throws JSONException{
String type = factoryObj.getString("type");
if(type.equals("virtuoso")){
return new VirtuosoSparqlQueryFactory();
}else if(type.equals("jena-text")){
return new JenaTextSparqlQueryFactory();
}else if(type.equals("bigowlim")){
return new BigOwlImSparqlQueryFactory();
}else{
//plain
return new PlainSparqlQueryFactory();
}
}
}