Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ RUN mvn clean
RUN mvn dependency:go-offline

ADD src/main src/main
ADD initialisation.ttl initialisation.ttl

RUN mvn package

Expand All @@ -17,4 +18,9 @@ FROM tomcat:9.0.43-jdk11 as server
COPY --from=maven_deps /app/target/mud.war /usr/local/tomcat/webapps/mud.war
COPY --from=maven_deps /app/pom.xml /usr/local/tomcat/webapps/pom.xml

ENV initialisation_file=/home/mud/initialisation.ttl
COPY initialisation.ttl /home/mud/initialisation.ttl

EXPOSE 8080

CMD ["catalina.sh", "run"]
52 changes: 52 additions & 0 deletions initialisation.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<http://localhost:8080/mud/settlements/#south_babylon_fc_stadium>
a <https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mudbuildings.ttl#Stadium> ;
<http://www.w3.org/2006/vcard/ns#fn>
"South Babylon Football Club Stadium" ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#primaryImageContent>
<https://www.arthistoryabroad.com/wp-content/uploads/2013/08/LOWRY-Football-Match.jpg> ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#primaryTextContent>
"A towering brickwork structure of an industrial appearance" ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mudevents.ttl#hasEvent>
<http://localhost:8080/mud/settlements/#demo_football_match> .

<http://localhost:8080/mud/settlements/#demo_football_match>
a <https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mudevents.ttl#FootballMatch> ;
<http://www.w3.org/2006/time#hasBeginning>
<http://localhost:8080/mud/settlements/#demo_football_match_begins> ;
<http://www.w3.org/2006/time#hasEnd>
<http://localhost:8080/mud/settlements/#demo_football_match_ends> .

<http://localhost:8080/mud/settlements/#demo_football_match_begins>
a <http://www.w3.org/2006/time#Instant> ;
<http://www.w3.org/2006/time#inXSDDateTimeStamp>
"2021-03-28T12:43:07.056722" .

<http://localhost:8080/mud/settlements/#demo_football_match_ends>
a <http://www.w3.org/2006/time#Instant> ;
<http://www.w3.org/2006/time#inXSDDateTimeStamp>
"2021-03-28T14:43:07.058671" .

<http://localhost:8080/mud/settlements/#the_collective_night_club>
a <https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mudbuildings.ttl#Nightclub> ;
<http://www.w3.org/2006/vcard/ns#fn>
"The Collective Night Club" .

<http://localhost:8080/mud/settlements/#babylon>
a <https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#Settlement> ;
<http://www.w3.org/2006/vcard/ns#fn>
"Babylon" ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#hasBuilding>
<http://localhost:8080/mud/settlements/#south_babylon_fc_stadium> , <http://localhost:8080/mud/settlements/#the_collective_night_club> ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#population>
"8000000" ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#primaryTextContent>
"The Capital of the Babylonian Empire" .

<http://localhost:8080/mud/settlements/#roric>
a <https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#Settlement> ;
<http://www.w3.org/2006/vcard/ns#fn>
"Roric" ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#population>
"1000000" ;
<https://raw.githubusercontent.com/Multi-User-Domain/vocab/main/mud.ttl#primaryTextContent>
"The Second City of the Babylon region, but a cosmopolis in its own right, and an industrial powerhouse" .
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.8.0</version>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -125,5 +130,15 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
30 changes: 30 additions & 0 deletions src/main/java/com/mackervoy/calum/mud/Initialisation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.mackervoy.calum.mud;

import com.mackervoy.calum.mud.io.IReader;
import org.apache.jena.rdf.model.Model;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;

public class Initialisation {
private final IReader reader;

public Initialisation(IReader reader) {
this.reader = reader;
}

public void init(Model model) throws IOException {
Path initialisationFile = FileSystems.getDefault().getPath(getInitialisationFile());
String initialisationFileContents = this.reader.readFile(initialisationFile);

model.read(new ByteArrayInputStream(initialisationFileContents.getBytes()), null, "TTL");
}

private String getInitialisationFile() {
String settlementsFile = System.getenv("initialisation_file");

return settlementsFile == null ? "/home/mud/initialisation.ttl" : settlementsFile;
}
}
117 changes: 24 additions & 93 deletions src/main/java/com/mackervoy/calum/mud/MUDApplication.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
package com.mackervoy.calum.mud;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import javax.servlet.ServletException;

import org.apache.jena.assembler.JA;
import com.mackervoy.calum.mud.behaviour.task.TransitActor;
import com.mackervoy.calum.mud.content.*;
import com.mackervoy.calum.mud.io.FileReader;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.ReadWrite;
import org.apache.jena.tdb.base.file.Location;
import org.apache.jena.rdf.model.*;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.sparql.vocabulary.FOAF;
import org.apache.jena.system.Txn;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.tdb2.TDB2Factory;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.VCARD4;

import com.mackervoy.calum.mud.vocabularies.*;
import com.mackervoy.calum.mud.behaviour.task.TransitActor;
import com.mackervoy.calum.mud.content.*;
import java.io.IOException;

public class MUDApplication extends javax.ws.rs.core.Application {

Expand All @@ -36,81 +18,30 @@ public class MUDApplication extends javax.ws.rs.core.Application {

public final static String getRootDirectory() { return ROOT_DIRECTORY; }
public final static String getSiteUrl() { return SITE_URL; }

protected static void initSettlement() {
// Make a TDB-backed dataset
//TODO: extend the DatasetItem class to wrap the Jena dataset, so that the write can be completed by this class
//TODO: use a new datasetItem for the world content or continue with the global one ? Open issue
//DatasetItem demoData = TDBStore.WORLD.getNewDataset();
Dataset dataset = TDB2Factory.connectDataset(TDBStore.WORLD.getFileLocation()) ;
try {
dataset.begin(ReadWrite.WRITE) ;

if(!dataset.isEmpty()) {
dataset.abort();
return;
}

Model model = dataset.getDefaultModel() ;

// add a football stadium (South Babylon FC)
Resource stadium = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("building", "south_babylon_fc_stadium"));
model.add(stadium, RDF.type, MUDBuildings.Stadium);
model.add(stadium, VCARD4.fn, "South Babylon Football Club Stadium");
Resource image = ResourceFactory.createResource("https://www.arthistoryabroad.com/wp-content/uploads/2013/08/LOWRY-Football-Match.jpg");
model.add(stadium, MUD.primaryImageContent, image);
model.add(stadium, MUD.primaryTextContent, "A towering brickwork structure of an industrial appearance");

// there's a match at the stadium
Resource match = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("event", "demo_football_match"));
model.add(match, RDF.type, MUDEvents.FootballMatch);

Resource matchBegins = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("instant", "demo_football_match_begins"));
model.add(matchBegins, RDF.type, Time.Instant);
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
model.add(matchBegins, Time.inXSDDateTimeStamp, LocalDateTime.now().format(formatter));

Resource matchEnds = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("instant", "demo_football_match_ends"));
model.add(matchEnds, RDF.type, Time.Instant);
model.add(matchEnds, Time.inXSDDateTimeStamp, LocalDateTime.now().plusHours(2).format(formatter));
model.add(match, Time.hasBeginning, matchBegins);
model.add(match, Time.hasEnd, matchEnds);

model.add(stadium, MUDEvents.hasEvent, match);

// add a night club in Babylon
Resource collective = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("building", "the_collective_night_club"));
model.add(collective, RDF.type, MUDBuildings.Nightclub);
model.add(collective, VCARD4.fn, "The Collective Night Club");

Resource babylon = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("settlement", "babylon"));
model.add(babylon, RDF.type, MUD.Settlement);
model.add(babylon, VCARD4.fn, "Babylon");
model.add(babylon, MUD.population, "8000000");
model.add(babylon, MUD.hasBuilding, stadium);
model.add(babylon, MUD.hasBuilding, collective);
model.add(babylon, MUD.primaryTextContent, "The Capital of the Babylonian Empire");

Resource roric = ResourceFactory.createResource(TDBStore.WORLD.getNewResourceUri("settlement", "roric"));
model.add(roric, RDF.type, MUD.Settlement);
model.add(roric, VCARD4.fn, "Roric");
model.add(roric, MUD.population, "1000000");
model.add(roric, MUD.primaryTextContent, "The Second City of the Babylon region, but a cosmopolis in its own right, and an industrial powerhouse");

model.commit();
}
finally {
dataset.end();
}
}


/**
* init a TDB server storing world from configuration in Assembler
* https://jena.apache.org/documentation/tdb/java_api.html
*/
public static void initWorld() {
MUDApplication.initSettlement();

Dataset dataset = TDB2Factory.connectDataset(TDBStore.WORLD.getFileLocation());
try {
dataset.begin(ReadWrite.WRITE);

if (!dataset.isEmpty()) {
dataset.abort();
return;
}

Model model = dataset.getDefaultModel();
new Initialisation(new FileReader()).init(model);

model.commit();

dataset.end();
} catch (IOException e) {
e.printStackTrace();
}
// TODO: we want to use Assembler method
// commented out because was having 404 on the Jena vocab
// on both http://jena.hpl.hp.com/2005/11/Assembler
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/mackervoy/calum/mud/io/FileReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mackervoy.calum.mud.io;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Scanner;

public class FileReader implements IReader {
@Override
public String readFile(Path path) throws IOException {
Scanner scanner = new Scanner(path.toFile());
StringBuilder builder = new StringBuilder();
while (scanner.hasNextLine()) {
builder.append(scanner.nextLine());
}
scanner.close();

return builder.toString();
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/mackervoy/calum/mud/io/IReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mackervoy.calum.mud.io;

import java.io.IOException;
import java.nio.file.Path;

public interface IReader {
String readFile(Path path) throws IOException;
}
48 changes: 48 additions & 0 deletions src/test/java/com/mackervoy/calum/mud/TestInitalisation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.mackervoy.calum.mud;

import com.mackervoy.calum.mud.io.IReader;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class TestInitalisation {
@Test(expected = IOException.class)
public void testThrowsExceptionIfReaderThrows() throws IOException {
IReader readerMock = mock(IReader.class);
when(readerMock.readFile(any())).thenThrow(new IOException());

Initialisation initialisation = new Initialisation(readerMock);

Model model = ModelFactory.createDefaultModel();
initialisation.init(model);
}

@Test
public void testGeneratesModelIfReaderReturnsValidTurtle() throws IOException {
StringBuilder initialisationInTurtle = new StringBuilder();
File initialisationFile = new File("/home/matttennison/development/multi-user-domain/mud-jena/initialisation.ttl");
Scanner scanner = new Scanner(initialisationFile);
while(scanner.hasNextLine()) {
String data = scanner.nextLine();
initialisationInTurtle.append(data);
}
IReader readerMock = mock(IReader.class);
when(readerMock.readFile(any())).thenReturn(initialisationInTurtle.toString());

Initialisation initialisation = new Initialisation(readerMock);
Model model = ModelFactory.createDefaultModel();
initialisation.init(model);

int propertiesOnCollectiveNightClub = model.getResource("http://localhost:8080/mud/settlements/#the_collective_night_club").listProperties().toList().size();
assertEquals(2, propertiesOnCollectiveNightClub);
}
}
Loading