From 7656e04aeb9cfd6fb1c5a7a3035d837f6cdf6729 Mon Sep 17 00:00:00 2001 From: wow-such-code Date: Sun, 24 Mar 2024 16:21:21 +0100 Subject: [PATCH 1/5] use openbis-internal wrapper class --- src/main/java/life/qbic/App.java | 14 ++++++-------- .../io/commandline/SampleHierarchyCommand.java | 5 +++-- .../qbic/model/download/OpenbisConnector.java | 18 +++++++++++------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/main/java/life/qbic/App.java b/src/main/java/life/qbic/App.java index 95b79a8..aa142b5 100644 --- a/src/main/java/life/qbic/App.java +++ b/src/main/java/life/qbic/App.java @@ -1,5 +1,6 @@ package life.qbic; +import ch.ethz.sis.openbis.generic.OpenBIS; import life.qbic.io.commandline.CommandLineOptions; import life.qbic.model.Configuration; import life.qbic.model.download.Authentication; @@ -39,8 +40,8 @@ private static Boolean isNotNullOrEmpty(String envVariableCommandLineParameter) * * @return An instance of the Authentication class. */ - public static Authentication loginToOpenBIS( - char[] password, String user, String as_url) { + public static OpenBIS loginToOpenBIS( + char[] password, String user, String url) { // Ensure 'logs' folder is created File logFolder = new File(Configuration.LOG_PATH.toAbsolutePath().toString()); @@ -52,13 +53,10 @@ public static Authentication loginToOpenBIS( } } - Authentication authentication = - new Authentication( - user, - new String(password), - as_url); + OpenBIS authentication = + new OpenBIS(url); try { - authentication.login(); + authentication.login(user, new String(password)); } catch (ConnectionException e) { LOG.error(e.getMessage(), e); LOG.error("Could not connect to QBiC's data source. Have you requested access to the " diff --git a/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java b/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java index b36af10..1b01349 100644 --- a/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java +++ b/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java @@ -1,5 +1,6 @@ package life.qbic.io.commandline; +import ch.ethz.sis.openbis.generic.OpenBIS; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; @@ -43,8 +44,8 @@ public void run() { } else { summary.add("Querying samples in all available spaces...\n"); } - Authentication authentication = App.loginToOpenBIS(auth.getPassword(), auth.user, auth.as_url); - OpenbisConnector openbis = new OpenbisConnector(auth.as_url, authentication.getSessionToken()); + OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.user, auth.as_url); + OpenbisConnector openbis = new OpenbisConnector(authentication); Map hierarchy = openbis.queryFullSampleHierarchy(spaces); hierarchy.entrySet().stream() diff --git a/src/main/java/life/qbic/model/download/OpenbisConnector.java b/src/main/java/life/qbic/model/download/OpenbisConnector.java index f91bf8e..3536415 100644 --- a/src/main/java/life/qbic/model/download/OpenbisConnector.java +++ b/src/main/java/life/qbic/model/download/OpenbisConnector.java @@ -1,6 +1,6 @@ package life.qbic.model.download; -import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.ethz.sis.openbis.generic.OpenBIS; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample; import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.SampleType; @@ -9,7 +9,6 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.Space; import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.fetchoptions.SpaceFetchOptions; import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.search.SpaceSearchCriteria; -import ch.systemsx.cisd.common.spring.HttpInvokerUtils; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -21,8 +20,7 @@ public class OpenbisConnector { private static final Logger LOG = LogManager.getLogger(OpenbisConnector.class); - private final IApplicationServerApi applicationServer; - private final String sessionToken; + OpenBIS openBIS; /** * Constructor for a QBiCDataDownloader instance * @@ -32,6 +30,7 @@ public class OpenbisConnector { public OpenbisConnector( String AppServerUri, String sessionToken) { + /* this.sessionToken = sessionToken; if (!AppServerUri.isEmpty()) { @@ -41,12 +40,18 @@ public OpenbisConnector( } else { applicationServer = null; } + + */ + } + + public OpenbisConnector(OpenBIS authentication) { + this.openBIS = authentication; } public List getSpaces() { SpaceSearchCriteria criteria = new SpaceSearchCriteria(); SpaceFetchOptions options = new SpaceFetchOptions(); - return applicationServer.searchSpaces(sessionToken, criteria, options).getObjects() + return openBIS.searchSpaces(criteria, options).getObjects() .stream().map(Space::getCode).collect(Collectors.toList()); } @@ -63,8 +68,7 @@ public Map queryFullSampleHierarchy(List withDescendants.withType(); SampleSearchCriteria criteria = new SampleSearchCriteria(); criteria.withSpace().withCode().thatEquals(space.toUpperCase()); - SearchResult result = applicationServer.searchSamples( - sessionToken, criteria, withDescendants); + SearchResult result = openBIS.searchSamples(criteria, withDescendants); for (Sample s : result.getObjects()) { SampleType parentType = s.getType(); List children = s.getChildren(); From 2f525bd4ab38e49060c086d79be5248a526ef4d4 Mon Sep 17 00:00:00 2001 From: wow-such-code Date: Thu, 27 Jun 2024 18:01:20 +0200 Subject: [PATCH 2/5] add data search and upload --- pom.xml | 8 ++ src/main/java/life/qbic/App.java | 46 ++++-- .../io/commandline/AuthenticationOptions.java | 82 ++++++++++- .../io/commandline/CommandLineOptions.java | 6 +- .../commandline/DownloadDatasetCommand.java | 68 +++++++++ .../io/commandline/FindDatasetsCommand.java | 70 +++++++++ .../commandline/SampleHierarchyCommand.java | 3 +- .../io/commandline/UploadDatasetCommand.java | 81 +++++++++++ .../qbic/model/download/OpenbisConnector.java | 136 ++++++++++++++++++ 9 files changed, 479 insertions(+), 21 deletions(-) create mode 100644 src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java create mode 100644 src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java create mode 100644 src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java diff --git a/pom.xml b/pom.xml index 28f0176..0cbf3be 100644 --- a/pom.xml +++ b/pom.xml @@ -138,6 +138,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + diff --git a/src/main/java/life/qbic/App.java b/src/main/java/life/qbic/App.java index aa142b5..a100f95 100644 --- a/src/main/java/life/qbic/App.java +++ b/src/main/java/life/qbic/App.java @@ -3,7 +3,6 @@ import ch.ethz.sis.openbis.generic.OpenBIS; import life.qbic.io.commandline.CommandLineOptions; import life.qbic.model.Configuration; -import life.qbic.model.download.Authentication; import life.qbic.model.download.AuthenticationException; import life.qbic.model.download.ConnectionException; import org.apache.logging.log4j.LogManager; @@ -36,25 +35,34 @@ private static Boolean isNotNullOrEmpty(String envVariableCommandLineParameter) } /** - * Logs into OpenBIS asks for and verifies password. + * Logs into OpenBIS, asks for and verifies password. * * @return An instance of the Authentication class. */ public static OpenBIS loginToOpenBIS( char[] password, String user, String url) { + //setupLog(); - // Ensure 'logs' folder is created - File logFolder = new File(Configuration.LOG_PATH.toAbsolutePath().toString()); - if (!logFolder.exists()) { - boolean logFolderCreated = logFolder.mkdirs(); - if (!logFolderCreated) { - LOG.error("Could not create log folder '" + logFolder.getAbsolutePath() + "'"); - System.exit(1); - } - } + OpenBIS authentication = new OpenBIS(url); + + return tryLogin(authentication, user, password); + } - OpenBIS authentication = - new OpenBIS(url); + /** + * Logs into OpenBIS, asks for and verifies password, includes Datastore Server connection. + * + * @return An instance of the Authentication class. + */ + public static OpenBIS loginToOpenBIS( + char[] password, String user, String url, String dssUrl) { + //setupLog(); + + OpenBIS authentication = new OpenBIS(url, dssUrl); + + return tryLogin(authentication, user, password); + } + + private static OpenBIS tryLogin(OpenBIS authentication, String user, char[] password) { try { authentication.login(user, new String(password)); } catch (ConnectionException e) { @@ -68,4 +76,16 @@ public static OpenBIS loginToOpenBIS( } return authentication; } + + private static void setupLog() { + // Ensure 'logs' folder is created + File logFolder = new File(Configuration.LOG_PATH.toAbsolutePath().toString()); + if (!logFolder.exists()) { + boolean logFolderCreated = logFolder.mkdirs(); + if (!logFolderCreated) { + LOG.error("Could not create log folder '" + logFolder.getAbsolutePath() + "'"); + System.exit(1); + } + } + } } diff --git a/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java b/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java index 8f49d7a..795fc33 100644 --- a/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java +++ b/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java @@ -3,7 +3,13 @@ import static java.util.Objects.nonNull; import static picocli.CommandLine.ArgGroup; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.util.StringJoiner; +import java.util.TreeMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import picocli.CommandLine; @@ -14,9 +20,8 @@ public class AuthenticationOptions { @Option( names = {"-u", "--user"}, - required = true, description = "openBIS user name") - public String user; + private String user; @ArgGroup(multiplicity = "1") // ensures the password is provided once with at least one of the possible options. PasswordOptions passwordOptions; @@ -24,7 +29,40 @@ public class AuthenticationOptions { names = {"-as", "-as_url"}, description = "ApplicationServer URL", scope = CommandLine.ScopeType.INHERIT) - public String as_url; + private String as_url; + + @Option( + names = {"-dss", "-dss_url"}, + description = "DatastoreServer URL", + scope = CommandLine.ScopeType.INHERIT) + private String dss_url; + + @Option( + names = {"-config", "-config_file"}, + description = "Config file path to provide openbis server information.", + scope = CommandLine.ScopeType.INHERIT) + public String configPath; + + public String getUser() { + if(user == null & configPath!=null && !configPath.isBlank()) { + user = ReadProperties.getProperties(configPath).get("user"); + } + return user; + } + + public String getDSS() { + if(dss_url == null & configPath!=null && !configPath.isBlank()) { + dss_url = ReadProperties.getProperties(configPath).get("dss"); + } + return dss_url; + } + + public String getAS() { + if(as_url == null & configPath!=null && !configPath.isBlank()) { + as_url = ReadProperties.getProperties(configPath).get("as"); + } + return as_url; + } public char[] getPassword() { return passwordOptions.getPassword(); @@ -76,4 +114,42 @@ public String toString() { .toString(); //ATTENTION: do not expose the password here! } + + public static class ReadProperties { + + public static TreeMap getProperties(String infile) { + final int lhs = 0; + final int rhs = 1; + + TreeMap map = new TreeMap(); + BufferedReader bfr = null; + try { + bfr = new BufferedReader(new FileReader(new File(infile))); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + + String line; + while (true) { + try { + if (!((line = bfr.readLine()) != null)) + break; + } catch (IOException e) { + throw new RuntimeException(e); + } + if (!line.startsWith("#") && !line.isEmpty()) { + String[] pair = line.trim().split("="); + map.put(pair[lhs].trim(), pair[rhs].trim()); + } + } + + try { + bfr.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return(map); + } + } } \ No newline at end of file diff --git a/src/main/java/life/qbic/io/commandline/CommandLineOptions.java b/src/main/java/life/qbic/io/commandline/CommandLineOptions.java index 315dd85..3acf00a 100644 --- a/src/main/java/life/qbic/io/commandline/CommandLineOptions.java +++ b/src/main/java/life/qbic/io/commandline/CommandLineOptions.java @@ -8,9 +8,9 @@ // main command with format specifiers for the usage help message @Command(name = "openbis-scripts", - subcommands = { SampleHierarchyCommand.class }, + subcommands = { SampleHierarchyCommand.class, FindDatasetsCommand.class, UploadDatasetCommand.class }, description = "A client software for querying openBIS.", - mixinStandardHelpOptions = true) + mixinStandardHelpOptions = true, versionProvider = ManifestVersionProvider.class) public class CommandLineOptions { private static final Logger LOG = LogManager.getLogger(CommandLineOptions.class); @@ -18,7 +18,7 @@ public class CommandLineOptions { versionHelp = true, description = "print version information", scope = CommandLine.ScopeType.INHERIT) - boolean versionRequested; + boolean versionRequested = false; @Option( names = {"-h", "--help"}, diff --git a/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java b/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java new file mode 100644 index 0000000..885a517 --- /dev/null +++ b/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java @@ -0,0 +1,68 @@ +package life.qbic.io.commandline; + +import ch.ethz.sis.openbis.generic.OpenBIS; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import life.qbic.App; +import life.qbic.model.download.OpenbisConnector; +import picocli.CommandLine.Command; +import picocli.CommandLine.Mixin; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "list-data", + description = "lists datasets and their details for a given experiment code") +public class DownloadDatasetCommand implements Runnable { + + @Parameters(arity = "1", paramLabel = "experiment", description = "The code of the experiment data is attached to") + private String experimentCode; + @Option(arity = "1", paramLabel = "", description = "Optional openBIS spaces to filter results", names = {"-s", "--space"}) + private String space; + @Mixin + AuthenticationOptions auth = new AuthenticationOptions(); + + @Override + public void run() { + List spaces = new ArrayList<>(); + if (space != null) { + System.out.println("Querying experiment in space: " + space + "..."); + spaces.add(space); + } else { + System.out.println("Querying experiment in all available spaces..."); + } + OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS()); + OpenbisConnector openbis = new OpenbisConnector(authentication); + List datasets = openbis.listDatasetsOfExperiment(spaces, experimentCode).stream() + .sorted(Comparator.comparing( + (DataSet d) -> d.getExperiment().getProject().getSpace().getCode())).collect( + Collectors.toList()); + int i = 0; + for (DataSet dataSet : datasets) { + i++; + System.out.println("["+i+"]"); + System.out.println(dataSet.getExperiment().getIdentifier()); + System.out.println(dataSet.getCode()); + System.out.println(dataSet.getType().getCode()); + System.out.println(dataSet.getRegistrationDate()); + System.out.println(new SimpleDateFormat("MM-dd-yyyy").format(dataSet.getRegistrationDate())); + Person person = dataSet.getRegistrator(); + System.out.println(person.getFirstName() + " " + person.getLastName()); + System.out.println(); + } + } + + private String getTimeStamp() { + final String PATTERN_FORMAT = "YYYY-MM-dd_HHmmss"; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT); + return LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).format(formatter); + } +} diff --git a/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java b/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java new file mode 100644 index 0000000..ab08afe --- /dev/null +++ b/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java @@ -0,0 +1,70 @@ +package life.qbic.io.commandline; + +import ch.ethz.sis.openbis.generic.OpenBIS; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.person.Person; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import life.qbic.App; +import life.qbic.model.download.OpenbisConnector; +import picocli.CommandLine.Command; +import picocli.CommandLine.Mixin; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "list-data", + description = "lists datasets and their details for a given experiment code") +public class FindDatasetsCommand implements Runnable { + + @Parameters(arity = "1", paramLabel = "experiment", description = "The code of the experiment data is attached to") + private String experimentCode; + @Option(arity = "1", paramLabel = "", description = "Optional openBIS spaces to filter samples", names = {"-s", "--space"}) + private String space; + @Mixin + AuthenticationOptions auth = new AuthenticationOptions(); + + @Override + public void run() { + List spaces = new ArrayList<>(); + if (space != null) { + System.out.println("Querying experiment in space: " + space + "..."); + spaces.add(space); + } else { + System.out.println("Querying experiment in all available spaces..."); + } + OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS()); + OpenbisConnector openbis = new OpenbisConnector(authentication); + List datasets = openbis.listDatasetsOfExperiment(spaces, experimentCode).stream() + .sorted(Comparator.comparing( + (DataSet d) -> d.getExperiment().getProject().getSpace().getCode())).collect( + Collectors.toList()); + int i = 0; + System.out.println(); + System.out.printf("Found %s datasets for experiment %s:%n", datasets.size(), experimentCode); + for (DataSet dataSet : datasets) { + i++; + System.out.println("["+i+"]"); + System.out.printf("ID: %s (%s)%n", dataSet.getCode(), dataSet.getExperiment().getIdentifier()); + System.out.println("Type: "+dataSet.getType().getCode()); + Person person = dataSet.getRegistrator(); + String simpleTime = new SimpleDateFormat("MM-dd-yy HH:mm:ss").format(dataSet.getRegistrationDate()); + String name = person.getFirstName() +" "+ person.getLastName(); + String uploadedBy = "Uploaded by "+name+" ("+simpleTime+")"; + System.out.println(uploadedBy); + System.out.println(); + } + } + + private String getTimeStamp() { + final String PATTERN_FORMAT = "YYYY-MM-dd_HHmmss"; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT); + return LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).format(formatter); + } +} diff --git a/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java b/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java index 1b01349..e9668d6 100644 --- a/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java +++ b/src/main/java/life/qbic/io/commandline/SampleHierarchyCommand.java @@ -15,7 +15,6 @@ import life.qbic.App; import life.qbic.model.Configuration; import life.qbic.model.SampleTypeConnection; -import life.qbic.model.download.Authentication; import life.qbic.model.download.FileSystemWriter; import life.qbic.model.download.ModelReporter; import life.qbic.model.download.OpenbisConnector; @@ -44,7 +43,7 @@ public void run() { } else { summary.add("Querying samples in all available spaces...\n"); } - OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.user, auth.as_url); + OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS()); OpenbisConnector openbis = new OpenbisConnector(authentication); Map hierarchy = openbis.queryFullSampleHierarchy(spaces); diff --git a/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java b/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java new file mode 100644 index 0000000..a3cd462 --- /dev/null +++ b/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java @@ -0,0 +1,81 @@ +package life.qbic.io.commandline; + +import ch.ethz.sis.openbis.generic.OpenBIS; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId; +import java.io.File; +import java.nio.file.Path; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import life.qbic.App; +import life.qbic.model.download.OpenbisConnector; +import picocli.CommandLine.Command; +import picocli.CommandLine.Mixin; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "upload-data", + description = "uploads a dataset and attaches it to an experiment and (optionally) other datasets") +public class UploadDatasetCommand implements Runnable { + + @Parameters(arity = "1", paramLabel = "file/folder", description = "The path to the file or folder to upload") + private String dataPath; + @Parameters(arity = "1", paramLabel = "experiment ID", description = "The full identifier of the experiment the data should be attached to. " + + "The identifier must be of the format: /space/project/experiment") + private String experimentID; + @Option(arity = "1..*", paramLabel = "", description = "Optional list of dataset codes to act" + + " as parents for the upload. E.g. when this dataset has been generated using these datasets as input.", names = {"-pa", "--parents"}) + private List parents = new ArrayList<>(); + @Mixin + AuthenticationOptions auth = new AuthenticationOptions(); + + private OpenbisConnector openbis; + + @Override + public void run() { + OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS(), auth.getDSS()); + openbis = new OpenbisConnector(authentication); + + if(!pathValid(dataPath)) { + System.out.printf("Path %s could not be found%n", dataPath); + return; + } + if(!experimentExists(experimentID)) { + System.out.printf("Experiment %s could not be found%n", experimentID); + return; + } + if(!datasetsExist(parents)) { + System.out.printf("One or more datasets %s could not be found%n", parents); + return; + } + System.out.println(); + System.out.println("Parameters verified, uploading dataset..."); + System.out.println(); + DataSetPermId result = openbis.registerDataset(Path.of(dataPath), experimentID, parents); + System.out.printf("Dataset %s was successfully created%n", result.getPermId()); + } + + private boolean datasetsExist(List parents) { + if(parents.isEmpty()) { + return true; + } + return openbis.findDataSets(parents).size() == parents.size(); + } + + private boolean experimentExists(String experimentID) { + return openbis.experimentExists(experimentID); + } + + private boolean pathValid(String dataPath) { + return new File(dataPath).exists(); + } + + private String getTimeStamp() { + final String PATTERN_FORMAT = "YYYY-MM-dd_HHmmss"; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT); + return LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).format(formatter); + } +} diff --git a/src/main/java/life/qbic/model/download/OpenbisConnector.java b/src/main/java/life/qbic/model/download/OpenbisConnector.java index 3536415..844aa9b 100644 --- a/src/main/java/life/qbic/model/download/OpenbisConnector.java +++ b/src/main/java/life/qbic/model/download/OpenbisConnector.java @@ -2,6 +2,15 @@ import ch.ethz.sis.openbis.generic.OpenBIS; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.EntityTypePermId; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions.ExperimentFetchOptions; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentIdentifier; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample; import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.SampleType; import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions; @@ -9,6 +18,20 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.Space; import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.fetchoptions.SpaceFetchOptions; import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.search.SpaceSearchCriteria; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.dataset.create.UploadedDataSetCreation; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.DataSetFile; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.download.DataSetFileDownload; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.download.DataSetFileDownloadOptions; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.download.DataSetFileDownloadReader; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.id.DataSetFilePermId; +import ch.ethz.sis.openbis.generic.dssapi.v3.dto.datasetfile.id.IDataSetFileId; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -55,6 +78,107 @@ public List getSpaces() { .stream().map(Space::getCode).collect(Collectors.toList()); } + public DataSetPermId registerDataset(Path uploadPath, String experimentID, List parentCodes) { + final String uploadId = openBIS.uploadFileWorkspaceDSS(uploadPath); + + final UploadedDataSetCreation creation = new UploadedDataSetCreation(); + creation.setUploadId(uploadId); + creation.setExperimentId(new ExperimentIdentifier(experimentID)); + creation.setParentIds(parentCodes.stream().map(DataSetPermId::new).collect( + Collectors.toList())); + creation.setTypeId(new EntityTypePermId("UNKNOWN", EntityKind.DATA_SET)); + + try + { + return openBIS.createUploadedDataSet(creation); + } catch (final Exception e) + { + e.printStackTrace(); + } + return null; + } + + public static void main(String[] args) throws IOException { + String as = ""; + String dss = ""; + String user = ""; + String pass = ""; + + OpenBIS authentication = + new OpenBIS(as, dss); + authentication.login(user, pass); + OpenbisConnector c = new OpenbisConnector(authentication); + + String space = "TEMP_PLAYGROUND"; + String project = "TEMP_PLAYGROUND"; + String experiment = "E123"; + String expID = "/TEMP_PLAYGROUND/TEMP_PLAYGROUND/E123"; + Path toUpload = Path.of("/Users/afriedrich/Downloads/cats"); + //c.registerDataset(toUpload, expID, List.of("20240512182451335-425180", "20240512191248297-425181")); + + String basePath = "/Users/afriedrich/Downloads/downloaded_cats"; + //c.downloadDataset(basePath, "20240503175717814-263844"); + c.listDatasetsOfExperiment(List.of(), experiment); + + } + + +private static void copyInputStreamToFile(InputStream inputStream, File file) + throws IOException { + try (FileOutputStream outputStream = new FileOutputStream(file, false)) { + int read; + byte[] bytes = new byte[8192]; + while ((read = inputStream.read(bytes)) != -1) { + outputStream.write(bytes, 0, read); + } + } +} + +public List listDatasetsOfExperiment(List spaces, String experiment) { + DataSetSearchCriteria criteria = new DataSetSearchCriteria(); + criteria.withExperiment().withCode().thatEquals(experiment); + if(!spaces.isEmpty()) { + criteria.withAndOperator(); + criteria.withExperiment().withProject().withSpace().withCodes().thatIn(spaces); + } + DataSetFetchOptions options = new DataSetFetchOptions(); + options.withType(); + options.withRegistrator(); + options.withExperiment().withProject().withSpace(); + return openBIS.searchDataSets(criteria, options).getObjects(); +} + + public void downloadDataset(String targetPath, String datasetID) throws IOException { + DataSetFileDownloadOptions options = new DataSetFileDownloadOptions(); + IDataSetFileId fileToDownload = new DataSetFilePermId(new DataSetPermId(datasetID), + "");//TODO test this path + + // Setting recursive flag to true will return both the subfolder directory object AND file3.txt + options.setRecursive(true); + + // Setting recursive flag to false will return just the meta data of the directory object + //options.setRecursive(false); + + // Read the contents and print them out + InputStream stream = openBIS.downloadFiles(new ArrayList<>(Arrays.asList(fileToDownload)), options); + DataSetFileDownloadReader reader = new DataSetFileDownloadReader(stream); + DataSetFileDownload file = null; + while ((file = reader.read()) != null) + { + DataSetFile df = file.getDataSetFile(); + String currentPath = df.getPath().replace("original",""); + if(df.isDirectory()) { + File newDeer = new File(targetPath, currentPath); + if (!newDeer.exists()) { + newDeer.mkdirs(); + } + } else { + File toWrite = new File(targetPath, currentPath); + copyInputStreamToFile(file.getInputStream(), toWrite); + } + } + } + public Map queryFullSampleHierarchy(List spaces) { Map hierarchy = new HashMap<>(); if(spaces.isEmpty()) { @@ -97,5 +221,17 @@ public Map queryFullSampleHierarchy(List return hierarchy; } + public List findDataSets(List codes) { + DataSetSearchCriteria criteria = new DataSetSearchCriteria(); + criteria.withCodes().thatIn(codes); + DataSetFetchOptions options = new DataSetFetchOptions(); + return openBIS.searchDataSets(criteria, options).getObjects(); + } + + public boolean experimentExists(String experimentID) { + ExperimentSearchCriteria criteria = new ExperimentSearchCriteria(); + criteria.withIdentifier().thatEquals(experimentID); + return !openBIS.searchExperiments(criteria, new ExperimentFetchOptions()).getObjects().isEmpty(); + } } From e56f4b8e07f5405fe165dc8018425393c684d026 Mon Sep 17 00:00:00 2001 From: wow-such-code Date: Fri, 28 Jun 2024 11:35:51 +0200 Subject: [PATCH 3/5] round 1 of review changes --- src/main/java/life/qbic/App.java | 4 +-- .../io/commandline/AuthenticationOptions.java | 12 +++---- .../io/commandline/FindDatasetsCommand.java | 6 ++-- .../io/commandline/UploadDatasetCommand.java | 7 ++-- .../qbic/model/download/OpenbisConnector.java | 34 ++++--------------- 5 files changed, 18 insertions(+), 45 deletions(-) diff --git a/src/main/java/life/qbic/App.java b/src/main/java/life/qbic/App.java index a100f95..6ad90a6 100644 --- a/src/main/java/life/qbic/App.java +++ b/src/main/java/life/qbic/App.java @@ -41,7 +41,7 @@ private static Boolean isNotNullOrEmpty(String envVariableCommandLineParameter) */ public static OpenBIS loginToOpenBIS( char[] password, String user, String url) { - //setupLog(); + setupLog(); OpenBIS authentication = new OpenBIS(url); @@ -55,7 +55,7 @@ public static OpenBIS loginToOpenBIS( */ public static OpenBIS loginToOpenBIS( char[] password, String user, String url, String dssUrl) { - //setupLog(); + setupLog(); OpenBIS authentication = new OpenBIS(url, dssUrl); diff --git a/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java b/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java index 795fc33..948ef7e 100644 --- a/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java +++ b/src/main/java/life/qbic/io/commandline/AuthenticationOptions.java @@ -118,10 +118,8 @@ public String toString() { public static class ReadProperties { public static TreeMap getProperties(String infile) { - final int lhs = 0; - final int rhs = 1; - TreeMap map = new TreeMap(); + TreeMap properties = new TreeMap<>(); BufferedReader bfr = null; try { bfr = new BufferedReader(new FileReader(new File(infile))); @@ -132,14 +130,14 @@ public static TreeMap getProperties(String infile) { String line; while (true) { try { - if (!((line = bfr.readLine()) != null)) + if ((line = bfr.readLine()) == null) break; } catch (IOException e) { throw new RuntimeException(e); } if (!line.startsWith("#") && !line.isEmpty()) { - String[] pair = line.trim().split("="); - map.put(pair[lhs].trim(), pair[rhs].trim()); + String[] property = line.trim().split("="); + properties.put(property[0].trim(), property[1].trim()); } } @@ -149,7 +147,7 @@ public static TreeMap getProperties(String infile) { throw new RuntimeException(e); } - return(map); + return(properties); } } } \ No newline at end of file diff --git a/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java b/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java index ab08afe..82c2a18 100644 --- a/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java +++ b/src/main/java/life/qbic/io/commandline/FindDatasetsCommand.java @@ -45,12 +45,12 @@ public void run() { .sorted(Comparator.comparing( (DataSet d) -> d.getExperiment().getProject().getSpace().getCode())).collect( Collectors.toList()); - int i = 0; + int datasetIndex = 0; System.out.println(); System.out.printf("Found %s datasets for experiment %s:%n", datasets.size(), experimentCode); for (DataSet dataSet : datasets) { - i++; - System.out.println("["+i+"]"); + datasetIndex++; + System.out.println("["+datasetIndex+"]"); System.out.printf("ID: %s (%s)%n", dataSet.getCode(), dataSet.getExperiment().getIdentifier()); System.out.println("Type: "+dataSet.getType().getCode()); Person person = dataSet.getRegistrator(); diff --git a/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java b/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java index a3cd462..9ea557e 100644 --- a/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java +++ b/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java @@ -58,11 +58,8 @@ public void run() { System.out.printf("Dataset %s was successfully created%n", result.getPermId()); } - private boolean datasetsExist(List parents) { - if(parents.isEmpty()) { - return true; - } - return openbis.findDataSets(parents).size() == parents.size(); + private boolean datasetsExist(List datasetCodes) { + return openbis.findDataSets(datasetCodes).size() == datasetCodes.size(); } private boolean experimentExists(String experimentID) { diff --git a/src/main/java/life/qbic/model/download/OpenbisConnector.java b/src/main/java/life/qbic/model/download/OpenbisConnector.java index 844aa9b..1e82adf 100644 --- a/src/main/java/life/qbic/model/download/OpenbisConnector.java +++ b/src/main/java/life/qbic/model/download/OpenbisConnector.java @@ -98,31 +98,6 @@ public DataSetPermId registerDataset(Path uploadPath, String experimentID, List< return null; } - public static void main(String[] args) throws IOException { - String as = ""; - String dss = ""; - String user = ""; - String pass = ""; - - OpenBIS authentication = - new OpenBIS(as, dss); - authentication.login(user, pass); - OpenbisConnector c = new OpenbisConnector(authentication); - - String space = "TEMP_PLAYGROUND"; - String project = "TEMP_PLAYGROUND"; - String experiment = "E123"; - String expID = "/TEMP_PLAYGROUND/TEMP_PLAYGROUND/E123"; - Path toUpload = Path.of("/Users/afriedrich/Downloads/cats"); - //c.registerDataset(toUpload, expID, List.of("20240512182451335-425180", "20240512191248297-425181")); - - String basePath = "/Users/afriedrich/Downloads/downloaded_cats"; - //c.downloadDataset(basePath, "20240503175717814-263844"); - c.listDatasetsOfExperiment(List.of(), experiment); - - } - - private static void copyInputStreamToFile(InputStream inputStream, File file) throws IOException { try (FileOutputStream outputStream = new FileOutputStream(file, false)) { @@ -168,9 +143,9 @@ public void downloadDataset(String targetPath, String datasetID) throws IOExcept DataSetFile df = file.getDataSetFile(); String currentPath = df.getPath().replace("original",""); if(df.isDirectory()) { - File newDeer = new File(targetPath, currentPath); - if (!newDeer.exists()) { - newDeer.mkdirs(); + File newDir = new File(targetPath, currentPath); + if (!newDir.exists()) { + newDir.mkdirs(); } } else { File toWrite = new File(targetPath, currentPath); @@ -222,6 +197,9 @@ public Map queryFullSampleHierarchy(List } public List findDataSets(List codes) { + if(codes.isEmpty()) { + return new ArrayList<>(); + } DataSetSearchCriteria criteria = new DataSetSearchCriteria(); criteria.withCodes().thatIn(codes); DataSetFetchOptions options = new DataSetFetchOptions(); From db4d888cde38b6210b394a261f751253f36c0ab8 Mon Sep 17 00:00:00 2001 From: wow-such-code Date: Fri, 28 Jun 2024 13:18:58 +0200 Subject: [PATCH 4/5] test and remove todos --- .../qbic/model/download/OpenbisConnector.java | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/src/main/java/life/qbic/model/download/OpenbisConnector.java b/src/main/java/life/qbic/model/download/OpenbisConnector.java index 1e82adf..f5e1654 100644 --- a/src/main/java/life/qbic/model/download/OpenbisConnector.java +++ b/src/main/java/life/qbic/model/download/OpenbisConnector.java @@ -44,15 +44,16 @@ public class OpenbisConnector { private static final Logger LOG = LogManager.getLogger(OpenbisConnector.class); OpenBIS openBIS; + /** * Constructor for a QBiCDataDownloader instance * - * @param AppServerUri The openBIS application server URL (AS) + * @param AppServerUri The openBIS application server URL (AS) * @param sessionToken The session token for the datastore & application servers */ public OpenbisConnector( - String AppServerUri, - String sessionToken) { + String AppServerUri, + String sessionToken) { /* this.sessionToken = sessionToken; @@ -78,7 +79,8 @@ public List getSpaces() { .stream().map(Space::getCode).collect(Collectors.toList()); } - public DataSetPermId registerDataset(Path uploadPath, String experimentID, List parentCodes) { + public DataSetPermId registerDataset(Path uploadPath, String experimentID, + List parentCodes) { final String uploadId = openBIS.uploadFileWorkspaceDSS(uploadPath); final UploadedDataSetCreation creation = new UploadedDataSetCreation(); @@ -88,78 +90,75 @@ public DataSetPermId registerDataset(Path uploadPath, String experimentID, List< Collectors.toList())); creation.setTypeId(new EntityTypePermId("UNKNOWN", EntityKind.DATA_SET)); - try - { + try { return openBIS.createUploadedDataSet(creation); - } catch (final Exception e) - { - e.printStackTrace(); + } catch (final Exception e) { + LOG.error(e.getMessage()); } return null; } -private static void copyInputStreamToFile(InputStream inputStream, File file) - throws IOException { - try (FileOutputStream outputStream = new FileOutputStream(file, false)) { - int read; - byte[] bytes = new byte[8192]; - while ((read = inputStream.read(bytes)) != -1) { - outputStream.write(bytes, 0, read); + private static void copyInputStreamToFile(InputStream inputStream, File file) + throws IOException { + System.err.println(file.getPath()); + try (FileOutputStream outputStream = new FileOutputStream(file, false)) { + int read; + byte[] bytes = new byte[8192]; + while ((read = inputStream.read(bytes)) != -1) { + outputStream.write(bytes, 0, read); + } } } -} -public List listDatasetsOfExperiment(List spaces, String experiment) { - DataSetSearchCriteria criteria = new DataSetSearchCriteria(); - criteria.withExperiment().withCode().thatEquals(experiment); - if(!spaces.isEmpty()) { - criteria.withAndOperator(); - criteria.withExperiment().withProject().withSpace().withCodes().thatIn(spaces); + public List listDatasetsOfExperiment(List spaces, String experiment) { + DataSetSearchCriteria criteria = new DataSetSearchCriteria(); + criteria.withExperiment().withCode().thatEquals(experiment); + if (!spaces.isEmpty()) { + criteria.withAndOperator(); + criteria.withExperiment().withProject().withSpace().withCodes().thatIn(spaces); + } + DataSetFetchOptions options = new DataSetFetchOptions(); + options.withType(); + options.withRegistrator(); + options.withExperiment().withProject().withSpace(); + return openBIS.searchDataSets(criteria, options).getObjects(); } - DataSetFetchOptions options = new DataSetFetchOptions(); - options.withType(); - options.withRegistrator(); - options.withExperiment().withProject().withSpace(); - return openBIS.searchDataSets(criteria, options).getObjects(); -} public void downloadDataset(String targetPath, String datasetID) throws IOException { DataSetFileDownloadOptions options = new DataSetFileDownloadOptions(); IDataSetFileId fileToDownload = new DataSetFilePermId(new DataSetPermId(datasetID), - "");//TODO test this path + ""); - // Setting recursive flag to true will return both the subfolder directory object AND file3.txt + System.err.println(fileToDownload); + // Setting recursive flag to true will return both subfolders and files options.setRecursive(true); - // Setting recursive flag to false will return just the meta data of the directory object - //options.setRecursive(false); - // Read the contents and print them out - InputStream stream = openBIS.downloadFiles(new ArrayList<>(Arrays.asList(fileToDownload)), options); + InputStream stream = openBIS.downloadFiles(new ArrayList<>(List.of(fileToDownload)), + options); DataSetFileDownloadReader reader = new DataSetFileDownloadReader(stream); DataSetFileDownload file = null; - while ((file = reader.read()) != null) - { + while ((file = reader.read()) != null) { DataSetFile df = file.getDataSetFile(); - String currentPath = df.getPath().replace("original",""); - if(df.isDirectory()) { - File newDir = new File(targetPath, currentPath); - if (!newDir.exists()) { - newDir.mkdirs(); - } + String currentPath = df.getPath().replace("original", ""); + if (df.isDirectory()) { + File newDir = new File(targetPath, currentPath); + if (!newDir.exists()) { + newDir.mkdirs(); + } } else { File toWrite = new File(targetPath, currentPath); copyInputStreamToFile(file.getInputStream(), toWrite); } } - } + } public Map queryFullSampleHierarchy(List spaces) { Map hierarchy = new HashMap<>(); - if(spaces.isEmpty()) { + if (spaces.isEmpty()) { spaces = getSpaces(); } - for(String space : spaces) { + for (String space : spaces) { SampleFetchOptions fetchType = new SampleFetchOptions(); fetchType.withType(); SampleFetchOptions withDescendants = new SampleFetchOptions(); @@ -169,27 +168,27 @@ public Map queryFullSampleHierarchy(List criteria.withSpace().withCode().thatEquals(space.toUpperCase()); SearchResult result = openBIS.searchSamples(criteria, withDescendants); for (Sample s : result.getObjects()) { - SampleType parentType = s.getType(); - List children = s.getChildren(); - if (children.isEmpty()) { - SampleTypeConnection leaf = new SampleTypeConnection(parentType); - if (hierarchy.containsKey(leaf)) { - int count = hierarchy.get(leaf) + 1; - hierarchy.put(leaf, count); - } else { - hierarchy.put(leaf, 1); - } + SampleType parentType = s.getType(); + List children = s.getChildren(); + if (children.isEmpty()) { + SampleTypeConnection leaf = new SampleTypeConnection(parentType); + if (hierarchy.containsKey(leaf)) { + int count = hierarchy.get(leaf) + 1; + hierarchy.put(leaf, count); } else { - for (Sample c : children) { - SampleType childType = c.getType(); - SampleTypeConnection connection = new SampleTypeConnection(parentType, childType); - if (hierarchy.containsKey(connection)) { - int count = hierarchy.get(connection) + 1; - hierarchy.put(connection, count); - } else { - hierarchy.put(connection, 1); - } + hierarchy.put(leaf, 1); + } + } else { + for (Sample c : children) { + SampleType childType = c.getType(); + SampleTypeConnection connection = new SampleTypeConnection(parentType, childType); + if (hierarchy.containsKey(connection)) { + int count = hierarchy.get(connection) + 1; + hierarchy.put(connection, count); + } else { + hierarchy.put(connection, 1); } + } } } } @@ -197,7 +196,7 @@ public Map queryFullSampleHierarchy(List } public List findDataSets(List codes) { - if(codes.isEmpty()) { + if (codes.isEmpty()) { return new ArrayList<>(); } DataSetSearchCriteria criteria = new DataSetSearchCriteria(); @@ -210,6 +209,7 @@ public boolean experimentExists(String experimentID) { ExperimentSearchCriteria criteria = new ExperimentSearchCriteria(); criteria.withIdentifier().thatEquals(experimentID); - return !openBIS.searchExperiments(criteria, new ExperimentFetchOptions()).getObjects().isEmpty(); + return !openBIS.searchExperiments(criteria, new ExperimentFetchOptions()).getObjects() + .isEmpty(); } } From 3a99d0d4ae49a63bb968754a228c719cd1de7765 Mon Sep 17 00:00:00 2001 From: wow-such-code Date: Fri, 28 Jun 2024 13:57:18 +0200 Subject: [PATCH 5/5] remaining fixes --- pom.xml | 7 +++---- .../life/qbic/io/commandline/DownloadDatasetCommand.java | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 0cbf3be..19f2587 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,7 @@ A client software written in Java to query openBIS jar - 11 - 11 + 11 UTF-8 5.3.31 @@ -142,8 +141,8 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + ${java.version} + ${java.version} diff --git a/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java b/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java index 885a517..102baff 100644 --- a/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java +++ b/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java @@ -45,10 +45,10 @@ public void run() { .sorted(Comparator.comparing( (DataSet d) -> d.getExperiment().getProject().getSpace().getCode())).collect( Collectors.toList()); - int i = 0; + int datasetIndex = 0; for (DataSet dataSet : datasets) { - i++; - System.out.println("["+i+"]"); + datasetIndex++; + System.out.println("["+datasetIndex+"]"); System.out.println(dataSet.getExperiment().getIdentifier()); System.out.println(dataSet.getCode()); System.out.println(dataSet.getType().getCode());