Skip to content

Commit

Permalink
small fixes and features
Browse files Browse the repository at this point in the history
  • Loading branch information
wow-such-code committed Oct 7, 2024
1 parent 3ec62fd commit a87fed8
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 37 deletions.
20 changes: 16 additions & 4 deletions src/main/java/life/qbic/io/commandline/AuthenticationOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.StringJoiner;
import java.util.TreeMap;
import org.apache.logging.log4j.LogManager;
Expand All @@ -29,13 +31,13 @@ public class AuthenticationOptions {

@Option(
names = {"-as", "-as_url"},
description = "ApplicationServer URL",
description = "OpenBIS ApplicationServer URL",
scope = CommandLine.ScopeType.INHERIT)
private String as_url;

@Option(
names = {"-dss", "--dss_url"},
description = "DatastoreServer URL",
description = "OpenBIS DatastoreServer URL",
scope = CommandLine.ScopeType.INHERIT)
private String dss_url;

Expand Down Expand Up @@ -85,14 +87,14 @@ public String getSeekURL() {
return seek_url;
}

public String getDSS() {
public String getOpenbisDSS() {
if(dss_url == null & configPath!=null && !configPath.isBlank()) {
dss_url = ReadProperties.getProperties(configPath).get("dss");
}
return dss_url;
}

public String getAS() {
public String getOpenbisAS() {
if(as_url == null & configPath!=null && !configPath.isBlank()) {
as_url = ReadProperties.getProperties(configPath).get("as");
}
Expand All @@ -107,6 +109,16 @@ public char[] getOpenbisPassword() {
return openbisPasswordOptions.getPassword();
}

public String getOpenbisBaseURL() throws MalformedURLException {
URL asURL = new URL(as_url);
String res = asURL.getProtocol()+ "://" +asURL.getHost();
if(asURL.getPort()!=-1) {
res+=":"+asURL.getPort();
}
System.err.println(res);
return res;
}

/**
* <a href="https://picocli.info/#_optionally_interactive">official picocli documentation example</a>
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class DownloadPetabCommand implements Runnable {

@Override
public void run() {
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getAS(), auth.getDSS());
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getOpenbisAS(), auth.getOpenbisDSS());
OpenbisConnector openbis = new OpenbisConnector(authentication);

List<DataSet> datasets = openbis.findDataSets(Collections.singletonList(datasetCode));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void run() {
} else {
System.out.println("Querying experiment in all available spaces...");
}
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getAS());
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getOpenbisAS());
OpenbisConnector openbis = new OpenbisConnector(authentication);
List<DataSet> datasets = openbis.listDatasetsOfExperiment(spaces, experimentCode).stream()
.sorted(Comparator.comparing(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void run() {
} else {
summary.add("Querying samples in all available spaces...");
}
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getAS());
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getOpenbisAS());
OpenbisConnector openbis = new OpenbisConnector(authentication);
Map<SampleTypeConnection, Integer> hierarchy = openbis.queryFullSampleHierarchy(spaces);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void run() {
} else {
summary.add("Querying samples in all available spaces...");
}
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getAS());
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getOpenbisAS());
OpenbisConnector openbis = new OpenbisConnector(authentication);

if (spaces.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void run() {
System.out.println("Connecting to openBIS...");

OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(),
auth.getAS(), auth.getDSS());
auth.getOpenbisAS(), auth.getOpenbisDSS());

openbis = new OpenbisConnector(authentication);

Expand Down Expand Up @@ -106,8 +106,8 @@ public void run() {
byte[] httpCredentials = Base64.encodeBase64(
(auth.getSeekUser() + ":" + new String(auth.getSeekPassword())).getBytes());
try {
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, "seek_test",
"lisym default study");
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, auth.getOpenbisBaseURL(),
"seek_test", "lisym default study");
translator = seek.getTranslator();
} catch (URISyntaxException | IOException | InterruptedException e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ public void run() {
System.out.println("auth...");

OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(),
auth.getAS(), auth.getDSS());
auth.getOpenbisAS(), auth.getOpenbisDSS());
System.out.println("openbis...");

openbis = new OpenbisConnector(authentication);

byte[] httpCredentials = Base64.encodeBase64(
(auth.getSeekUser() + ":" + new String(auth.getSeekPassword())).getBytes());
try {
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, "seek_test",
"lisym default study");
seek = new SEEKConnector(auth.getSeekURL(), httpCredentials, auth.getOpenbisBaseURL(),
"seek_test", "lisym default study");
translator = seek.getTranslator();
} catch (URISyntaxException | IOException | InterruptedException e) {
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class UploadDatasetCommand implements Runnable {

@Override
public void run() {
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getAS(), auth.getDSS());
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getOpenbisAS(), auth.getOpenbisDSS());
openbis = new OpenbisConnector(authentication);

if(!pathValid(dataPath)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class UploadPetabResultCommand implements Runnable {

@Override
public void run() {
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getAS(), auth.getDSS());
OpenBIS authentication = App.loginToOpenBIS(auth.getOpenbisPassword(), auth.getOpenbisUser(), auth.getOpenbisAS(), auth.getOpenbisDSS());
openbis = new OpenbisConnector(authentication);

if(!pathValid(dataPath)) {
Expand Down
36 changes: 29 additions & 7 deletions src/main/java/life/qbic/model/OpenbisSeekTranslator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static java.util.Map.entry;

import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment;
Expand All @@ -16,13 +15,13 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import life.qbic.model.isa.GenericSeekAsset;
import life.qbic.model.isa.ISAAssay;
import life.qbic.model.isa.ISADataFile;
import life.qbic.model.isa.ISASample;
import life.qbic.model.isa.ISASampleType;
import life.qbic.model.isa.ISASampleType.SampleAttribute;
Expand All @@ -34,12 +33,24 @@ public class OpenbisSeekTranslator {
private final String DEFAULT_PROJECT_ID;
private final String DEFAULT_STUDY_ID;
private final String DEFAULT_TRANSFERRED_SAMPLE_TITLE = "openBIS Name";
private final String openBISBaseURL;

public OpenbisSeekTranslator(String defaultProjectID, String defaultStudyID) {
public OpenbisSeekTranslator(String openBISBaseURL, String defaultProjectID, String defaultStudyID) {
this.openBISBaseURL = openBISBaseURL;
this.DEFAULT_PROJECT_ID = defaultProjectID;
this.DEFAULT_STUDY_ID = defaultStudyID;
}

private String generateOpenBISLinkFromPermID(String entityType, String permID) {
StringBuilder builder = new StringBuilder();
builder.append(openBISBaseURL);
builder.append("#entity=");
builder.append(entityType);
builder.append("&permId=");
builder.append(permID);
return builder.toString();
}

Map<String, String> experimentTypeToAssayClass = Map.ofEntries(
entry("00_MOUSE_DATABASE", "EXP"),
entry("00_PATIENT_DATABASE", "EXP"),
Expand All @@ -63,8 +74,8 @@ public OpenbisSeekTranslator(String defaultProjectID, String defaultStudyID) {
new SampleAttributeType("8", "String", "String")),
entry(DataType.HYPERLINK, new SampleAttributeType("8", "String", "String")),
entry(DataType.XML, new SampleAttributeType("7", "Text", "Text")),
entry(DataType.SAMPLE, //should be handled before mapping types
new SampleAttributeType("8", "String", "String")),
entry(DataType.SAMPLE, //we link the sample as URL to openBIS for now
new SampleAttributeType("5", "Web link", "String")),
entry(DataType.DATE, new SampleAttributeType("2", "Date time", "Date"))
);

Expand Down Expand Up @@ -150,12 +161,23 @@ public SeekStructure translate(OpenbisExperimentWithDescendants experiment,

//try to put all attributes into sample properties, as they should be a 1:1 mapping
Map<String, String> typeCodesToNames = new HashMap<>();
Set<String> propertiesLinkingSamples = new HashSet<>();
for (PropertyAssignment a : sampleType.getPropertyAssignments()) {
typeCodesToNames.put(a.getPropertyType().getCode(), a.getPropertyType().getLabel());
String code = a.getPropertyType().getCode();
String label = a.getPropertyType().getLabel();
DataType type = a.getPropertyType().getDataType();
typeCodesToNames.put(code, label);
if(type.equals(DataType.SAMPLE)) {
propertiesLinkingSamples.add(code);
}
}
Map<String, Object> attributes = new HashMap<>();
for(String code : sample.getProperties().keySet()) {
attributes.put(typeCodesToNames.get(code), sample.getProperties().get(code));
String value = sample.getProperty(code);
if(propertiesLinkingSamples.contains(code)) {
value = generateOpenBISLinkFromPermID("SAMPLE", value);
}
attributes.put(typeCodesToNames.get(code), value);
}

attributes.put(DEFAULT_TRANSFERRED_SAMPLE_TITLE, sample.getIdentifier().getIdentifier());
Expand Down
73 changes: 59 additions & 14 deletions src/main/java/life/qbic/model/download/SEEKConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import life.qbic.model.isa.ISASample;
import life.qbic.model.isa.ISASampleType;
import life.qbic.model.isa.ISAStudy;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.utils.URIBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -41,13 +40,56 @@ public class SEEKConnector {
private String apiURL;
private byte[] credentials;
private OpenbisSeekTranslator translator;
private final String DEFAULT_PROJECT_ID;

public SEEKConnector(String apiURL, byte[] httpCredentials, String defaultProjectTitle,
String defaultStudyTitle) throws URISyntaxException, IOException, InterruptedException {
public SEEKConnector(String apiURL, byte[] httpCredentials, String openBISBaseURL,
String defaultProjectTitle, String defaultStudyTitle) throws URISyntaxException, IOException,
InterruptedException {
this.apiURL = apiURL;
this.credentials = httpCredentials;
translator = new OpenbisSeekTranslator("1", //searchNodeWithTitle("projects", defaultProjectTitle),
"1");//searchNodeWithTitle("studies", defaultStudyTitle));
Optional<String> projectID = getProjectWithTitle(defaultProjectTitle);
if(projectID.isEmpty()) {
throw new RuntimeException("Failed to find project with title: " + defaultProjectTitle+". "
+ "Please provide an existing default project.");
}
DEFAULT_PROJECT_ID = projectID.get();

translator = new OpenbisSeekTranslator(openBISBaseURL, DEFAULT_PROJECT_ID,
searchNodeWithTitle("studies", defaultStudyTitle));
}

/**
* Lists projects and returns the optional identifier of the one matching the provided ID.
* Necessary because project search does not seem to work.
* @param projectTitle the title to search for
* @return
*/
private Optional<String> getProjectWithTitle(String projectTitle)
throws IOException, InterruptedException, URISyntaxException {
String endpoint = apiURL+"/projects/";
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(endpoint))
.headers("Content-Type", "application/json")
.headers("Accept", "application/json")
.headers("Authorization", "Basic " + new String(credentials))
.GET().build();
HttpResponse<String> response = HttpClient.newBuilder().build()
.send(request, BodyHandlers.ofString());
if(response.statusCode() == 200) {
JsonNode rootNode = new ObjectMapper().readTree(response.body());
JsonNode hits = rootNode.path("data");
for (Iterator<JsonNode> it = hits.elements(); it.hasNext(); ) {
JsonNode hit = it.next();
String id = hit.get("id").asText();
String title = hit.get("attributes").get("title").asText();
if(title.equals(projectTitle)) {
return Optional.of(id);
}
}
} else {
throw new RuntimeException("Failed : HTTP error code : " + response.statusCode());
}
return Optional.empty();
}

public String addAssay(ISAAssay assay)
Expand Down Expand Up @@ -231,13 +273,16 @@ public String uploadStreamContent(String blobEndpoint,
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(blobEndpoint))
.headers("Content-Type", "application/octet-stream")
.headers("Accept", "application/octet-stream")
.headers("Accept", "*/*")
.headers("Authorization", "Basic " + new String(credentials))
.PUT(BodyPublishers.ofInputStream(streamSupplier)).build();

HttpResponse<String> response = HttpClient.newBuilder().build()
.send(request, BodyHandlers.ofString());

System.err.println("response was: "+response);
System.err.println("response body: "+response.body());

if(response.statusCode()!=200) {
System.err.println(response.body());
throw new RuntimeException("Failed : HTTP error code : " + response.statusCode());
Expand Down Expand Up @@ -276,9 +321,9 @@ public Optional<AssetToUpload> createAssetForFile(DataSetFile file, String asset
if(!file.getPath().isBlank() && !file.isDirectory()) {
File f = new File(file.getPath());
String datasetCode = file.getDataSetPermId().toString();
String assetName = datasetCode+": "+f.getName();
GenericSeekAsset isaFile = new GenericSeekAsset("data_files", assetName, file.getPath(),
Arrays.asList("1"));//TODO
String assetName = datasetCode+": "+f.getName();//TODO what do we want to call the asset?
GenericSeekAsset isaFile = new GenericSeekAsset(assetType, assetName, file.getPath(),
Arrays.asList(DEFAULT_PROJECT_ID));
isaFile.withAssays(assays);
String fileExtension = f.getName().substring(f.getName().lastIndexOf(".")+1);
String annotation = translator.dataFormatAnnotationForExtension(fileExtension);
Expand All @@ -298,9 +343,9 @@ public List<AssetToUpload> createAssets(List<DataSetFile> filesInDataset,
if(!file.getPath().isBlank() && !file.isDirectory()) {
File f = new File(file.getPath());
String datasetCode = file.getDataSetPermId().toString();
String assetName = datasetCode+": "+f.getName();//TODO?
String assetName = datasetCode+": "+f.getName();//TODO what do we want to call the asset?
GenericSeekAsset isaFile = new GenericSeekAsset("data_files", assetName, file.getPath(),
Arrays.asList("1"));
Arrays.asList(DEFAULT_PROJECT_ID));
isaFile.withAssays(assays);
String fileExtension = f.getName().substring(f.getName().lastIndexOf(".")+1);
String annotation = translator.dataFormatAnnotationForExtension(fileExtension);
Expand Down Expand Up @@ -384,7 +429,7 @@ private Map<String, String> parseSampleTypesJSON(String json) throws JsonProcess

private String searchNodeWithTitle(String nodeType, String title)
throws URISyntaxException, IOException, InterruptedException {
String endpoint = apiURL+"/search/";
String endpoint = apiURL+"/search";
URIBuilder builder = new URIBuilder(endpoint);
builder.setParameter("q", title).setParameter("search_type", nodeType);

Expand All @@ -402,8 +447,7 @@ private String searchNodeWithTitle(String nodeType, String title)
JsonNode hits = rootNode.path("data");
for (Iterator<JsonNode> it = hits.elements(); it.hasNext(); ) {
JsonNode hit = it.next();
System.err.println(hit.asText());
if(hit.get("title").asText().equals(title)) {
if(hit.get("attributes").get("title").asText().equals(title)) {
return hit.get("id").asText();
}
}
Expand Down Expand Up @@ -458,6 +502,7 @@ public AssayWithQueuedAssets createNode(SeekStructure nodeWithChildren, boolean
throws URISyntaxException, IOException, InterruptedException {
String assayID = addAssay(nodeWithChildren.getAssay());
for(ISASample sample : nodeWithChildren.getSamples()) {
sample.setAssayIDs(Arrays.asList(assayID));
createSample(sample);
}

Expand Down

0 comments on commit a87fed8

Please sign in to comment.