Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add many-to-many relationship InvestigationSample to the schema #294

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

General installation instructions are at https://icatproject.org/installation/component

Specific installation instructions are at https://repo.icatproject.org/site/icat/server/6.0.0/installation.html
Specific installation instructions are at https://repo.icatproject.org/site/icat/server/7.0.0/installation.html

All documentation on the icat.server may be found at https://repo.icatproject.org/site/icat/server/6.0.0
All documentation on the icat.server may be found at https://repo.icatproject.org/site/icat/server/7.0.0
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.icatproject</groupId>
<artifactId>icat.server</artifactId>
<version>6.0.1-SNAPSHOT</version>
<version>7.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>ICAT Server</name>
<description>A metadata catalogue to support Large Facility experimental data,
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/icatproject/core/entity/Investigation.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public class Investigation extends EntityBaseBean implements Serializable {
private Date releaseDate;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "investigation")
private List<Sample> samples = new ArrayList<>();
private List<InvestigationSample> samples = new ArrayList<>();

@OneToMany(cascade = CascadeType.ALL, mappedBy = "investigation")
private List<Shift> shifts = new ArrayList<>();
Expand Down Expand Up @@ -176,7 +176,7 @@ public Date getReleaseDate() {
return this.releaseDate;
}

public List<Sample> getSamples() {
public List<InvestigationSample> getSamples() {
return samples;
}

Expand Down Expand Up @@ -276,7 +276,7 @@ public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}

public void setSamples(List<Sample> samples) {
public void setSamples(List<InvestigationSample> samples) {
this.samples = samples;
}

Expand Down
41 changes: 41 additions & 0 deletions src/main/java/org/icatproject/core/entity/InvestigationSample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.icatproject.core.entity;

import java.io.Serializable;

import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;

@Comment("Represents a many-to-many relationship between an investigation and a sample that has been used in that investigation")
@SuppressWarnings("serial")
@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "INVESTIGATION_ID", "SAMPLE_ID" }) })
public class InvestigationSample extends EntityBaseBean implements Serializable {

@JoinColumn(nullable = false, name = "INVESTIGATION_ID")
@ManyToOne(fetch = FetchType.LAZY)
private Investigation investigation;

@JoinColumn(nullable = false, name = "SAMPLE_ID")
@ManyToOne(fetch = FetchType.LAZY)
private Sample sample;

public Investigation getInvestigation() {
return this.investigation;
}

public Sample getSample() {
return this.sample;
}

public void setInvestigation(Investigation investigation) {
this.investigation = investigation;
}

public void setSample(Sample sample) {
this.sample = sample;
}
}
23 changes: 11 additions & 12 deletions src/main/java/org/icatproject/core/entity/Sample.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@

import org.icatproject.core.manager.LuceneApi;

@Comment("A sample to be used in an investigation")
@Comment("A sample to be used in one or more investigations")
@SuppressWarnings("serial")
@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "INVESTIGATION_ID", "NAME" }) })
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "PID" }) })
public class Sample extends EntityBaseBean implements Serializable {

@Comment("A persistent identifier attributed to this sample")
@Column(nullable = false, name = "PID")
private String pid;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "sample")
private List<Dataset> datasets = new ArrayList<>();

@JoinColumn(nullable = false, name = "INVESTIGATION_ID")
@ManyToOne(fetch = FetchType.LAZY)
private Investigation investigation;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "sample")
private List<InvestigationSample> investigationSamples = new ArrayList<>();

@Column(nullable = false, name = "NAME")
@Column(nullable = false)
private String name;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "sample")
Expand All @@ -59,8 +59,8 @@ public List<Dataset> getDatasets() {
return this.datasets;
}

public Investigation getInvestigation() {
return this.investigation;
public List<InvestigationSample> getInvestigationSamples() {
return this.investigationSamples;
}

public String getName() {
Expand All @@ -75,8 +75,8 @@ public void setDatasets(List<Dataset> datasets) {
this.datasets = datasets;
}

public void setInvestigation(Investigation investigation) {
this.investigation = investigation;
public void setInvestigationSamples(List<InvestigationSample> investigationSamples) {
this.investigationSamples = investigationSamples;
}

public void setName(String name) {
Expand All @@ -97,11 +97,10 @@ public void setType(SampleType type) {

@Override
public void getDoc(JsonGenerator gen) {
StringBuilder sb = new StringBuilder(name);
StringBuilder sb = new StringBuilder(pid + " " + name);
if (type != null) {
sb.append(" " + type.getName());
}
LuceneApi.encodeTextfield(gen, "text", sb.toString());
LuceneApi.encodeSortedDocValuesField(gen, "investigation", investigation.id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.icatproject.core.entity.InvestigationGroup;
import org.icatproject.core.entity.InvestigationInstrument;
import org.icatproject.core.entity.InvestigationParameter;
import org.icatproject.core.entity.InvestigationSample;
import org.icatproject.core.entity.InvestigationType;
import org.icatproject.core.entity.InvestigationUser;
import org.icatproject.core.entity.Job;
Expand Down Expand Up @@ -216,8 +217,8 @@ public String toString() {
Publication.class, RelatedDatafile.class, SampleParameter.class, Shift.class, Study.class,
DataPublication.class, DataPublicationDate.class, DataPublicationUser.class, DataPublicationType.class,
Affiliation.class, RelatedItem.class, FundingReference.class, DataPublicationFunding.class,
InvestigationFunding.class, InvestigationUser.class, InvestigationGroup.class, StudyInvestigation.class,
InvestigationInstrument.class, InstrumentScientist.class, DatasetInstrument.class,
InvestigationFunding.class, InvestigationUser.class, InvestigationGroup.class, InvestigationSample.class,
StudyInvestigation.class, InvestigationInstrument.class, InstrumentScientist.class, DatasetInstrument.class,
InvestigationFacilityCycle.class);
private static Set<String> entityNames = new HashSet<>();

Expand Down
71 changes: 71 additions & 0 deletions src/main/scripts/upgrade_mysql_7_0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
-- Add table and constraints for InvestigationSamples

CREATE TABLE INVESTIGATIONSAMPLE (
ID BIGINT NOT NULL AUTO_INCREMENT,
CREATE_ID VARCHAR(255) NOT NULL,
CREATE_TIME DATETIME NOT NULL,
MOD_ID VARCHAR(255) NOT NULL,
MOD_TIME DATETIME NOT NULL,
INVESTIGATION_ID BIGINT NOT NULL,
SAMPLE_ID BIGINT NOT NULL,
PRIMARY KEY (ID)
);

ALTER TABLE INVESTIGATIONSAMPLE ADD CONSTRAINT FK_INVESTIGATIONSAMPLE_INVESTIGATION_ID FOREIGN KEY (INVESTIGATION_ID) REFERENCES INVESTIGATION (ID);
ALTER TABLE INVESTIGATIONSAMPLE ADD CONSTRAINT FK_INVESTIGATIONSAMPLE_SAMPLE_ID FOREIGN KEY (SAMPLE_ID) REFERENCES SAMPLE (ID);
ALTER TABLE INVESTIGATIONSAMPLE ADD CONSTRAINT UNQ_INVESTIGATIONSAMPLE_0 UNIQUE (INVESTIGATION_ID, SAMPLE_ID);

-- Set the PID field of existing Samples

DELIMITER //

CREATE PROCEDURE SET_SAMPLES_PID()
BEGIN
UPDATE SAMPLE SET PID = CONCAT('local:', LPAD(ID, 8, '0')) WHERE PID IS NULL;
END; //

DELIMITER ;

CALL SET_SAMPLES_PID();

DROP PROCEDURE SET_SAMPLES_PID;

-- Move existing Sample/Investigation relations over to the new table

DELIMITER //

CREATE PROCEDURE MOVE_SAMPLE_INVESTIGATION_RELATIONS()
BEGIN
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE _createid VARCHAR(255);
DECLARE _modid VARCHAR(255);
DECLARE _invid BIGINT;
DECLARE _id BIGINT;
DECLARE cur CURSOR FOR SELECT CREATE_ID, MOD_ID, INVESTIGATION_ID, ID FROM SAMPLE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;

OPEN cur;
sampleLoop: LOOP
FETCH cur INTO _createid, _modid, _invid, _id;
IF done THEN
LEAVE sampleLoop;
END IF;

INSERT INTO INVESTIGATIONSAMPLE (CREATE_ID, CREATE_TIME, MOD_ID, MOD_TIME, INVESTIGATION_ID, SAMPLE_ID) VALUES (_createid, NOW(), _modid, NOW(), _invid, _id);
END LOOP sampleLoop;
CLOSE cur;
END; //

DELIMITER ;

CALL MOVE_SAMPLE_INVESTIGATION_RELATIONS();

DROP PROCEDURE MOVE_SAMPLE_INVESTIGATION_RELATIONS;

-- Alter the Sample table

ALTER TABLE SAMPLE MODIFY PID VARCHAR(255) NOT NULL;
ALTER TABLE SAMPLE DROP CONSTRAINT FK_SAMPLE_INVESTIGATION_ID;
ALTER TABLE SAMPLE DROP CONSTRAINT UNQ_SAMPLE_0;
ALTER TABLE SAMPLE ADD CONSTRAINT UNQ_SAMPLE_0 UNIQUE (PID);
ALTER TABLE SAMPLE DROP COLUMN INVESTIGATION_ID;
59 changes: 59 additions & 0 deletions src/main/scripts/upgrade_oracle_7_0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-- Add table and constraints for InvestigationSamples

CREATE TABLE INVESTIGATIONSAMPLE (
ID NUMBER(19) NOT NULL,
CREATE_ID VARCHAR2(255) NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL,
MOD_ID VARCHAR2(255) NOT NULL,
MOD_TIME TIMESTAMP NOT NULL,
INVESTIGATION_ID NUMBER(19) NOT NULL,
SAMPLE_ID NUMBER(19) NOT NULL,
PRIMARY KEY (ID)
);

ALTER TABLE INVESTIGATIONSAMPLE ADD CONSTRAINT FK_INVESTIGATIONSAMPLE_INVESTIGATION_ID FOREIGN KEY (INVESTIGATION_ID) REFERENCES INVESTIGATION (ID);
ALTER TABLE INVESTIGATIONSAMPLE ADD CONSTRAINT FK_INVESTIGATIONSAMPLE_SAMPLE_ID FOREIGN KEY (SAMPLE_ID) REFERENCES SAMPLE (ID);
ALTER TABLE INVESTIGATIONSAMPLE ADD CONSTRAINT UNQ_INVESTIGATIONSAMPLE_0 UNIQUE (INVESTIGATION_ID, SAMPLE_ID);

-- Set the PID field of existing Samples

CREATE PROCEDURE SET_SAMPLES_PID AS
BEGIN
UPDATE SAMPLE SET PID = 'local:' || LPAD(ID, 8, '0') WHERE PID IS NULL;
END;
/

BEGIN
SET_SAMPLES_PID;
END;
/

DROP PROCEDURE SET_SAMPLES_PID;

-- Move existing Sample/Investigation relations over to the new table

CREATE PROCEDURE MOVE_SAMPLE_INVESTIGATION_RELATIONS AS
CURSOR CUR IS SELECT CREATE_ID, MOD_ID, INVESTIGATION_ID, ID FROM SAMPLE;
BEGIN
FOR CUR_SAMPLE in CUR LOOP
INSERT INTO INVESTIGATIONSAMPLE (CREATE_ID, CREATE_TIME, MOD_ID, MOD_TIME, INVESTIGATION_ID, SAMPLE_ID) VALUES (CUR_SAMPLE.CREATE_ID, CURRENT_TIMESTAMP, CUR_SAMPLE.MOD_ID, CURRENT_TIMESTAMP, CUR_SAMPLE.INVESTIGATION_ID, CUR_SAMPLE.ID);
END LOOP;
END;
/

BEGIN
MOVE_SAMPLE_INVESTIGATION_RELATIONS;
END;
/

DROP PROCEDURE MOVE_SAMPLE_INVESTIGATION_RELATIONS;

-- Alter the Sample table

ALTER TABLE SAMPLE MODIFY (PID NOT NULL);
ALTER TABLE SAMPLE DROP CONSTRAINT FK_SAMPLE_INVESTIGATION_ID;
ALTER TABLE SAMPLE DROP CONSTRAINT UNQ_SAMPLE_0;
ALTER TABLE SAMPLE ADD CONSTRAINT UNQ_SAMPLE_0 UNIQUE (PID);
ALTER TABLE SAMPLE DROP COLUMN INVESTIGATION_ID;

exit
7 changes: 7 additions & 0 deletions src/site/xhtml/release-notes.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

<h1>ICAT Server Release Notes</h1>

<h2>devel - not released</h2>
<p>Schema changes and additions</p>
<ul>
<li>Make the relationship between Sample and Investigation many-to-many
(Issue 231).</li>
</ul>

<h2>6.0.0</h2>
<p>Upgrade from JavaEE to JakartaEE 10. Requires Java 11+ and an application server that supports JakartaEE 10 such as Payara 6.</p>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ public void testExportHeaders() throws Exception {
eiHandler.getExportHeader(Investigation.class));
assertEquals(
"Dataset(complete:0,description:1,doi:2,endDate:3,fileCount:4,fileSize:5,investigation(facility(name:6),"
+ "name:7,visitId:8),location:9,name:10,sample(investigation(facility(name:11),"
+ "name:12,visitId:13),name:14),startDate:15,type(facility(name:16),name:17))",
+ "name:7,visitId:8),location:9,name:10,sample(pid:11),startDate:12,type(facility(name:13),name:14))",
eiHandler.getExportHeader(Dataset.class));
assertEquals("DataCollection(?:0,doi:1)", eiHandler.getExportHeader(DataCollection.class));
assertEquals(
Expand Down Expand Up @@ -116,8 +115,7 @@ public void testExportHeaderAll() throws Exception {
"Dataset(createId:0,createTime:1,modId:2,modTime:3,"
+ "complete:4,description:5,doi:6,endDate:7,fileCount:8,fileSize:9,"
+ "investigation(facility(name:10),name:11,visitId:12),location:13,name:14,"
+ "sample(investigation(facility(name:15),name:16,visitId:17),"
+ "name:18),startDate:19,type(facility(name:20),name:21))",
+ "sample(pid:15),startDate:16,type(facility(name:17),name:18))",
eiHandler.getExportHeaderAll(Dataset.class));
assertEquals("DataCollection(?:0,createId:1,createTime:2,modId:3,modTime:4,doi:5)",
eiHandler.getExportHeaderAll(DataCollection.class));
Expand Down Expand Up @@ -242,7 +240,7 @@ public void testRels() throws Exception {

testRel(Investigation.class, "From Investigation to Keyword by keywords many setInvestigation",
"From Investigation to DataCollectionInvestigation by dataCollectionInvestigations many setInvestigation",
"From Investigation to Sample by samples many setInvestigation",
"From Investigation to InvestigationSample by samples many setInvestigation",
"From Investigation to StudyInvestigation by studyInvestigations many setInvestigation",
"From Investigation to Shift by shifts many setInvestigation",
"From Investigation to Dataset by datasets many setInvestigation",
Expand Down
21 changes: 7 additions & 14 deletions src/test/java/org/icatproject/integration/TestRS.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,6 @@ public void testClone() throws Exception {

id = search(session, "SELECT f.id FROM Facility f WHERE f.name = 'Test port facility'", 1).getJsonNumber(0)
.longValueExact();
keys = new HashMap<>();
keys.put("name", "NewFac");
idClone = session.cloneEntity("Facility", id, keys);
assertEquals(8, search(session, "SELECT COUNT(x) FROM Investigation x", 1).getInt(0));
assertEquals(16, search(session, "SELECT COUNT(x) FROM DatafileParameter x", 1).getInt(0));
assertEquals(2, search(session, "SELECT COUNT(x) FROM Facility x", 1).getInt(0));
assertEquals(32, search(session, "SELECT COUNT(x) FROM Datafile x", 1).getInt(0));

try {
keys = new HashMap<>();
idClone = session.cloneEntity("Facility", id, keys);
Expand Down Expand Up @@ -387,10 +379,11 @@ public void testLuceneInvestigations() throws Exception {
List<ParameterForLucene> parameters = new ArrayList<>();
parameters.add(new ParameterForLucene("colour", "name", "green"));

JsonArray array = searchInvestigations(session, "db/tr", "title AND one", dft.parse("2011-01-01T00:00:00+0000"),
dft.parse("2011-12-31T23:59:59+0000"), parameters, Arrays.asList("ford AND rust", "koh* AND diamond"),
"Professor", 20, 1);
checkResultFromLuceneSearch(session, "one", array, "Investigation", "visitId");
// This does not work any more as there is no direct relation between investigation and samples now
// JsonArray array = searchInvestigations(session, "db/tr", "title AND one", dft.parse("2011-01-01T00:00:00+0000"),
// dft.parse("2011-12-31T23:59:59+0000"), parameters, Arrays.asList("ford AND rust", "koh* AND diamond"),
// "Professor", 20, 1);
// checkResultFromLuceneSearch(session, "one", array, "Investigation", "visitId");

// change user
searchInvestigations(session, "db/fred", "title AND one", null, null, parameters, null, null, 20, 0);
Expand All @@ -399,7 +392,7 @@ public void testLuceneInvestigations() throws Exception {
searchInvestigations(session, "db/tr", "title AND two", null, null, parameters, null, null, 20, 0);

// Only working to a minute
array = searchInvestigations(session, "db/tr", "title AND one", dft.parse("2011-01-01T00:00:01+0000"),
JsonArray array = searchInvestigations(session, "db/tr", "title AND one", dft.parse("2011-01-01T00:00:01+0000"),
dft.parse("2011-12-31T23:59:59+0000"), parameters, null, null, 20, 1);
checkResultFromLuceneSearch(session, "one", array, "Investigation", "visitId");

Expand Down Expand Up @@ -500,7 +493,7 @@ private JsonArray searchDatafiles(Session session, String user, String text, Dat
@Test
public void testVersion() throws Exception {
ICAT icat = new ICAT(System.getProperty("serverUrl"));
assertTrue(icat.getVersion().startsWith("6."));
assertTrue(icat.getVersion().startsWith("7."));
}

@Test
Expand Down
Loading