Skip to content

Commit 419a12a

Browse files
committed
First refactor part
1 parent a8414c2 commit 419a12a

20 files changed

Lines changed: 1196 additions & 10 deletions

File tree

user-interface/src/main/java/life/qbic/datamanager/files/export/FileNameFormatter.java renamed to application-commons/src/main/java/life/qbic/application/commons/FileNameFormatter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package life.qbic.datamanager.files.export;
1+
package life.qbic.application.commons;
22

33
import java.time.LocalDate;
44
import java.time.format.DateTimeFormatter;

project-management-infrastructure/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@
129129
<artifactId>jakarta.xml.bind-api</artifactId>
130130
<version>4.0.2</version>
131131
</dependency>
132+
133+
<!-- Needed for xlsx support !-->
134+
<dependency>
135+
<groupId>org.apache.poi</groupId>
136+
<artifactId>poi</artifactId>
137+
<version>5.4.0</version>
138+
</dependency>
139+
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
140+
<dependency>
141+
<groupId>org.apache.poi</groupId>
142+
<artifactId>poi-ooxml</artifactId>
143+
<version>5.4.0</version>
144+
</dependency>
132145
</dependencies>
133146

134147
</project>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package life.qbic.projectmanagement.infrastructure.api.template;
2+
3+
import java.util.Optional;
4+
import life.qbic.projectmanagement.infrastructure.api.template.ExampleProvider.Helper;
5+
6+
/**
7+
* A column in a file (for example xlsx files or TSV files)
8+
*
9+
* @since 1.8.0
10+
*/
11+
public interface Column {
12+
13+
/**
14+
* The index of the column 0-based
15+
*
16+
* @return the index of this column
17+
*/
18+
int index();
19+
20+
/**
21+
* The name of the column as it can be used in a header cell for the column
22+
*
23+
* @return the name of the column
24+
*/
25+
String headerName();
26+
27+
/**
28+
* @return true if filling out this column is mandatory; false otherwise
29+
*/
30+
boolean isMandatory();
31+
32+
/**
33+
* @return true if the content of this column is only provided and not considered relevant for
34+
* parsing; false otherwise
35+
*/
36+
boolean isReadOnly();
37+
38+
/**
39+
* Information on how to fill this column
40+
*
41+
* @return a helper with information on how to fill this column. Can be {@link Optional#empty()}
42+
* if no help is provided.
43+
*/
44+
Optional<Helper> getFillHelp();
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package life.qbic.projectmanagement.infrastructure.api.template;
2+
3+
import java.util.Optional;
4+
import life.qbic.projectmanagement.application.confounding.ConfoundingVariableService.VariableReference;
5+
import life.qbic.projectmanagement.infrastructure.api.template.ExampleProvider.Helper;
6+
7+
public record ConfoundingVariableColumn(VariableReference variableReference, int index,
8+
String headerName) implements Column {
9+
10+
@Override
11+
public boolean isMandatory() {
12+
return false;
13+
}
14+
15+
@Override
16+
public boolean isReadOnly() {
17+
return false;
18+
}
19+
20+
@Override
21+
public Optional<Helper> getFillHelp() {
22+
return Optional.empty();
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package life.qbic.projectmanagement.infrastructure.api.template;
2+
3+
/**
4+
* TODO!
5+
* <b>short description</b>
6+
*
7+
* <p>detailed description</p>
8+
*
9+
* @since <version tag>
10+
*/
11+
public interface ExampleProvider {
12+
13+
record Helper(String exampleValue, String description) {
14+
15+
}
16+
17+
Helper getHelper(Column column);
18+
19+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package life.qbic.projectmanagement.infrastructure.api.template;
2+
3+
import java.util.Arrays;
4+
import java.util.Optional;
5+
import java.util.Set;
6+
import java.util.stream.Collectors;
7+
import life.qbic.projectmanagement.infrastructure.api.template.ExampleProvider.Helper;
8+
9+
/**
10+
* <b>Sample Register Columns</b>
11+
*
12+
* <p>Enumeration of the columns shown in the file used for sample registration
13+
* in the context of sample batch file based upload. Provides the name of the header column, the
14+
* column index and if the column should be set to readOnly in the generated sheet
15+
* </p>
16+
*/
17+
public enum RegisterColumn implements Column {
18+
19+
SAMPLE_NAME("Sample Name", 0, false, true),
20+
ANALYSIS("Analysis to be performed", 1, false, true),
21+
BIOLOGICAL_REPLICATE("Biological Replicate", 2, false, false),
22+
CONDITION("Condition", 3, false, true),
23+
SPECIES("Species", 4, false, true),
24+
SPECIMEN("Specimen", 5, false, true),
25+
ANALYTE("Analyte", 6, false, true),
26+
COMMENT("Comment", 7, false, false);
27+
28+
private static final ExampleProvider exampleProvider = column -> {
29+
if (column instanceof RegisterColumn registerColumn) {
30+
return switch (registerColumn) {
31+
case SAMPLE_NAME -> new Helper("Free text, e.g. RNA Sample 1, RNA Sample 2",
32+
"A visual aid to simplify navigation for the person managing the metadata.");
33+
case ANALYSIS -> new Helper("Enumeration, Select a value from the dropdown",
34+
"The test performed on samples for the purpose of finding and measuring chemical substances.");
35+
case BIOLOGICAL_REPLICATE -> new Helper("Free text, e.g. patient1, patient2, Mouse1", """
36+
Different samples measured accross multiple conditions.
37+
Tip: You can use this column to identifiy whether the samples belong to the same source.""");
38+
case CONDITION -> new Helper("Enumeration, Select a value from the dropdown", """
39+
A distinct value or condition of the independent variable at which the dependent variable is measured in order to carry out statistical analysis.
40+
Note: The values in the dropdown are the predefined values from the experimental design.""");
41+
case SPECIES -> new Helper("Enumeration, Select a value from the dropdown", """
42+
Scientific name of the organism(s) from which the biological material is derived. E.g. Homo sapiens, Mus musculus.
43+
Note: The values in the dropdown are the predefined values from the experimental design.""");
44+
case ANALYTE -> new Helper("Enumeration, Select a value from the dropdown", """
45+
The chemical substance extracted from the biological material that is identified and measured.
46+
Note: The values in the dropdown are the predefined values from the experimental design.""");
47+
case SPECIMEN -> new Helper("Enumeration, Select a value from the dropdown", """
48+
Name of the biological material from which the analytes would be extracted.
49+
Note: The values in the dropdown are the predefined values from the experimental design.""");
50+
case COMMENT -> new Helper("Free text", "Notes about the sample. (Max 500 characters)");
51+
};
52+
}
53+
throw new IllegalArgumentException(
54+
"Column not of class " + RegisterColumn.class.getName() + " but is "
55+
+ column.getClass().getName());
56+
};
57+
58+
private final String headerName;
59+
private final int columnIndex;
60+
private final boolean readOnly;
61+
private final boolean mandatory;
62+
63+
public static int maxColumnIndex() {
64+
return Arrays.stream(values())
65+
.mapToInt(RegisterColumn::index)
66+
.max().orElse(0);
67+
}
68+
69+
public static Set<String> headerNames() {
70+
return Arrays.stream(values()).map(RegisterColumn::headerName).collect(Collectors.toSet());
71+
}
72+
73+
/**
74+
* @param headerName the name in the header
75+
* @param columnIndex the index of the column this property is in
76+
* @param readOnly is the property read only
77+
* @param mandatory
78+
*/
79+
RegisterColumn(String headerName, int columnIndex, boolean readOnly, boolean mandatory) {
80+
this.headerName = headerName;
81+
this.columnIndex = columnIndex;
82+
this.readOnly = readOnly;
83+
this.mandatory = mandatory;
84+
}
85+
86+
@Override
87+
public String headerName() {
88+
return headerName;
89+
}
90+
91+
@Override
92+
public int index() {
93+
return columnIndex;
94+
}
95+
96+
@Override
97+
public boolean isReadOnly() {
98+
return readOnly;
99+
}
100+
101+
@Override
102+
public boolean isMandatory() {
103+
return mandatory;
104+
}
105+
106+
@Override
107+
public Optional<Helper> getFillHelp() {
108+
return Optional.of(exampleProvider.getHelper(this));
109+
}
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package life.qbic.projectmanagement.infrastructure.api.template;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Optional;
6+
import java.util.function.BinaryOperator;
7+
import life.qbic.projectmanagement.application.confounding.ConfoundingVariableService.ConfoundingVariableInformation;
8+
import org.apache.poi.ss.usermodel.CreationHelper;
9+
import org.apache.poi.ss.usermodel.Row;
10+
import org.apache.poi.ss.usermodel.Sheet;
11+
12+
public class SampleRegisterFactory implements WorkbookFactory {
13+
14+
private final List<String> analysisMethods;
15+
private final List<String> conditions;
16+
private final List<String> analytes;
17+
private final List<String> species;
18+
private final List<String> specimen;
19+
private final List<ConfoundingVariableInformation> confoundingVariables;
20+
21+
public SampleRegisterFactory(List<String> analysisMethods, List<String> conditions,
22+
List<String> analytes, List<String> species,
23+
List<String> specimen, List<ConfoundingVariableInformation> confoundingVariables) {
24+
this.analysisMethods = analysisMethods;
25+
this.conditions = conditions;
26+
this.analytes = analytes;
27+
this.species = species;
28+
this.specimen = specimen;
29+
this.confoundingVariables = confoundingVariables;
30+
}
31+
32+
@Override
33+
public int numberOfRowsToGenerate() {
34+
return 2_000;
35+
}
36+
37+
@Override
38+
public void enterValuesAsRows(Sheet sheet, CellStyles cellStyles) {
39+
//nothing to do
40+
}
41+
42+
@Override
43+
public String sheetName() {
44+
return "Sample Metadata";
45+
}
46+
47+
@Override
48+
public Column[] getColumns() {
49+
ArrayList<Column> columns = new ArrayList<>(List.of(RegisterColumn.values()));
50+
51+
var colOffset = RegisterColumn.maxColumnIndex() + 1; //offset + 0 is the next free column
52+
for (int i = 0; i < confoundingVariables.size(); i++) {
53+
var confoundingVariable = confoundingVariables.get(i);
54+
int columnIndex = colOffset + i;
55+
columns.add(
56+
new ConfoundingVariableColumn(confoundingVariable.id(), columnIndex,
57+
confoundingVariable.variableName()));
58+
}
59+
60+
return columns.toArray(new Column[0]);
61+
}
62+
63+
64+
@Override
65+
public void customizeValidation(Sheet hiddenSheet, Sheet sheet) {
66+
WorkbookFactory.addValidation(hiddenSheet,
67+
sheet,
68+
1,
69+
numberOfRowsToGenerate() - 1,
70+
RegisterColumn.ANALYSIS.index(),
71+
"Analysis Method",
72+
analysisMethods);
73+
74+
WorkbookFactory.addValidation(hiddenSheet,
75+
sheet,
76+
1,
77+
numberOfRowsToGenerate() - 1,
78+
RegisterColumn.CONDITION.index(),
79+
"Condition",
80+
conditions);
81+
WorkbookFactory.addValidation(hiddenSheet,
82+
sheet,
83+
1,
84+
numberOfRowsToGenerate() - 1,
85+
RegisterColumn.ANALYTE.index(),
86+
"Analytes",
87+
analytes);
88+
WorkbookFactory.addValidation(hiddenSheet,
89+
sheet,
90+
1,
91+
numberOfRowsToGenerate() - 1,
92+
RegisterColumn.SPECIES.index(),
93+
"Species",
94+
species);
95+
WorkbookFactory.addValidation(hiddenSheet,
96+
sheet,
97+
1,
98+
numberOfRowsToGenerate() - 1,
99+
RegisterColumn.SPECIMEN.index(),
100+
"Specimen",
101+
specimen);
102+
}
103+
104+
@Override
105+
public Optional<String> longestValueForColumn(int columnIndex) {
106+
BinaryOperator<String> keepLongerString = (String s1, String s2) -> s1.length() > s2.length()
107+
? s1 : s2;
108+
if (columnIndex == RegisterColumn.ANALYSIS.index()) {
109+
return analysisMethods.stream().reduce(keepLongerString);
110+
} else if (columnIndex == RegisterColumn.CONDITION.index()) {
111+
return conditions.stream().reduce(keepLongerString);
112+
} else if (columnIndex == RegisterColumn.ANALYTE.index()) {
113+
return analytes.stream().reduce(keepLongerString);
114+
} else if (columnIndex == RegisterColumn.SPECIES.index()) {
115+
return species.stream().reduce(keepLongerString);
116+
} else if (columnIndex == RegisterColumn.SPECIMEN.index()) {
117+
return specimen.stream().reduce(keepLongerString);
118+
}
119+
return Optional.empty();
120+
}
121+
122+
123+
@Override
124+
public void customizeHeaderCells(Row header, CreationHelper creationHelper,
125+
CellStyles cellStyles) {
126+
// nothing to do
127+
}
128+
}

0 commit comments

Comments
 (0)