diff --git a/src/main/java/com/mackervoy/calum/mud/AbstractMUDController.java b/src/main/java/com/mackervoy/calum/mud/AbstractMUDController.java index e8c9e27..87d1b8b 100644 --- a/src/main/java/com/mackervoy/calum/mud/AbstractMUDController.java +++ b/src/main/java/com/mackervoy/calum/mud/AbstractMUDController.java @@ -1,11 +1,17 @@ package com.mackervoy.calum.mud; import java.io.ByteArrayOutputStream; +import java.io.StringReader; import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; public abstract class AbstractMUDController { + public Model serializeTurtleRequestToModel(String requestBody) { + return ModelFactory.createDefaultModel().read(new StringReader(requestBody), "", "TURTLE"); + } + public String serializeModelToTurtle(Model m) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); m.write(baos, "Turtle"); diff --git a/src/main/java/com/mackervoy/calum/mud/behaviour/ActionController.java b/src/main/java/com/mackervoy/calum/mud/behaviour/ActionController.java new file mode 100644 index 0000000..effb389 --- /dev/null +++ b/src/main/java/com/mackervoy/calum/mud/behaviour/ActionController.java @@ -0,0 +1,54 @@ +package com.mackervoy.calum.mud.behaviour; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.vocabulary.RDF; + +import java.util.Set; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +import com.mackervoy.calum.mud.AbstractMUDController; +import com.mackervoy.calum.mud.MUDApplication; +import com.mackervoy.calum.mud.behaviour.task.TaskActorFactory; +import com.mackervoy.calum.mud.vocabularies.MUDLogic; + +/** + * @author Calum Mackervoy + * Provides Action Discovery (https://multi-user-domain.github.io/docs/05-action-server.html) + */ + +@Path("/mud/act/discover/") +public class ActionController extends AbstractMUDController { + private String getActAtURL(Resource action) { + String base = MUDApplication.getSiteUrl() + "mud/act/"; + return action.getPropertyResourceValue(RDF.type) == MUDLogic.Task ? base + "task/" : base; + } + + // pass a URI in the query string for an object + // expect to get back the configured endpoints for actions and tasks on this object + @POST + public Response discoverActions(String requestBody) { + // TODO: analyse the objects in the request (the scene), and return those Actions which have matching shapes for them + // https://github.com/Multi-User-Domain/mud-jena/issues/44 + // final Model request = this.serializeTurtleRequestToModel(requestBody); + + Model result = ModelFactory.createDefaultModel(); + + Set keys = TaskActorFactory.keySet(); + + for(String key : keys) { + Model m = ModelFactory.createDefaultModel().read(key, "TURTLE"); + Resource r = m.getResource(key); + result.add(r, RDF.type, r.getPropertyResourceValue(RDF.type)); + result.add(r, MUDLogic.actAt, this.getActAtURL(r)); + } + + String responseData = result.isEmpty() ? null : serializeModelToTurtle(result); + return Response.ok(responseData).build(); + } + +} diff --git a/src/main/java/com/mackervoy/calum/mud/behaviour/task/TaskActorFactory.java b/src/main/java/com/mackervoy/calum/mud/behaviour/task/TaskActorFactory.java index 86c8afb..872da94 100644 --- a/src/main/java/com/mackervoy/calum/mud/behaviour/task/TaskActorFactory.java +++ b/src/main/java/com/mackervoy/calum/mud/behaviour/task/TaskActorFactory.java @@ -1,9 +1,9 @@ package com.mackervoy.calum.mud.behaviour.task; import java.lang.reflect.Constructor; -import java.util.Dictionary; import java.util.Hashtable; import java.util.Optional; +import java.util.Set; import javax.ws.rs.BadRequestException; @@ -16,7 +16,7 @@ * Resolves at runtime a TaskActor class for a requested RDF class */ public class TaskActorFactory { - private static Dictionary> taskActors = + private static Hashtable> taskActors = new Hashtable>(); /* @@ -62,4 +62,8 @@ public Optional getActorWithExistingTask(Resource task) { return Optional.empty(); } } + + public static Set keySet() { + return taskActors.keySet(); + } } diff --git a/src/main/java/com/mackervoy/calum/mud/content/ContentController.java b/src/main/java/com/mackervoy/calum/mud/content/ContentController.java index d006481..9e9b887 100644 --- a/src/main/java/com/mackervoy/calum/mud/content/ContentController.java +++ b/src/main/java/com/mackervoy/calum/mud/content/ContentController.java @@ -28,8 +28,7 @@ public class ContentController extends AbstractMUDController { //NOTE: the ContentContoller POST must receives objects with RDF type set, or it will ignore them @POST public Response post(String requestBody) { - final Model request = ModelFactory.createDefaultModel(); - request.read(new StringReader(requestBody), "", "TURTLE"); + final Model request = this.serializeTurtleRequestToModel(requestBody); //build the result model by iterating over each object in the scene and annotating a description //TODO: for now we are just describing everything, later we will want to be able to optimise what is described @@ -37,8 +36,7 @@ public Response post(String requestBody) { ResIterator resources = request.listResourcesWithProperty(RDF.type); while(resources.hasNext()) { Resource res = resources.next(); - Model m = ModelFactory.createDefaultModel(); - m.read(res.getURI()); + Model m = ModelFactory.createDefaultModel().read(res.getURI()); final Resource r = m.getResource(res.getURI()); System.out.println(r); diff --git a/src/main/java/com/mackervoy/calum/mud/vocabularies/MUDLogic.java b/src/main/java/com/mackervoy/calum/mud/vocabularies/MUDLogic.java index 002539f..8d42d57 100644 --- a/src/main/java/com/mackervoy/calum/mud/vocabularies/MUDLogic.java +++ b/src/main/java/com/mackervoy/calum/mud/vocabularies/MUDLogic.java @@ -30,6 +30,7 @@ protected static final Property property( String local ) public final static Resource Action = resource( "Action" ); public final static Resource Task = resource( "Task" ); public final static Resource Transit = resource( "Transit" ); + public final static Property actAt = property( "actAt" ); public final static Property taskImplements = property( "taskImplements" ); public final static Property isComplete = property( "isComplete" ); public final static Property endState = property( "endState" ); diff --git a/src/main/webapp/WEB-INF/mudserver.ttl b/src/main/webapp/WEB-INF/mudserver.ttl index 532ba22..f5e3ac0 100644 --- a/src/main/webapp/WEB-INF/mudserver.ttl +++ b/src/main/webapp/WEB-INF/mudserver.ttl @@ -1,3 +1,4 @@ +@prefix : <#>. @prefix mud: . @prefix mudcontent: . @prefix mudlogic: . @@ -5,4 +6,6 @@ :configuration a mud:Configuration ; mud:worldEndpoint ; mudcontent:SceneDescriptionEndpoint ; - mudcontent:SimpleObjectDescriptionEndpoint . + mudcontent:SimpleObjectDescriptionEndpoint ; + mudlogic:actionDiscoveryEndpoint ; + mudlogic:Transit .