-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add implementation of DIVIDE central services (version of 1 May 2022)
- Loading branch information
Showing
153 changed files
with
17,153 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>divide</artifactId> | ||
<groupId>be.ugent.idlab</groupId> | ||
<version>1.0</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>divide-api</artifactId> | ||
|
||
<repositories> | ||
<repository> | ||
<id>maven-restlet</id> | ||
<name>Public online Restlet repository</name> | ||
<url>https://maven.restlet.org</url> | ||
</repository> | ||
</repositories> | ||
|
||
<dependencies> | ||
<!-- DIVIDE engine --> | ||
<dependency> | ||
<groupId>be.ugent.idlab</groupId> | ||
<artifactId>divide-engine</artifactId> | ||
<version>1.0</version> | ||
</dependency> | ||
|
||
<!-- Java Restlet: to set up REST APIs --> | ||
<dependency> | ||
<groupId>org.restlet.jse</groupId> | ||
<artifactId>org.restlet</artifactId> | ||
<version>2.3.6</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.restlet.jee</groupId> | ||
<artifactId>org.restlet.ext.slf4j</artifactId> | ||
<version>2.2.2</version> | ||
<exclusions> | ||
<exclusion> | ||
<artifactId>slf4j-api</artifactId> | ||
<groupId>org.slf4j</groupId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
|
||
<!-- Google Gson: for JSON parsing --> | ||
<dependency> | ||
<groupId>com.google.code.gson</groupId> | ||
<artifactId>gson</artifactId> | ||
<version>2.8.5</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
65 changes: 65 additions & 0 deletions
65
...vide-central/divide-api/src/main/java/be/ugent/idlab/divide/api/DivideApiApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package be.ugent.idlab.divide.api; | ||
|
||
import be.ugent.idlab.divide.api.endpoints.component.ComponentEndpoint; | ||
import be.ugent.idlab.divide.api.endpoints.component.GeneralComponentEndpoint; | ||
import be.ugent.idlab.divide.api.endpoints.query.DivideQueryEndpoint; | ||
import be.ugent.idlab.divide.api.endpoints.query.DivideQueryRegistrationAsRspQlEndpoint; | ||
import be.ugent.idlab.divide.api.endpoints.query.DivideQueryRegistrationAsSparqlEndpoint; | ||
import be.ugent.idlab.divide.api.endpoints.query.GeneralDivideQueryEndpoint; | ||
import be.ugent.idlab.divide.core.engine.IDivideEngine; | ||
import org.restlet.Application; | ||
import org.restlet.Restlet; | ||
import org.restlet.routing.Router; | ||
import org.restlet.routing.Template; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class DivideApiApplication extends Application { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(DivideApiApplication.class.getName()); | ||
|
||
public static final String ATTR_DIVIDE_ENGINE = "divide_engine"; | ||
|
||
private final IDivideEngine divideEngine; | ||
|
||
public DivideApiApplication(IDivideEngine divideEngine) { | ||
this.divideEngine = divideEngine; | ||
} | ||
|
||
@Override | ||
public Restlet createInboundRoot() { | ||
getContext().getAttributes().put(ATTR_DIVIDE_ENGINE, divideEngine); | ||
|
||
Router router = new Router(getContext()); | ||
router.setDefaultMatchingMode(Template.MODE_EQUALS); | ||
|
||
router.attach(DivideRoutes.ENDPOINT_COMPONENT, ComponentEndpoint.class); | ||
LOGGER.info("DIVIDE API endpoint {}", DivideRoutes.ENDPOINT_COMPONENT); | ||
ComponentEndpoint.logEndpoints(LOGGER); | ||
|
||
router.attach(DivideRoutes.ENDPOINT_COMPONENT_GENERAL, GeneralComponentEndpoint.class); | ||
LOGGER.info("DIVIDE API endpoint {}", DivideRoutes.ENDPOINT_COMPONENT_GENERAL); | ||
GeneralComponentEndpoint.logEndpoints(LOGGER); | ||
|
||
router.attach(DivideRoutes.ENDPOINT_DIVIDE_QUERY, DivideQueryEndpoint.class); | ||
LOGGER.info("DIVIDE API endpoint {}", DivideRoutes.ENDPOINT_DIVIDE_QUERY); | ||
DivideQueryEndpoint.logEndpoints(LOGGER); | ||
|
||
router.attach(DivideRoutes.ENDPOINT_DIVIDE_QUERY_REGISTER_AS_SPARQL, | ||
DivideQueryRegistrationAsSparqlEndpoint.class); | ||
LOGGER.info("DIVIDE API endpoint {}", DivideRoutes.ENDPOINT_DIVIDE_QUERY_REGISTER_AS_SPARQL); | ||
DivideQueryRegistrationAsSparqlEndpoint.logEndpoints(LOGGER); | ||
|
||
router.attach(DivideRoutes.ENDPOINT_DIVIDE_QUERY_REGISTER_AS_RSP_QL, | ||
DivideQueryRegistrationAsRspQlEndpoint.class); | ||
LOGGER.info("DIVIDE API endpoint {}", DivideRoutes.ENDPOINT_DIVIDE_QUERY_REGISTER_AS_RSP_QL); | ||
DivideQueryRegistrationAsRspQlEndpoint.logEndpoints(LOGGER); | ||
|
||
router.attach(DivideRoutes.ENDPOINT_DIVIDE_QUERY_GENERAL, GeneralDivideQueryEndpoint.class); | ||
LOGGER.info("DIVIDE API endpoint {}", DivideRoutes.ENDPOINT_DIVIDE_QUERY_GENERAL); | ||
GeneralDivideQueryEndpoint.logEndpoints(LOGGER); | ||
|
||
return router; | ||
} | ||
|
||
} |
58 changes: 58 additions & 0 deletions
58
...central/divide-api/src/main/java/be/ugent/idlab/divide/api/DivideApiComponentFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package be.ugent.idlab.divide.api; | ||
|
||
import be.ugent.idlab.divide.core.engine.IDivideEngine; | ||
import org.restlet.Component; | ||
import org.restlet.data.Protocol; | ||
|
||
@SuppressWarnings("unused") | ||
public class DivideApiComponentFactory { | ||
|
||
/** | ||
* Create a Restlet {@link Component} that can be started to host an API | ||
* for the given DIVIDE engine. This DIVIDE API will be hosted via the | ||
* HTTP protocol on the given host and port, on the root path, | ||
* i.e., at http://[host]:[port]/. | ||
* | ||
* @param divideEngine DIVIDE engine that should be wrapped by the created | ||
* API component | ||
* @param host host at which the DIVIDE API should run | ||
* @param port port at which the DIVIDE API should run | ||
* @return a Restlet {@link Component} which can be started with the | ||
* {@link Component#start()} method to host the DIVIDE API | ||
*/ | ||
public static Component createRestApiComponent(IDivideEngine divideEngine, | ||
String host, | ||
int port) { | ||
return createRestApiComponent(divideEngine, host, port, ""); | ||
} | ||
|
||
/** | ||
* Create a Restlet {@link Component} that can be started to host an API | ||
* for the given DIVIDE engine. This DIVIDE API will be hosted via the | ||
* HTTP protocol on the given host and port, on the specified uri path, | ||
* i.e., at http://[host]:[port]/[uri]. | ||
* | ||
* @param divideEngine DIVIDE engine that should be wrapped by the created | ||
* API component | ||
* @param host host at which the DIVIDE API should run | ||
* @param port port at which the DIVIDE API should run | ||
* @param uri path URI string at which the DIVIDE API should run | ||
* @return a Restlet {@link Component} which can be started with the | ||
* {@link Component#start()} method to host the DIVIDE API | ||
*/ | ||
public static Component createRestApiComponent(IDivideEngine divideEngine, | ||
String host, | ||
int port, | ||
String uri) { | ||
// create Restlet component | ||
Component component = new Component(); | ||
component.getServers().add(Protocol.HTTP, host, port); | ||
|
||
// create and attach Servlet application | ||
DivideApiApplication divideApiApplication = new DivideApiApplication(divideEngine); | ||
component.getDefaultHost().attach(uri, divideApiApplication); | ||
|
||
return component; | ||
} | ||
|
||
} |
24 changes: 24 additions & 0 deletions
24
src/divide-central/divide-api/src/main/java/be/ugent/idlab/divide/api/DivideRoutes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package be.ugent.idlab.divide.api; | ||
|
||
import static be.ugent.idlab.divide.api.endpoints.CustomEndpoint.SERVER_ATTR_ID; | ||
|
||
class DivideRoutes { | ||
|
||
private static final String COMPONENT_ENTITY = "component"; | ||
private static final String QUERY_ENTITY = "query"; | ||
|
||
static final String ENDPOINT_COMPONENT_GENERAL = | ||
"/" + COMPONENT_ENTITY; | ||
static final String ENDPOINT_COMPONENT = | ||
"/" + COMPONENT_ENTITY + "/{" + SERVER_ATTR_ID + "}"; | ||
|
||
static final String ENDPOINT_DIVIDE_QUERY_GENERAL = | ||
"/" + QUERY_ENTITY; | ||
static final String ENDPOINT_DIVIDE_QUERY = | ||
"/" + QUERY_ENTITY + "/{" + SERVER_ATTR_ID + "}"; | ||
static final String ENDPOINT_DIVIDE_QUERY_REGISTER_AS_SPARQL = | ||
"/" + QUERY_ENTITY + "/sparql/{" + SERVER_ATTR_ID + "}"; | ||
static final String ENDPOINT_DIVIDE_QUERY_REGISTER_AS_RSP_QL = | ||
"/" + QUERY_ENTITY + "/rspql/{" + SERVER_ATTR_ID + "}"; | ||
|
||
} |
20 changes: 20 additions & 0 deletions
20
...-central/divide-api/src/main/java/be/ugent/idlab/divide/api/endpoints/CustomEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package be.ugent.idlab.divide.api.endpoints; | ||
|
||
import be.ugent.idlab.divide.api.DivideApiApplication; | ||
import be.ugent.idlab.divide.core.engine.IDivideEngine; | ||
import org.restlet.resource.ServerResource; | ||
|
||
public abstract class CustomEndpoint extends ServerResource { | ||
|
||
public static final String SERVER_ATTR_ID = "id"; | ||
|
||
protected IDivideEngine getDivideEngine() { | ||
return (IDivideEngine) getContext().getAttributes().get( | ||
DivideApiApplication.ATTR_DIVIDE_ENGINE); | ||
} | ||
|
||
protected String getIdAttribute() { | ||
return (String) getRequest().getAttributes().get(SERVER_ATTR_ID); | ||
} | ||
|
||
} |
139 changes: 139 additions & 0 deletions
139
...de-api/src/main/java/be/ugent/idlab/divide/api/endpoints/component/ComponentEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package be.ugent.idlab.divide.api.endpoints.component; | ||
|
||
import be.ugent.idlab.divide.api.endpoints.CustomEndpoint; | ||
import be.ugent.idlab.divide.api.representation.component.ComponentRepresentation; | ||
import be.ugent.idlab.divide.core.component.IComponent; | ||
import be.ugent.idlab.divide.core.engine.IDivideEngine; | ||
import be.ugent.idlab.divide.core.exception.DivideNotInitializedException; | ||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import org.restlet.data.MediaType; | ||
import org.restlet.data.Method; | ||
import org.restlet.data.Status; | ||
import org.restlet.representation.Representation; | ||
import org.restlet.resource.Delete; | ||
import org.restlet.resource.Get; | ||
import org.restlet.resource.Options; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
public class ComponentEndpoint extends CustomEndpoint { | ||
|
||
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); | ||
private static final Logger LOGGER = LoggerFactory.getLogger(ComponentEndpoint.class.getName()); | ||
|
||
@Options | ||
public void optionsRequestHandler() { | ||
Set<Method> allowedMethods = new HashSet<>(); | ||
allowedMethods.add(Method.GET); | ||
allowedMethods.add(Method.DELETE); | ||
getResponse().setAccessControlAllowMethods(allowedMethods); | ||
getResponse().setAccessControlAllowOrigin("*"); | ||
} | ||
|
||
public static void logEndpoints(Logger logger) { | ||
logger.info(" GET: retrieve DIVIDE component with ID {}", SERVER_ATTR_ID); | ||
logger.info(" DELETE: unregister DIVIDE component with ID {}", SERVER_ATTR_ID); | ||
} | ||
|
||
@Get | ||
public void getComponent() { | ||
getResponse().setAccessControlAllowOrigin("*"); | ||
|
||
IDivideEngine divideEngine = getDivideEngine(); | ||
|
||
try { | ||
String componentId = getIdAttribute(); | ||
|
||
IComponent component = divideEngine.getRegisteredComponentById(componentId); | ||
|
||
if (component != null) { | ||
ComponentRepresentation componentRepresentation = | ||
new ComponentRepresentation(component); | ||
|
||
String message = "Component with ID " + componentId + " successfully retrieved"; | ||
getResponse().setStatus(Status.SUCCESS_OK, message); | ||
getResponse().setEntity(GSON.toJson(componentRepresentation), | ||
MediaType.APPLICATION_JSON); | ||
|
||
} else { | ||
String message = "Component with ID '" + componentId + "' does not exist"; | ||
getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND, message); | ||
getResponse().setEntity(message, MediaType.TEXT_PLAIN); | ||
} | ||
|
||
} catch (DivideNotInitializedException e) { | ||
String message = e.getMessage(); | ||
LOGGER.error(message, e); | ||
getResponse().setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE, message); | ||
getResponse().setEntity(message, MediaType.TEXT_PLAIN); | ||
|
||
} catch (Exception e) { | ||
String logMessage = "Error while getting component data"; | ||
String eMessage = e.getMessage(); | ||
String message = logMessage + (eMessage != null ? ": " + eMessage : ""); | ||
LOGGER.error(logMessage, e); | ||
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL, message); | ||
getResponse().setEntity(message, MediaType.TEXT_PLAIN); | ||
|
||
} finally { | ||
getResponse().commit(); | ||
commit(); | ||
release(); | ||
} | ||
} | ||
|
||
@Delete | ||
public void unregisterComponent(Representation rep) { | ||
getResponse().setAccessControlAllowOrigin("*"); | ||
|
||
IDivideEngine divideEngine = getDivideEngine(); | ||
|
||
try { | ||
String componentId = getIdAttribute(); | ||
|
||
IComponent component = divideEngine.getRegisteredComponentById(componentId); | ||
|
||
if (component != null) { | ||
// retrieve url parameter which specifies whether the queries of this | ||
// component should be unregistered | ||
// (default when it is not specified = false) | ||
boolean unregisterQueries = | ||
Boolean.parseBoolean(getQueryValue("unregister")); | ||
|
||
divideEngine.unregisterComponent(componentId, unregisterQueries); | ||
|
||
String message = "Component with ID " + componentId + " successfully unregistered"; | ||
getResponse().setStatus(Status.SUCCESS_NO_CONTENT, message); | ||
|
||
} else { | ||
String message = "Component with ID '" + componentId + "' does not exist"; | ||
getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND, message); | ||
getResponse().setEntity(message, MediaType.TEXT_PLAIN); | ||
} | ||
|
||
} catch (DivideNotInitializedException e) { | ||
String message = e.getMessage(); | ||
LOGGER.error(message, e); | ||
getResponse().setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE, message); | ||
getResponse().setEntity(message, MediaType.TEXT_PLAIN); | ||
|
||
} catch (Exception e) { | ||
String logMessage = "Error while unregistering component"; | ||
String eMessage = e.getMessage(); | ||
String message = logMessage + (eMessage != null ? ": " + eMessage : ""); | ||
LOGGER.error(logMessage, e); | ||
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL, message); | ||
getResponse().setEntity(message, MediaType.TEXT_PLAIN); | ||
|
||
} finally { | ||
getResponse().commit(); | ||
commit(); | ||
release(); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.