diff --git a/src/main/java/org/icatproject/core/entity/Datafile.java b/src/main/java/org/icatproject/core/entity/Datafile.java index 3905dc87..b58d158a 100644 --- a/src/main/java/org/icatproject/core/entity/Datafile.java +++ b/src/main/java/org/icatproject/core/entity/Datafile.java @@ -206,6 +206,9 @@ public void getDoc(JsonGenerator gen) { if (description != null) { SearchApi.encodeString(gen, "description", description); } + if (location != null) { + SearchApi.encodeString(gen, "location", location); + } if (doi != null) { SearchApi.encodeString(gen, "doi", doi); } @@ -220,7 +223,15 @@ public void getDoc(JsonGenerator gen) { SearchApi.encodeLong(gen, "date", modTime); } SearchApi.encodeString(gen, "id", id); - SearchApi.encodeString(gen, "investigation.id", dataset.getInvestigation().id); + if (dataset != null) { + SearchApi.encodeString(gen, "dataset.id", dataset.id); + SearchApi.encodeString(gen, "dataset.name", dataset.getName()); + Investigation investigation = dataset.getInvestigation(); + if (investigation != null) { + SearchApi.encodeString(gen, "investigation.id", investigation.id); + SearchApi.encodeString(gen, "investigation.name", investigation.getName()); + } + } } /** @@ -239,16 +250,27 @@ public static Map getDocumentFields() throws IcatExcepti EntityInfoHandler eiHandler = EntityInfoHandler.getInstance(); Relationship[] datafileFormatRelationships = { eiHandler.getRelationshipsByName(Datafile.class).get("datafileFormat") }; - Relationship[] investigationRelationships = { + Relationship[] datasetRelationships = { eiHandler.getRelationshipsByName(Datafile.class).get("dataset") }; + Relationship[] investigationRelationships = { + eiHandler.getRelationshipsByName(Datafile.class).get("dataset"), + eiHandler.getRelationshipsByName(Dataset.class).get("investigation") }; + Relationship[] instrumentRelationships = { + eiHandler.getRelationshipsByName(Investigation.class).get("investigationInstruments"), + eiHandler.getRelationshipsByName(InvestigationInstrument.class).get("instrument") }; documentFields.put("name", null); documentFields.put("description", null); + documentFields.put("location", null); documentFields.put("doi", null); documentFields.put("date", null); documentFields.put("id", null); - documentFields.put("investigation.id", investigationRelationships); + documentFields.put("dataset.id", null); + documentFields.put("dataset.name", datasetRelationships); + documentFields.put("investigation.id", datasetRelationships); + documentFields.put("investigation.name", investigationRelationships); documentFields.put("datafileFormat.id", null); documentFields.put("datafileFormat.name", datafileFormatRelationships); + documentFields.put("InvestigationInstrument instrument.id", instrumentRelationships); } return documentFields; } diff --git a/src/main/java/org/icatproject/core/entity/Dataset.java b/src/main/java/org/icatproject/core/entity/Dataset.java index 7ebb8980..970c0946 100644 --- a/src/main/java/org/icatproject/core/entity/Dataset.java +++ b/src/main/java/org/icatproject/core/entity/Dataset.java @@ -209,6 +209,13 @@ public void getDoc(JsonGenerator gen) { } SearchApi.encodeString(gen, "id", id); SearchApi.encodeString(gen, "investigation.id", investigation.id); + SearchApi.encodeString(gen, "investigation.name", investigation.getName()); + if (investigation.getStartDate() != null) { + SearchApi.encodeLong(gen, "investigation.startDate", investigation.getStartDate()); + } else { + SearchApi.encodeLong(gen, "investigation.startDate", investigation.getCreateTime()); + } + SearchApi.encodeString(gen, "investigation.title", investigation.getTitle()); if (sample != null) { sample.getDoc(gen, "sample."); @@ -234,6 +241,11 @@ public static Map getDocumentFields() throws IcatExcepti Relationship[] sampleTypeRelationships = { eiHandler.getRelationshipsByName(Dataset.class).get("sample"), eiHandler.getRelationshipsByName(Sample.class).get("type") }; Relationship[] typeRelationships = { eiHandler.getRelationshipsByName(Dataset.class).get("type") }; + Relationship[] investigationRelationships = { + eiHandler.getRelationshipsByName(Dataset.class).get("investigation") }; + Relationship[] instrumentRelationships = { + eiHandler.getRelationshipsByName(Investigation.class).get("investigationInstruments"), + eiHandler.getRelationshipsByName(InvestigationInstrument.class).get("instrument") }; documentFields.put("name", null); documentFields.put("description", null); documentFields.put("doi", null); @@ -241,6 +253,9 @@ public static Map getDocumentFields() throws IcatExcepti documentFields.put("endDate", null); documentFields.put("id", null); documentFields.put("investigation.id", null); + documentFields.put("investigation.title", investigationRelationships); + documentFields.put("investigation.name", investigationRelationships); + documentFields.put("investigation.startDate", investigationRelationships); documentFields.put("sample.id", null); documentFields.put("sample.name", sampleRelationships); documentFields.put("sample.investigation.id", sampleRelationships); @@ -248,6 +263,7 @@ public static Map getDocumentFields() throws IcatExcepti documentFields.put("sample.type.name", sampleTypeRelationships); documentFields.put("type.id", null); documentFields.put("type.name", typeRelationships); + documentFields.put("InvestigationInstrument instrument.id", instrumentRelationships); } return documentFields; } diff --git a/src/main/java/org/icatproject/core/entity/Instrument.java b/src/main/java/org/icatproject/core/entity/Instrument.java index 485550f4..97dc2bb4 100644 --- a/src/main/java/org/icatproject/core/entity/Instrument.java +++ b/src/main/java/org/icatproject/core/entity/Instrument.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; +import javax.json.stream.JsonGenerator; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; @@ -14,6 +15,8 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.icatproject.core.manager.search.SearchApi; + @Comment("Used by a user within an investigation") @SuppressWarnings("serial") @Entity @@ -138,4 +141,13 @@ public void setShifts(List shifts) { this.shifts = shifts; } + @Override + public void getDoc(JsonGenerator gen) { + if (fullName != null) { + SearchApi.encodeText(gen, "instrument.fullName", fullName); + } + SearchApi.encodeString(gen, "instrument.name", name); + SearchApi.encodeString(gen, "instrument.id", id); + } + } diff --git a/src/main/java/org/icatproject/core/entity/InstrumentScientist.java b/src/main/java/org/icatproject/core/entity/InstrumentScientist.java index 0cc5c794..795ada82 100644 --- a/src/main/java/org/icatproject/core/entity/InstrumentScientist.java +++ b/src/main/java/org/icatproject/core/entity/InstrumentScientist.java @@ -2,6 +2,7 @@ import java.io.Serializable; +import javax.json.stream.JsonGenerator; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; @@ -9,6 +10,8 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.icatproject.core.manager.search.SearchApi; + @Comment("Relationship between an ICAT user as an instrument scientist and the instrument") @SuppressWarnings("serial") @Entity @@ -43,4 +46,11 @@ public void setInstrument(Instrument instrument) { public InstrumentScientist() { } + @Override + public void getDoc(JsonGenerator gen) { + user.getDoc(gen); + SearchApi.encodeString(gen, "instrument.id", instrument.id); + SearchApi.encodeString(gen, "id", id); + } + } diff --git a/src/main/java/org/icatproject/core/entity/Investigation.java b/src/main/java/org/icatproject/core/entity/Investigation.java index 50ccd474..e3fc6d73 100644 --- a/src/main/java/org/icatproject/core/entity/Investigation.java +++ b/src/main/java/org/icatproject/core/entity/Investigation.java @@ -310,6 +310,8 @@ public static Map getDocumentFields() throws IcatExcepti Relationship[] typeRelationships = { eiHandler.getRelationshipsByName(Investigation.class).get("type") }; Relationship[] facilityRelationships = { eiHandler.getRelationshipsByName(Investigation.class).get("facility") }; + Relationship[] sampleRelationships = { eiHandler.getRelationshipsByName(Investigation.class).get("samples") }; + Relationship[] instrumentRelationships = { eiHandler.getRelationshipsByName(Investigation.class).get("investigationInstruments"), eiHandler.getRelationshipsByName(InvestigationInstrument.class).get("instrument") }; documentFields.put("name", null); documentFields.put("visitId", null); documentFields.put("title", null); @@ -322,6 +324,10 @@ public static Map getDocumentFields() throws IcatExcepti documentFields.put("facility.id", null); documentFields.put("type.name", typeRelationships); documentFields.put("type.id", null); + documentFields.put("Sample name", sampleRelationships); + documentFields.put("InvestigationInstrument instrument.fullName", instrumentRelationships); + documentFields.put("InvestigationInstrument instrument.id", instrumentRelationships); + documentFields.put("InvestigationInstrument instrument.name", instrumentRelationships); } return documentFields; } diff --git a/src/main/java/org/icatproject/core/entity/InvestigationInstrument.java b/src/main/java/org/icatproject/core/entity/InvestigationInstrument.java index b8f751f4..7a07efff 100644 --- a/src/main/java/org/icatproject/core/entity/InvestigationInstrument.java +++ b/src/main/java/org/icatproject/core/entity/InvestigationInstrument.java @@ -2,6 +2,7 @@ import java.io.Serializable; +import javax.json.stream.JsonGenerator; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; @@ -9,6 +10,8 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.icatproject.core.manager.search.SearchApi; + @Comment("Represents a many-to-many relationship between an investigation and the instruments assigned") @SuppressWarnings("serial") @Entity @@ -39,4 +42,11 @@ public void setInvestigation(Investigation investigation) { this.investigation = investigation; } + @Override + public void getDoc(JsonGenerator gen) { + instrument.getDoc(gen); + SearchApi.encodeString(gen, "investigation.id", investigation.id); + SearchApi.encodeString(gen, "id", id); + } + } diff --git a/src/main/java/org/icatproject/core/manager/PropertyHandler.java b/src/main/java/org/icatproject/core/manager/PropertyHandler.java index 276a28d6..f5374ba7 100644 --- a/src/main/java/org/icatproject/core/manager/PropertyHandler.java +++ b/src/main/java/org/icatproject/core/manager/PropertyHandler.java @@ -397,8 +397,9 @@ private void init() { * currently override the EntityBaseBean.getDoc() method. This should * result in no change to behaviour if the property is not specified. */ - entitiesToIndex.addAll(Arrays.asList("Datafile", "Dataset", "Investigation", "InvestigationUser", - "DatafileParameter", "DatasetParameter", "InvestigationParameter", "Sample")); + entitiesToIndex.addAll(Arrays.asList("Datafile", "Dataset", "Investigation", "InvestigationInstrument", + "InstrumentScientist", "InvestigationUser", "DatafileParameter", "DatasetParameter", + "InvestigationParameter", "Sample", "Parameter", "User")); logger.info("search.entitiesToIndex not set. Defaulting to: {}", entitiesToIndex.toString()); } formattedProps.add("search.entitiesToIndex " + entitiesToIndex.toString()); @@ -485,9 +486,9 @@ private void init() { if (searchUrls.size() != 1) { String msg = "Exactly one value for search.urls must be provided when using " + searchEngine; throw new IllegalStateException(msg); - // } else if (searchUrls.size() == 0) { - // String msg = "At least one value for search.urls must be provided"; - // throw new IllegalStateException(msg); + // } else if (searchUrls.size() == 0) { + // String msg = "At least one value for search.urls must be provided"; + // throw new IllegalStateException(msg); } formattedProps.add("search.urls" + " " + searchUrls.toString()); logger.info("Using {} as search engine with url(s) {}", searchEngine, searchUrls); @@ -514,7 +515,6 @@ private void init() { logger.info("'search.engine' entry not present so no free text search available"); } - unitAliasOptions = props.getString("units", ""); /* diff --git a/src/main/java/org/icatproject/core/manager/search/LuceneApi.java b/src/main/java/org/icatproject/core/manager/search/LuceneApi.java index a422abad..93701e7c 100644 --- a/src/main/java/org/icatproject/core/manager/search/LuceneApi.java +++ b/src/main/java/org/icatproject/core/manager/search/LuceneApi.java @@ -62,7 +62,7 @@ public JsonObject buildSearchAfter(ScoredEntityBaseBean lastBean, String sort) t builder.add("score", score); } JsonArrayBuilder arrayBuilder; - if (sort == null || sort.equals("")) { + if (sort == null || sort.equals("") || sort.equals("{}")) { arrayBuilder = Json.createArrayBuilder().add(score); } else { arrayBuilder = searchAfterArrayBuilder(lastBean, sort); @@ -99,7 +99,7 @@ public void addNow(String entityName, List ids, EntityManager manager, gen.writeEnd(); return null; } catch (Exception e) { - logger.error("About to throw internal exception because of", e); + logger.error("About to throw internal exception for ids {} because of", ids, e); throw new IcatException(IcatExceptionType.INTERNAL, e.getMessage()); } finally { manager.close(); diff --git a/src/main/java/org/icatproject/core/manager/search/SearchApi.java b/src/main/java/org/icatproject/core/manager/search/SearchApi.java index d418e64f..a7c56a29 100644 --- a/src/main/java/org/icatproject/core/manager/search/SearchApi.java +++ b/src/main/java/org/icatproject/core/manager/search/SearchApi.java @@ -172,7 +172,7 @@ public static void encodeText(JsonGenerator gen, String name, String value) { */ public JsonValue buildSearchAfter(ScoredEntityBaseBean lastBean, String sort) throws IcatException { JsonArrayBuilder arrayBuilder; - if (sort != null && !sort.equals("")) { + if (sort != null && !sort.equals("") || sort.equals("{}")) { arrayBuilder = searchAfterArrayBuilder(lastBean, sort); } else { arrayBuilder = Json.createArrayBuilder(); diff --git a/src/main/java/org/icatproject/exposed/ICATRest.java b/src/main/java/org/icatproject/exposed/ICATRest.java index 4603712e..d486cc2c 100644 --- a/src/main/java/org/icatproject/exposed/ICATRest.java +++ b/src/main/java/org/icatproject/exposed/ICATRest.java @@ -1256,6 +1256,11 @@ public String search(@Context HttpServletRequest request, @QueryParam("sessionId * "range" key should denote an array of objects with "lower" * and "upper" values. * + * @param restrict + * Whether to perform a quicker search which restricts the + * results based on an InvestigationUser or + * InstrumentScientist being able to read their "own" data. + * * @return Set of entity ids, relevance scores and Document source encoded as * json. * @@ -1267,14 +1272,15 @@ public String search(@Context HttpServletRequest request, @QueryParam("sessionId @Produces(MediaType.APPLICATION_JSON) public String search(@Context HttpServletRequest request, @QueryParam("sessionId") String sessionId, @QueryParam("query") String query, @QueryParam("search_after") String searchAfter, - @QueryParam("limit") int limit, @QueryParam("sort") String sort, @QueryParam("facets") String facets) + @QueryParam("limit") int limit, @QueryParam("sort") String sort, @QueryParam("facets") String facets, + @QueryParam("restrict") boolean restrict) throws IcatException { if (query == null) { throw new IcatException(IcatExceptionType.BAD_PARAMETER, "query is not set"); } String userName = beanManager.getUserName(sessionId, manager); JsonValue searchAfterValue = null; - if (searchAfter.length() > 0) { + if (searchAfter != null && searchAfter.length() > 0) { try (JsonReader jr = Json.createReader(new StringReader(searchAfter))) { searchAfterValue = jr.read(); } @@ -1282,6 +1288,13 @@ public String search(@Context HttpServletRequest request, @QueryParam("sessionId ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (JsonReader jr = Json.createReader(new StringReader(query))) { JsonObject jo = jr.readObject(); + if (restrict && !jo.containsKey("user")) { + JsonObjectBuilder builder = Json.createObjectBuilder(); + for (Entry entry : jo.entrySet()) { + builder.add(entry.getKey(), entry.getValue()); + } + jo = builder.add("user", userName).build(); + } String target = jo.getString("target", null); if (jo.containsKey("parameters")) { for (JsonValue val : jo.getJsonArray("parameters")) { @@ -1318,7 +1331,7 @@ public String search(@Context HttpServletRequest request, @QueryParam("sessionId } else { throw new IcatException(IcatExceptionType.BAD_PARAMETER, "target:" + target + " is not expected"); } - logger.debug("Free text search with query: {}", jo.toString()); + logger.debug("Free text search with query: {}, facets: {}", jo.toString(), facets); result = beanManager.freeTextSearchDocs(userName, jo, searchAfterValue, limit, sort, facets, manager, request.getRemoteAddr(), klass);