diff --git a/pom.xml b/pom.xml
index 19f2587..b9c9238 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,6 +94,11 @@
picocli
4.6.2
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ 2.17.2
+
jline
jline
diff --git a/src/main/java/life/qbic/io/PetabParser.java b/src/main/java/life/qbic/io/PetabParser.java
new file mode 100644
index 0000000..220e41b
--- /dev/null
+++ b/src/main/java/life/qbic/io/PetabParser.java
@@ -0,0 +1,97 @@
+package life.qbic.io;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import life.qbic.model.petab.PetabMetadata;
+
+public class PetabParser {
+
+ private final String META_INFO_YAML = "metaInformation.yaml";
+
+ public PetabMetadata parse(String dataPath) {
+
+ File directory = new File(dataPath);
+ List sourcePetabReferences = new ArrayList<>();
+
+ File yaml = findYaml(directory);
+ if (yaml != null) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(yaml));
+ boolean inIDBlock = false;
+ while (true) {
+ String line = reader.readLine();
+ if (line == null) {
+ break;
+ }
+ // the id block ends, when a new key with colon is found
+ if (inIDBlock && line.contains(":")) {
+ inIDBlock = false;
+ }
+ // if we are in the id block, we collect one dataset code per line
+ if (inIDBlock) {
+ parseDatasetCode(line).ifPresent(sourcePetabReferences::add);
+ }
+ if (line.contains("openBISSourceIds:")) {
+ inIDBlock = true;
+ }
+ }
+ reader.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return new PetabMetadata(sourcePetabReferences);
+ }
+
+ private Optional parseDatasetCode(String line) {
+ // expected input: " - 20240702093837370-684137"
+ String[] tokens = line.split("-");
+ if(tokens.length == 3) {
+ return Optional.of(tokens[1].strip()+"-"+tokens[2].strip());
+ } else {
+ System.out.println("Could not extract dataset code from the following line:");
+ System.out.println(line);
+ }
+ return Optional.empty();
+ }
+
+ public void addDatasetId(String outputPath, String datasetCode) throws IOException {
+
+ Path path = Paths.get(Objects.requireNonNull(findYaml(new File(outputPath))).getPath());
+ Charset charset = StandardCharsets.UTF_8;
+
+ final String keyWord = "openBISId";
+
+ String idInLine = keyWord+":(.*)?(\\r\\n|[\\r\\n])";
+
+ String content = Files.readString(path, charset);
+ content = content.replaceAll(idInLine, keyWord+": "+datasetCode+"\n");
+ Files.write(path, content.getBytes(charset));
+ }
+
+ private File findYaml(File directory) {
+ for (File file : Objects.requireNonNull(directory.listFiles())) {
+ if (file.isFile() && file.getName().equalsIgnoreCase(META_INFO_YAML)) {
+ return file;
+ }
+ if (file.isDirectory()) {
+ return findYaml(file);
+ }
+ }
+ System.out.println(META_INFO_YAML + " not found");
+ return null;
+ }
+
+}
\ 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 f2d1538..d050ebf 100644
--- a/src/main/java/life/qbic/io/commandline/CommandLineOptions.java
+++ b/src/main/java/life/qbic/io/commandline/CommandLineOptions.java
@@ -8,8 +8,8 @@
// main command with format specifiers for the usage help message
@Command(name = "openbis-scripts",
- subcommands = { SampleHierarchyCommand.class, FindDatasetsCommand.class,
- UploadDatasetCommand.class, SpaceStatisticsCommand.class },
+ subcommands = { SampleHierarchyCommand.class, FindDatasetsCommand.class, DownloadPetabCommand.class,
+ UploadPetabResultCommand.class, UploadDatasetCommand.class, SpaceStatisticsCommand.class },
description = "A client software for querying openBIS.",
mixinStandardHelpOptions = true, versionProvider = ManifestVersionProvider.class)
public class CommandLineOptions {
diff --git a/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java b/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java
deleted file mode 100644
index 102baff..0000000
--- a/src/main/java/life/qbic/io/commandline/DownloadDatasetCommand.java
+++ /dev/null
@@ -1,68 +0,0 @@
-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 datasetIndex = 0;
- for (DataSet dataSet : datasets) {
- datasetIndex++;
- System.out.println("["+datasetIndex+"]");
- 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/DownloadPetabCommand.java b/src/main/java/life/qbic/io/commandline/DownloadPetabCommand.java
new file mode 100644
index 0000000..f09d973
--- /dev/null
+++ b/src/main/java/life/qbic/io/commandline/DownloadPetabCommand.java
@@ -0,0 +1,60 @@
+package life.qbic.io.commandline;
+
+import ch.ethz.sis.openbis.generic.OpenBIS;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import life.qbic.App;
+import life.qbic.io.PetabParser;
+import life.qbic.model.DatasetWithProperties;
+import life.qbic.model.download.OpenbisConnector;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Mixin;
+import picocli.CommandLine.Parameters;
+
+@Command(name = "download-petab",
+ description = "Downloads PEtab dataset and stores some additional information from openbis in the petab.yaml")
+public class DownloadPetabCommand implements Runnable {
+
+ @Parameters(arity = "1", paramLabel = "dataset id", description = "The code of the dataset to download. Can be found via list-data.")
+ private String datasetCode;
+ @Parameters(arity = "1", paramLabel = "download path", description = "The local path where to store the downloaded data")
+ private String outputPath;
+ @Mixin
+ AuthenticationOptions auth = new AuthenticationOptions();
+
+ @Override
+ public void run() {
+ OpenBIS authentication = App.loginToOpenBIS(auth.getPassword(), auth.getUser(), auth.getAS(), auth.getDSS());
+ OpenbisConnector openbis = new OpenbisConnector(authentication);
+
+ List datasets = openbis.findDataSets(Collections.singletonList(datasetCode));
+
+ if(datasets.isEmpty()) {
+ System.out.println(datasetCode+" not found");
+ return;
+ }
+ DatasetWithProperties result = new DatasetWithProperties(datasets.get(0));
+ Optional patientID = openbis.findPropertyInSampleHierarchy("PATIENT_DKFZ_ID",
+ result.getExperiment().getIdentifier());
+ patientID.ifPresent(s -> result.addProperty("patientID", s));
+
+ System.out.println("Found dataset, downloading.");
+ System.out.println();
+
+ openbis.downloadDataset(outputPath, datasetCode);
+
+ PetabParser parser = new PetabParser();
+ try {
+ System.out.println("Adding dataset identifier to metaInformation.yaml.");
+ parser.addDatasetId(outputPath, datasetCode);
+ } catch (IOException e) {
+ System.out.println("Could not add dataset identifier.");
+ throw new RuntimeException(e);
+ }
+ System.out.println("Done");
+ }
+
+}
diff --git a/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java b/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java
index 9ea557e..74fa98e 100644
--- a/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java
+++ b/src/main/java/life/qbic/io/commandline/UploadDatasetCommand.java
@@ -70,9 +70,4 @@ 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/io/commandline/UploadPetabResultCommand.java b/src/main/java/life/qbic/io/commandline/UploadPetabResultCommand.java
new file mode 100644
index 0000000..3f29163
--- /dev/null
+++ b/src/main/java/life/qbic/io/commandline/UploadPetabResultCommand.java
@@ -0,0 +1,79 @@
+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.util.ArrayList;
+import java.util.List;
+import life.qbic.App;
+import life.qbic.io.PetabParser;
+import life.qbic.model.download.OpenbisConnector;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Mixin;
+import picocli.CommandLine.Parameters;
+
+@Command(name = "upload-petab",
+ description = "uploads a PETab folder and attaches it to a provided experiment and any datasets referenced in the PETab metadata (e.g. for PETab results).")
+public class UploadPetabResultCommand 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;
+ private PetabParser petabParser = new PetabParser();
+
+ @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;
+ }
+ System.out.println("Looking for reference datasets in metaInformation.yaml...");
+ parents = petabParser.parse(dataPath).getSourcePetabReferences();
+ if(parents.isEmpty()) {
+ System.out.println("No reference datasets found in openBISSourceIds property. Assuming"
+ + "this is a new dataset.");
+ } else {
+ System.out.println("Found reference ids: " + String.join(", ", parents));
+ if (!datasetsExist(parents)) {
+ System.out.printf("One or more datasets %s could not be found%n", parents);
+ return;
+ } else {
+ System.out.println("Referenced datasets found");
+ }
+ }
+ System.out.println("Uploading dataset...");
+ //TODO copy and remove source references here
+ DataSetPermId result = openbis.registerDataset(Path.of(dataPath), experimentID, parents);
+ System.out.printf("Dataset %s was successfully created%n", result.getPermId());
+ }
+
+ private boolean datasetsExist(List datasetCodes) {
+ return openbis.findDataSets(datasetCodes).size() == datasetCodes.size();
+ }
+
+ private boolean experimentExists(String experimentID) {
+ return openbis.experimentExists(experimentID);
+ }
+
+ private boolean pathValid(String dataPath) {
+ return new File(dataPath).exists();
+ }
+
+}
diff --git a/src/main/java/life/qbic/model/petab/Arguments.java b/src/main/java/life/qbic/model/petab/Arguments.java
new file mode 100644
index 0000000..05629ed
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/Arguments.java
@@ -0,0 +1,16 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+public class Arguments {
+ @JsonProperty
+ List housekeeperObservableIds;
+
+ @Override
+ public String toString() {
+ return "Arguments{" +
+ "housekeeperObservableIds=" + housekeeperObservableIds +
+ '}';
+ }
+}
diff --git a/src/main/java/life/qbic/model/petab/CellCountInfo.java b/src/main/java/life/qbic/model/petab/CellCountInfo.java
new file mode 100644
index 0000000..e65ce59
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/CellCountInfo.java
@@ -0,0 +1,23 @@
+package life.qbic.model.petab;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CellCountInfo {
+ @JsonProperty
+ double seeded;
+ @JsonProperty
+ String ncellsCount;
+ @JsonProperty
+ String unit;
+
+ @Override
+ public String toString() {
+ return "CellCountInfo{" +
+ "seeded=" + seeded +
+ ", ncellsCount='" + ncellsCount + '\'' +
+ ", unit='" + unit + '\'' +
+ '}';
+ }
+}
+
diff --git a/src/main/java/life/qbic/model/petab/ConditionWithUnit.java b/src/main/java/life/qbic/model/petab/ConditionWithUnit.java
new file mode 100644
index 0000000..d46e925
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/ConditionWithUnit.java
@@ -0,0 +1,26 @@
+package life.qbic.model.petab;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ConditionWithUnit {
+ @JsonProperty
+ String name;
+ @JsonProperty
+ String unit;
+
+ public ConditionWithUnit() {}
+
+ public ConditionWithUnit(String name, String unit) {
+ this.name = name;
+ this.unit = unit;
+ }
+
+ @Override
+ public String toString() {
+ return "ConditionWithUnit{" +
+ "name='" + name + '\'' +
+ ", unit='" + unit + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/life/qbic/model/petab/ExperimentalCondition.java b/src/main/java/life/qbic/model/petab/ExperimentalCondition.java
new file mode 100644
index 0000000..8672a80
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/ExperimentalCondition.java
@@ -0,0 +1,35 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+
+public class ExperimentalCondition {
+ @JsonProperty
+ IdWithPattern conditionId;
+ @JsonProperty
+ List conditions;
+
+ public ExperimentalCondition() {}
+
+ public ExperimentalCondition(IdWithPattern pattern, List conditions) {
+ this.conditionId = pattern;
+ this.conditions = conditions;
+ }
+
+ public void setConditions(List conditions) {
+ this.conditions = conditions;
+ }
+
+ public void setConditionId(IdWithPattern id) {
+ this.conditionId = id;
+ }
+
+ @Override
+ public String toString() {
+ return "ExperimentalCondition{" +
+ "conditionId=" + conditionId +
+ ", conditions=" + conditions +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/life/qbic/model/petab/IdWithPattern.java b/src/main/java/life/qbic/model/petab/IdWithPattern.java
new file mode 100644
index 0000000..98ab352
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/IdWithPattern.java
@@ -0,0 +1,22 @@
+package life.qbic.model.petab;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class IdWithPattern {
+ @JsonProperty
+ String pattern;
+
+ public IdWithPattern() {}
+
+ public IdWithPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ @Override
+ public String toString() {
+ return "IdWithPattern{" +
+ "pattern='" + pattern + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/life/qbic/model/petab/Measurement.java b/src/main/java/life/qbic/model/petab/Measurement.java
new file mode 100644
index 0000000..531e7b5
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/Measurement.java
@@ -0,0 +1,19 @@
+package life.qbic.model.petab;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Measurement {
+ @JsonProperty
+ String unit;
+ @JsonProperty
+ String lloq;
+
+ @Override
+ public String toString() {
+ return "Measurement{" +
+ "unit='" + unit + '\'' +
+ ", lloq='" + lloq + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/life/qbic/model/petab/MeasurementData.java b/src/main/java/life/qbic/model/petab/MeasurementData.java
new file mode 100644
index 0000000..62b449a
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/MeasurementData.java
@@ -0,0 +1,21 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class MeasurementData {
+ @JsonProperty
+ private Measurement measurement;
+ @JsonProperty
+ private Time time;
+ @JsonProperty
+ private IdWithPattern replicateId;
+
+ @Override
+ public String toString() {
+ return "MeasurementData{" +
+ "measurement=" + measurement +
+ ", time=" + time +
+ ", replicateId=" + replicateId +
+ '}';
+ }
+}
diff --git a/src/main/java/life/qbic/model/petab/Medium.java b/src/main/java/life/qbic/model/petab/Medium.java
new file mode 100644
index 0000000..d5c4ed3
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/Medium.java
@@ -0,0 +1,22 @@
+package life.qbic.model.petab;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Medium {
+ @JsonProperty
+ String type;
+ @JsonProperty
+ double volume;
+ @JsonProperty
+ String unit;
+
+ @Override
+ public String toString() {
+ return "Medium{" +
+ "type='" + type + '\'' +
+ ", volume=" + volume +
+ ", unit='" + unit + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/life/qbic/model/petab/MetaInformation.java b/src/main/java/life/qbic/model/petab/MetaInformation.java
new file mode 100644
index 0000000..ff19ab3
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/MetaInformation.java
@@ -0,0 +1,90 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+public class MetaInformation {
+
+ @JsonProperty
+ private ExperimentInformation ExperimentInformation;
+
+ @JsonProperty
+ private Units units;
+ @JsonProperty
+ private PreprocessingInformation PreprocessingInformation;
+ @JsonProperty
+ private MeasurementData measurementData;
+ @JsonProperty
+ private ExperimentalCondition experimentalCondition;
+
+
+ @Override
+ public String toString() {
+ return "MetaInformation{" +
+ "units=" + units +
+ ", preprocessingInformation=" + PreprocessingInformation +
+ ", measurementData=" + measurementData +
+ ", experimentalCondition=" + experimentalCondition +
+ '}';
+ }
+
+ public Units getUnits() {
+ return units;
+ }
+
+ public class ExperimentInformation {
+
+ @Override
+ public String toString() {
+ return "MetaInformation{}";
+ }
+ }
+
+ public class Units {
+ @JsonProperty
+ private String measurement;
+ @JsonProperty
+ private String time;
+ @JsonProperty
+ private String treatment;
+ @JsonProperty
+ private String stimulus;
+ @JsonProperty
+ private Medium medium;
+ @JsonProperty
+ private CellCountInfo ncells;
+ @JsonProperty
+ private String measurement_technique;
+ @JsonProperty
+ private String openBISId;
+ @JsonProperty
+ private List openBISParentIds;
+ @JsonProperty
+ private List dateOfExperiment;
+
+ @Override
+ public String toString() {
+ return "Units{" +
+ "measurement='" + measurement + '\'' +
+ ", time='" + time + '\'' +
+ ", treatment='" + treatment + '\'' +
+ ", stimulus='" + stimulus + '\'' +
+ ", medium=" + medium +
+ ", ncells=" + ncells +
+ ", measurement_technique='" + measurement_technique + '\'' +
+ ", openBISId='" + openBISId + '\'' +
+ ", openBISParentIds=" + openBISParentIds +
+ ", dateOfExperiment=" + dateOfExperiment +
+ '}';
+ }
+
+ public void setOpenbisParentIds(List list) {
+ this.openBISParentIds = list;
+ }
+
+ public void setOpenbisId(String id) {
+ this.openBISId = id;
+ }
+ }
+
+}
diff --git a/src/main/java/life/qbic/model/petab/PetabMetadata.java b/src/main/java/life/qbic/model/petab/PetabMetadata.java
new file mode 100644
index 0000000..7fb8b01
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/PetabMetadata.java
@@ -0,0 +1,16 @@
+package life.qbic.model.petab;
+
+import java.util.List;
+
+public class PetabMetadata {
+
+ List sourceDatasetIdentifiers;
+
+ public PetabMetadata(List sourceDatasetIdentifiers) {
+ this.sourceDatasetIdentifiers = sourceDatasetIdentifiers;
+ }
+
+ public List getSourcePetabReferences() {
+ return sourceDatasetIdentifiers;
+ }
+}
diff --git a/src/main/java/life/qbic/model/petab/Preprocessing.java b/src/main/java/life/qbic/model/petab/Preprocessing.java
new file mode 100644
index 0000000..6bc4dbf
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/Preprocessing.java
@@ -0,0 +1,21 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Preprocessing {
+ @JsonProperty
+ private String method;
+ @JsonProperty
+ private String description;
+ @JsonProperty
+ private Arguments arguments;
+
+ @Override
+ public String toString() {
+ return "Preprocessing{" +
+ "method='" + method + '\'' +
+ ", description='" + description + '\'' +
+ ", arguments=" + arguments +
+ '}';
+ }
+}
diff --git a/src/main/java/life/qbic/model/petab/PreprocessingInformation.java b/src/main/java/life/qbic/model/petab/PreprocessingInformation.java
new file mode 100644
index 0000000..b7a2290
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/PreprocessingInformation.java
@@ -0,0 +1,18 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class PreprocessingInformation {
+ @JsonProperty
+ private String normalizationStatus;
+ @JsonProperty
+ private Preprocessing preprocessing;
+
+ @Override
+ public String toString() {
+ return "PreprocessingInformation{" +
+ "normalizationStatus='" + normalizationStatus + '\'' +
+ ", preprocessing=" + preprocessing +
+ '}';
+ }
+}
diff --git a/src/main/java/life/qbic/model/petab/Time.java b/src/main/java/life/qbic/model/petab/Time.java
new file mode 100644
index 0000000..ce9ea4f
--- /dev/null
+++ b/src/main/java/life/qbic/model/petab/Time.java
@@ -0,0 +1,15 @@
+package life.qbic.model.petab;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Time {
+ @JsonProperty
+ String unit;
+
+ @Override
+ public String toString() {
+ return "Time{" +
+ "unit='" + unit + '\'' +
+ '}';
+ }
+}