diff --git a/inception/inception-imls-external/pom.xml b/inception/inception-imls-external/pom.xml
index 9de05bf4fd3..189304f0b84 100644
--- a/inception/inception-imls-external/pom.xml
+++ b/inception/inception-imls-external/pom.xml
@@ -104,10 +104,6 @@
com.fasterxml.jackson.core
jackson-core
-
- com.fasterxml.jackson.core
- jackson-databind
-
com.fasterxml.jackson.core
jackson-annotations
diff --git a/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommender.java b/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommender.java
index 8d553e8d731..2963e1febf4 100644
--- a/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommender.java
+++ b/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommender.java
@@ -27,8 +27,8 @@
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import java.io.IOException;
-import java.io.InputStream;
import java.io.StringWriter;
+import java.lang.invoke.MethodHandles;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
@@ -52,11 +52,8 @@
import org.springframework.http.HttpHeaders;
import org.xml.sax.SAXException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
import de.tudarmstadt.ukp.clarin.webanno.api.annotation.util.WebAnnoCasUtil;
import de.tudarmstadt.ukp.clarin.webanno.api.type.CASMetadata;
-import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer;
import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
import de.tudarmstadt.ukp.inception.recommendation.api.evaluation.DataSplitter;
import de.tudarmstadt.ukp.inception.recommendation.api.evaluation.EvaluationResult;
@@ -80,7 +77,7 @@ public class ExternalRecommender
{
public static final Key KEY_TRAINING_COMPLETE = new Key<>("training_complete");
- private static final Logger LOG = LoggerFactory.getLogger(ExternalRecommender.class);
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final int HTTP_TOO_MANY_REQUESTS = 429;
private static final int HTTP_BAD_REQUEST = 400;
@@ -96,7 +93,9 @@ public ExternalRecommender(ExternalRecommenderProperties aProperties, Recommende
properties = aProperties;
traits = aTraits;
- client = HttpClient.newBuilder().connectTimeout(properties.getConnectTimeout()).build();
+ client = HttpClient.newBuilder() //
+ .connectTimeout(properties.getConnectTimeout()) //
+ .build();
}
@Override
@@ -105,18 +104,18 @@ public boolean isReadyForPrediction(RecommenderContext aContext)
if (traits.isTrainable()) {
return aContext.get(KEY_TRAINING_COMPLETE).orElse(false);
}
- else {
- return true;
- }
+
+ return true;
}
@Override
public void train(RecommenderContext aContext, List aCasses) throws RecommendationException
{
- TrainingRequest trainingRequest = new TrainingRequest();
+ var trainingRequest = new TrainingRequest();
// We assume that the type system for all CAS are the same
- String typeSystem = serializeTypeSystem(aCasses.get(0));
+ var representativeCas = aCasses.get(0);
+ var typeSystem = serializeTypeSystem(representativeCas);
trainingRequest.setTypeSystem(typeSystem);
// Fill in metadata. We use the type system of the first CAS in the list
@@ -126,21 +125,22 @@ public void train(RecommenderContext aContext, List aCasses) throws Recomme
// of the other CAS. This should happen really rarely, therefore this potential
// error is neglected.
- trainingRequest.setMetadata(buildMetadata(aCasses.get(0)));
+ trainingRequest.setMetadata(
+ buildMetadata(representativeCas, Range.rangeCoveringDocument(representativeCas)));
- List documents = new ArrayList<>();
+ var documents = new ArrayList();
for (CAS cas : aCasses) {
documents.add(buildDocument(cas));
}
trainingRequest.setDocuments(documents);
- HttpRequest request = HttpRequest.newBuilder() //
+ var request = HttpRequest.newBuilder() //
.uri(URI.create(appendIfMissing(traits.getRemoteUrl(), "/")).resolve("train")) //
.header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_VALUE) //
.timeout(properties.getReadTimeout())
.POST(BodyPublishers.ofString(toJson(trainingRequest), UTF_8)).build();
- HttpResponse response = sendRequest(request);
+ var response = sendRequest(request);
if (response.statusCode() == HTTP_TOO_MANY_REQUESTS) {
LOG.info("External recommender is already training");
}
@@ -148,8 +148,8 @@ public void train(RecommenderContext aContext, List aCasses) throws Recomme
// If the response indicates that the request was not successful,
// then it does not make sense to go on and try to decode the XMI
else if (response.statusCode() >= HTTP_BAD_REQUEST) {
- String responseBody = getResponseBody(response);
- String msg = format("Request was not successful: [%d] - [%s]", response.statusCode(),
+ var responseBody = getResponseBody(response);
+ var msg = format("Request was not successful: [%d] - [%s]", response.statusCode(),
responseBody);
throw new RecommendationException(msg);
}
@@ -161,35 +161,35 @@ else if (response.statusCode() >= HTTP_BAD_REQUEST) {
public Range predict(RecommenderContext aContext, CAS aCas, int aBegin, int aEnd)
throws RecommendationException
{
- String typeSystem = serializeTypeSystem(aCas);
+ var typeSystem = serializeTypeSystem(aCas);
- PredictionRequest predictionRequest = new PredictionRequest();
+ var predictionRequest = new PredictionRequest();
predictionRequest.setTypeSystem(typeSystem);
predictionRequest.setDocument(buildDocument(aCas));
// Fill in metadata
- predictionRequest.setMetadata(buildMetadata(aCas));
+ predictionRequest.setMetadata(buildMetadata(aCas, new Range(aBegin, aEnd)));
- HttpRequest request = HttpRequest.newBuilder() //
+ var request = HttpRequest.newBuilder() //
.uri(URI.create(appendIfMissing(traits.getRemoteUrl(), "/")).resolve("predict")) //
.header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_VALUE) //
.timeout(properties.getReadTimeout()) //
.POST(BodyPublishers.ofString(toJson(predictionRequest), UTF_8)) //
.build();
- HttpResponse response = sendRequest(request);
+ var response = sendRequest(request);
// If the response indicates that the request was not successful,
// then it does not make sense to go on and try to decode the XMI
if (response.statusCode() >= HTTP_BAD_REQUEST) {
- String responseBody = getResponseBody(response);
- String msg = format("Request was not successful: [%d] - [%s]", response.statusCode(),
+ var responseBody = getResponseBody(response);
+ var msg = format("Request was not successful: [%d] - [%s]", response.statusCode(),
responseBody);
throw new RecommendationException(msg);
}
- PredictionResponse predictionResponse = deserializePredictionResponse(response);
+ var predictionResponse = deserializePredictionResponse(response);
- try (InputStream is = IOUtils.toInputStream(predictionResponse.getDocument(), UTF_8)) {
+ try (var is = IOUtils.toInputStream(predictionResponse.getDocument(), UTF_8)) {
XmiCasDeserializer.deserialize(is, WebAnnoCasUtil.getRealCas(aCas), true);
}
catch (SAXException | IOException e) {
@@ -226,7 +226,7 @@ private String serializeCas(CAS aCas) throws RecommendationException
try (var out = new StringWriter()) {
// Passing "null" as the type system to the XmiCasSerializer means that we want
// to serialize all types (i.e. no filtering for a specific target type system).
- XmiCasSerializer xmiCasSerializer = new XmiCasSerializer(null);
+ var xmiCasSerializer = new XmiCasSerializer(null);
var contentHandler = new XMLSerializer(out, true).getContentHandler();
contentHandler = new IllegalXmlCharacterSanitizingContentHandler(contentHandler);
xmiCasSerializer.serialize(getRealCas(aCas), contentHandler, null, null, null);
@@ -239,10 +239,10 @@ private String serializeCas(CAS aCas) throws RecommendationException
private Document buildDocument(CAS aCas) throws RecommendationException
{
- CASMetadata casMetadata = getCasMetadata(aCas);
- String xmi = serializeCas(aCas);
- long documentId = casMetadata.getSourceDocumentId();
- String userId = casMetadata.getUsername();
+ var casMetadata = getCasMetadata(aCas);
+ var xmi = serializeCas(aCas);
+ var documentId = casMetadata.getSourceDocumentId();
+ var userId = casMetadata.getUsername();
return new Document(xmi, documentId, userId);
}
@@ -257,21 +257,20 @@ private CASMetadata getCasMetadata(CAS aCas) throws RecommendationException
}
}
- private Metadata buildMetadata(CAS aCas) throws RecommendationException
+ private Metadata buildMetadata(CAS aCas, Range aRange) throws RecommendationException
{
- CASMetadata casMetadata = getCasMetadata(aCas);
- AnnotationLayer layer = recommender.getLayer();
+ var casMetadata = getCasMetadata(aCas);
+ var layer = recommender.getLayer();
return new Metadata(layer.getName(), recommender.getFeature().getName(),
casMetadata.getProjectId(), layer.getAnchoringMode().getId(),
- layer.isCrossSentence());
+ layer.isCrossSentence(), aRange);
}
private PredictionResponse deserializePredictionResponse(HttpResponse response)
throws RecommendationException
{
- ObjectMapper objectMapper = new ObjectMapper();
try {
- return objectMapper.readValue(response.body(), PredictionResponse.class);
+ return JSONUtil.fromJsonString(PredictionResponse.class, response.body());
}
catch (IOException e) {
throw new RecommendationException("Error while deserializing prediction response!", e);
@@ -298,14 +297,13 @@ private HttpResponse sendRequest(HttpRequest aRequest) throws Recommenda
}
}
- private String getResponseBody(HttpResponse response) throws RecommendationException
+ private String getResponseBody(HttpResponse response)
{
- if (response.body() != null) {
- return response.body();
- }
- else {
+ if (response.body() == null) {
return "";
}
+
+ return response.body();
}
@Override
@@ -317,7 +315,7 @@ public int estimateSampleCount(List aCasses)
@Override
public EvaluationResult evaluate(List aCasses, DataSplitter aDataSplitter)
{
- EvaluationResult result = new EvaluationResult();
+ var result = new EvaluationResult();
result.setEvaluationSkipped(true);
result.setErrorMsg("ExternalRecommender does not support evaluation.");
return result;
@@ -326,14 +324,12 @@ public EvaluationResult evaluate(List aCasses, DataSplitter aDataSplitter)
@Override
public TrainingCapability getTrainingCapability()
{
- if (traits.isTrainable()) {
- //
- // return TRAINING_SUPPORTED;
- // We need to get at least one training CAS because we need to extract the type system
- return TRAINING_REQUIRED;
- }
- else {
+ if (!traits.isTrainable()) {
return TRAINING_NOT_SUPPORTED;
}
+
+ // return TRAINING_SUPPORTED;
+ // We need to get at least one training CAS because we need to extract the type system
+ return TRAINING_REQUIRED;
}
}
diff --git a/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/model/Metadata.java b/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/model/Metadata.java
index 0d06d31056e..dedd7f7ad1e 100644
--- a/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/model/Metadata.java
+++ b/inception/inception-imls-external/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/model/Metadata.java
@@ -19,9 +19,11 @@
import com.fasterxml.jackson.annotation.JsonProperty;
+import de.tudarmstadt.ukp.inception.rendering.model.Range;
+
public class Metadata
{
-
+ private final Range range;
private final String layer;
private final String feature;
private final long projectId;
@@ -32,13 +34,15 @@ public Metadata(@JsonProperty(value = "layer", required = true) String aLayer,
@JsonProperty(value = "feature", required = true) String aFeature,
@JsonProperty(value = "projectId", required = true) long aProjectId,
@JsonProperty(value = "anchoringMode", required = true) String aAnchoringMode,
- @JsonProperty(value = "crossSentence", required = true) boolean aCrossSentence)
+ @JsonProperty(value = "crossSentence", required = true) boolean aCrossSentence,
+ @JsonProperty(value = "range", required = true) Range aRange)
{
layer = aLayer;
feature = aFeature;
projectId = aProjectId;
anchoringMode = aAnchoringMode;
crossSentence = aCrossSentence;
+ range = aRange;
}
public String getLayer()
@@ -65,4 +69,9 @@ public boolean isCrossSentence()
{
return crossSentence;
}
+
+ public Range getRange()
+ {
+ return range;
+ }
}
diff --git a/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommenderIntegrationTest.java b/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommenderIntegrationTest.java
index 37217d7a571..ff51b7c146f 100644
--- a/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommenderIntegrationTest.java
+++ b/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/ExternalRecommenderIntegrationTest.java
@@ -38,7 +38,6 @@
import org.apache.uima.UIMAException;
import org.apache.uima.cas.CAS;
-import org.apache.uima.collection.CollectionReader;
import org.apache.uima.fit.factory.JCasFactory;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.metadata.TypeSystemDescription;
@@ -62,7 +61,6 @@
import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.config.ExternalRecommenderPropertiesImpl;
import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.messages.PredictionRequest;
import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.messages.TrainingRequest;
-import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.model.Document;
import de.tudarmstadt.ukp.inception.support.test.recommendation.DkproTestHelper;
import de.tudarmstadt.ukp.inception.support.test.recommendation.RecommenderTestHelper;
import okhttp3.mockwebserver.MockResponse;
@@ -85,7 +83,7 @@ public class ExternalRecommenderIntegrationTest
private RecommenderContext context;
private ExternalRecommender sut;
private ExternalRecommenderTraits traits;
- private RemoteStringMatchingNerRecommender remoteRecommender;
+ private MockRemoteStringMatchingNerRecommender remoteRecommender;
private MockWebServer server;
private List requestBodies;
private CasStorageSession casStorageSession;
@@ -100,7 +98,7 @@ public void setUp() throws Exception
traits = new ExternalRecommenderTraits();
sut = new ExternalRecommender(new ExternalRecommenderPropertiesImpl(), recommender, traits);
- remoteRecommender = new RemoteStringMatchingNerRecommender(recommender);
+ remoteRecommender = new MockRemoteStringMatchingNerRecommender(recommender);
server = new MockWebServer();
server.setDispatcher(buildDispatcher());
@@ -122,7 +120,7 @@ public void tearDown() throws Exception
@Test
public void thatTrainingWorks() throws Exception
{
- List data = loadDevelopmentData();
+ var data = loadDevelopmentData();
assertThatCode(() -> sut.train(context, data)).doesNotThrowAnyException();
}
@@ -130,14 +128,14 @@ public void thatTrainingWorks() throws Exception
@Test
public void thatPredictingWorks() throws Exception
{
- List casses = loadDevelopmentData();
+ var casses = loadDevelopmentData();
sut.train(context, casses);
- CAS cas = casses.get(0);
+ var cas = casses.get(0);
RecommenderTestHelper.addScoreFeature(cas, NamedEntity.class, "value");
sut.predict(context, cas);
- List predictions = getPredictions(cas, NamedEntity.class);
+ var predictions = getPredictions(cas, NamedEntity.class);
assertThat(predictions).as("Predictions are not empty").isNotEmpty();
@@ -151,22 +149,25 @@ public void thatPredictingWorks() throws Exception
@Test
public void thatTrainingSendsCorrectRequest() throws Exception
{
- List casses = loadDevelopmentData();
+ var casses = loadDevelopmentData();
sut.train(context, casses);
- TrainingRequest request = fromJsonString(TrainingRequest.class, requestBodies.get(0));
+ var request = fromJsonString(TrainingRequest.class, requestBodies.get(0));
assertThat(request.getMetadata()) //
.hasNoNullFieldsOrProperties() //
.hasFieldOrPropertyWithValue("projectId", PROJECT_ID)
.hasFieldOrPropertyWithValue("layer", recommender.getLayer().getName())
.hasFieldOrPropertyWithValue("feature", recommender.getFeature().getName())
+ .hasFieldOrPropertyWithValue("range.begin", 0)
+ .hasFieldOrPropertyWithValue("range.end", 263034)
.hasFieldOrPropertyWithValue("crossSentence", CROSS_SENTENCE)
.hasFieldOrPropertyWithValue("anchoringMode", ANCHORING_MODE.getId());
for (int i = 0; i < request.getDocuments().size(); i++) {
- Document doc = request.getDocuments().get(i);
- assertThat(doc).hasFieldOrPropertyWithValue("documentId", (long) i)
+ var doc = request.getDocuments().get(i);
+ assertThat(doc) //
+ .hasFieldOrPropertyWithValue("documentId", (long) i) //
.hasFieldOrPropertyWithValue("userId", USER_NAME);
}
}
@@ -174,33 +175,38 @@ public void thatTrainingSendsCorrectRequest() throws Exception
@Test
public void thatPredictingSendsCorrectRequest() throws Exception
{
- List casses = loadDevelopmentData();
+ var casses = loadDevelopmentData();
sut.train(context, casses);
- CAS cas = casses.get(0);
+
+ var cas = casses.get(0);
RecommenderTestHelper.addScoreFeature(cas, NamedEntity.class, "value");
sut.predict(context, cas);
- PredictionRequest request = fromJsonString(PredictionRequest.class, requestBodies.get(1));
+ var request = fromJsonString(PredictionRequest.class, requestBodies.get(1));
assertThat(request.getMetadata()) //
.hasNoNullFieldsOrProperties() //
.hasFieldOrPropertyWithValue("projectId", PROJECT_ID)
.hasFieldOrPropertyWithValue("layer", recommender.getLayer().getName())
.hasFieldOrPropertyWithValue("feature", recommender.getFeature().getName())
+ .hasFieldOrPropertyWithValue("range.begin", 0)
+ .hasFieldOrPropertyWithValue("range.end", 263034)
.hasFieldOrPropertyWithValue("crossSentence", CROSS_SENTENCE)
.hasFieldOrPropertyWithValue("anchoringMode", ANCHORING_MODE.getId());
- assertThat(request.getDocument()).hasFieldOrPropertyWithValue("userId", USER_NAME)
+
+ assertThat(request.getDocument()) //
+ .hasFieldOrPropertyWithValue("userId", USER_NAME) //
.hasFieldOrPropertyWithValue("documentId", 0L);
}
private List loadDevelopmentData() throws Exception
{
try {
- Dataset ds = loader.load("germeval2014-de", CONTINUE);
- List data = loadData(ds, ds.getDefaultSplit().getDevelopmentFiles());
+ var ds = loader.load("germeval2014-de", CONTINUE);
+ var data = loadData(ds, ds.getDefaultSplit().getDevelopmentFiles());
for (int i = 0; i < data.size(); i++) {
- CAS cas = data.get(i);
+ var cas = data.get(i);
addCasMetadata(cas.getJCas(), i);
casStorageSession.add("testDataCas" + i, EXCLUSIVE_WRITE_ACCESS, cas);
}
@@ -215,7 +221,7 @@ private List loadDevelopmentData() throws Exception
private List loadData(Dataset ds, File... files) throws UIMAException, IOException
{
- CollectionReader reader = createReader( //
+ var reader = createReader( //
Conll2002Reader.class, //
Conll2002Reader.PARAM_PATTERNS, files, //
Conll2002Reader.PARAM_LANGUAGE, ds.getLanguage(), //
@@ -239,15 +245,15 @@ private List loadData(Dataset ds, File... files) throws UIMAException, IOEx
private static Recommender buildRecommender()
{
- AnnotationLayer layer = new AnnotationLayer();
+ var layer = new AnnotationLayer();
layer.setName(TYPE);
layer.setCrossSentence(CROSS_SENTENCE);
layer.setAnchoringMode(ANCHORING_MODE);
- AnnotationFeature feature = new AnnotationFeature();
+ var feature = new AnnotationFeature();
feature.setName("value");
- Recommender recommender = new Recommender();
+ var recommender = new Recommender();
recommender.setLayer(layer);
recommender.setFeature(feature);
recommender.setMaxRecommendations(3);
@@ -263,7 +269,7 @@ private QueueDispatcher buildDispatcher()
public MockResponse dispatch(RecordedRequest request)
{
try {
- String body = request.getBody().readUtf8();
+ var body = request.getBody().readUtf8();
requestBodies.add(body);
if (Objects.equals(request.getPath(), "/train")) {
@@ -271,7 +277,7 @@ public MockResponse dispatch(RecordedRequest request)
return new MockResponse().setResponseCode(204);
}
else if (request.getPath().equals("/predict")) {
- String response = remoteRecommender.predict(body);
+ var response = remoteRecommender.predict(body);
return new MockResponse().setResponseCode(200).setBody(response);
}
}
@@ -287,7 +293,7 @@ else if (request.getPath().equals("/predict")) {
private void addCasMetadata(JCas aJCas, long aDocumentId)
{
- CASMetadata cmd = new CASMetadata(aJCas);
+ var cmd = new CASMetadata(aJCas);
cmd.setUsername(USER_NAME);
cmd.setProjectId(PROJECT_ID);
cmd.setSourceDocumentId(aDocumentId);
diff --git a/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/RemoteStringMatchingNerRecommender.java b/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/MockRemoteStringMatchingNerRecommender.java
similarity index 66%
rename from inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/RemoteStringMatchingNerRecommender.java
rename to inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/MockRemoteStringMatchingNerRecommender.java
index eedf7986ea7..6b4ecee37dd 100644
--- a/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/RemoteStringMatchingNerRecommender.java
+++ b/inception/inception-imls-external/src/test/java/de/tudarmstadt/ukp/inception/recommendation/imls/external/v1/MockRemoteStringMatchingNerRecommender.java
@@ -17,13 +17,13 @@
*/
package de.tudarmstadt.ukp.inception.recommendation.imls.external.v1;
+import static de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil.fromJsonString;
import static de.tudarmstadt.ukp.inception.recommendation.api.RecommendationService.FEATURE_NAME_IS_PREDICTION;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -31,80 +31,61 @@
import org.apache.uima.UIMAException;
import org.apache.uima.UIMAFramework;
import org.apache.uima.cas.CAS;
-import org.apache.uima.cas.Feature;
-import org.apache.uima.cas.Type;
import org.apache.uima.cas.impl.XmiCasDeserializer;
import org.apache.uima.cas.impl.XmiCasSerializer;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.fit.factory.JCasFactory;
import org.apache.uima.fit.util.CasUtil;
-import org.apache.uima.jcas.JCas;
-import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.util.XMLInputSource;
import org.xml.sax.SAXException;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
+import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
import de.tudarmstadt.ukp.inception.recommendation.api.model.Recommender;
import de.tudarmstadt.ukp.inception.recommendation.api.recommender.RecommendationException;
import de.tudarmstadt.ukp.inception.recommendation.api.recommender.RecommenderContext;
import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.messages.PredictionRequest;
import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.messages.PredictionResponse;
import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.messages.TrainingRequest;
-import de.tudarmstadt.ukp.inception.recommendation.imls.external.v1.model.Document;
import de.tudarmstadt.ukp.inception.recommendation.imls.stringmatch.span.StringMatchingRecommender;
import de.tudarmstadt.ukp.inception.recommendation.imls.stringmatch.span.StringMatchingRecommenderTraits;
-public class RemoteStringMatchingNerRecommender
+public class MockRemoteStringMatchingNerRecommender
{
private final Recommender recommender;
private final RecommenderContext context;
private final StringMatchingRecommender recommendationEngine;
- public RemoteStringMatchingNerRecommender(Recommender aRecommender)
+ public MockRemoteStringMatchingNerRecommender(Recommender aRecommender)
{
recommender = aRecommender;
context = new RecommenderContext();
- StringMatchingRecommenderTraits traits = new StringMatchingRecommenderTraits();
+ var traits = new StringMatchingRecommenderTraits();
recommendationEngine = new StringMatchingRecommender(recommender, traits);
}
public void train(String aTrainingRequestJson)
throws UIMAException, SAXException, IOException, RecommendationException
{
- TrainingRequest request = deserializeTrainingRequest(aTrainingRequestJson);
+ var request = fromJsonString(TrainingRequest.class, aTrainingRequestJson);
List casses = new ArrayList<>();
- for (Document doc : request.getDocuments()) {
- CAS cas = deserializeCas(doc.getXmi(), request.getTypeSystem());
+ for (var doc : request.getDocuments()) {
+ var cas = deserializeCas(doc.getXmi(), request.getTypeSystem());
casses.add(cas);
}
recommendationEngine.train(context, casses);
}
- private TrainingRequest deserializeTrainingRequest(String aRequestJson)
- {
- try {
- ObjectMapper objectMapper = new ObjectMapper();
- return objectMapper.readValue(aRequestJson, TrainingRequest.class);
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
public String predict(String aPredictionRequestJson)
throws IOException, UIMAException, SAXException, RecommendationException
{
- PredictionRequest request = deserializePredictionRequest(aPredictionRequestJson);
- CAS cas = deserializeCas(request.getDocument().getXmi(), request.getTypeSystem());
+ var request = fromJsonString(PredictionRequest.class, aPredictionRequestJson);
+ var cas = deserializeCas(request.getDocument().getXmi(), request.getTypeSystem());
// Only work on real annotations, not on predictions
- Type predictedType = CasUtil.getType(cas, recommender.getLayer().getName());
- Feature feature = predictedType.getFeatureByBaseName(FEATURE_NAME_IS_PREDICTION);
+ var predictedType = CasUtil.getType(cas, recommender.getLayer().getName());
+ var feature = predictedType.getFeatureByBaseName(FEATURE_NAME_IS_PREDICTION);
for (AnnotationFS fs : CasUtil.select(cas, predictedType)) {
if (fs.getBooleanValue(feature)) {
@@ -117,20 +98,13 @@ public String predict(String aPredictionRequestJson)
return buildPredictionResponse(cas);
}
- private PredictionRequest deserializePredictionRequest(String aPredictionRequestJson)
- throws JsonParseException, JsonMappingException, IOException
- {
- ObjectMapper objectMapper = new ObjectMapper();
- return objectMapper.readValue(aPredictionRequestJson, PredictionRequest.class);
- }
-
// CAS handling
private CAS deserializeCas(String xmi, String typeSystem)
throws SAXException, IOException, UIMAException
{
CAS cas = buildCas(typeSystem);
- try (InputStream bais = new ByteArrayInputStream(xmi.getBytes(UTF_8))) {
+ try (var bais = new ByteArrayInputStream(xmi.getBytes(UTF_8))) {
XmiCasDeserializer.deserialize(bais, cas);
}
return cas;
@@ -140,20 +114,18 @@ private CAS buildCas(String typeSystem) throws IOException, UIMAException
{
// We need to save the typeSystem XML to disk as the
// JCasFactory needs a file and not a string
- TypeSystemDescription tsd = UIMAFramework.getXMLParser().parseTypeSystemDescription(
+ var tsd = UIMAFramework.getXMLParser().parseTypeSystemDescription(
new XMLInputSource(IOUtils.toInputStream(typeSystem, UTF_8), null));
- JCas jCas = JCasFactory.createJCas(tsd);
- return jCas.getCas();
+ return JCasFactory.createJCas(tsd).getCas();
}
private String buildPredictionResponse(CAS aCas) throws SAXException, IOException
{
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
XmiCasSerializer.serialize(aCas, null, out, true, null);
- PredictionResponse response = new PredictionResponse();
+ var response = new PredictionResponse();
response.setDocument(new String(out.toByteArray(), UTF_8));
- ObjectMapper mapper = new ObjectMapper();
- return mapper.writeValueAsString(response);
+ return JSONUtil.toJsonString(response);
}
}
}