diff --git a/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventResponseProcessingService.java b/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventResponseProcessingService.java
index 0744d327..2a4ba3dd 100644
--- a/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventResponseProcessingService.java
+++ b/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventResponseProcessingService.java
@@ -113,6 +113,7 @@ private Stream resultDocuments2Events(Stream docum
Optional likelihood = eventDocument.get(FIELD_EVENT_LIKELIHOOD);
Optional sentence = eventDocument.get(FIELD_EVENT_SENTENCE_TEXT);
Optional paragraph = eventDocument.get(FIELD_EVENT_PARAGRAPH_TEXT);
+ String source = (String)eventDocument.get(FIELD_SOURCE).get(); // pubmed or pmc
List sentenceArgumentHl = eventDocument.getHighlights().get(FIELD_EVENT_SENTENCE_TEXT_ARGUMENTS);
List sentenceTriggerHl = eventDocument.getHighlights().get(FIELD_EVENT_SENTENCE_TEXT_TRIGGER);
List sentenceFilterHl = eventDocument.getHighlights().get(FIELD_EVENT_SENTENCE_TEXT);
@@ -170,9 +171,12 @@ private Stream resultDocuments2Events(Stream docum
Event event = new Event();
event.setArity(eventArity);
- // Only one ID is present currently
- pmid.ifPresent(event::setDocId);
- pmcid.ifPresent(event::setDocId);
+
+ if (source.equals("pubmed") && pmid.isPresent())
+ event.setDocId(pmid.get());
+ else if (source.equals("pmc") && pmcid.isPresent())
+ event.setDocId(pmcid.get());
+
event.setEventId(eventId);
event.setArguments(arguments);
if (likelihood.isPresent())
diff --git a/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventRetrievalService.java b/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventRetrievalService.java
index 8aa50fe1..1e8d4a68 100644
--- a/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventRetrievalService.java
+++ b/gepi/gepi-core/src/main/java/de/julielab/gepi/core/retrieval/services/EventRetrievalService.java
@@ -117,6 +117,8 @@ public class EventRetrievalService implements IEventRetrievalService {
public static final String FIELD_AGGREGATION_VALUE = "aggregationvalue";
+ public static final String FIELD_SOURCE = "source";
+
/**
* The values in the field have the form symbol1---symbol2
*/
@@ -131,6 +133,7 @@ public class EventRetrievalService implements IEventRetrievalService {
public static final List FIELDS_FOR_TABLE = Arrays.asList(
FIELD_PMID,
FIELD_PMCID,
+ FIELD_SOURCE,
FIELD_EVENT_LIKELIHOOD,
FIELD_EVENT_SENTENCE_TEXT,
// FIELD_EVENT_PARAGRAPH_TEXT,
diff --git a/gepi/gepi-webapp/pom.xml b/gepi/gepi-webapp/pom.xml
index f97424a2..00b3b7b7 100644
--- a/gepi/gepi-webapp/pom.xml
+++ b/gepi/gepi-webapp/pom.xml
@@ -35,6 +35,12 @@
${tapestry-release-version}
+
+ org.apache.tapestry
+ tapestry-rest-jackson
+ ${tapestry-release-version}
+
+
@@ -90,6 +96,14 @@ of testing facilities designed for use with TestNG (http://testng.org/), so it's
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
org.apache.tapestry
@@ -171,26 +185,26 @@ of testing facilities designed for use with TestNG (http://testng.org/), so it's
false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
org.apache.maven.plugins
maven-war-plugin
diff --git a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/GepiInput.java b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/GepiInput.java
index fca34a50..71874b8a 100644
--- a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/GepiInput.java
+++ b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/GepiInput.java
@@ -179,6 +179,11 @@ public class GepiInput {
*/
@ActivationRequestParameter
private boolean reset;
+
+ public GepiRequestData getRequestData() {
+ return requestData;
+ }
+
/**
* TODO This is here to allow for paging requests. It overlaps with {@link #data} which should be sorted out at some point.
*/
diff --git a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/TableResultWidget.java b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/TableResultWidget.java
index 0329b912..8ccb8b86 100644
--- a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/TableResultWidget.java
+++ b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/components/TableResultWidget.java
@@ -16,6 +16,7 @@
import de.julielab.java.utilities.FileUtilities;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.StreamResponse;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.beanmodel.BeanModel;
import org.apache.tapestry5.beanmodel.services.BeanModelSource;
@@ -24,6 +25,7 @@
import org.apache.tapestry5.http.services.Response;
import org.apache.tapestry5.ioc.LoggerSource;
import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.slf4j.Logger;
@@ -88,58 +90,31 @@ public class TableResultWidget extends GepiWidget {
@Persist(TabPersistentField.TAB)
private Format contextFormat;
@Inject
+ @Symbol(SymbolConstants.PRODUCTION_MODE)
+ private boolean productionMode;
+ @Inject
private IEventRetrievalService eventRetrievalService;
@Inject
private LoggerSource loggerSource;
@Environmental
private JavaScriptSupport javaScriptSupport;
-// @Property
-// private List selectedColumns;
@Inject
private IGeneIdService geneIdService;
-// @Inject
-// private TypeCoercer typeCoercer;
-//
-// public ValueEncoder getColumnsEncoder() {
-// return new StringValueEncoder();
-// }
-//
-// public SelectModel getColumnsModel() {
-// return new SelectModelImpl(tableModel.getPropertyNames().stream().map(p -> new OptionModelImpl(p)).toArray(OptionModel[]::new));
-// }
-// @Inject
-// private AjaxResponseRenderer ajaxResponseRenderer;
-//
-// @InjectComponent
-// private GepiWidgetLayout gepiWidgetLayout;
-//
- // for columns selection
-// public void onSuccessFromColumnsForm() {
-// tableModel.include(selectedColumns.toArray(String[]::new));
-// ajaxResponseRenderer.addRender(gepiWidgetLayout.getBodyZone());
-// }
@Log
void setupRender() {
getEventSource();
List availableColumns = new ArrayList<>(List.of("firstArgumentPreferredName",
"secondArgumentPreferredName",
-// "firstArgumentText",
-// "secondArgumentText",
"firstArgumentGeneId",
"secondArgumentGeneId",
-// "firstArgumentMatchType",
-// "secondArgumentMatchType",
"allEventTypes",
"factuality",
"fulltextMatchSource",
"docId",
-// "eventId",
"context"
-// ,
-// "geneMappingSources"
));
if (inputMode != null && !inputMode.contains(InputMode.FULLTEXT_QUERY))
availableColumns.remove("fulltextMatchSource");
@@ -149,16 +124,10 @@ void setupRender() {
tableModel.get("firstArgumentPreferredName").label("Gene A Symbol");
tableModel.get("secondArgumentPreferredName").label("Gene B Symbol");
-// tableModel.get("firstArgumentText").label("Gene A Text");
-// tableModel.get("secondArgumentText").label("Gene B Text");
tableModel.get("firstArgumentGeneId").label("Gene A Gene ID");
tableModel.get("secondArgumentGeneId").label("Gene B Gene ID");
-// tableModel.get("firstArgumentMatchType").label("gene A match type");
-// tableModel.get("secondArgumentMatchType").label("gene B match type");
tableModel.get("allEventTypes").label("Relation Types");
tableModel.get("docId").label("Document ID");
-// tableModel.get("eventId").label("event id");
-// tableModel.get("geneMappingSources").label("gene tagger");
// Disable the sorting buttons. Since we reorder the event arguments so that arguments from list A
// always appear as the "first" argument, we cannot sort in ElasticSearch because there is no fixed
// field we could sort on for the gene arguments. Other columns would be possible to sort on but
@@ -177,28 +146,14 @@ public Object parseObject(String source, ParsePosition pos) {
return source;
}
};
-// selectedColumns = tableModel.getPropertyNames();
}
- /**
- * When the form containing the filter elements is submitted, we want to re-render the table via AJAX
- */
-// void onValidateFromFilterCriteria() {
-// if (request.isXHR()) {
-// ajaxResponseRenderer.addRender(tableZone);
-// }
-// }
public EventPagesDataSource getEventSource() {
-// FilteredGepiRequestData filteredRequest = new FilteredGepiRequestData(requestData);
-// filteredRequest.setEventTypeFilter(filterEventType);
return new EventPagesDataSource(loggerSource.getLogger(EventPagesDataSource.class), dataService.getData(requestData.getDataSessionId()).getPagedResult(), eventRetrievalService, geneIdService, requestData);
}
void onUpdateTableData() {
log.debug("Waiting for table data.");
-// beanEvents = getEsResult().get().getEventList().stream()
-// .map(e -> new BeanModelEvent(e))
-// .collect(Collectors.toList());
log.debug("Table data was loaded.");
}
@@ -233,18 +188,6 @@ public StreamResponse onDownload() {
@Override
public void prepareResponse(Response response) {
try {
-// Future unrolledResult4download = getUnrolledResult4download();
-// // Check if we have the download data cached. Otherwise, get it and cache it
-// if (unrolledResult4download == null) {
-// long time = System.currentTimeMillis();
-// log.info("[{}] Retrieving unrolled result for Excel sheet creation.", requestData.getDataSessionId());
-// unrolledResult4download = eventRetrievalService.getEvents(requestData, 0, Integer.MAX_VALUE, false);
-// // We use a weak reference for the complete data since it requires much memory because of all
-// // the context data. The GC should be able to evict it, if necessary.
-// dataService.getData(requestData.getDataSessionId()).setUnrolledResult4download(new WeakReference<>(unrolledResult4download));
-// time = System.currentTimeMillis() - time;
-// log.info("[{}] Unrolled result retrieval for Excel sheet creation took {} seconds", requestData.getDataSessionId(), time / 1000);
-// }
final Future unrolledResult4download = dataService.getUnrolledResult4download(requestData, eventRetrievalService);
statisticsFile = dataService.getOverviewExcel(unrolledResult4download, requestData.getDataSessionId(), requestData.getInputMode(), requestData.getSentenceFilterString(), requestData.getParagraphFilterString(), requestData.getSectionNameFilterString());
@@ -293,7 +236,7 @@ public String getArgumentLink(int argPosition) {
public void afterRender() {
final Link downloadEventLink = resources.createEventLink("download");
- javaScriptSupport.require("gepi/charts/tablewidget").invoke("download").with(downloadEventLink.toAbsoluteURI().replace(":80", ""));
+ javaScriptSupport.require("gepi/charts/tablewidget").invoke("download").with(downloadEventLink.toAbsoluteURI(productionMode));
javaScriptSupport.require("gepi/charts/tablewidget").invoke("setupHighlightTooltips");
javaScriptSupport.require("gepi/base").invoke("setuptooltips");
}
diff --git a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/data/GepiQueryParameters.java b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/data/GepiQueryParameters.java
index c6048ebc..09b97cef 100644
--- a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/data/GepiQueryParameters.java
+++ b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/data/GepiQueryParameters.java
@@ -117,12 +117,12 @@ private void readParameters(Request request) {
if (listATextAreaValue == null)
listATextAreaValue = request.getParameter(ALIST);
if (listATextAreaValue != null)
- listATextAreaValue = Arrays.stream(listATextAreaValue.split("[\n,]")).map(this::decodeUrlEncoding).collect(Collectors.joining("\n"));
+ listATextAreaValue = Arrays.stream(decodeUrlEncoding(listATextAreaValue).split("[\n,]")).collect(Collectors.joining("\n"));
listBTextAreaValue = request.getParameter(LISTB);
if (listBTextAreaValue == null)
listBTextAreaValue = request.getParameter(BLIST);
if (listBTextAreaValue != null)
- listBTextAreaValue = Arrays.stream(listBTextAreaValue.split("[\n,]")).map(this::decodeUrlEncoding).collect(Collectors.joining("\n"));
+ listBTextAreaValue = Arrays.stream(decodeUrlEncoding(listBTextAreaValue).split("[\n,]")).collect(Collectors.joining("\n"));
taxId = request.getParameter(TAXID);
selectedEventTypes = new ArrayList<>(EnumSet.allOf(EventTypes.class));
final String eventTypesString = request.getParameter(EVENTTYPES);
@@ -161,7 +161,7 @@ private void readParameters(Request request) {
interactionRetrievalLimitForAggregations = INTERACTION_RETRIEVAL_LIMIT_FOR_AGGREGATIONS;
format = request.getParameter(FORMAT) != null ? request.getParameter(FORMAT).toLowerCase() : null;
if (format == null)
- format = "web";
+ format = "tsv";
try {
interactionRetrievalLimitForAggregations = Integer.parseInt(request.getParameter(INTERACTION_RETRIEVAL_LIMIT));
} catch (NumberFormatException e) {
@@ -170,6 +170,14 @@ private void readParameters(Request request) {
}
}
+ /**
+ * This method is required for the help pages. For some reason, Tapestry converts the percent-URL-encodings
+ * in the HTML attributes into these dollar-sign encodings which are then not translated back.
+ *
+ * The API - when used with cURL, for example - works just fine.
+ * @param encodedString
+ * @return
+ */
private String decodeUrlEncoding(String encodedString) {
return encodedString.replaceAll("\\$002520", " ")
.replaceAll("\\$00253[Aa]", ":")
diff --git a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/Index.java b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/Index.java
index 716b7d19..23f17f63 100644
--- a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/Index.java
+++ b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/Index.java
@@ -8,16 +8,13 @@
import de.julielab.gepi.webapp.components.TableResultWidget;
import de.julielab.gepi.webapp.data.GepiQueryParameters;
import de.julielab.gepi.webapp.state.GePiSessionState;
-import de.julielab.java.utilities.FileUtilities;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventContext;
-import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.http.services.Request;
-import org.apache.tapestry5.http.services.Response;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.json.JSONArray;
@@ -27,10 +24,6 @@
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.slf4j.Logger;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
@@ -86,8 +79,17 @@ public class Index {
@Inject
private IGePiDataService dataService;
+ public GepiInput getGepiInput() {
+ return gepiInput;
+ }
+
@InjectComponent
private GepiInput gepiInput;
+
+ public TableResultWidget getTableResultWidget() {
+ return tableResultWidget;
+ }
+
@InjectComponent
private TableResultWidget tableResultWidget;
private boolean sessionExists = false;
@@ -124,42 +126,42 @@ Object onActivate(EventContext eventContext) {
if (gepiQueryParameters.isValidRequest()) {
log.info("Received valid query parameters for GePI search.");
gepiInput.executeSearch(gepiQueryParameters, dataSessionId);
- switch (gepiQueryParameters.getFormat()) {
- case "excel":
- return tableResultWidget.onDownload();
- case "tsv":
- final Future unrolledRetrievalResult = dataService.getUnrolledResult4download(requestData, eventRetrievalService);
- try {
- final Path tsvFile = dataService.writeOverviewTsvFile(unrolledRetrievalResult.get().getEventList(), requestData.getDataSessionId());
- return new StreamResponse() {
-
- @Override
- public void prepareResponse(Response response) {
- try {
- response.setHeader("Content-Length", "" + Files.size(tsvFile)); // output into file
- response.setHeader("Content-disposition", "attachment; filename=" + tsvFile.getFileName());
- } catch (Exception e) {
- log.error("Could not create TSV result for dataSessionId {}", requestData.getDataSessionId(), e);
- }
- }
-
- @Override
- public InputStream getStream() throws IOException {
- return FileUtilities.getInputStreamFromFile(tsvFile.toFile());
- }
-
- @Override
- public String getContentType() {
- return "text/csv";
- }
- };
- } catch (Exception e) {
- log.error("Could not serve TSV file due to Exception", e);
- }
- return dataService;
- default: return this;
- }
- //return this;
+// switch (gepiQueryParameters.getFormat()) {
+// case "excel":
+// return tableResultWidget.onDownload();
+// case "tsv":
+// final Future unrolledRetrievalResult = dataService.getUnrolledResult4download(requestData, eventRetrievalService);
+// try {
+// final Path tsvFile = dataService.writeOverviewTsvFile(unrolledRetrievalResult.get().getEventList(), requestData.getDataSessionId());
+// return new StreamResponse() {
+//
+// @Override
+// public void prepareResponse(Response response) {
+// try {
+// response.setHeader("Content-Length", "" + Files.size(tsvFile)); // output into file
+// response.setHeader("Content-disposition", "attachment; filename=" + tsvFile.getFileName());
+// } catch (Exception e) {
+// log.error("Could not create TSV result for dataSessionId {}", requestData.getDataSessionId(), e);
+// }
+// }
+//
+// @Override
+// public InputStream getStream() throws IOException {
+// return FileUtilities.getInputStreamFromFile(tsvFile.toFile());
+// }
+//
+// @Override
+// public String getContentType() {
+// return "text/csv";
+// }
+// };
+// } catch (Exception e) {
+// log.error("Could not serve TSV file due to Exception", e);
+// }
+// return dataService;
+// default: return this;
+// }
+ return this;
} else {
log.debug("Query parameters did not contain a valid GePI search.");
}
@@ -172,18 +174,18 @@ public Future getUnrolledResult4download() {
}
void afterRender() {
- System.out.println("Server Name: " + request.getServerName());
- System.out.println("Server Port: " + request.getServerPort());
- System.out.println("Local Port: " + request.getLocalPort());
- System.out.println("Is Secure: " + request.isSecure());
- System.out.println("Path: " + request.getPath());
- System.out.println("Remote Host: " + request.getRemoteHost());
- for (var name : request.getAttributeNames())
- System.out.println("Attribute " + name + ": " + request.getAttribute(name));
+// System.out.println("Server Name: " + request.getServerName());
+// System.out.println("Server Port: " + request.getServerPort());
+// System.out.println("Local Port: " + request.getLocalPort());
+// System.out.println("Is Secure: " + request.isSecure());
+// System.out.println("Path: " + request.getPath());
+// System.out.println("Remote Host: " + request.getRemoteHost());
+// for (var name : request.getAttributeNames())
+// System.out.println("Attribute " + name + ": " + request.getAttribute(name));
javaScriptSupport.require("gepi/base").invoke("setuptooltips");
javaScriptSupport.require("gepi/charts/data").invoke("setDataUrl").with(resources.createEventLink("loadDataToClient").toAbsoluteURI(productionMode));
javaScriptSupport.require("gepi/pages/index").invoke("setupDownloadUrlCopyButton");
- javaScriptSupport.require("gepi/pages/index").invoke("displayRoadworksWarningToast");
+// javaScriptSupport.require("gepi/pages/index").invoke("displayRoadworksWarningToast");
if (isResultPresent()) {
// If there already is data at loading the page, the input panel is already hidden (see #getShowInputClass)
// and we can display the widgets.
diff --git a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/api/v1/Interactions.java b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/api/v1/Interactions.java
new file mode 100644
index 00000000..ea46aed6
--- /dev/null
+++ b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/pages/api/v1/Interactions.java
@@ -0,0 +1,125 @@
+package de.julielab.gepi.webapp.pages.api.v1;
+
+import de.julielab.gepi.core.retrieval.data.Event;
+import de.julielab.gepi.core.retrieval.data.EventRetrievalResult;
+import de.julielab.gepi.core.retrieval.data.GepiRequestData;
+import de.julielab.gepi.core.retrieval.services.IEventRetrievalService;
+import de.julielab.gepi.core.services.IGePiDataService;
+import de.julielab.gepi.webapp.base.TabPersistentField;
+import de.julielab.gepi.webapp.components.GepiInput;
+import de.julielab.gepi.webapp.components.TableResultWidget;
+import de.julielab.gepi.webapp.data.GepiQueryParameters;
+import de.julielab.gepi.webapp.pages.Index;
+import de.julielab.java.utilities.FileUtilities;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.annotations.InjectPage;
+import org.apache.tapestry5.annotations.OnEvent;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.http.services.Response;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.ApplicationStateManager;
+import org.apache.tapestry5.services.HttpStatus;
+import org.apache.tapestry5.util.TextStreamResponse;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class Interactions {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private ApplicationStateManager asm;
+
+ @Inject
+ private Request request;
+
+ @Inject
+ private IGePiDataService dataService;
+
+ @Inject
+ private IEventRetrievalService eventRetrievalService;
+
+ @InjectPage
+ private Index index;
+
+ @Property
+ @Persist(TabPersistentField.TAB)
+ private GepiRequestData requestData;
+
+ @Property
+ @Persist(TabPersistentField.TAB)
+ private long dataSessionId;
+
+ @OnEvent(EventConstants.HTTP_GET)
+ Object onHttpGet() {
+ if (requestData == null) {
+ dataSessionId = dataService.newSession();
+ log.debug("Current dataSessionId is 0, initializing GePi session with ID {}", dataSessionId);
+ log.debug("No session");
+ }
+
+ final GepiQueryParameters gepiQueryParameters = new GepiQueryParameters(request);
+ if (gepiQueryParameters.isValidRequest()) {
+ log.info("Received valid query parameters for GePI search.");
+ GepiInput gepiInput = index.getGepiInput();
+ TableResultWidget tableResultWidget = index.getTableResultWidget();
+ gepiInput.executeSearch(gepiQueryParameters, dataSessionId);
+ if (requestData == null)
+ requestData = gepiInput.getRequestData();
+ switch (gepiQueryParameters.getFormat()) {
+ case "excel":
+ return tableResultWidget.onDownload();
+ case "tsv":
+ final Future unrolledRetrievalResult = dataService.getUnrolledResult4download(requestData, eventRetrievalService);
+ try {
+ final EventRetrievalResult eventRetrievalResult = unrolledRetrievalResult.get();
+ final List eventList = eventRetrievalResult.getEventList();
+ final Path tsvFile = dataService.writeOverviewTsvFile(eventList, requestData.getDataSessionId());
+ return new TextStreamResponse("text/csv", "UTF-8") {
+
+ @Override
+ public void prepareResponse(Response response) {
+ try {
+ response.setHeader("Content-Length", "" + Files.size(tsvFile)); // output into file
+ response.setHeader("Content-disposition", "attachment; filename=" + tsvFile.getFileName());
+ } catch (Exception e) {
+ log.error("Could not create TSV result for dataSessionId {}", requestData.getDataSessionId(), e);
+ }
+ }
+
+ @Override
+ public InputStream getStream() throws IOException {
+ return FileUtilities.getInputStreamFromFile(tsvFile.toFile());
+ }
+
+ @Override
+ public String getContentType() {
+ return "text/csv";
+ }
+ };
+ } catch (Exception e) {
+ log.error("Could not serve TSV file due to Exception", e);
+ JSONObject response = new JSONObject("status", 500, "errorMessage", "Internal Server Error");
+ return new HttpStatus(500, response.toString());
+ }
+ default:
+ JSONObject response = new JSONObject("status", HttpStatus.badRequest().getStatusCode(), "errorMessage", "Unsupported return format '" + gepiQueryParameters.getFormat() + "'. Valid values are 'excel' and 'tsv'.");
+ return new HttpStatus(HttpStatus.badRequest().getStatusCode(), response.toString());
+ }
+ } else {
+ log.debug("Query parameters did not contain a valid GePI search.");
+ }
+ JSONObject response = new JSONObject("status", HttpStatus.badRequest().getStatusCode(), "errorMessage", "Not a valid GePI request. Refer to the help page of the GePI Web application.");
+ return new HttpStatus(HttpStatus.badRequest().getStatusCode(), response.toString());
+ }
+}
diff --git a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/services/AppModule.java b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/services/AppModule.java
index 13c7f887..a0939404 100644
--- a/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/services/AppModule.java
+++ b/gepi/gepi-webapp/src/main/java/de/julielab/gepi/webapp/services/AppModule.java
@@ -4,18 +4,19 @@
import de.julielab.gepi.core.services.ConfigurationSymbolProvider;
import de.julielab.gepi.core.services.GepiCoreModule;
import de.julielab.gepi.webapp.base.TabPersistentField;
-import de.julielab.gepi.webapp.state.GePiSessionState;
-import de.julielab.gepi.webapp.state.GePiSessionStateCreator;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MetaDataConstants;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.commons.MappedConfiguration;
import org.apache.tapestry5.commons.OrderedConfiguration;
import org.apache.tapestry5.http.Link;
-import org.apache.tapestry5.http.services.*;
+import org.apache.tapestry5.http.services.Response;
import org.apache.tapestry5.ioc.LoggerSource;
import org.apache.tapestry5.ioc.ServiceBinder;
-import org.apache.tapestry5.ioc.annotations.*;
+import org.apache.tapestry5.ioc.annotations.Autobuild;
+import org.apache.tapestry5.ioc.annotations.Contribute;
+import org.apache.tapestry5.ioc.annotations.ImportModule;
+import org.apache.tapestry5.ioc.annotations.Startup;
import org.apache.tapestry5.ioc.services.ApplicationDefaults;
import org.apache.tapestry5.ioc.services.ParallelExecutor;
import org.apache.tapestry5.ioc.services.SymbolProvider;
@@ -24,7 +25,6 @@
import org.apache.tapestry5.services.*;
import org.apache.tapestry5.services.javascript.JavaScriptStack;
import org.apache.tapestry5.services.javascript.StackExtension;
-import org.slf4j.Logger;
import java.io.IOException;
import java.nio.file.Path;
@@ -75,7 +75,7 @@ public static void contributeFactoryDefaults(
// This is something that should be removed when going to production, but is useful
// in the early stages of development.
- configuration.override(SymbolConstants.PRODUCTION_MODE, true);
+ configuration.override(SymbolConstants.PRODUCTION_MODE, false);
// This symbol is meant to be controlled through a configuration properties file (loaded with the contributed
// symbol source at the top). This is here to give a default value when the property is not included in the
@@ -121,10 +121,10 @@ public static void overrideJquery(OrderedConfiguration conf) {
conf.override("jquery-library", StackExtension.library("classpath:META-INF/assets/jquery-3.6.0.min.js"));
}
- @Contribute(RequestHandler.class)
- public static void contributeRequestFilters(final OrderedConfiguration filters) {
- filters.addInstance(GePiRequestFilter.class.getSimpleName(), GePiRequestFilter.class, "after:ErrorFilter");
- }
+// @Contribute(RequestHandler.class)
+// public static void contributeRequestFilters(final OrderedConfiguration filters) {
+// filters.addInstance(GePiRequestFilter.class.getSimpleName(), GePiRequestFilter.class, "after:ErrorFilter");
+// }
@Startup
public static void scheduleJobs(ParallelExecutor pExecutor, PeriodicExecutor executor, IStatisticsCollector statisticsCollector, ITempFileCleaner tempFileCleaner) {
@@ -159,54 +159,54 @@ public void contributeMetaDataLocator(MappedConfiguration config
* a service named "RequestFilter" we use an explicit service id that we can reference
* inside the contribution method.
*/
- @ServiceId("timingFilter")
- public RequestFilter buildTimingFilter(final Logger log) {
- return new RequestFilter() {
- public boolean service(Request request, Response response, RequestHandler handler)
- throws IOException {
- long startTime = System.currentTimeMillis();
-
- try {
- // The responsibility of a filter is to invoke the corresponding method
- // in the handler. When you chain multiple filters together, each filter
- // received a handler that is a bridge to the next filter.
-
- return handler.service(request, response);
- } finally {
- long elapsed = System.currentTimeMillis() - startTime;
-
- log.info("Request time: {} ms", elapsed);
- }
- }
- };
- }
+// @ServiceId("timingFilter")
+// public RequestFilter buildTimingFilter(final Logger log) {
+// return new RequestFilter() {
+// public boolean service(Request request, Response response, RequestHandler handler)
+// throws IOException {
+// long startTime = System.currentTimeMillis();
+//
+// try {
+// // The responsibility of a filter is to invoke the corresponding method
+// // in the handler. When you chain multiple filters together, each filter
+// // received a handler that is a bridge to the next filter.
+//
+// return handler.service(request, response);
+// } finally {
+// long elapsed = System.currentTimeMillis() - startTime;
+//
+// log.info("Request time: {} ms", elapsed);
+// }
+// }
+// };
+// }
- @ServiceId("sessionCheckFilter")
- public RequestFilter buildSessionCheckFilter(final Logger log, PageRenderLinkSource pageRenderLinkSource) {
- return (request, response, handler) -> {
- Session session = request.getSession(false);
-// log.debug("Session is {}", session);
- if (session != null) {
- for (String name : session.getAttributeNames()) {
- log.debug("Session attribute {} has value {}", name, session.getAttribute(name));
- }
- log.debug("dataSessionId is {}", session.getAttribute("dataSessionId"));
- }
-// Link linkToRequestedPage = pageRenderLinkSource.createPageRenderLink(Index.class.getSimpleName());
-// boolean targetsIndex = request.getPath().contains(Index.class.getSimpleName());
-// if (!targetsIndex && session == null) {
-// log.debug("Sending redirect to Index page because the session is null.");
-// response.sendRedirect(linkToRequestedPage);
-// } else if (!targetsIndex) {
-// Object dataSessionId = session.getAttribute("dataSessionId");
-// if (dataSessionId == null || ((long) dataSessionId) == 0) {
-// log.debug("Sending redirect to Index page because dataSessionId is 0.");
-// response.sendRedirect(linkToRequestedPage);
+// @ServiceId("sessionCheckFilter")
+// public RequestFilter buildSessionCheckFilter(final Logger log, PageRenderLinkSource pageRenderLinkSource) {
+// return (request, response, handler) -> {
+// Session session = request.getSession(false);
+//// log.debug("Session is {}", session);
+// if (session != null) {
+// for (String name : session.getAttributeNames()) {
+// log.debug("Session attribute {} has value {}", name, session.getAttribute(name));
// }
+// log.debug("dataSessionId is {}", session.getAttribute("dataSessionId"));
// }
- return handler.service(request, response);
- };
- }
+//// Link linkToRequestedPage = pageRenderLinkSource.createPageRenderLink(Index.class.getSimpleName());
+//// boolean targetsIndex = request.getPath().contains(Index.class.getSimpleName());
+//// if (!targetsIndex && session == null) {
+//// log.debug("Sending redirect to Index page because the session is null.");
+//// response.sendRedirect(linkToRequestedPage);
+//// } else if (!targetsIndex) {
+//// Object dataSessionId = session.getAttribute("dataSessionId");
+//// if (dataSessionId == null || ((long) dataSessionId) == 0) {
+//// log.debug("Sending redirect to Index page because dataSessionId is 0.");
+//// response.sendRedirect(linkToRequestedPage);
+//// }
+//// }
+// return handler.service(request, response);
+// };
+// }
/**
* This is a contribution to the RequestHandler service configuration. This is how we extend
@@ -215,18 +215,18 @@ public RequestFilter buildSessionCheckFilter(final Logger log, PageRenderLinkSou
* from the same module. Without @Local, there would be an error due to the other service(s)
* that implement RequestFilter (defined in other modules).
*/
- @Contribute(RequestHandler.class)
- public void addTimingFilter(OrderedConfiguration configuration,
- @InjectService("timingFilter")
- RequestFilter filter,
- @InjectService("sessionCheckFilter") RequestFilter sessionCheckFilter) {
- // Each contribution to an ordered configuration has a name, When necessary, you may
- // set constraints to precisely control the invocation order of the contributed filter
- // within the pipeline.
-
-// configuration.add("Timing", filter);
-// configuration.add("SessionCheck", sessionCheckFilter);
- }
+// @Contribute(RequestHandler.class)
+// public void addTimingFilter(OrderedConfiguration configuration,
+// @InjectService("timingFilter")
+// RequestFilter filter,
+// @InjectService("sessionCheckFilter") RequestFilter sessionCheckFilter) {
+// // Each contribution to an ordered configuration has a name, When necessary, you may
+// // set constraints to precisely control the invocation order of the contributed filter
+// // within the pipeline.
+//
+//// configuration.add("Timing", filter);
+//// configuration.add("SessionCheck", sessionCheckFilter);
+// }
/**
* This sets up the custom "tab" state persistence strategy.
@@ -239,11 +239,11 @@ public void contributePersistentFieldManager(MappedConfiguration, ApplicationStateContribution> configuration, @Inject Request request,
- @Autobuild GePiSessionStateCreator sessionStateCreator) {
- configuration.add(GePiSessionState.class, new ApplicationStateContribution("session", sessionStateCreator));
- }
+// public void contributeApplicationStateManager(
+// MappedConfiguration, ApplicationStateContribution> configuration, @Inject Request request,
+// @Autobuild GePiSessionStateCreator sessionStateCreator) {
+// configuration.add(GePiSessionState.class, new ApplicationStateContribution("session", sessionStateCreator));
+// }
/**
* Redirect the user to the intended page when browsing through
@@ -267,4 +267,10 @@ public void handleRequestException(Throwable exception) throws IOException {
}
};
}
+
+// public static void contributeMappedEntityManager(Configuration configuration,
+// @Symbol(TapestryHttpInternalConstants.TAPESTRY_APP_PACKAGE_PARAM) String appRootPackage)
+// {
+// configuration.add(appRootPackage + ".data.api.v1");
+// }
}
diff --git a/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/FAQ.tml b/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/FAQ.tml
index ff6f49eb..aa973f1d 100644
--- a/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/FAQ.tml
+++ b/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/FAQ.tml
@@ -90,9 +90,9 @@
Why do full-text query or filter results highlight words that do not seem to match a query term?
- For full-text queries GePI expands abbreviations. Consider the abbreviation cyclic mechanical stress (CMS), used for example in PMC2654047. It is introduced at the beginning of the document and then used throughout the text. Thus, the query stress would only work on the first occurrence of the term when the long form is given. To allow matches for all the other places, too, we internally expand abbreviations to make such matches possible.
+ For full-text queries GePI expands abbreviations. Consider the abbreviation oscillatory shear stress (OS), used for example in PMC10835076. It is introduced at the beginning of the document and then used throughout the text. Thus, the query stress would only work on the first occurrence of the term when the long form is given. To allow matches for all the other places, too, we internally expand abbreviations to make such matches possible.
-
+
Show this example in GePI
diff --git a/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/Help.tml b/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/Help.tml
index 36bd44b2..6b12374b 100644
--- a/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/Help.tml
+++ b/gepi/gepi-webapp/src/main/resources/de/julielab/gepi/webapp/pages/Help.tml
@@ -494,11 +494,12 @@
flatly listing all retrieved interactions can be obtained.
- The API is realized through URL request parameters, i.e. the GePI Web address followed by a
+ The API is realized through URL request parameters, i.e. the GePI Web address followed by
+ /api/v1/
, a
single question mark (?
) and parameter-value pairs. A parameter-value pair
is separated by an equal sign (=
) and a sequence of such pairs are separated by
the ampersand characters (&
).
- For example:
https://gepi.coling.uni-jena.de?alist=mtor&blist=jun
+ For example: https://gepi.coling.uni-jena.de/api/v1?alist=mtor&blist=jun
A comprehensive list of parameters and their possible values is given in the table below.
diff --git a/gepi/reset_missing_documents.sh b/gepi/reset_missing_documents.sh
index 968c0812..9645e39c 100644
--- a/gepi/reset_missing_documents.sh
+++ b/gepi/reset_missing_documents.sh
@@ -31,15 +31,28 @@ fi
HEADER="-H Content-Type:application/json"
curl -XPOST $ES_URL/$ES_INDEX/_search $HEADER -d '{
"query": {
- "match_all": {}
- },
+ "match": {
+ "source": "pubmed"
+ }
+ },
+ "size": 0,
"aggs": {
"pmids": {
"terms": {
"field": "pmid",
"size": 10000000
}
- },
+ }
+ }
+}' > pmid_es_docid_aggregation.json
+curl -XPOST $ES_URL/$ES_INDEX/_search $HEADER -d '{
+ "query": {
+ "match": {
+ "source": "pmc"
+ }
+ },
+ "size": 0,
+ "aggs": {
"pmcids": {
"terms": {
"field": "pmcid",
@@ -47,15 +60,15 @@ curl -XPOST $ES_URL/$ES_INDEX/_search $HEADER -d '{
}
}
}
-}' > es_docid_aggregation.json
-grep -oE 'key":"[0-9]+' es_docid_aggregation.json | grep -oE '[0-9]+' > pmid_es.txt
-grep -oE 'key":"PMC[0-9]+' es_docid_aggregation.json | grep -oE 'PMC[0-9]+' > pmcid_es.txt
+}' > pmcid_es_docid_aggregation.json
+grep -oE 'key":"[0-9]+' pmid_es_docid_aggregation.json | grep -oE '[0-9]+' > pmid_es.txt
+grep -oE 'key":"PMC[0-9]+' pmcid_es_docid_aggregation.json | grep -oE 'PMC[0-9]+' > pmcid_es.txt
echo "PubMed: Got `wc -l pmid_pg.txt` IDs from Postgres and `wc -l pmid_es.txt` from ElasticSearch"
echo "PMC: Got `wc -l pmcid_pg.txt` IDs from Postgres and `wc -l pmcid_es.txt` from ElasticSearch"
-cat pmid_es.txt pmid_pg.txt | sort | uniq > pmid_missing.txt
-cat pmcid_es.txt pmcid_pg.txt | sort | uniq > pmcid_missing.txt
+cat pmid_es.txt pmid_pg.txt | sort | uniq -u > pmid_missing.txt
+cat pmcid_es.txt pmcid_pg.txt | sort | uniq -u > pmcid_missing.txt
echo "Missing PubMed: Got `wc -l pmid_missing.txt` unique doc IDs; assuming those are missing from ElasticSearch"
echo "Missing PMC: Got `wc -l pmcid_missing.txt` unique doc IDs; assuming those are missing from ElasticSearch"