You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by en...@apache.org on 2011/08/25 20:21:27 UTC
svn commit: r1161677 -
/incubator/stanbol/branches/jena-reasoners/reasoners/web/src/main/java/org/apache/stanbol/reasoners/web/resources/ReasoningServiceTaskResource.java
Author: enridaga
Date: Thu Aug 25 18:21:27 2011
New Revision: 1161677
URL: http://svn.apache.org/viewvc?rev=1161677&view=rev
Log:
Some more work to support scope and session paramters (STANBOL-185)
(Still ongoing work)
Modified:
incubator/stanbol/branches/jena-reasoners/reasoners/web/src/main/java/org/apache/stanbol/reasoners/web/resources/ReasoningServiceTaskResource.java
Modified: incubator/stanbol/branches/jena-reasoners/reasoners/web/src/main/java/org/apache/stanbol/reasoners/web/resources/ReasoningServiceTaskResource.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/branches/jena-reasoners/reasoners/web/src/main/java/org/apache/stanbol/reasoners/web/resources/ReasoningServiceTaskResource.java?rev=1161677&r1=1161676&r2=1161677&view=diff
==============================================================================
--- incubator/stanbol/branches/jena-reasoners/reasoners/web/src/main/java/org/apache/stanbol/reasoners/web/resources/ReasoningServiceTaskResource.java (original)
+++ incubator/stanbol/branches/jena-reasoners/reasoners/web/src/main/java/org/apache/stanbol/reasoners/web/resources/ReasoningServiceTaskResource.java Thu Aug 25 18:21:27 2011
@@ -4,10 +4,13 @@ import static javax.ws.rs.core.MediaType
import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -28,10 +31,22 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.core.serializedform.Parser;
+import org.apache.clerezza.rdf.core.serializedform.Serializer;
+import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
import org.apache.stanbol.commons.web.base.ContextHelper;
import org.apache.stanbol.commons.web.base.format.KRFormat;
import org.apache.stanbol.commons.web.base.resource.BaseStanbolResource;
+import org.apache.stanbol.ontologymanager.ontonet.api.ONManager;
+import org.apache.stanbol.ontologymanager.ontonet.api.ontology.OntologyScope;
+import org.apache.stanbol.ontologymanager.ontonet.api.ontology.OntologySpace;
+import org.apache.stanbol.owl.transformation.JenaToOwlConvert;
import org.apache.stanbol.reasoners.jena.JenaReasoningService;
import org.apache.stanbol.reasoners.owlapi.OWLApiReasoningService;
import org.apache.stanbol.reasoners.servicesapi.ReasoningService;
@@ -40,19 +55,29 @@ import org.apache.stanbol.reasoners.serv
import org.apache.stanbol.reasoners.web.utils.ReasoningServiceExecutor;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.OWLOntologyCreationIOException;
+import org.semanticweb.owlapi.io.RDFXMLOntologyFormat;
+import org.semanticweb.owlapi.model.AddImport;
+import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.MissingImportEvent;
import org.semanticweb.owlapi.model.MissingImportListener;
+import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.model.OWLOntologySetProvider;
+import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import org.semanticweb.owlapi.model.SWRLRule;
+import org.semanticweb.owlapi.util.OWLOntologyMerger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
+import com.hp.hpl.jena.shared.DoesNotExistException;
+import com.hp.hpl.jena.vocabulary.OWL;
import com.sun.jersey.api.core.HttpContext;
import com.sun.jersey.api.core.HttpRequestContext;
import com.sun.jersey.api.view.Viewable;
@@ -61,514 +86,1030 @@ import com.sun.jersey.multipart.FormData
import com.sun.jersey.multipart.FormDataMultiPart;
/**
- * Endpoint for reasoning services. Services can be invoked using the service name and task in the request
- * path. The related active SCR service is selected, then the concrete execution is delegated to a {@see
+ * Endpoint for reasoning services. Services can be invoked using the service
+ * name and task in the request path. The related active SCR service is
+ * selected, then the concrete execution is delegated to a {@see
* ReasoningServiceExecutor}.
*
- * Two different kind of implementation of {@see ReasoningService} are supported: {@see JenaReasoningService}
- * and {@see OWLApiReasonngService}.
+ * Two different kind of implementation of {@see ReasoningService} are
+ * supported: {@see JenaReasoningService} and {@see OWLApiReasonngService}.
*
- * This class includes methods to prepare the input and dispatch the output (back to the client in the
- * requested format or saved in the triple store).
+ * This class includes methods to prepare the input and dispatch the output
+ * (back to the client in the requested format or saved in the triple store).
*
*/
@Path("/reasoners/services/{service}/{task}")
public class ReasoningServiceTaskResource extends BaseStanbolResource {
- private Logger log = LoggerFactory.getLogger(getClass());
- private ServletContext context;
- private ReasoningService<?,?,?> service;
- private String taskID;
- private HttpContext httpContext;
- private Map<String,List<String>> parameters;
- private TcManager tcManager;
- private HttpHeaders headers;
-
- public ReasoningServiceTaskResource(@PathParam(value = "service") String serviceID,
- @PathParam(value = "task") String taskID,
- @Context ServletContext servletContext,
- @Context HttpHeaders headers,
- @Context HttpContext httpContext) {
- super();
- log.info("Called service {} to perform task {}", serviceID, taskID);
-
- // ServletContext
- this.context = servletContext;
-
- // HttpContext
- this.httpContext = httpContext;
-
- // HttpHeaders
- this.headers = headers;
-
- // Parameters for customized reasoning services
- this.parameters = prepareParameters();
-
- // Clerezza storage
- this.tcManager = (TcManager) ContextHelper.getServiceFromContext(TcManager.class, servletContext);
-
- // Retrieve the service
- try {
- service = getService(serviceID);
- } catch (UnboundReasoningServiceException e) {
- log.error("Service not found: {}", serviceID);
- throw new WebApplicationException(e, Response.Status.NOT_FOUND);
- }
- log.info("Service retrieved");
- // Check if the task is allowed
- if (this.service.supportsTask(taskID) || taskID.equals(ReasoningServiceExecutor.TASK_CHECK)) {
- this.taskID = taskID;
- } else {
- log.error("Unsupported task (not found): {}", taskID);
- throw new WebApplicationException(new Exception("Unsupported task (not found): " + taskID),
- Response.Status.BAD_REQUEST);
- }
- log.info("Task is OK");
- // Now we check if the service implementation is supported
- if (getCurrentService() instanceof JenaReasoningService) {} else if (getCurrentService() instanceof OWLApiReasoningService) {} else {
- log.error("This implementation of ReasoningService is not supported: {}", getCurrentService()
- .getClass());
- throw new WebApplicationException(new Exception(
- "This implementation of ReasoningService is not supported: "
- + getCurrentService().getClass()), Response.Status.INTERNAL_SERVER_ERROR);
- }
- log.info("Implementation is supported");
-
- }
-
- // @GET
- // @Path("/ontonet/session")
- // @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE, "text/turtle", "text/n3"})
- // public Response getOntonetSession(@QueryParam("session") String sessionID,
- // @QueryParam("target") String targetGraphID) {
- // log.info("Called /ontonet/session with session={} and target={}", sessionID, targetGraphID);
- // // If session is null, describe the service
- // if (sessionID == null) {
- // return Response.ok(new Viewable("ontonet-session", this)).build();
- // }
- // // Get the session
- // log.info("Session requested is {}", sessionID);
- // Set<OntologyScope> scopes = this.onManager.getScopeRegistry().getRegisteredScopes();
- // log.info("Registered scopes are {}", scopes.size());
- // OntologyScope scope = null;
- // SessionOntologySpace sspace = null;
- // for (OntologyScope sc : scopes) {
- // log.info("Lookup for session space in scope {}", sc);
- // if (sc == null) {
- // log.warn("A Scope is null! Why it's in the registry!?");
- // continue;
- // } else {
- // sspace = sc.getSessionSpace(IRI.create(sessionID));
- // if (sspace != null) {
- // scope = sc;
- // break;
- // }
- // }
- // }
- // log.info("Found scope: {}", scope);
- // log.info("Found session space: {}", sspace);
- //
- // // If session cannot be retrieved, return 404
- // if (sspace == null) {
- // log.error("Session space does not exists!: {}", sessionID);
- // throw new WebApplicationException(new IllegalArgumentException("Session does not exists!"),
- // Response.Status.NOT_FOUND);
- // }
- //
- // // Get the session as OWLOntology
- // OWLOntology input = sspace.asOWLOntology();
- // log.info("Session ontology is: {}", input);
- //
- // // Now we select the service type
- // if (service instanceof JenaReasoningService) {
- // Model inputModel = new JenaToOwlConvert().ModelOwlToJenaConvert(input, "TURTLE");
- // return executeJenaReasoningService((JenaReasoningService) service, inputModel, null,
- // targetGraphID);
- // } else if (service instanceof OWLApiReasoningService) {
- // return executeOWLApiReasoningService((OWLApiReasoningService) service, input, null, targetGraphID);
- // } else {
- // throw new WebApplicationException(new Exception("Unsupported implementation"),
- // Response.Status.INTERNAL_SERVER_ERROR);
- // }
- //
- // }
-
- // @GET
- // @Path("/ontonet/scope")
- // @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE, "text/turtle", "text/n3"})
- // public Response getOntonetScope(@QueryParam("scope") String scopeID,
- // @QueryParam("recipe") String recipeID,
- // @QueryParam("target") String targetGraph) {
- // // If session is null, describe the service
- // // If target is null, then get back results, elsewhere put it in target graph
- // return null;
- // }
- /**
- *
- * @return
- */
- private Map<String,List<String>> prepareParameters() {
- Map<String,List<String>> parameters = new HashMap<String,List<String>>();
-
- log.info("Preparing parameters...");
- HttpRequestContext request = this.httpContext.getRequest();
- // Parameters for a GET request
- MultivaluedMap<String,String> queryParameters = request.getQueryParameters();
- log.info("... {} query parameters found", queryParameters.size());
- for (Entry<String,List<String>> e : queryParameters.entrySet()) {
- parameters.put(e.getKey(), e.getValue());
- }
- // Parameters for a POST request with content-type application/x-www-form-urlencoded
- MultivaluedMap<String,String> formParameters = request.getFormParameters();
- log.info("... {} form urlencoded parameters found", formParameters.size());
- for (Entry<String,List<String>> e : formParameters.entrySet()) {
- parameters.put(e.getKey(), e.getValue());
- }
- log.info("Paramters prepared");
- return parameters;
- }
-
- /**
- * This is an alias of the get method.
- *
- * @param url
- * @param targetGraphID
- * @return
- */
- @POST
- @Consumes({APPLICATION_FORM_URLENCODED})
- @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE, "text/turtle", "text/n3"})
- public Response post(@FormParam("url") String url,
- @FormParam("scope") String scope,
- @FormParam("session") String session,
- @FormParam("recipe") String recipe,
- @FormParam("target") String targetGraphID) {
- return get(url, scope, session, recipe, targetGraphID);
- }
-
- /**
- * Get the inferences from input URL. If url param is null, get the HTML description of this service/task
- *
- * @param url
- * @return
- */
- @GET
- @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE, "text/turtle", "text/n3"})
- public Response get(@QueryParam("url") String url,
- @QueryParam("scope") String scope,
- @QueryParam("session") String session,
- @QueryParam("recipe") String recipe,
- @QueryParam("target") String targetGraphID) {
- // If all parameters are missing we produce the service/task welcome page
- if (this.parameters.isEmpty()) {
- return Response.ok(new Viewable("index", this)).build();
- }
- if (url != null) {
- // We remove it form the additional parameter list
- this.parameters.remove("url");
- }
- // We remove also target
- this.parameters.remove("target");
- log.info("Called GET with input url: {} and target {}", url, targetGraphID);
-
- // The service executor
- ReasoningServiceExecutor executor = new ReasoningServiceExecutor(tcManager, headers, servletContext,
- uriInfo);
-
- /**
- * Select the service implementation
- */
- if (getCurrentService() instanceof JenaReasoningService) {
- // Prepare input data
- Model input = prepareJenaInputFromGET(url, scope, session);
- // Prepare rules
- List<Rule> rules = prepareJenaRules(recipe);
- return executor.executeJenaReasoningService(getCurrentTask(),
- (JenaReasoningService) getCurrentService(), input, rules, targetGraphID, false,
- this.parameters);
- } else if (getCurrentService() instanceof OWLApiReasoningService) {
- OWLOntology input = null;
- try {
- input = prepareOWLApiInputFromGET(url, scope, session);
- } catch (OWLOntologyCreationIOException e) {
- throw new WebApplicationException(e, Response.Status.NOT_FOUND);
- } catch (OWLOntologyCreationException e) {
- throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
- }
- return executor.executeOWLApiReasoningService(getCurrentTask(),
- (OWLApiReasoningService) getCurrentService(), input, null, targetGraphID, this.parameters);
- }
- throw new WebApplicationException(new Exception("Unsupported implementation"),
- Response.Status.INTERNAL_SERVER_ERROR);
- }
-
- /**
- * To catch additional parameters in case of a POST with content-type multipart/form-data, we need to
- * acces the {@link FormDataMultiPart} representation of the input.
- *
- * @param data
- * @return
- */
- @POST
- @Consumes({MULTIPART_FORM_DATA})
- @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE, "text/turtle", "text/n3"})
- public Response post(FormDataMultiPart data) {
- File file = null;
- String scope = null;
- String session = null;
- String recipe = null;
- String targetGraphID = null;
- for (BodyPart bpart : data.getBodyParts()) {
- log.info("is a {}", bpart.getClass());
- if (bpart instanceof FormDataBodyPart) {
- FormDataBodyPart dbp = (FormDataBodyPart) bpart;
- if (dbp.getName().equals("target")) {
- targetGraphID = dbp.getValue();
- } else if (dbp.getName().equals("file")) {
- file = bpart.getEntityAs(File.class);
- } else if (dbp.getName().equals("scope")) {
- scope = ((FormDataBodyPart) bpart).getValue();
- } else if (dbp.getName().equals("session")) {
- session = ((FormDataBodyPart) bpart).getValue();
- } else if (dbp.getName().equals("recipe")) {
- recipe = ((FormDataBodyPart) bpart).getValue();
- } else {
- // We put all the rest in the parameters field
- // XXX We supports here only simple fields
- // We do NOT support the sent of additional files, for example
- if (dbp.isSimple()) {
- if (this.parameters.containsKey(dbp.getName())) {
- this.parameters.get(dbp.getName()).add(dbp.getValue());
- } else {
- List<String> values = new ArrayList<String>();
- values.add(dbp.getValue());
- this.parameters.put(dbp.getName(), values);
- }
- }
- }
- }
- }
- return postData(file, scope, session, recipe, targetGraphID);
- }
-
- /**
- * Generate inferences from the input file. Output comes back to the client.
- *
- * @param file
- * @return
- */
- private Response postData(File file, String scope, String session, String recipe, String targetGraphID) {
- log.info("Called POST with input file: {} and target: {}", file, targetGraphID);
- if (file.exists() && file.canRead()) {
- // The service executor
- ReasoningServiceExecutor executor = new ReasoningServiceExecutor(tcManager, headers, servletContext,
- uriInfo);
-
- // Select the service implementation
- if (getCurrentService() instanceof JenaReasoningService) {
- // Prepare input data
- Model input;
- try {
- input = prepareJenaInputFromPOST(file, scope, session);
- } catch (MalformedURLException e) {
- throw new WebApplicationException(new IllegalArgumentException("Cannot read file"),
- Response.Status.INTERNAL_SERVER_ERROR);
- }
- // Prepare rules
- List<Rule> rules = prepareJenaRules(recipe);
- return executor.executeJenaReasoningService(getCurrentTask(),
- (JenaReasoningService) getCurrentService(), input, rules, targetGraphID, false,
- this.parameters);
- } else if (getCurrentService() instanceof OWLApiReasoningService) {
- OWLOntology input = null;
- try {
- input = prepareOWLApiInputFromPOST(file, scope, session);
- } catch (OWLOntologyCreationIOException e) {
- throw new WebApplicationException(e, Response.Status.NOT_FOUND);
- } catch (OWLOntologyCreationException e) {
- throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
- }
- // Prepare rules
- List<SWRLRule> rules = prepareOWLApiRules(recipe);
- return executor.executeOWLApiReasoningService(getCurrentTask(),
- (OWLApiReasoningService) getCurrentService(), input, rules, targetGraphID,
- this.parameters);
- }
- throw new WebApplicationException(new Exception("Unsupported implementation"),
- Response.Status.INTERNAL_SERVER_ERROR);
- } else {
- log.error("Cannot read file: {}", file);
- throw new WebApplicationException(new IllegalArgumentException("Cannot read file"),
- Response.Status.INTERNAL_SERVER_ERROR);
- }
- }
-
- private OWLOntologyManager createOWLOntologyManager() {
- // We isolate here the creation of the temporary manager
- // TODO How to behave when resolving owl:imports?
- // We should set the manager to use a service to lookup for ontologies, instead of trying on the web
- // directly
- OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
- // FIXME Which is the other way of doing this?
- manager.setSilentMissingImportsHandling(true);
- // Listening for missing imports
- manager.addMissingImportListener(new MissingImportListener() {
- @Override
- public void importMissing(MissingImportEvent arg0) {
- log.warn("Missing import: {}", arg0.getImportedOntologyURI());
- }
- });
- return manager;
- }
-
- /**
- * The actual path, to be used in the template.
- *
- * @return
- */
- public String getCurrentPath() {
- return uriInfo.getPath().replaceAll("[\\/]*$", "");
- }
-
- /**
- * The selected service
- *
- * @return
- */
- public ReasoningService<?,?,?> getCurrentService() {
- return this.service;
- }
-
- /**
- * The selected task
- *
- * @return
- */
- public String getCurrentTask() {
- return this.taskID;
- }
-
- /**
- * The list of supported tasks. We include CHECK, which is managed directly by the endpoint.
- */
- public List<String> getSupportedTasks() {
- List<String> supported = new ArrayList<String>();
- supported.add(ReasoningServiceExecutor.TASK_CHECK);
- supported.addAll(getCurrentService().getSupportedTasks());
- return supported;
- }
-
- /**
- * To retrieve the service using the service manager
- *
- * @param servicePath
- * @return
- * @throws UnboundReasoningServiceException
- */
- private ReasoningService<?,?,?> getService(String servicePath) throws UnboundReasoningServiceException {
- return getServicesManager().get(servicePath);
- }
-
- /**
- * Get the service manager from the context
- *
- * @return
- */
- private ReasoningServicesManager getServicesManager() {
- log.debug("(getServicesManager()) ");
- return (ReasoningServicesManager) ContextHelper.getServiceFromContext(ReasoningServicesManager.class,
- this.context);
- }
-
- /**
- * Gets the list of active services
- *
- * @return
- */
- public Set<ReasoningService<?,?,?>> getActiveServices() {
- log.debug("(getActiveServices()) There are {} reasoning services", getServicesManager().size());
- return getServicesManager().asUnmodifiableSet();
- }
-
- private Model prepareJenaInputFromGET(String url, String scope, String session) {
- Model input = ModelFactory.createDefaultModel();
- // TODO
- // If session exists, get the ontology and load it in a Jena model
- // If scope exists, get the ontology and load it in a Jena model
- if (session != null || scope != null) {
- log.error("prepareJenaInputFromGET(String url, String scope, String session) Not implemented yet!");
- throw new WebApplicationException(501);
- }
-
- // If url exists, merge the location within the model
- if (url != null) {
- input.read(url);
- }
-
- return input;
- }
-
- private Model prepareJenaInputFromPOST(File file, String scope, String session) throws MalformedURLException {
- Model input = ModelFactory.createDefaultModel();
- // TODO
- // If session exists, get the ontology and load it in a Jena model
- // If scope exists, get the ontology and load it in a Jena model
- if (scope != null || session != null) {
- log.error("prepareJenaInputForPOST(File file, String scope, String session) Not implemented yet!");
- throw new WebApplicationException(501);
- }
- // If file exists, merge the location within the model
- if (file != null) {
- input.read(file.toURI().toURL().toString());
- }
- return input;
- }
-
- private OWLOntology prepareOWLApiInputFromGET(String url, String scope, String session) throws OWLOntologyCreationException {
- OWLOntologyManager m = createOWLOntologyManager();
- // TODO
- // If session exists, load it
- // If scope exists, load it
- if (scope != null || session != null) {
- log.error("prepareOWLApiInputFromGET(String url, String scope, String session) Not implemented yet!");
- throw new WebApplicationException(501);
- }
- // If url exists, load it as triples, then include an import statement to the session/scope, then load
- // it in the manager (TODO)
- return m.loadOntologyFromOntologyDocument(IRI.create(url));
- }
-
- private OWLOntology prepareOWLApiInputFromPOST(File file, String scope, String session) throws OWLOntologyCreationException {
- OWLOntologyManager m = createOWLOntologyManager();
- // TODO
- // If session exists, load it
- // If scope exists, load it
- if (scope != null || session != null) {
- log.error("prepareOWLApiInputFromPOST(File file, String scope, String session) Not implemented yet!");
- throw new WebApplicationException(501);
- }
- // If url exists, load it as triples, then include an import statement to the session/scope, then load
- // it in the manager
- // FIXME
- return m.loadOntologyFromOntologyDocument(file);
- }
-
- private List<Rule> prepareJenaRules(String recipe) {
- if (recipe != null) {
- // If recipe exists, parse it as a list of Jena rules
- // TODO This cannot be implemented since Jena rules format is not yet supported by the Rules
- // module!!!
- log.error("prepareJenaRules(String recipe) Not implemented yet!");
- throw new WebApplicationException(501);
- }
- return null;
- }
-
- private List<SWRLRule> prepareOWLApiRules(String recipe) {
- if (recipe != null) {
- // If recipe exists, return it as a list of SWRL rules
- log.error("prepareOWLApiRules(String recipe) Not implemented yet!");
- throw new WebApplicationException(501);
- }
- return null;
- }
+ private Logger log = LoggerFactory.getLogger(getClass());
+ private ServletContext context;
+ private ReasoningService<?, ?, ?> service;
+ private String taskID;
+ private HttpContext httpContext;
+ private Map<String, List<String>> parameters;
+ private TcManager tcManager;
+ private HttpHeaders headers;
+ private ONManager onm;
+ private Serializer serializer;
+
+ public ReasoningServiceTaskResource(
+ @PathParam(value = "service") String serviceID,
+ @PathParam(value = "task") String taskID,
+ @Context ServletContext servletContext,
+ @Context HttpHeaders headers, @Context HttpContext httpContext) {
+ super();
+ log.info("Called service {} to perform task {}", serviceID, taskID);
+
+ // ServletContext
+ this.context = servletContext;
+
+ // HttpContext
+ this.httpContext = httpContext;
+
+ // HttpHeaders
+ this.headers = headers;
+
+ // Parameters for customized reasoning services
+ this.parameters = prepareParameters();
+
+ // Clerezza storage
+ this.tcManager = (TcManager) ContextHelper.getServiceFromContext(
+ TcManager.class, servletContext);
+
+ // Retrieve the ontology network manager
+ this.onm = (ONManager) ContextHelper.getServiceFromContext(
+ ONManager.class, servletContext);
+
+ // Retrieve the clerezza serializer
+ this.serializer = (Serializer) ContextHelper.getServiceFromContext(
+ Serializer.class, servletContext);
+
+ // Retrieve the service
+ try {
+ service = getService(serviceID);
+ } catch (UnboundReasoningServiceException e) {
+ log.error("Service not found: {}", serviceID);
+ throw new WebApplicationException(e, Response.Status.NOT_FOUND);
+ }
+ log.info("Service retrieved");
+ // Check if the task is allowed
+ if (this.service.supportsTask(taskID)
+ || taskID.equals(ReasoningServiceExecutor.TASK_CHECK)) {
+ this.taskID = taskID;
+ } else {
+ log.error("Unsupported task (not found): {}", taskID);
+ throw new WebApplicationException(new Exception(
+ "Unsupported task (not found): " + taskID),
+ Response.Status.BAD_REQUEST);
+ }
+ log.info("Task is OK");
+ // Now we check if the service implementation is supported
+ if (getCurrentService() instanceof JenaReasoningService) {
+ } else if (getCurrentService() instanceof OWLApiReasoningService) {
+ } else {
+ log.error(
+ "This implementation of ReasoningService is not supported: {}",
+ getCurrentService().getClass());
+ throw new WebApplicationException(new Exception(
+ "This implementation of ReasoningService is not supported: "
+ + getCurrentService().getClass()),
+ Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ log.info("Implementation is supported");
+
+ }
+
+ // @GET
+ // @Path("/ontonet/session")
+ // @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE,
+ // "text/turtle", "text/n3"})
+ // public Response getOntonetSession(@QueryParam("session") String
+ // sessionID,
+ // @QueryParam("target") String targetGraphID) {
+ // log.info("Called /ontonet/session with session={} and target={}",
+ // sessionID, targetGraphID);
+ // // If session is null, describe the service
+ // if (sessionID == null) {
+ // return Response.ok(new Viewable("ontonet-session", this)).build();
+ // }
+ // // Get the session
+ // log.info("Session requested is {}", sessionID);
+ // Set<OntologyScope> scopes =
+ // this.onManager.getScopeRegistry().getRegisteredScopes();
+ // log.info("Registered scopes are {}", scopes.size());
+ // OntologyScope scope = null;
+ // SessionOntologySpace sspace = null;
+ // for (OntologyScope sc : scopes) {
+ // log.info("Lookup for session space in scope {}", sc);
+ // if (sc == null) {
+ // log.warn("A Scope is null! Why it's in the registry!?");
+ // continue;
+ // } else {
+ // sspace = sc.getSessionSpace(IRI.create(sessionID));
+ // if (sspace != null) {
+ // scope = sc;
+ // break;
+ // }
+ // }
+ // }
+ // log.info("Found scope: {}", scope);
+ // log.info("Found session space: {}", sspace);
+ //
+ // // If session cannot be retrieved, return 404
+ // if (sspace == null) {
+ // log.error("Session space does not exists!: {}", sessionID);
+ // throw new WebApplicationException(new
+ // IllegalArgumentException("Session does not exists!"),
+ // Response.Status.NOT_FOUND);
+ // }
+ //
+ // // Get the session as OWLOntology
+ // OWLOntology input = sspace.asOWLOntology();
+ // log.info("Session ontology is: {}", input);
+ //
+ // // Now we select the service type
+ // if (service instanceof JenaReasoningService) {
+ // Model inputModel = new JenaToOwlConvert().ModelOwlToJenaConvert(input,
+ // "TURTLE");
+ // return executeJenaReasoningService((JenaReasoningService) service,
+ // inputModel, null,
+ // targetGraphID);
+ // } else if (service instanceof OWLApiReasoningService) {
+ // return executeOWLApiReasoningService((OWLApiReasoningService) service,
+ // input, null, targetGraphID);
+ // } else {
+ // throw new WebApplicationException(new
+ // Exception("Unsupported implementation"),
+ // Response.Status.INTERNAL_SERVER_ERROR);
+ // }
+ //
+ // }
+
+ // @GET
+ // @Path("/ontonet/scope")
+ // @Produces({TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE,
+ // "text/turtle", "text/n3"})
+ // public Response getOntonetScope(@QueryParam("scope") String scopeID,
+ // @QueryParam("recipe") String recipeID,
+ // @QueryParam("target") String targetGraph) {
+ // // If session is null, describe the service
+ // // If target is null, then get back results, elsewhere put it in target
+ // graph
+ // return null;
+ // }
+ /**
+ *
+ * @return
+ */
+ private Map<String, List<String>> prepareParameters() {
+ Map<String, List<String>> parameters = new HashMap<String, List<String>>();
+
+ log.info("Preparing parameters...");
+ HttpRequestContext request = this.httpContext.getRequest();
+ // Parameters for a GET request
+ MultivaluedMap<String, String> queryParameters = request
+ .getQueryParameters();
+ log.info("... {} query parameters found", queryParameters.size());
+ for (Entry<String, List<String>> e : queryParameters.entrySet()) {
+ parameters.put(e.getKey(), e.getValue());
+ }
+ // Parameters for a POST request with content-type
+ // application/x-www-form-urlencoded
+ MultivaluedMap<String, String> formParameters = request
+ .getFormParameters();
+ log.info("... {} form urlencoded parameters found",
+ formParameters.size());
+ for (Entry<String, List<String>> e : formParameters.entrySet()) {
+ parameters.put(e.getKey(), e.getValue());
+ }
+ log.info("Paramters prepared");
+ return parameters;
+ }
+
+ /**
+ * This is an alias of the get method.
+ *
+ * @param url
+ * @param targetGraphID
+ * @return
+ */
+ @POST
+ @Consumes({ APPLICATION_FORM_URLENCODED })
+ @Produces({ TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE,
+ "text/turtle", "text/n3" })
+ public Response post(@FormParam("url") String url,
+ @FormParam("scope") String scope,
+ @FormParam("session") String session,
+ @FormParam("recipe") String recipe,
+ @FormParam("target") String targetGraphID) {
+ return get(url, scope, session, recipe, targetGraphID);
+ }
+
+ /**
+ * Get the inferences from input URL. If url param is null, get the HTML
+ * description of this service/task
+ *
+ * @param url
+ * @return
+ */
+ @GET
+ @Produces({ TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE,
+ "text/turtle", "text/n3" })
+ public Response get(@QueryParam("url") String url,
+ @QueryParam("scope") String scope,
+ @QueryParam("session") String session,
+ @QueryParam("recipe") String recipe,
+ @QueryParam("target") String targetGraphID) {
+ // If all parameters are missing we produce the service/task welcome
+ // page
+ if (this.parameters.isEmpty()) {
+ return Response.ok(new Viewable("index", this)).build();
+ }
+ if (url != null) {
+ // We remove it form the additional parameter list
+ this.parameters.remove("url");
+ }
+ // We remove also target
+ this.parameters.remove("target");
+ log.info("Called GET with input url: {} and target {}", url,
+ targetGraphID);
+
+ // The service executor
+ ReasoningServiceExecutor executor = new ReasoningServiceExecutor(
+ tcManager, headers, servletContext, uriInfo);
+
+ /**
+ * Select the service implementation
+ */
+ if (getCurrentService() instanceof JenaReasoningService) {
+ // Prepare input data
+ Model input;
+ try {
+ input = prepareJenaInputFromGET(url, scope, session);
+ } catch (DoesNotExistException e) {
+ throw new WebApplicationException(e, Response.Status.NOT_FOUND);
+ }
+ // Prepare rules
+ List<Rule> rules = prepareJenaRules(recipe);
+ return executor.executeJenaReasoningService(getCurrentTask(),
+ (JenaReasoningService) getCurrentService(), input, rules,
+ targetGraphID, false, this.parameters);
+ } else if (getCurrentService() instanceof OWLApiReasoningService) {
+ OWLOntology input = null;
+ try {
+ input = prepareOWLApiInputFromGET(url, scope, session);
+ } catch (OWLOntologyCreationIOException e) {
+ throw new WebApplicationException(e, Response.Status.NOT_FOUND);
+ } catch (OWLOntologyCreationException e) {
+ throw new WebApplicationException(e,
+ Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ return executor.executeOWLApiReasoningService(getCurrentTask(),
+ (OWLApiReasoningService) getCurrentService(), input, null,
+ targetGraphID, this.parameters);
+ }
+ throw new WebApplicationException(new Exception(
+ "Unsupported implementation"),
+ Response.Status.INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * To catch additional parameters in case of a POST with content-type
+ * multipart/form-data, we need to acces the {@link FormDataMultiPart}
+ * representation of the input.
+ *
+ * @param data
+ * @return
+ */
+ @POST
+ @Consumes({ MULTIPART_FORM_DATA })
+ @Produces({ TEXT_HTML, "text/plain", KRFormat.RDF_XML, KRFormat.TURTLE,
+ "text/turtle", "text/n3" })
+ public Response post(FormDataMultiPart data) {
+ File file = null;
+ String scope = null;
+ String session = null;
+ String recipe = null;
+ String targetGraphID = null;
+ for (BodyPart bpart : data.getBodyParts()) {
+ log.info("is a {}", bpart.getClass());
+ if (bpart instanceof FormDataBodyPart) {
+ FormDataBodyPart dbp = (FormDataBodyPart) bpart;
+ if (dbp.getName().equals("target")) {
+ targetGraphID = dbp.getValue();
+ } else if (dbp.getName().equals("file")) {
+ file = bpart.getEntityAs(File.class);
+ } else if (dbp.getName().equals("scope")) {
+ scope = ((FormDataBodyPart) bpart).getValue();
+ } else if (dbp.getName().equals("session")) {
+ session = ((FormDataBodyPart) bpart).getValue();
+ } else if (dbp.getName().equals("recipe")) {
+ recipe = ((FormDataBodyPart) bpart).getValue();
+ } else {
+ // We put all the rest in the parameters field
+ // XXX We supports here only simple fields
+ // We do NOT support the sent of additional files, for
+ // example
+ if (dbp.isSimple()) {
+ if (this.parameters.containsKey(dbp.getName())) {
+ this.parameters.get(dbp.getName()).add(
+ dbp.getValue());
+ } else {
+ List<String> values = new ArrayList<String>();
+ values.add(dbp.getValue());
+ this.parameters.put(dbp.getName(), values);
+ }
+ }
+ }
+ }
+ }
+ return postData(file, scope, session, recipe, targetGraphID);
+ }
+
+ /**
+ * Generate inferences from the input file. Output comes back to the client.
+ *
+ * @param file
+ * @return
+ */
+ private Response postData(File file, String scope, String session,
+ String recipe, String targetGraphID) {
+ log.info("Called POST with input file: {} and target: {}", file,
+ targetGraphID);
+ if (file.exists() && file.canRead()) {
+ // The service executor
+ ReasoningServiceExecutor executor = new ReasoningServiceExecutor(
+ tcManager, headers, servletContext, uriInfo);
+
+ // Select the service implementation
+ if (getCurrentService() instanceof JenaReasoningService) {
+ // Prepare input data
+ Model input;
+ try {
+ input = prepareJenaInputFromPOST(file, scope, session);
+ } catch (MalformedURLException e) {
+ throw new WebApplicationException(
+ new IllegalArgumentException("Cannot read file"),
+ Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ // Prepare rules
+ List<Rule> rules = prepareJenaRules(recipe);
+ return executor.executeJenaReasoningService(getCurrentTask(),
+ (JenaReasoningService) getCurrentService(), input,
+ rules, targetGraphID, false, this.parameters);
+ } else if (getCurrentService() instanceof OWLApiReasoningService) {
+ OWLOntology input = null;
+ try {
+ input = prepareOWLApiInputFromPOST(file, scope, session);
+ } catch (OWLOntologyCreationIOException e) {
+ throw new WebApplicationException(e,
+ Response.Status.NOT_FOUND);
+ } catch (OWLOntologyCreationException e) {
+ throw new WebApplicationException(e,
+ Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ // Prepare rules
+ List<SWRLRule> rules = prepareOWLApiRules(recipe);
+ return executor.executeOWLApiReasoningService(getCurrentTask(),
+ (OWLApiReasoningService) getCurrentService(), input,
+ rules, targetGraphID, this.parameters);
+ }
+ throw new WebApplicationException(new Exception(
+ "Unsupported implementation"),
+ Response.Status.INTERNAL_SERVER_ERROR);
+ } else {
+ log.error("Cannot read file: {}", file);
+ throw new WebApplicationException(new IllegalArgumentException(
+ "Cannot read file"), Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ private OWLOntologyManager createOWLOntologyManager() {
+ // We isolate here the creation of the temporary manager
+ // TODO How to behave when resolving owl:imports?
+ // We should set the manager to use a service to lookup for ontologies,
+ // instead of trying on the web
+ // directly
+ OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
+ // FIXME Which is the other way of doing this?
+ manager.setSilentMissingImportsHandling(true);
+ // Listening for missing imports
+ manager.addMissingImportListener(new MissingImportListener() {
+ @Override
+ public void importMissing(MissingImportEvent arg0) {
+ log.warn("Missing import {} ", arg0.getImportedOntologyURI());
+ }
+ });
+ return manager;
+ }
+
+ /**
+ * The actual path, to be used in the template.
+ *
+ * @return
+ */
+ public String getCurrentPath() {
+ return uriInfo.getPath().replaceAll("[\\/]*$", "");
+ }
+
+ /**
+ * The selected service
+ *
+ * @return
+ */
+ public ReasoningService<?, ?, ?> getCurrentService() {
+ return this.service;
+ }
+
+ /**
+ * The selected task
+ *
+ * @return
+ */
+ public String getCurrentTask() {
+ return this.taskID;
+ }
+
+ /**
+ * The list of supported tasks. We include CHECK, which is managed directly
+ * by the endpoint.
+ */
+ public List<String> getSupportedTasks() {
+ List<String> supported = new ArrayList<String>();
+ supported.add(ReasoningServiceExecutor.TASK_CHECK);
+ supported.addAll(getCurrentService().getSupportedTasks());
+ return supported;
+ }
+
+ /**
+ * To retrieve the service using the service manager
+ *
+ * @param servicePath
+ * @return
+ * @throws UnboundReasoningServiceException
+ */
+ private ReasoningService<?, ?, ?> getService(String servicePath)
+ throws UnboundReasoningServiceException {
+ return getServicesManager().get(servicePath);
+ }
+
+ /**
+ * Get the service manager from the context
+ *
+ * @return
+ */
+ private ReasoningServicesManager getServicesManager() {
+ log.debug("(getServicesManager()) ");
+ return (ReasoningServicesManager) ContextHelper.getServiceFromContext(
+ ReasoningServicesManager.class, this.context);
+ }
+
+ private Object getFromOntonet(String scopeID, String sessionID,
+ Class<?> type) {
+
+ /**
+ * FIXME The code below does not work, even if it should, or the API is
+ * not clear at all...
+ *
+ *
+ * Set<SessionOntologySpace> spaces = onm.getSessionManager()
+ * .getSessionSpaces(sessionIRI);
+ *
+ * There MUST be 1 single session which such ID. Why this method? What
+ * happens if there are more then 1 space? Probably it is not possible,
+ * but why this method returns a set? In addition, the method returns
+ * **all** sessions (?!).
+ *
+ * The code below seems do not work properly (maybe I misunderstood
+ * something) also:
+ *
+ * try {
+ *
+ *
+ * if (!spaces.isEmpty()) {
+ *
+ * log.info("found {} session spaces", spaces.size());
+ *
+ * for (SessionOntologySpace s : spaces)
+ *
+ * log.info(" - {}", s.asOWLOntology());
+ *
+ * All empty ontologies! (and not only the one identified by the session
+ * ID, there are other sessions within, this is puzzling...)
+ *
+ * Then, even if we get the first possible, at the moment ...
+ *
+ * SessionOntologySpace session = spaces.iterator().next();
+ * log.info("Found session: {}", session);
+ *
+ * OWLOntology sessionOntology = session.asOWLOntology();
+ *
+ *
+ * // WHAT I EXPECTED? I expect here to have the ontology network of the
+ * session, in this fashion:
+ *
+ * - The SESSION space ontology, which includes (owl:imports):
+ *
+ * 1) 0...n ontologies, loaded after session creation; they owl:imports
+ * the CUSTOM ontology
+ *
+ * 2) The CUSTOM space ontology, which includes (owl:imports):
+ *
+ * - 0...n ontologies, loaded after scope creation, they owl:imports the
+ * CORE
+ *
+ * - The CORE space ontology, which includes (owl:imports):
+ *
+ * - 0...n ontologies loaded on scope creation
+ *
+ *
+ * Instead, I have an empty ontology :(
+ *
+ * int importsSize = sessionOntology.getImports().size();
+ *
+ * log.info("Session ontology: {}", sessionOntology); // No axioms
+ * log.info("Imports {} ontologies", importsSize); // No imports
+ *
+ * for (OWLOntology i : sessionOntology.getImports()) {
+ * log.info(" - {}", i);
+ *
+ * }
+ *
+ * return sessionOntology;
+ *
+ * } else {
+ *
+ * log.error( "The session {} does not exists or have been deleted",
+ * sessionID);
+ *
+ * throw new IllegalArgumentException("Session does not exists!");
+ *
+ * }
+ *
+ * } catch (NonReferenceableSessionException e) {
+ * log.error("The session {} does not exists or have been deleted",
+ * sessionID);
+ *
+ * throw new IllegalArgumentException("Session does not exists!", e);
+ *
+ * }
+ */
+
+ /**
+ * FIXME! Another problem with the OntoNet API: Sessions are retrieved
+ * from ANY scope, in other words if we have a session we cannot know
+ * which is the scope bound. Maybe because you can use data in a session
+ * with any other scope? If yes, why this method? Why I can access
+ * sessions from a scope?
+ *
+ * IRI sessionIRI = IRI.create(sessionID);
+ *
+ * ScopeRegistry registry = onm.getScopeRegistry();
+ *
+ * Set<OntologyScope> scopes = registry.getActiveScopes();
+ *
+ *
+ * OntologyScope scope = null;
+ *
+ * SessionOntologySpace sessionSpace = null;
+ *
+ * for (OntologyScope s : scopes) {
+ *
+ * sessionSpace = s.getSessionSpace(sessionIRI);
+ *
+ * if (sessionSpace != null) {
+ *
+ * log.info("Found session on scope {}", s.getID());
+ *
+ * scope = s;
+ *
+ * }
+ *
+ * }
+ */
+
+ /**
+ * FIXME! THIS SHOULD BE DONE BY ONTONET! We pack the ontology network
+ * on our own...
+ *
+ */
+ try {
+ // We must know both scope and session
+ IRI scopeIRI = IRI.create(scopeID);
+
+ OntologyScope scope = onm.getScopeRegistry().getScope(scopeIRI);
+ if (scope == null) {
+ log.error("Scope {} cannot be retrieved", sessionID);
+ throw new WebApplicationException(Response.Status.NOT_FOUND);
+ }
+ OntologySpace sessionSpace = null;
+ if (sessionID != null) {
+ IRI sessionIRI = IRI.create(sessionID);
+ sessionSpace = scope.getSessionSpace(sessionIRI);
+ }
+ OntologySpace coreSpace = scope.getCoreSpace();
+ Set<OWLOntology> coreOntologies = coreSpace.getOntologies(true);
+ OntologySpace customSpace = scope.getCustomSpace();
+ Set<OWLOntology> customOntologies = customSpace.getOntologies(true);
+
+ Set<OWLOntology> sessionOntologies = new HashSet<OWLOntology>();
+
+ if (sessionSpace != null) {
+ // We collect all the ontologies in session (here we use
+ // 'false')
+ // The reason is that the set contains also an ontology which is
+ // the
+ // root of the session space, with buggy owl:import
+ sessionOntologies.addAll(sessionSpace.getOntologies(false));
+ }
+
+ /**
+ * FIXME Remove this code. It is not runtime code!!!
+ *
+ * We have tried here to create a real network, anyway this is very
+ * inefficient, so we use the latter way...
+ *
+ * We keep it here for the moment as study...
+ *
+ */
+ if (false) {
+ // Prepare the CORE space
+ OWLOntologyManager m = createOWLOntologyManager();
+ OWLDataFactory f = m.getOWLDataFactory();
+ OWLOntology on_CORE = m.createOntology(IRI
+ .create("ontonet:__CORE__"));
+ List<OWLOntologyChange> addImports = new ArrayList<OWLOntologyChange>();
+ // We want to load ALL ontologies (to support transitive
+ // imports)
+ log.info("CORE space: {} [{}]", coreSpace.getID(),
+ coreOntologies.size());
+ for (OWLOntology o : coreOntologies) {
+ log.info(" loading {}", o);
+ OWLOntology oLoaded = decantOntology(o, m);
+ log.info("Loaded {}", oLoaded);
+ // We add the import if it is a direct import
+ if (coreSpace.getOntologies(false).contains(o)) {
+ // The we prepare the import statement for the CORE
+ // ontology
+ addImports.add(new AddImport(on_CORE, f
+ .getOWLImportsDeclaration(oLoaded
+ .getOntologyID().getOntologyIRI())));
+ log.info(" preparing change CORE owl:imports {}",
+ oLoaded);
+ }
+ }
+ m.applyChanges(addImports);
+ log.info("Change applied");
+
+ log.info("NETWORK::CORE :: {}", on_CORE);
+ log.info(buildImportsTree(on_CORE));
+
+ // Prepare the CUSTOM space
+ OWLOntology on_CUSTOM = m.createOntology(IRI
+ .create("ontonet:__CUSTOM__"));
+ // Reset changes
+ addImports = new ArrayList<OWLOntologyChange>();
+ log.info("CUSTOM space: {} [{}]", customSpace.getID(),
+ customOntologies.size());
+ for (OWLOntology o : customOntologies) {
+ log.info(" loading {}", o);
+
+ // We add the import if it is a direct import
+ if (customSpace.getOntologies(false).contains(o)) {
+ /**
+ * We need this conversion every time we want to change
+ * the imports declaration of an ontology which contains
+ * axioms. This because an import statement change the
+ * way an axiom is interpreted. For example, if a
+ * property is not defined as OWLObjectProperty or
+ * rdfs:Property, it will be loaded as
+ * OWLAnnotationProperty !!!
+ */
+ MGraph g = toGraph(o);
+ log.info(" adding owl:imports CORE");
+ // In the network, this ontology will import the CORE
+ g.add(new TripleImpl(new UriRef(o.getOntologyID()
+ .getOntologyIRI().toString()), new UriRef(
+ OWL.imports.getURI().toString()), new UriRef(
+ on_CORE.getOntologyID().getOntologyIRI()
+ .toString())));
+ // Load in manager
+ OWLOntology oImported = loadGraph(g, m);
+ g.clear();
+
+ // Custom imports this ontology (custom is empty, so we
+ // don't need a graph)
+ log.info(" preparing change CUSTOM owl:imports {}",
+ oImported);
+ // The we prepare the import statement for the CUSTOM
+ // ontology
+ addImports.add(new AddImport(on_CUSTOM, f
+ .getOWLImportsDeclaration(o.getOntologyID()
+ .getOntologyIRI())));
+ log.info("Loaded {}", oImported);
+ } else {
+ // We directly load it in the manager
+ OWLOntology oLoaded = decantOntology(o, m);
+ log.info("Loaded {}", oLoaded);
+ }
+ }
+ // CUSTOM imports CORE
+ addImports.add(new AddImport(on_CUSTOM, f
+ .getOWLImportsDeclaration(on_CORE.getOntologyID()
+ .getOntologyIRI())));
+ log.info(" preparing change CUSTOM owl:imports CORE");
+ m.applyChanges(addImports);
+
+ log.info("NETWORK::CUSTOM :: {}", on_CUSTOM);
+ log.info(buildImportsTree(on_CUSTOM));
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+ // Prepare the SESSION
+ OWLOntology on_SESSION = m.createOntology(IRI
+ .create("ontonet:__SESSION__"));
+ // Reset changes
+ addImports = new ArrayList<OWLOntologyChange>();
+
+ // Prepare SESSION
+ log.info("SESSION space: {} [{}]", sessionSpace.getID(),
+ sessionOntologies.size());
+
+ for (OWLOntology o : sessionOntologies) {
+ log.info(" loading {}", o);
+
+ // We add the import if it is a direct import
+ if (sessionSpace.getOntologies(false).contains(o)) {
+ log.info(" adding owl:imports CUSTOM");
+ /**
+ * We need this conversion every time we want to change
+ * the imports declaration of an ontology which contains
+ * axioms. This because an import statement change the
+ * way an axiom is interpreted. For example, if a
+ * property is not defined as OWLObjectProperty or
+ * rdfs:Property, it will be loaded as
+ * OWLAnnotationProperty !!!
+ */
+ MGraph g = toGraph(o);
+ // In the network, this ontology will import the CUSTOM
+ Triple triple = new TripleImpl(new UriRef(o
+ .getOntologyID().getOntologyIRI().toString()),
+ new UriRef(OWL.imports.getURI().toString()),
+ new UriRef(on_CUSTOM.getOntologyID()
+ .getOntologyIRI().toString()));
+ log.info(" prepared import triple: {}", triple);
+ g.add(triple);
+ // Load in manager
+ OWLOntology oLoaded = loadGraph(g, m);
+ // remove the temporary mgraph
+ g.clear();
+
+ log.info(" preparing change SESSION owl:imports {}",
+ oLoaded);
+ // The we prepare the import statement for the CUSTOM
+ // ontology
+ addImports.add(new AddImport(on_SESSION, f
+ .getOWLImportsDeclaration(o.getOntologyID()
+ .getOntologyIRI())));
+ log.info("Loaded {}", oLoaded);
+ } else {
+ // Or we directly go in the manager
+ OWLOntology oLoaded = decantOntology(o, m);
+ log.info("Loaded {}", oLoaded);
+ }
+ log.info(" loaded.");
+
+ }
+ // SESSION imports CUSTOM
+ log.info(" preparing change SESSION owl:imports CUSTOM");
+ addImports.add(new AddImport(on_SESSION, f
+ .getOWLImportsDeclaration(on_CUSTOM.getOntologyID()
+ .getOntologyIRI())));
+ for (OWLOntologyChange change : addImports)
+ log.info("CHANGE : {}", change);
+ m.applyChanges(addImports);
+
+ log.info("NETWORK::SESSION :: {}", on_SESSION);
+ log.info(buildImportsTree(on_SESSION));
+ // log.info("Check");
+ // for (OWLOntology o : on_SESSION.getImports()) {
+ // log.info("checking {}", o);
+ // for (OWLAxiom a : o.getAxioms())
+ // log.info("- {} [{}]", a, a.getAxiomType());
+ // }
+ }
+
+ /**
+ * This way is more efficient
+ */
+ final Set<OWLOntology> set = new HashSet<OWLOntology>();
+ set.addAll(coreOntologies);
+ set.addAll(customOntologies);
+ set.addAll(sessionOntologies);
+ /**
+ * Now we try another thing ...
+ */
+ OWLOntologyMerger merger = new OWLOntologyMerger(
+ new OWLOntologySetProvider() {
+ @Override
+ public Set<OWLOntology> getOntologies() {
+ return set;
+ }
+ });
+ OWLOntology merged = merger
+ .createMergedOntology(
+ createOWLOntologyManager(),
+ IRI.create("reasoners:input-"
+ + System.currentTimeMillis()));
+ Object output;
+ if (type.isAssignableFrom(Model.class)) {
+ output = new JenaToOwlConvert().ModelOwlToJenaConvert(merged,
+ "RDF/XML");
+ } else if (type.isAssignableFrom(OWLOntology.class)) {
+ OWLOntology ready = decantOntology(merged,
+ createOWLOntologyManager());
+ output = ready;
+ // log.info("Merged ontology: {}", merged);
+ // log.info("Ready ontology: {}", ready);
+ } else
+ throw new IllegalArgumentException(new Exception(
+ "Only Model.class and OWLOntology.class are allowed"));
+ return output;
+ } catch (OWLOntologyCreationException e) {
+ log.error("The network for scope/session cannot be retrieved");
+ throw new IllegalArgumentException();
+ } catch (OWLOntologyStorageException e) {
+ log.error("The network for scope/session cannot be retrieved");
+ throw new IllegalArgumentException(
+ "The network for scope/session cannot be retrieved");
+ }
+ }
+
+ private OWLOntology decantOntology(OWLOntology o, OWLOntologyManager into)
+ throws OWLOntologyStorageException, OWLOntologyCreationException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ o.getOWLOntologyManager().saveOntology(o, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ return into.loadOntologyFromOntologyDocument(bais);
+ }
+
+ /**
+ * The returned graph must be removed as soon as possible!
+ *
+ * @param o
+ * @return
+ * @throws OWLOntologyStorageException
+ */
+ private MGraph toGraph(OWLOntology o) throws OWLOntologyStorageException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ o.getOWLOntologyManager().saveOntology(o, new RDFXMLOntologyFormat(),
+ baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ final Parser parser = Parser.getInstance();
+ Graph deserializedGraph = parser.parse(bais, "application/rdf+xml");
+ // FIXME Find a better way to generate the temporary ID
+ String temporaryID = "reasoners-network-temporary-"
+ + System.currentTimeMillis();
+ MGraph temporaryGraph = tcManager.createMGraph(new UriRef(temporaryID));
+ temporaryGraph.addAll(deserializedGraph);
+ return temporaryGraph;
+ }
+
+ private OWLOntology loadGraph(MGraph g, OWLOntologyManager m)
+ throws OWLOntologyCreationException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.serialize(baos, g, SupportedFormat.RDF_XML);
+ return m.loadOntologyFromOntologyDocument(new ByteArrayInputStream(baos
+ .toByteArray()));
+ }
+
+ private StringBuilder recursiveImportsTree(OWLOntology on,
+ StringBuilder builder, int level) {
+ String ls = System.getProperty("line.separator");
+ String lvl = "--";
+ for (OWLOntology ch : on.getDirectImports()) {
+ builder.append(ls);
+ for (int x = 0; x < level; x++) {
+ builder.append(lvl);
+ }
+ builder.append("> ");
+ builder.append(ch.getOntologyID());
+ builder.append(" [imports: ");
+ builder.append(ch.getDirectImports().size());
+ builder.append("] [axioms: ");
+ builder.append(ch.getAxiomCount());
+ builder.append("] [logical axioms: ");
+ builder.append(ch.getLogicalAxiomCount());
+ builder.append("] [annotations: ");
+ builder.append(ch.getAxiomCount(AxiomType.ANNOTATION_ASSERTION));
+ builder.append("]");
+ if (ch.getDirectImports().size() > 0) {
+ builder = recursiveImportsTree(ch, builder, level + 1);
+ }
+ }
+ return builder;
+ }
+
+ private String buildImportsTree(OWLOntology o) {
+ StringBuilder b = new StringBuilder();
+ b.append(System.getProperty("line.separator"));
+ b.append(o);
+ return recursiveImportsTree(o, b, 1).toString();
+ }
+
+ /**
+ * Gets the list of active services
+ *
+ * @return
+ */
+ public Set<ReasoningService<?, ?, ?>> getActiveServices() {
+ log.debug("(getActiveServices()) There are {} reasoning services",
+ getServicesManager().size());
+ return getServicesManager().asUnmodifiableSet();
+ }
+
+ private Model prepareJenaInputFromGET(String url, String scope,
+ String session) {
+ log.info("[start] Prepare input for Jena ");
+ Model input = ModelFactory.createDefaultModel();
+ // Get the network as Jena model
+ if (scope != null) {
+ log.info("1");
+ input.add((Model) getFromOntonet(scope, session, Model.class));
+ log.info("2");
+ }
+ // If url exists, merge the location within the model
+ if (url != null) {
+ input.read(url);
+ }
+ log.info("[end] Prepared input for Jena : {}", input);
+ return input;
+ }
+
+ private Model prepareJenaInputFromPOST(File file, String scope,
+ String session) throws MalformedURLException {
+ Model input = ModelFactory.createDefaultModel();
+ // Get the network as Jena model
+ if (scope != null) {
+ input.add((Model) getFromOntonet(scope, session, Model.class));
+ }
+ // If file exists, merge the location within the model
+ if (file != null) {
+ input.read(file.toURI().toURL().toString());
+ }
+ return input;
+ }
+
+ private OWLOntology prepareOWLApiInputFromGET(String url, String scope,
+ String session) throws OWLOntologyCreationException {
+ OWLOntologyManager m = createOWLOntologyManager();
+ // TODO
+ // If session exists, load it
+ // If scope exists, load it
+ if (scope != null || session != null) {
+ log.error("prepareOWLApiInputFromGET(String url, String scope, String session) Not implemented yet!");
+ throw new WebApplicationException(501);
+ }
+ // TODO If url exists, load it as triples, then include an import
+ // statement
+ // to the session/scope, then load
+ // it in the manager (TODO)
+ return m.loadOntologyFromOntologyDocument(IRI.create(url));
+ }
+
+ private OWLOntology prepareOWLApiInputFromPOST(File file, String scope,
+ String session) throws OWLOntologyCreationException {
+ OWLOntologyManager m = createOWLOntologyManager();
+ // TODO
+ // If session exists, load it
+ // If scope exists, load it
+ if (scope != null || session != null) {
+ log.error("prepareOWLApiInputFromPOST(File file, String scope, String session) Not implemented yet!");
+ throw new WebApplicationException(501);
+ }
+ // If url exists, load it as triples, then include an import statement
+ // to the session/scope, then load
+ // it in the manager
+ // FIXME
+ return m.loadOntologyFromOntologyDocument(file);
+ }
+
+ private List<Rule> prepareJenaRules(String recipe) {
+ if (recipe != null) {
+ // If recipe exists, parse it as a list of Jena rules
+ // TODO This cannot be implemented since Jena rules format is not
+ // yet supported by the Rules
+ // module!!!
+ log.error("prepareJenaRules(String recipe) Not implemented yet!");
+ throw new WebApplicationException(501);
+ }
+ return null;
+ }
+
+ private List<SWRLRule> prepareOWLApiRules(String recipe) {
+ if (recipe != null) {
+ // If recipe exists, return it as a list of SWRL rules
+ log.error("prepareOWLApiRules(String recipe) Not implemented yet!");
+ throw new WebApplicationException(501);
+ }
+ return null;
+ }
}