7139 |
27 Apr 23 |
nicklas |
1 |
package net.sf.basedb.reggie.plugins; |
7139 |
27 Apr 23 |
nicklas |
2 |
|
7139 |
27 Apr 23 |
nicklas |
3 |
import java.io.IOException; |
7139 |
27 Apr 23 |
nicklas |
4 |
import java.io.InputStream; |
7139 |
27 Apr 23 |
nicklas |
5 |
import java.util.ArrayList; |
7191 |
23 May 23 |
nicklas |
6 |
import java.util.Collection; |
7139 |
27 Apr 23 |
nicklas |
7 |
import java.util.HashMap; |
7191 |
23 May 23 |
nicklas |
8 |
import java.util.LinkedHashMap; |
7139 |
27 Apr 23 |
nicklas |
9 |
import java.util.List; |
7155 |
10 May 23 |
nicklas |
10 |
import java.util.Locale; |
7139 |
27 Apr 23 |
nicklas |
11 |
import java.util.Map; |
7139 |
27 Apr 23 |
nicklas |
12 |
import java.util.regex.Pattern; |
7139 |
27 Apr 23 |
nicklas |
13 |
|
7141 |
02 May 23 |
nicklas |
14 |
import org.json.simple.JSONArray; |
7139 |
27 Apr 23 |
nicklas |
15 |
import org.json.simple.JSONObject; |
7139 |
27 Apr 23 |
nicklas |
16 |
|
7158 |
10 May 23 |
nicklas |
17 |
import net.sf.basedb.core.AnnotationRestriction; |
7158 |
10 May 23 |
nicklas |
18 |
import net.sf.basedb.core.AnnotationSimpleRestriction; |
7185 |
22 May 23 |
nicklas |
19 |
import net.sf.basedb.core.AnyToAny; |
7142 |
04 May 23 |
nicklas |
20 |
import net.sf.basedb.core.BioMaterialEvent; |
7141 |
02 May 23 |
nicklas |
21 |
import net.sf.basedb.core.BioPlate; |
7140 |
28 Apr 23 |
nicklas |
22 |
import net.sf.basedb.core.BioWell; |
7139 |
27 Apr 23 |
nicklas |
23 |
import net.sf.basedb.core.DbControl; |
7141 |
02 May 23 |
nicklas |
24 |
import net.sf.basedb.core.Extract; |
7185 |
22 May 23 |
nicklas |
25 |
import net.sf.basedb.core.File; |
7161 |
11 May 23 |
nicklas |
26 |
import net.sf.basedb.core.InvalidDataException; |
7142 |
04 May 23 |
nicklas |
27 |
import net.sf.basedb.core.ItemList; |
7141 |
02 May 23 |
nicklas |
28 |
import net.sf.basedb.core.ItemQuery; |
7158 |
10 May 23 |
nicklas |
29 |
import net.sf.basedb.core.ItemSubtype; |
7141 |
02 May 23 |
nicklas |
30 |
import net.sf.basedb.core.MeasuredBioMaterial; |
7158 |
10 May 23 |
nicklas |
31 |
import net.sf.basedb.core.Operator; |
7162 |
12 May 23 |
nicklas |
32 |
import net.sf.basedb.core.ProgressReporter; |
7141 |
02 May 23 |
nicklas |
33 |
import net.sf.basedb.core.Sample; |
7168 |
12 May 23 |
nicklas |
34 |
import net.sf.basedb.core.StringUtil; |
7141 |
02 May 23 |
nicklas |
35 |
import net.sf.basedb.core.query.Annotations; |
7141 |
02 May 23 |
nicklas |
36 |
import net.sf.basedb.core.query.Expressions; |
7141 |
02 May 23 |
nicklas |
37 |
import net.sf.basedb.core.query.Hql; |
7141 |
02 May 23 |
nicklas |
38 |
import net.sf.basedb.core.query.Restrictions; |
7140 |
28 Apr 23 |
nicklas |
39 |
import net.sf.basedb.reggie.JsonUtil; |
7141 |
02 May 23 |
nicklas |
40 |
import net.sf.basedb.reggie.Reggie; |
7251 |
08 Jun 23 |
nicklas |
41 |
import net.sf.basedb.reggie.Site; |
7141 |
02 May 23 |
nicklas |
42 |
import net.sf.basedb.reggie.dao.Annotationtype; |
7164 |
12 May 23 |
nicklas |
43 |
import net.sf.basedb.reggie.dao.BiomaterialList; |
7143 |
05 May 23 |
nicklas |
44 |
import net.sf.basedb.reggie.dao.Blood; |
7142 |
04 May 23 |
nicklas |
45 |
import net.sf.basedb.reggie.dao.Case; |
7144 |
05 May 23 |
nicklas |
46 |
import net.sf.basedb.reggie.dao.Consent; |
7142 |
04 May 23 |
nicklas |
47 |
import net.sf.basedb.reggie.dao.Dna; |
7142 |
04 May 23 |
nicklas |
48 |
import net.sf.basedb.reggie.dao.FlowThrough; |
7142 |
04 May 23 |
nicklas |
49 |
import net.sf.basedb.reggie.dao.Lysate; |
7141 |
02 May 23 |
nicklas |
50 |
import net.sf.basedb.reggie.dao.NoSpecimen; |
7142 |
04 May 23 |
nicklas |
51 |
import net.sf.basedb.reggie.dao.Patient; |
7142 |
04 May 23 |
nicklas |
52 |
import net.sf.basedb.reggie.dao.ReggieItem; |
7142 |
04 May 23 |
nicklas |
53 |
import net.sf.basedb.reggie.dao.Rna; |
7140 |
28 Apr 23 |
nicklas |
54 |
import net.sf.basedb.reggie.dao.SpecimenTube; |
7140 |
28 Apr 23 |
nicklas |
55 |
import net.sf.basedb.reggie.dao.StoragePlate; |
7141 |
02 May 23 |
nicklas |
56 |
import net.sf.basedb.reggie.dao.Subtype; |
7193 |
23 May 23 |
nicklas |
57 |
import net.sf.basedb.util.EqualsHelper; |
7185 |
22 May 23 |
nicklas |
58 |
import net.sf.basedb.util.FileUtil; |
7161 |
11 May 23 |
nicklas |
59 |
import net.sf.basedb.util.Values; |
7139 |
27 Apr 23 |
nicklas |
60 |
import net.sf.basedb.util.excel.XlsxToCsvUtil; |
7139 |
27 Apr 23 |
nicklas |
61 |
import net.sf.basedb.util.parser.ConstantMapper; |
7139 |
27 Apr 23 |
nicklas |
62 |
import net.sf.basedb.util.parser.FlatFileParser; |
7139 |
27 Apr 23 |
nicklas |
63 |
import net.sf.basedb.util.parser.Mapper; |
7139 |
27 Apr 23 |
nicklas |
64 |
import net.sf.basedb.util.parser.FlatFileParser.LineType; |
7139 |
27 Apr 23 |
nicklas |
65 |
|
7139 |
27 Apr 23 |
nicklas |
66 |
/** |
7139 |
27 Apr 23 |
nicklas |
Importer for the sample sheet with information about |
7139 |
27 Apr 23 |
nicklas |
transport boxes from CMD. |
7139 |
27 Apr 23 |
nicklas |
@since 4.47 |
7139 |
27 Apr 23 |
nicklas |
70 |
*/ |
7139 |
27 Apr 23 |
nicklas |
71 |
public class TransportBoxImporter |
7139 |
27 Apr 23 |
nicklas |
72 |
{ |
7142 |
04 May 23 |
nicklas |
73 |
/** |
7142 |
04 May 23 |
nicklas |
This ID is used on work lists for transport boxes. |
7142 |
04 May 23 |
nicklas |
75 |
*/ |
7142 |
04 May 23 |
nicklas |
76 |
public static final String WORK_LIST_ID = "net.sf.basedb.reggie.transport-box"; |
7139 |
27 Apr 23 |
nicklas |
77 |
|
7142 |
04 May 23 |
nicklas |
78 |
private final List<String> messages; |
7139 |
27 Apr 23 |
nicklas |
79 |
private final List<String> errorMessages; |
7144 |
05 May 23 |
nicklas |
80 |
private final List<String> debugMessages; |
7139 |
27 Apr 23 |
nicklas |
81 |
|
7139 |
27 Apr 23 |
nicklas |
82 |
private final List<SampleEntry> specimen; |
7139 |
27 Apr 23 |
nicklas |
83 |
private final Map<String, SampleEntry> specimenByClarityId; |
7191 |
23 May 23 |
nicklas |
84 |
private final Map<String, Box> boxes; |
7139 |
27 Apr 23 |
nicklas |
85 |
|
7139 |
27 Apr 23 |
nicklas |
86 |
private List<String> worksheets; |
7139 |
27 Apr 23 |
nicklas |
87 |
private String parsedWorksheet; |
7141 |
02 May 23 |
nicklas |
88 |
private int totalErrors; |
7141 |
02 May 23 |
nicklas |
89 |
private int totalWarnings; |
7139 |
27 Apr 23 |
nicklas |
90 |
|
7143 |
05 May 23 |
nicklas |
91 |
private int numMappedToSpecimen; |
7143 |
05 May 23 |
nicklas |
92 |
private int numMappedToNoSpecimen; |
7143 |
05 May 23 |
nicklas |
93 |
private int numMappedToCase; |
7143 |
05 May 23 |
nicklas |
94 |
private int numMappedToBlood; |
7143 |
05 May 23 |
nicklas |
95 |
private int numMappedToNothing; |
7143 |
05 May 23 |
nicklas |
96 |
private int numNoConsent; |
7143 |
05 May 23 |
nicklas |
97 |
|
7191 |
23 May 23 |
nicklas |
98 |
private JSONObject requestParameters; |
7161 |
11 May 23 |
nicklas |
99 |
|
7139 |
27 Apr 23 |
nicklas |
100 |
public TransportBoxImporter() |
7139 |
27 Apr 23 |
nicklas |
101 |
{ |
7142 |
04 May 23 |
nicklas |
102 |
this.messages = new ArrayList<>(); |
7142 |
04 May 23 |
nicklas |
103 |
this.errorMessages = new ArrayList<>(); |
7144 |
05 May 23 |
nicklas |
104 |
this.debugMessages = new ArrayList<>(); |
7139 |
27 Apr 23 |
nicklas |
105 |
this.specimen = new ArrayList<>(); |
7139 |
27 Apr 23 |
nicklas |
106 |
this.specimenByClarityId = new HashMap<>(); |
7191 |
23 May 23 |
nicklas |
107 |
this.boxes = new LinkedHashMap<>(); |
7139 |
27 Apr 23 |
nicklas |
108 |
} |
7139 |
27 Apr 23 |
nicklas |
109 |
|
7139 |
27 Apr 23 |
nicklas |
110 |
public boolean hasWarning() |
7139 |
27 Apr 23 |
nicklas |
111 |
{ |
7141 |
02 May 23 |
nicklas |
112 |
return totalWarnings > 0; |
7139 |
27 Apr 23 |
nicklas |
113 |
} |
7139 |
27 Apr 23 |
nicklas |
114 |
|
7141 |
02 May 23 |
nicklas |
115 |
public int getTotalWarnings() |
7141 |
02 May 23 |
nicklas |
116 |
{ |
7141 |
02 May 23 |
nicklas |
117 |
return totalWarnings; |
7141 |
02 May 23 |
nicklas |
118 |
} |
7141 |
02 May 23 |
nicklas |
119 |
|
7139 |
27 Apr 23 |
nicklas |
120 |
public boolean hasError() |
7139 |
27 Apr 23 |
nicklas |
121 |
{ |
7141 |
02 May 23 |
nicklas |
122 |
return totalErrors > 0; |
7139 |
27 Apr 23 |
nicklas |
123 |
} |
7139 |
27 Apr 23 |
nicklas |
124 |
|
7141 |
02 May 23 |
nicklas |
125 |
public int getTotalErrors() |
7141 |
02 May 23 |
nicklas |
126 |
{ |
7141 |
02 May 23 |
nicklas |
127 |
return totalErrors; |
7141 |
02 May 23 |
nicklas |
128 |
} |
7141 |
02 May 23 |
nicklas |
129 |
|
7142 |
04 May 23 |
nicklas |
130 |
public List<String> getMessages() |
7142 |
04 May 23 |
nicklas |
131 |
{ |
7142 |
04 May 23 |
nicklas |
132 |
return messages; |
7142 |
04 May 23 |
nicklas |
133 |
} |
7142 |
04 May 23 |
nicklas |
134 |
|
7139 |
27 Apr 23 |
nicklas |
135 |
public List<String> getErrorMessages() |
7139 |
27 Apr 23 |
nicklas |
136 |
{ |
7139 |
27 Apr 23 |
nicklas |
137 |
return errorMessages; |
7139 |
27 Apr 23 |
nicklas |
138 |
} |
7141 |
02 May 23 |
nicklas |
139 |
|
7144 |
05 May 23 |
nicklas |
140 |
public List<String> getDebugMessages() |
7144 |
05 May 23 |
nicklas |
141 |
{ |
7144 |
05 May 23 |
nicklas |
142 |
return debugMessages; |
7144 |
05 May 23 |
nicklas |
143 |
} |
7144 |
05 May 23 |
nicklas |
144 |
|
7144 |
05 May 23 |
nicklas |
145 |
public void addDebugMessage(String msg) |
7144 |
05 May 23 |
nicklas |
146 |
{ |
7144 |
05 May 23 |
nicklas |
147 |
this.messages.add("[Debug] " + msg); |
7144 |
05 May 23 |
nicklas |
148 |
} |
7144 |
05 May 23 |
nicklas |
149 |
|
7139 |
27 Apr 23 |
nicklas |
150 |
public void addWarningMessage(String msg) |
7139 |
27 Apr 23 |
nicklas |
151 |
{ |
7142 |
04 May 23 |
nicklas |
152 |
this.messages.add("[Warning] " + msg); |
7141 |
02 May 23 |
nicklas |
153 |
this.totalWarnings++; |
7139 |
27 Apr 23 |
nicklas |
154 |
} |
7139 |
27 Apr 23 |
nicklas |
155 |
|
7139 |
27 Apr 23 |
nicklas |
156 |
public void addErrorMessage(String msg) |
7139 |
27 Apr 23 |
nicklas |
157 |
{ |
7142 |
04 May 23 |
nicklas |
158 |
msg = "[Error] " + msg; |
7142 |
04 May 23 |
nicklas |
159 |
this.messages.add(msg); |
7142 |
04 May 23 |
nicklas |
160 |
this.errorMessages.add(msg); |
7141 |
02 May 23 |
nicklas |
161 |
this.totalErrors++; |
7139 |
27 Apr 23 |
nicklas |
162 |
} |
7139 |
27 Apr 23 |
nicklas |
163 |
|
7142 |
04 May 23 |
nicklas |
164 |
public void addImportMessage(String msg) |
7142 |
04 May 23 |
nicklas |
165 |
{ |
7142 |
04 May 23 |
nicklas |
166 |
this.messages.add(msg); |
7142 |
04 May 23 |
nicklas |
167 |
} |
7142 |
04 May 23 |
nicklas |
168 |
|
7143 |
05 May 23 |
nicklas |
169 |
public int getNumSamples() |
7139 |
27 Apr 23 |
nicklas |
170 |
{ |
7139 |
27 Apr 23 |
nicklas |
171 |
return specimen.size(); |
7139 |
27 Apr 23 |
nicklas |
172 |
} |
7139 |
27 Apr 23 |
nicklas |
173 |
|
7139 |
27 Apr 23 |
nicklas |
174 |
public int getNumBoxes() |
7139 |
27 Apr 23 |
nicklas |
175 |
{ |
7139 |
27 Apr 23 |
nicklas |
176 |
return boxes.size(); |
7139 |
27 Apr 23 |
nicklas |
177 |
} |
7139 |
27 Apr 23 |
nicklas |
178 |
|
7139 |
27 Apr 23 |
nicklas |
179 |
public List<SampleEntry> getSpecimen() |
7139 |
27 Apr 23 |
nicklas |
180 |
{ |
7139 |
27 Apr 23 |
nicklas |
181 |
return specimen; |
7139 |
27 Apr 23 |
nicklas |
182 |
} |
7139 |
27 Apr 23 |
nicklas |
183 |
|
7191 |
23 May 23 |
nicklas |
184 |
public Collection<Box> getBoxes() |
7139 |
27 Apr 23 |
nicklas |
185 |
{ |
7191 |
23 May 23 |
nicklas |
186 |
return boxes.values(); |
7139 |
27 Apr 23 |
nicklas |
187 |
} |
7139 |
27 Apr 23 |
nicklas |
188 |
|
7139 |
27 Apr 23 |
nicklas |
189 |
public List<String> getWorksheets() |
7139 |
27 Apr 23 |
nicklas |
190 |
{ |
7139 |
27 Apr 23 |
nicklas |
191 |
return worksheets; |
7139 |
27 Apr 23 |
nicklas |
192 |
} |
7139 |
27 Apr 23 |
nicklas |
193 |
|
7139 |
27 Apr 23 |
nicklas |
194 |
public String getParsedWorksheet() |
7139 |
27 Apr 23 |
nicklas |
195 |
{ |
7139 |
27 Apr 23 |
nicklas |
196 |
return parsedWorksheet; |
7139 |
27 Apr 23 |
nicklas |
197 |
} |
7139 |
27 Apr 23 |
nicklas |
198 |
|
7143 |
05 May 23 |
nicklas |
199 |
public int getMappedToSpecimen() |
7143 |
05 May 23 |
nicklas |
200 |
{ |
7143 |
05 May 23 |
nicklas |
201 |
return numMappedToSpecimen; |
7143 |
05 May 23 |
nicklas |
202 |
} |
7143 |
05 May 23 |
nicklas |
203 |
|
7143 |
05 May 23 |
nicklas |
204 |
public int getMappedToNoSpecimen() |
7143 |
05 May 23 |
nicklas |
205 |
{ |
7143 |
05 May 23 |
nicklas |
206 |
return numMappedToNoSpecimen; |
7143 |
05 May 23 |
nicklas |
207 |
} |
7143 |
05 May 23 |
nicklas |
208 |
|
7143 |
05 May 23 |
nicklas |
209 |
public int getMappedToCase() |
7143 |
05 May 23 |
nicklas |
210 |
{ |
7143 |
05 May 23 |
nicklas |
211 |
return numMappedToCase; |
7143 |
05 May 23 |
nicklas |
212 |
} |
7143 |
05 May 23 |
nicklas |
213 |
|
7143 |
05 May 23 |
nicklas |
214 |
public int getMappedToBlood() |
7143 |
05 May 23 |
nicklas |
215 |
{ |
7143 |
05 May 23 |
nicklas |
216 |
return numMappedToBlood; |
7143 |
05 May 23 |
nicklas |
217 |
} |
7143 |
05 May 23 |
nicklas |
218 |
|
7143 |
05 May 23 |
nicklas |
219 |
public int getMappedToNothing() |
7143 |
05 May 23 |
nicklas |
220 |
{ |
7143 |
05 May 23 |
nicklas |
221 |
return numMappedToNothing; |
7143 |
05 May 23 |
nicklas |
222 |
} |
7143 |
05 May 23 |
nicklas |
223 |
|
7143 |
05 May 23 |
nicklas |
224 |
public int getNumNoConsent() |
7143 |
05 May 23 |
nicklas |
225 |
{ |
7143 |
05 May 23 |
nicklas |
226 |
return numNoConsent; |
7143 |
05 May 23 |
nicklas |
227 |
} |
7143 |
05 May 23 |
nicklas |
228 |
|
7139 |
27 Apr 23 |
nicklas |
229 |
/** |
7161 |
11 May 23 |
nicklas |
Set parameters that was entered on the import form in the web client. |
7161 |
11 May 23 |
nicklas |
The array should have the same number of elements as there are rows |
7161 |
11 May 23 |
nicklas |
in the imported file. |
7161 |
11 May 23 |
nicklas |
233 |
*/ |
7191 |
23 May 23 |
nicklas |
234 |
public void setRequestParameters(JSONObject json) |
7161 |
11 May 23 |
nicklas |
235 |
{ |
7161 |
11 May 23 |
nicklas |
236 |
this.requestParameters = json; |
7161 |
11 May 23 |
nicklas |
237 |
} |
7161 |
11 May 23 |
nicklas |
238 |
|
7161 |
11 May 23 |
nicklas |
239 |
/** |
7139 |
27 Apr 23 |
nicklas |
Import data from the input stream. |
7139 |
27 Apr 23 |
nicklas |
@param in |
7139 |
27 Apr 23 |
nicklas |
242 |
*/ |
7185 |
22 May 23 |
nicklas |
243 |
public boolean doImport(DbControl dc, File importFile, String workSheet, boolean validateOnly, ProgressReporter progress) |
7139 |
27 Apr 23 |
nicklas |
244 |
throws IOException |
7139 |
27 Apr 23 |
nicklas |
245 |
{ |
7161 |
11 May 23 |
nicklas |
246 |
if (!validateOnly && requestParameters == null) |
7161 |
11 May 23 |
nicklas |
247 |
{ |
7161 |
11 May 23 |
nicklas |
248 |
throw new IllegalStateException("Must set 'requestParameters' before importing"); |
7161 |
11 May 23 |
nicklas |
249 |
} |
7161 |
11 May 23 |
nicklas |
250 |
|
7139 |
27 Apr 23 |
nicklas |
251 |
specimen.clear(); |
7139 |
27 Apr 23 |
nicklas |
252 |
specimenByClarityId.clear(); |
7139 |
27 Apr 23 |
nicklas |
253 |
boxes.clear(); |
7142 |
04 May 23 |
nicklas |
254 |
messages.clear(); |
7139 |
27 Apr 23 |
nicklas |
255 |
worksheets = null; |
7139 |
27 Apr 23 |
nicklas |
256 |
parsedWorksheet = null; |
7141 |
02 May 23 |
nicklas |
257 |
totalErrors = 0; |
7141 |
02 May 23 |
nicklas |
258 |
totalWarnings = 0; |
7143 |
05 May 23 |
nicklas |
259 |
numMappedToSpecimen = 0; |
7143 |
05 May 23 |
nicklas |
260 |
numMappedToNoSpecimen = 0; |
7143 |
05 May 23 |
nicklas |
261 |
numMappedToCase = 0; |
7143 |
05 May 23 |
nicklas |
262 |
numMappedToBlood = 0; |
7143 |
05 May 23 |
nicklas |
263 |
numMappedToNothing = 0; |
7143 |
05 May 23 |
nicklas |
264 |
numNoConsent = 0; |
7143 |
05 May 23 |
nicklas |
265 |
|
7185 |
22 May 23 |
nicklas |
266 |
InputStream in = null; |
7185 |
22 May 23 |
nicklas |
267 |
try |
7139 |
27 Apr 23 |
nicklas |
268 |
{ |
7185 |
22 May 23 |
nicklas |
269 |
String fileName = importFile.getName(); |
7185 |
22 May 23 |
nicklas |
270 |
in = importFile.getDownloadStream(0); |
7185 |
22 May 23 |
nicklas |
271 |
if (progress != null) progress.display(5, "Parsing "+fileName+"..."); |
7185 |
22 May 23 |
nicklas |
272 |
|
7185 |
22 May 23 |
nicklas |
273 |
FlatFileParser ffp = new FlatFileParser(); |
7185 |
22 May 23 |
nicklas |
274 |
ffp.setExcelSheet(workSheet); |
7185 |
22 May 23 |
nicklas |
275 |
ffp.setDataHeaderRegexp(Pattern.compile(".*\\bClarity ID\\b.*")); |
7185 |
22 May 23 |
nicklas |
276 |
ffp.setDataSplitterRegexp(Pattern.compile("\t")); // Split on tab |
7185 |
22 May 23 |
nicklas |
277 |
ffp.setIgnoreRegexp(Pattern.compile("\\s*")); // Ignore lines with only white-space |
7185 |
22 May 23 |
nicklas |
278 |
ffp.setUseNullIfEmpty(true); |
7185 |
22 May 23 |
nicklas |
279 |
ffp.setTrimWhiteSpace(true); |
7185 |
22 May 23 |
nicklas |
280 |
|
7185 |
22 May 23 |
nicklas |
281 |
ffp.setInputStream(in, "UTF-8"); |
7185 |
22 May 23 |
nicklas |
282 |
|
7185 |
22 May 23 |
nicklas |
283 |
XlsxToCsvUtil workbook = ffp.getCurrentExcelWorkbook(); |
7185 |
22 May 23 |
nicklas |
284 |
if (workbook != null) |
7162 |
12 May 23 |
nicklas |
285 |
{ |
7185 |
22 May 23 |
nicklas |
286 |
worksheets = workbook.getSheetNames(); |
7185 |
22 May 23 |
nicklas |
287 |
parsedWorksheet = ffp.getExcelSheet(); |
7185 |
22 May 23 |
nicklas |
288 |
fileName += "/" + parsedWorksheet; |
7162 |
12 May 23 |
nicklas |
289 |
} |
7185 |
22 May 23 |
nicklas |
290 |
|
7185 |
22 May 23 |
nicklas |
291 |
LineType headerLine = ffp.parseHeaders(); |
7185 |
22 May 23 |
nicklas |
292 |
int lineNo = ffp.getParsedLines(); |
7185 |
22 May 23 |
nicklas |
293 |
if (headerLine != LineType.DATA_HEADER) |
7142 |
04 May 23 |
nicklas |
294 |
{ |
7185 |
22 May 23 |
nicklas |
295 |
addErrorMessage("File '" + fileName + "' line 1−" + lineNo + ": Could not find header line with 'Clarity ID' column."); |
7185 |
22 May 23 |
nicklas |
296 |
return false; // Can't continue if no data is found in the file |
7185 |
22 May 23 |
nicklas |
297 |
} |
7185 |
22 May 23 |
nicklas |
298 |
ffp.setIgnoreNonExistingColumns(true); |
7185 |
22 May 23 |
nicklas |
299 |
|
7185 |
22 May 23 |
nicklas |
300 |
String fileAndLine = "File '" + fileName + "' line " + lineNo + ": "; |
7185 |
22 May 23 |
nicklas |
301 |
Mapper clarityIdMapper = getRequiredMapper(ffp, "Clarity ID", fileAndLine); |
7185 |
22 May 23 |
nicklas |
302 |
Mapper scanbIdMapper = getRequiredMapper(ffp, "SCAN-B nummer", fileAndLine); |
7185 |
22 May 23 |
nicklas |
303 |
Mapper boxMapper = getRequiredMapper(ffp, "Förvaring", fileAndLine); |
7185 |
22 May 23 |
nicklas |
304 |
if (hasError()) return false; |
7185 |
22 May 23 |
nicklas |
305 |
|
7185 |
22 May 23 |
nicklas |
306 |
Mapper padMapper = getOptionalMapper(ffp, "PADRemiss", fileAndLine); |
7185 |
22 May 23 |
nicklas |
// Parse the complete file before validation so that we can use the progress reporter |
7185 |
22 May 23 |
nicklas |
308 |
while (ffp.hasMoreData()) |
7185 |
22 May 23 |
nicklas |
309 |
{ |
7185 |
22 May 23 |
nicklas |
310 |
FlatFileParser.Data data = ffp.nextData(); |
7185 |
22 May 23 |
nicklas |
311 |
lineNo = ffp.getParsedLines(); |
7185 |
22 May 23 |
nicklas |
312 |
fileAndLine = "File '" + fileName + "' line " + lineNo + ": "; |
7185 |
22 May 23 |
nicklas |
313 |
|
7185 |
22 May 23 |
nicklas |
314 |
SampleEntry s = new SampleEntry(data.line(), fileAndLine, lineNo); |
7185 |
22 May 23 |
nicklas |
315 |
specimen.add(s); |
7185 |
22 May 23 |
nicklas |
316 |
s.clarityId = clarityIdMapper.getString(data); |
7185 |
22 May 23 |
nicklas |
317 |
s.scanBId = scanbIdMapper.getString(data); |
7234 |
02 Jun 23 |
nicklas |
318 |
if (s.scanBId != null && s.scanBId.endsWith("T")) |
7234 |
02 Jun 23 |
nicklas |
319 |
{ |
7234 |
02 Jun 23 |
nicklas |
// Suffix 'T' is for the frozen piece and we should normally not see it |
7234 |
02 Jun 23 |
nicklas |
// but if it is here we simple remove it |
7246 |
07 Jun 23 |
nicklas |
322 |
s.scanBId = s.scanBId.substring(0, s.scanBId.length()-1); |
7234 |
02 Jun 23 |
nicklas |
323 |
} |
7185 |
22 May 23 |
nicklas |
324 |
s.transportBox = boxMapper.getString(data); |
7185 |
22 May 23 |
nicklas |
325 |
s.pad = padMapper.getString(data); |
7185 |
22 May 23 |
nicklas |
326 |
if (s.pad != null) s.pad = s.pad.toUpperCase(Locale.ROOT); |
7191 |
23 May 23 |
nicklas |
327 |
if (s.transportBox != null) |
7191 |
23 May 23 |
nicklas |
328 |
{ |
7191 |
23 May 23 |
nicklas |
329 |
Box b = boxes.get(s.transportBox); |
7191 |
23 May 23 |
nicklas |
330 |
if (b == null) |
7191 |
23 May 23 |
nicklas |
331 |
{ |
7191 |
23 May 23 |
nicklas |
332 |
b = new Box(s.transportBox); |
7191 |
23 May 23 |
nicklas |
333 |
boxes.put(s.transportBox, b); |
7191 |
23 May 23 |
nicklas |
334 |
} |
7191 |
23 May 23 |
nicklas |
335 |
b.numSamples++; |
7191 |
23 May 23 |
nicklas |
336 |
} |
7185 |
22 May 23 |
nicklas |
337 |
} |
7185 |
22 May 23 |
nicklas |
338 |
|
7185 |
22 May 23 |
nicklas |
339 |
int numEntries = specimen.size(); |
7185 |
22 May 23 |
nicklas |
340 |
int entryNo = 0; |
7185 |
22 May 23 |
nicklas |
341 |
for (SampleEntry s : specimen) |
7185 |
22 May 23 |
nicklas |
342 |
{ |
7185 |
22 May 23 |
nicklas |
343 |
entryNo++; |
7185 |
22 May 23 |
nicklas |
344 |
if (progress != null) |
7148 |
08 May 23 |
nicklas |
345 |
{ |
7185 |
22 May 23 |
nicklas |
346 |
progress.display(5+((validateOnly?85:55)*entryNo)/numEntries, "Validating entry "+entryNo+" of " + numEntries+"..."); |
7148 |
08 May 23 |
nicklas |
347 |
} |
7185 |
22 May 23 |
nicklas |
348 |
try |
7142 |
04 May 23 |
nicklas |
349 |
{ |
7185 |
22 May 23 |
nicklas |
// Basic checks that all required values are present and valid |
7185 |
22 May 23 |
nicklas |
351 |
boolean validForMap = checkEntry(s); |
7193 |
23 May 23 |
nicklas |
352 |
boolean mapped = s.mappedTo != null;; |
7185 |
22 May 23 |
nicklas |
353 |
|
7193 |
23 May 23 |
nicklas |
354 |
if (validForMap && !mapped) |
7143 |
05 May 23 |
nicklas |
355 |
{ |
7185 |
22 May 23 |
nicklas |
// Try to map to information in our database: |
7185 |
22 May 23 |
nicklas |
// Match rule 1: Place existing Specimen, Lysate, etc. at new box locations |
7185 |
22 May 23 |
nicklas |
358 |
if (!mapped) mapped = mapEntryToExistingSpecimenByClarityId(dc, s); |
7185 |
22 May 23 |
nicklas |
359 |
|
7185 |
22 May 23 |
nicklas |
// Match rule 2: Convert existing NoSpecimen to Specimen, create child items and place at new box locations |
7185 |
22 May 23 |
nicklas |
361 |
if (!mapped) mapped = mapEntryToExistingNoSpecimenByScanBId(dc, s); |
7185 |
22 May 23 |
nicklas |
362 |
|
7185 |
22 May 23 |
nicklas |
// Match rule 3: Create Specimen (link to existing case) and child items and place at new box locations |
7185 |
22 May 23 |
nicklas |
364 |
if (!mapped) mapped = mapEntryToExistingCaseByScanBId(dc, s); |
7185 |
22 May 23 |
nicklas |
365 |
|
7185 |
22 May 23 |
nicklas |
// Match rule 4: Create Case (link to Patient) and child items and place at new box locations |
7185 |
22 May 23 |
nicklas |
367 |
if (!mapped) mapped = mapEntryToExistingBloodByScanBId(dc, s); |
7185 |
22 May 23 |
nicklas |
368 |
|
7185 |
22 May 23 |
nicklas |
// Match rule 5: Create Case (no link to Patient) and child items and place at new box locations |
7185 |
22 May 23 |
nicklas |
370 |
if (!mapped) mapped = mapEntryToNothing(dc, s); |
7185 |
22 May 23 |
nicklas |
371 |
} |
7185 |
22 May 23 |
nicklas |
372 |
|
7185 |
22 May 23 |
nicklas |
373 |
if (mapped) |
7185 |
22 May 23 |
nicklas |
374 |
{ |
7185 |
22 May 23 |
nicklas |
375 |
if (s.theCase != null || s.blood != null) |
7143 |
05 May 23 |
nicklas |
376 |
{ |
7185 |
22 May 23 |
nicklas |
// Verify consent |
7185 |
22 May 23 |
nicklas |
378 |
String consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, s.theCase == null ? s.blood.getItem() : s.theCase.getItem()); |
7185 |
22 May 23 |
nicklas |
379 |
if (consent != null && !consent.equals("Yes")) |
7185 |
22 May 23 |
nicklas |
380 |
{ |
7185 |
22 May 23 |
nicklas |
381 |
numNoConsent++; |
7185 |
22 May 23 |
nicklas |
382 |
s.canImport = false; |
7185 |
22 May 23 |
nicklas |
383 |
s.noConsent = true; |
7185 |
22 May 23 |
nicklas |
384 |
s.action = "No import (Consent="+consent+"). Leave all tubes in the transport boxes."; |
7185 |
22 May 23 |
nicklas |
385 |
} |
7143 |
05 May 23 |
nicklas |
386 |
} |
7143 |
05 May 23 |
nicklas |
387 |
} |
7185 |
22 May 23 |
nicklas |
388 |
else if (s.errors.size() == 0) |
7185 |
22 May 23 |
nicklas |
389 |
{ |
7185 |
22 May 23 |
nicklas |
// This should not really happen but we leave it here as a safe-guard |
7185 |
22 May 23 |
nicklas |
// in case we have missed an unusal case |
7185 |
22 May 23 |
nicklas |
392 |
s.addError("Could not be mapped by any existing method"); |
7185 |
22 May 23 |
nicklas |
393 |
} |
7143 |
05 May 23 |
nicklas |
394 |
} |
7185 |
22 May 23 |
nicklas |
395 |
catch (RuntimeException ex) |
7143 |
05 May 23 |
nicklas |
396 |
{ |
7185 |
22 May 23 |
nicklas |
397 |
s.addError(ex.getMessage()); |
7185 |
22 May 23 |
nicklas |
398 |
ex.printStackTrace(System.out); |
7142 |
04 May 23 |
nicklas |
399 |
} |
7142 |
04 May 23 |
nicklas |
400 |
} |
7185 |
22 May 23 |
nicklas |
401 |
|
7185 |
22 May 23 |
nicklas |
402 |
if (progress != null) progress.display(validateOnly?95:65, "Assigning new storage box locations..."); |
7185 |
22 May 23 |
nicklas |
// Assign new storage locations, but we do not auto-create new storage boxes here |
7185 |
22 May 23 |
nicklas |
404 |
SpecimenTube lastPlacedSpecimen = SpecimenTube.getLastPlacedSpecimen(dc, null, "E-Sp"); |
7185 |
22 May 23 |
nicklas |
405 |
List<StoragePlate> spBoxes = StoragePlate.findExistingStorageBoxes(dc, lastPlacedSpecimen, "E-Sp"); |
7185 |
22 May 23 |
nicklas |
406 |
List<BioWell> wells = StoragePlate.findEmptyWells(dc, spBoxes, specimen.size(), null); // "null" means that we do not create new boxes |
7185 |
22 May 23 |
nicklas |
407 |
int wellNo = 0; |
7185 |
22 May 23 |
nicklas |
408 |
for (SampleEntry s : specimen) |
7142 |
04 May 23 |
nicklas |
409 |
{ |
7185 |
22 May 23 |
nicklas |
410 |
if (s.canImport) |
7143 |
05 May 23 |
nicklas |
411 |
{ |
7185 |
22 May 23 |
nicklas |
412 |
if (wellNo < wells.size()) |
7185 |
22 May 23 |
nicklas |
413 |
{ |
7185 |
22 May 23 |
nicklas |
414 |
s.well = wells.get(wellNo); |
7185 |
22 May 23 |
nicklas |
415 |
wellNo++; |
7185 |
22 May 23 |
nicklas |
416 |
} |
7185 |
22 May 23 |
nicklas |
417 |
else |
7185 |
22 May 23 |
nicklas |
418 |
{ |
7185 |
22 May 23 |
nicklas |
419 |
s.addError("No storage box available"); |
7185 |
22 May 23 |
nicklas |
420 |
} |
7143 |
05 May 23 |
nicklas |
421 |
} |
7185 |
22 May 23 |
nicklas |
422 |
|
7185 |
22 May 23 |
nicklas |
423 |
if (s.warnings.size() > 0) totalWarnings++; |
7185 |
22 May 23 |
nicklas |
424 |
if (validateOnly) |
7185 |
22 May 23 |
nicklas |
425 |
{ |
7185 |
22 May 23 |
nicklas |
426 |
if (s.errors.size() > 0) totalErrors++; |
7185 |
22 May 23 |
nicklas |
427 |
} |
7143 |
05 May 23 |
nicklas |
428 |
else |
7143 |
05 May 23 |
nicklas |
429 |
{ |
7185 |
22 May 23 |
nicklas |
// Copy errors when importing |
7185 |
22 May 23 |
nicklas |
431 |
for (String e : s.errors) |
7185 |
22 May 23 |
nicklas |
432 |
{ |
7185 |
22 May 23 |
nicklas |
433 |
addErrorMessage("Line "+s.lineNo+": "+e); |
7185 |
22 May 23 |
nicklas |
434 |
} |
7143 |
05 May 23 |
nicklas |
435 |
} |
7140 |
28 Apr 23 |
nicklas |
436 |
} |
7158 |
10 May 23 |
nicklas |
437 |
|
7185 |
22 May 23 |
nicklas |
438 |
if (!validateOnly && !hasError()) |
7142 |
04 May 23 |
nicklas |
439 |
{ |
7185 |
22 May 23 |
nicklas |
// Create items lists -- one list per transport box and item type |
7191 |
23 May 23 |
nicklas |
441 |
JSONObject jsonBoxes = (JSONObject)requestParameters.get("boxes"); |
7185 |
22 May 23 |
nicklas |
442 |
Map<String, ListSet> itemLists = new HashMap<>(); |
7191 |
23 May 23 |
nicklas |
443 |
for (String boxName : boxes.keySet()) |
7142 |
04 May 23 |
nicklas |
444 |
{ |
7191 |
23 May 23 |
nicklas |
445 |
JSONObject jsonBox = (JSONObject)jsonBoxes.get(boxName); |
7191 |
23 May 23 |
nicklas |
446 |
itemLists.put(boxName, new ListSet(dc, boxName, importFile, jsonBox)); |
7185 |
22 May 23 |
nicklas |
//addImportMessage("Created item lists for transport box: " + boxName); |
7142 |
04 May 23 |
nicklas |
448 |
} |
7185 |
22 May 23 |
nicklas |
449 |
|
7185 |
22 May 23 |
nicklas |
450 |
int sampleNo = -1; |
7185 |
22 May 23 |
nicklas |
451 |
Stats stats = new Stats(); |
7191 |
23 May 23 |
nicklas |
452 |
JSONArray jsonSamples = (JSONArray)requestParameters.get("samples"); |
7185 |
22 May 23 |
nicklas |
453 |
for (SampleEntry s : specimen) |
7162 |
12 May 23 |
nicklas |
454 |
{ |
7185 |
22 May 23 |
nicklas |
455 |
sampleNo++; |
7185 |
22 May 23 |
nicklas |
456 |
if (progress != null) |
7168 |
12 May 23 |
nicklas |
457 |
{ |
7185 |
22 May 23 |
nicklas |
458 |
progress.display(65+(30*sampleNo)/numEntries, "Creating and updating items "+sampleNo+" of "+numEntries+"..."); |
7168 |
12 May 23 |
nicklas |
459 |
} |
7185 |
22 May 23 |
nicklas |
460 |
ListSet listSet = itemLists.get(s.transportBox); |
7191 |
23 May 23 |
nicklas |
461 |
JSONObject parameters = (JSONObject)jsonSamples.get(sampleNo); |
7185 |
22 May 23 |
nicklas |
462 |
s.updateFromRequestParameters(parameters); |
7185 |
22 May 23 |
nicklas |
463 |
if (!s.canImport) |
7143 |
05 May 23 |
nicklas |
464 |
{ |
7185 |
22 May 23 |
nicklas |
//addImportMessage("Line "+s.lineNo+": Skipped (no consent)"); |
7185 |
22 May 23 |
nicklas |
466 |
stats.skipped++; |
7185 |
22 May 23 |
nicklas |
467 |
String msg = s.clarityId+":"; |
7185 |
22 May 23 |
nicklas |
468 |
if (s.action != null) msg += " "+s.action; |
7185 |
22 May 23 |
nicklas |
469 |
if (s.comment != null) msg += " "+s.comment; |
7185 |
22 May 23 |
nicklas |
470 |
if (s.action == null && s.comment == null) |
7144 |
05 May 23 |
nicklas |
471 |
{ |
7185 |
22 May 23 |
nicklas |
472 |
msg += " Not imported. Leave all tubes in the transport boxes."; |
7144 |
05 May 23 |
nicklas |
473 |
} |
7185 |
22 May 23 |
nicklas |
474 |
listSet.transportMessages.add(StringUtil.trimString(msg, 255)); |
7143 |
05 May 23 |
nicklas |
475 |
} |
7185 |
22 May 23 |
nicklas |
476 |
else |
7143 |
05 May 23 |
nicklas |
477 |
{ |
7185 |
22 May 23 |
nicklas |
478 |
try |
7185 |
22 May 23 |
nicklas |
479 |
{ |
7185 |
22 May 23 |
nicklas |
480 |
s.createMissingItems(dc, stats); |
7185 |
22 May 23 |
nicklas |
481 |
s.placeInStorageBoxes(dc); |
7185 |
22 May 23 |
nicklas |
482 |
s.addToItemLists(dc, listSet, stats); |
7185 |
22 May 23 |
nicklas |
483 |
s.appendWarnings(dc); |
7185 |
22 May 23 |
nicklas |
484 |
|
7185 |
22 May 23 |
nicklas |
//addImportMessage("Line "+s.lineNo+": Imported to "+s.specimen.getName()+(s.specimen.getId()==0?" (new)":"")); |
7185 |
22 May 23 |
nicklas |
// Copy debug messages |
7185 |
22 May 23 |
nicklas |
487 |
for (String d : s.debug) |
7185 |
22 May 23 |
nicklas |
488 |
{ |
7185 |
22 May 23 |
nicklas |
489 |
addDebugMessage("Line "+s.lineNo+": "+d); |
7185 |
22 May 23 |
nicklas |
490 |
} |
7185 |
22 May 23 |
nicklas |
491 |
} |
7185 |
22 May 23 |
nicklas |
492 |
catch (RuntimeException ex) |
7185 |
22 May 23 |
nicklas |
493 |
{ |
7185 |
22 May 23 |
nicklas |
494 |
addErrorMessage("Line "+s.lineNo+": "+ex.getMessage()); |
7185 |
22 May 23 |
nicklas |
495 |
ex.printStackTrace(System.out); |
7185 |
22 May 23 |
nicklas |
496 |
} |
7143 |
05 May 23 |
nicklas |
497 |
} |
7142 |
04 May 23 |
nicklas |
498 |
} |
7185 |
22 May 23 |
nicklas |
499 |
|
7185 |
22 May 23 |
nicklas |
// Add TransportMessages to the item lists |
7185 |
22 May 23 |
nicklas |
501 |
for (ListSet ls : itemLists.values()) |
7185 |
22 May 23 |
nicklas |
502 |
{ |
7185 |
22 May 23 |
nicklas |
503 |
ls.addTransportMessages(dc); |
7185 |
22 May 23 |
nicklas |
504 |
} |
7185 |
22 May 23 |
nicklas |
505 |
|
7185 |
22 May 23 |
nicklas |
506 |
addImportMessage("Successfully imported "+specimen.size()+" lines from "+fileName); |
7185 |
22 May 23 |
nicklas |
507 |
addImportMessage("Mapped "+stats.mappedExistingSpecimen+" lines to existing Specimen"); |
7185 |
22 May 23 |
nicklas |
508 |
addImportMessage("Converted "+stats.convertedNoSpecimen+" NoSpecimen items to Specimen"); |
7185 |
22 May 23 |
nicklas |
509 |
addImportMessage("Created "+stats.newSpecimen+" new Specimen items"); |
7193 |
23 May 23 |
nicklas |
510 |
addImportMessage("Skipped "+stats.skipped+" lines"); |
7185 |
22 May 23 |
nicklas |
511 |
addImportMessage("Added "+stats.flagged+" Specimen to the 'Flagged External Specimen' list"); |
7142 |
04 May 23 |
nicklas |
512 |
} |
7142 |
04 May 23 |
nicklas |
513 |
} |
7185 |
22 May 23 |
nicklas |
514 |
finally |
7185 |
22 May 23 |
nicklas |
515 |
{ |
7185 |
22 May 23 |
nicklas |
516 |
FileUtil.close(in); |
7185 |
22 May 23 |
nicklas |
517 |
} |
7142 |
04 May 23 |
nicklas |
518 |
|
7139 |
27 Apr 23 |
nicklas |
519 |
return !hasError(); |
7139 |
27 Apr 23 |
nicklas |
520 |
} |
7139 |
27 Apr 23 |
nicklas |
521 |
|
7139 |
27 Apr 23 |
nicklas |
522 |
public boolean checkEntry(SampleEntry s) |
7139 |
27 Apr 23 |
nicklas |
523 |
{ |
7141 |
02 May 23 |
nicklas |
// Clarity ID should not be missing |
7141 |
02 May 23 |
nicklas |
525 |
if (s.clarityId == null) |
7139 |
27 Apr 23 |
nicklas |
526 |
{ |
7141 |
02 May 23 |
nicklas |
527 |
s.addError("Missing Clarity ID"); |
7139 |
27 Apr 23 |
nicklas |
528 |
} |
7148 |
08 May 23 |
nicklas |
529 |
|
7141 |
02 May 23 |
nicklas |
// SCAN-B ID should not be missing |
7141 |
02 May 23 |
nicklas |
531 |
if (s.scanBId == null) |
7139 |
27 Apr 23 |
nicklas |
532 |
{ |
7148 |
08 May 23 |
nicklas |
// A missing SCANB-ID can be either a warning or error |
7148 |
08 May 23 |
nicklas |
// depending on what it maps to, so we ignore this for now |
7148 |
08 May 23 |
nicklas |
// s.addWarning("Missing SCAN-B ID"); |
7140 |
28 Apr 23 |
nicklas |
536 |
} |
7234 |
02 Jun 23 |
nicklas |
537 |
else if (!s.scanBId.matches("\\d{7}(C|D|T)?")) |
7140 |
28 Apr 23 |
nicklas |
538 |
{ |
7141 |
02 May 23 |
nicklas |
// and must match 7-digits + optional C or D suffix |
7141 |
02 May 23 |
nicklas |
540 |
s.addError("Invalid SCAN-B ID"); |
7140 |
28 Apr 23 |
nicklas |
541 |
} |
7251 |
08 Jun 23 |
nicklas |
542 |
else if (Site.findByCaseName(s.scanBId) == Site.UNKNOWN) |
7251 |
08 Jun 23 |
nicklas |
543 |
{ |
7251 |
08 Jun 23 |
nicklas |
544 |
s.addError("SCAN-B ID doesn't match a known site"); |
7251 |
08 Jun 23 |
nicklas |
545 |
} |
7141 |
02 May 23 |
nicklas |
546 |
|
7141 |
02 May 23 |
nicklas |
// Transport box should not be missing |
7141 |
02 May 23 |
nicklas |
548 |
if (s.transportBox == null) |
7141 |
02 May 23 |
nicklas |
549 |
{ |
7141 |
02 May 23 |
nicklas |
550 |
s.addError("Missing transport box name"); |
7141 |
02 May 23 |
nicklas |
551 |
} |
7139 |
27 Apr 23 |
nicklas |
552 |
|
7156 |
10 May 23 |
nicklas |
553 |
boolean validForMap = s.errors.size() == 0; |
7156 |
10 May 23 |
nicklas |
554 |
|
7193 |
23 May 23 |
nicklas |
// A duplicated Clarity ID is an error or warning, but can never be imported |
7156 |
10 May 23 |
nicklas |
556 |
SampleEntry other = specimenByClarityId.get(s.clarityId); |
7156 |
10 May 23 |
nicklas |
557 |
if (other != null) |
7156 |
10 May 23 |
nicklas |
558 |
{ |
7193 |
23 May 23 |
nicklas |
559 |
s.canImport = false; |
7193 |
23 May 23 |
nicklas |
// If the same Clarity ID references different SCAN-B ID:s we set both to an error |
7193 |
23 May 23 |
nicklas |
561 |
if (!EqualsHelper.equals(s.scanBId, other.scanBId)) |
7193 |
23 May 23 |
nicklas |
562 |
{ |
7193 |
23 May 23 |
nicklas |
563 |
s.addError("Duplicate Clarity ID with different SCAN-B ID (also on line "+other.lineNo+")"); |
7193 |
23 May 23 |
nicklas |
564 |
s.addError(s.scanBId+"<>"+other.scanBId); |
7193 |
23 May 23 |
nicklas |
565 |
other.addError("Duplicate Clarity ID with different SCAN-B ID (also on line "+s.lineNo+")"); |
7193 |
23 May 23 |
nicklas |
566 |
other.addError(s.scanBId+"<>"+other.scanBId); |
7193 |
23 May 23 |
nicklas |
567 |
other.canImport = false; |
7193 |
23 May 23 |
nicklas |
568 |
other.action = null; |
7193 |
23 May 23 |
nicklas |
569 |
} |
7193 |
23 May 23 |
nicklas |
570 |
else |
7193 |
23 May 23 |
nicklas |
571 |
{ |
7193 |
23 May 23 |
nicklas |
// Otherwise it is only a warning and a "No import" action on the current sample |
7193 |
23 May 23 |
nicklas |
573 |
other.addWarning("Duplicate Clarity ID (also on line "+s.lineNo+")"); |
7193 |
23 May 23 |
nicklas |
574 |
s.addWarning("Duplicate Clarity ID (also on line "+other.lineNo+")"); |
7193 |
23 May 23 |
nicklas |
575 |
s.action = "No import (Duplicate). Leave extra tubes in the transport boxes."; |
7193 |
23 May 23 |
nicklas |
576 |
s.mappedTo = other.mappedTo; |
7193 |
23 May 23 |
nicklas |
577 |
validForMap = false; |
7193 |
23 May 23 |
nicklas |
578 |
} |
7156 |
10 May 23 |
nicklas |
579 |
} |
7156 |
10 May 23 |
nicklas |
580 |
specimenByClarityId.put(s.clarityId, s); |
7156 |
10 May 23 |
nicklas |
581 |
return validForMap; |
7141 |
02 May 23 |
nicklas |
582 |
} |
7141 |
02 May 23 |
nicklas |
583 |
|
7141 |
02 May 23 |
nicklas |
584 |
/** |
7141 |
02 May 23 |
nicklas |
Rule 1: Find an existing Specimen with matching Clarity ID that |
7141 |
02 May 23 |
nicklas |
has data and child items but is missing a storage location. |
7141 |
02 May 23 |
nicklas |
Returns TRUE if the mapping was successful, FALSE otherwise. |
7141 |
02 May 23 |
nicklas |
588 |
*/ |
7141 |
02 May 23 |
nicklas |
589 |
public boolean mapEntryToExistingSpecimenByClarityId(DbControl dc, SampleEntry s) |
7141 |
02 May 23 |
nicklas |
590 |
{ |
7141 |
02 May 23 |
nicklas |
591 |
if (!s.findSpecimenByClarityId(dc)) return false; |
7141 |
02 May 23 |
nicklas |
592 |
|
7143 |
05 May 23 |
nicklas |
593 |
s.mappedTo = s.specimen.getItem(); |
7159 |
11 May 23 |
nicklas |
594 |
s.comment = s.mappedTo.getDescription(); |
7159 |
11 May 23 |
nicklas |
595 |
s.otherPathNote = (String)Annotationtype.OTHER_PATH_NOTE.getAnnotationValue(dc, s.mappedTo); |
7143 |
05 May 23 |
nicklas |
596 |
numMappedToSpecimen++; |
7143 |
05 May 23 |
nicklas |
597 |
|
7142 |
04 May 23 |
nicklas |
// Find all child items |
7141 |
02 May 23 |
nicklas |
599 |
s.findLysate(dc); |
7141 |
02 May 23 |
nicklas |
600 |
s.findRna(dc); |
7142 |
04 May 23 |
nicklas |
601 |
s.findDna(dc); |
7142 |
04 May 23 |
nicklas |
602 |
s.findFlowThrough(dc); |
7141 |
02 May 23 |
nicklas |
603 |
|
7141 |
02 May 23 |
nicklas |
// Check that current storage is not set |
7141 |
02 May 23 |
nicklas |
605 |
s.checkStorage(s.specimen); |
7141 |
02 May 23 |
nicklas |
606 |
s.checkStorage(s.lysate); |
7141 |
02 May 23 |
nicklas |
607 |
s.checkStorage(s.rna); |
7141 |
02 May 23 |
nicklas |
608 |
s.checkStorage(s.dna); |
7141 |
02 May 23 |
nicklas |
609 |
s.checkStorage(s.flowThrough); |
7148 |
08 May 23 |
nicklas |
610 |
|
7148 |
08 May 23 |
nicklas |
// If both PAD and SCAN-B ID mismatch it is an error, |
7148 |
08 May 23 |
nicklas |
// otherwise a warning if a a single mismatch |
7148 |
08 May 23 |
nicklas |
613 |
String currentPad = (String)Annotationtype.PAD.getAnnotationValue(dc, s.specimen.getItem()); |
7155 |
10 May 23 |
nicklas |
614 |
if (currentPad != null) currentPad = currentPad.toUpperCase(Locale.ROOT); |
7148 |
08 May 23 |
nicklas |
615 |
boolean padMismatch = s.pad != null && currentPad != null && !s.pad.contains(currentPad); |
7148 |
08 May 23 |
nicklas |
616 |
boolean scanbMismatch = s.scanBId == null || !s.specimen.getName().startsWith(s.scanBId.substring(0, 7)); |
7148 |
08 May 23 |
nicklas |
617 |
if (padMismatch && scanbMismatch) |
7148 |
08 May 23 |
nicklas |
618 |
{ |
7158 |
10 May 23 |
nicklas |
619 |
s.addError("Clarity ID matched a Specimen with different SCAN-B ID and PAD: "+currentPad+"<>"+s.pad); |
7148 |
08 May 23 |
nicklas |
620 |
} |
7148 |
08 May 23 |
nicklas |
621 |
else if (padMismatch) |
7148 |
08 May 23 |
nicklas |
622 |
{ |
7158 |
10 May 23 |
nicklas |
623 |
s.addWarning("Clarity ID matched a Specimen with different PAD: "+currentPad+"<>"+s.pad); |
7148 |
08 May 23 |
nicklas |
624 |
} |
7148 |
08 May 23 |
nicklas |
625 |
else if (scanbMismatch) |
7148 |
08 May 23 |
nicklas |
626 |
{ |
7162 |
12 May 23 |
nicklas |
627 |
s.addWarning(s.scanBId == null ? "SCAN-B ID is missing" : "Clarity ID matched a Specimen with different SCAN-B ID: "+s.specimen.getName()+"<>"+s.scanBId); |
7148 |
08 May 23 |
nicklas |
628 |
} |
7158 |
10 May 23 |
nicklas |
629 |
if (padMismatch) |
7158 |
10 May 23 |
nicklas |
630 |
{ |
7158 |
10 May 23 |
nicklas |
631 |
Sample otherSampleWithPAD = s.findSampleByPad(dc, s.pad); |
7158 |
10 May 23 |
nicklas |
632 |
if (otherSampleWithPAD != null) |
7158 |
10 May 23 |
nicklas |
633 |
{ |
7158 |
10 May 23 |
nicklas |
634 |
ItemSubtype otherType = otherSampleWithPAD.getItemSubtype(); |
7158 |
10 May 23 |
nicklas |
635 |
s.addWarning("Found other "+(otherType==null?"sample":otherType.getName())+", "+otherSampleWithPAD.getName()+", with PAD=" + s.pad); |
7158 |
10 May 23 |
nicklas |
636 |
} |
7158 |
10 May 23 |
nicklas |
637 |
else |
7158 |
10 May 23 |
nicklas |
638 |
{ |
7158 |
10 May 23 |
nicklas |
639 |
s.addWarning("Could not find any other item with PAD="+s.pad); |
7158 |
10 May 23 |
nicklas |
640 |
} |
7158 |
10 May 23 |
nicklas |
641 |
} |
7148 |
08 May 23 |
nicklas |
642 |
|
7148 |
08 May 23 |
nicklas |
// Now check for other warnings |
7142 |
04 May 23 |
nicklas |
644 |
String exists = (String)Annotationtype.EXTERNAL_SPECIMEN_EXISTS.getAnnotationValue(dc, s.specimen.getItem()); |
7141 |
02 May 23 |
nicklas |
645 |
if (!"Yes".equals(exists)) |
7139 |
27 Apr 23 |
nicklas |
646 |
{ |
7141 |
02 May 23 |
nicklas |
647 |
s.addWarning("Annotation ExternalSpecimenExists="+exists+" (expected 'Yes')"); |
7141 |
02 May 23 |
nicklas |
648 |
} |
7141 |
02 May 23 |
nicklas |
649 |
|
7141 |
02 May 23 |
nicklas |
650 |
if (s.errors.size() == 0) |
7141 |
02 May 23 |
nicklas |
651 |
{ |
7141 |
02 May 23 |
nicklas |
// The mapping is OK |
7143 |
05 May 23 |
nicklas |
653 |
s.canImport = true; |
7158 |
10 May 23 |
nicklas |
654 |
s.action = "Assign new storage locations to existing Specimen, Lysate, RNA, DNA and FT."; |
7141 |
02 May 23 |
nicklas |
655 |
} |
7141 |
02 May 23 |
nicklas |
656 |
|
7148 |
08 May 23 |
nicklas |
657 |
return s.mappedTo != null; |
7141 |
02 May 23 |
nicklas |
658 |
} |
7141 |
02 May 23 |
nicklas |
659 |
|
7141 |
02 May 23 |
nicklas |
660 |
|
7141 |
02 May 23 |
nicklas |
661 |
/** |
7141 |
02 May 23 |
nicklas |
Rule 2: Find an existing NoSpecimen with matching SCAN-B ID that |
7141 |
02 May 23 |
nicklas |
has EXTERNAL_SPECIMEN_EXISTS=Yes. |
7141 |
02 May 23 |
nicklas |
664 |
*/ |
7141 |
02 May 23 |
nicklas |
665 |
public boolean mapEntryToExistingNoSpecimenByScanBId(DbControl dc, SampleEntry s) |
7141 |
02 May 23 |
nicklas |
666 |
{ |
7141 |
02 May 23 |
nicklas |
667 |
if (!s.findNoSpecimenByScanBId(dc)) return false; |
7139 |
27 Apr 23 |
nicklas |
668 |
|
7143 |
05 May 23 |
nicklas |
669 |
s.mappedTo = s.noSpecimen.getItem(); |
7159 |
11 May 23 |
nicklas |
670 |
s.comment = s.mappedTo.getDescription(); |
7159 |
11 May 23 |
nicklas |
671 |
s.otherPathNote = (String)Annotationtype.OTHER_PATH_NOTE.getAnnotationValue(dc, s.mappedTo); |
7143 |
05 May 23 |
nicklas |
672 |
numMappedToNoSpecimen++; |
7143 |
05 May 23 |
nicklas |
673 |
|
7141 |
02 May 23 |
nicklas |
674 |
if (s.pad != null) |
7141 |
02 May 23 |
nicklas |
675 |
{ |
7142 |
04 May 23 |
nicklas |
676 |
String currentPad = (String)Annotationtype.PAD.getAnnotationValue(dc, s.noSpecimen.getItem()); |
7155 |
10 May 23 |
nicklas |
677 |
if (currentPad != null) currentPad = currentPad.toUpperCase(Locale.ROOT); |
7158 |
10 May 23 |
nicklas |
678 |
if (currentPad == null || !s.pad.contains(currentPad)) |
7141 |
02 May 23 |
nicklas |
679 |
{ |
7158 |
10 May 23 |
nicklas |
680 |
s.addWarning("PAD mismatch: "+currentPad+"<>"+s.pad); |
7158 |
10 May 23 |
nicklas |
681 |
s.alternateAction = "Create a new Specimen, Lysate, RNA, DNA and FT and link them to this Case."; |
7158 |
10 May 23 |
nicklas |
682 |
s.alternateIsDefault = true; |
7158 |
10 May 23 |
nicklas |
683 |
Sample otherSampleWithPAD = s.findSampleByPad(dc, s.pad); |
7158 |
10 May 23 |
nicklas |
684 |
if (otherSampleWithPAD != null) |
7158 |
10 May 23 |
nicklas |
685 |
{ |
7158 |
10 May 23 |
nicklas |
686 |
ItemSubtype otherType = otherSampleWithPAD.getItemSubtype(); |
7158 |
10 May 23 |
nicklas |
687 |
s.addWarning("Found other "+(otherType==null?"sample":otherType.getName())+", "+otherSampleWithPAD.getName()+", with PAD=" + s.pad); |
7158 |
10 May 23 |
nicklas |
688 |
} |
7158 |
10 May 23 |
nicklas |
689 |
else |
7158 |
10 May 23 |
nicklas |
690 |
{ |
7158 |
10 May 23 |
nicklas |
691 |
s.addWarning("Could not find any other item with PAD="+s.pad); |
7158 |
10 May 23 |
nicklas |
692 |
} |
7141 |
02 May 23 |
nicklas |
693 |
} |
7141 |
02 May 23 |
nicklas |
694 |
} |
7141 |
02 May 23 |
nicklas |
695 |
|
7141 |
02 May 23 |
nicklas |
696 |
if (s.errors.size() == 0) |
7141 |
02 May 23 |
nicklas |
697 |
{ |
7141 |
02 May 23 |
nicklas |
// The mapping is OK |
7143 |
05 May 23 |
nicklas |
699 |
s.canImport = true; |
7158 |
10 May 23 |
nicklas |
700 |
s.action = "Convert to Specimen, and create new Lysate, RNA, DNA and FT."; |
7141 |
02 May 23 |
nicklas |
701 |
} |
7141 |
02 May 23 |
nicklas |
702 |
|
7148 |
08 May 23 |
nicklas |
703 |
return s.mappedTo != null; |
7139 |
27 Apr 23 |
nicklas |
704 |
} |
7139 |
27 Apr 23 |
nicklas |
705 |
|
7139 |
27 Apr 23 |
nicklas |
706 |
/** |
7143 |
05 May 23 |
nicklas |
Rule 3: Find an existing Case with matching SCAN-B ID. |
7143 |
05 May 23 |
nicklas |
708 |
*/ |
7143 |
05 May 23 |
nicklas |
709 |
public boolean mapEntryToExistingCaseByScanBId(DbControl dc, SampleEntry s) |
7143 |
05 May 23 |
nicklas |
710 |
{ |
7143 |
05 May 23 |
nicklas |
711 |
if (!s.findCaseByScanBId(dc)) return false; |
7143 |
05 May 23 |
nicklas |
712 |
|
7143 |
05 May 23 |
nicklas |
713 |
s.mappedTo = s.theCase.getItem(); |
7143 |
05 May 23 |
nicklas |
714 |
numMappedToCase++; |
7143 |
05 May 23 |
nicklas |
715 |
|
7143 |
05 May 23 |
nicklas |
716 |
if (s.errors.size() == 0) |
7143 |
05 May 23 |
nicklas |
717 |
{ |
7143 |
05 May 23 |
nicklas |
// The mapping is OK |
7143 |
05 May 23 |
nicklas |
719 |
s.canImport = true; |
7158 |
10 May 23 |
nicklas |
720 |
s.action = "Create a new Specimen, Lysate, RNA, DNA and FT and link them to this Case."; |
7143 |
05 May 23 |
nicklas |
721 |
} |
7143 |
05 May 23 |
nicklas |
722 |
|
7148 |
08 May 23 |
nicklas |
723 |
return s.mappedTo != null; |
7143 |
05 May 23 |
nicklas |
724 |
} |
7143 |
05 May 23 |
nicklas |
725 |
|
7143 |
05 May 23 |
nicklas |
726 |
/** |
7143 |
05 May 23 |
nicklas |
Rule 4: Find an existing Blood with matching SCAN-B ID. |
7143 |
05 May 23 |
nicklas |
728 |
*/ |
7143 |
05 May 23 |
nicklas |
729 |
public boolean mapEntryToExistingBloodByScanBId(DbControl dc, SampleEntry s) |
7143 |
05 May 23 |
nicklas |
730 |
{ |
7143 |
05 May 23 |
nicklas |
731 |
if (!s.findBloodByScanBId(dc)) return false; |
7143 |
05 May 23 |
nicklas |
732 |
|
7143 |
05 May 23 |
nicklas |
733 |
s.mappedTo = s.blood.getItem(); |
7143 |
05 May 23 |
nicklas |
734 |
numMappedToBlood++; |
7143 |
05 May 23 |
nicklas |
735 |
|
7143 |
05 May 23 |
nicklas |
736 |
if (s.errors.size() == 0) |
7143 |
05 May 23 |
nicklas |
737 |
{ |
7143 |
05 May 23 |
nicklas |
// The mapping is OK |
7143 |
05 May 23 |
nicklas |
739 |
s.canImport = true; |
7158 |
10 May 23 |
nicklas |
740 |
s.action = "Create a new Case, Specimen, Lysate, RNA, DNA and FT and link them to the Patient."; |
7143 |
05 May 23 |
nicklas |
741 |
} |
7143 |
05 May 23 |
nicklas |
742 |
|
7148 |
08 May 23 |
nicklas |
743 |
return s.mappedTo != null; |
7143 |
05 May 23 |
nicklas |
744 |
} |
7143 |
05 May 23 |
nicklas |
745 |
|
7143 |
05 May 23 |
nicklas |
746 |
/** |
7143 |
05 May 23 |
nicklas |
Rule 5: Map the entry to nothing. |
7143 |
05 May 23 |
nicklas |
748 |
*/ |
7143 |
05 May 23 |
nicklas |
749 |
public boolean mapEntryToNothing(DbControl dc, SampleEntry s) |
7143 |
05 May 23 |
nicklas |
750 |
{ |
7143 |
05 May 23 |
nicklas |
751 |
numMappedToNothing++; |
7157 |
10 May 23 |
nicklas |
752 |
|
7157 |
10 May 23 |
nicklas |
753 |
if (s.scanBId == null) |
7157 |
10 May 23 |
nicklas |
754 |
{ |
7177 |
17 May 23 |
nicklas |
755 |
s.canImport = false; |
7177 |
17 May 23 |
nicklas |
756 |
s.addWarning("SCAN-B ID is missing"); |
7177 |
17 May 23 |
nicklas |
757 |
s.action = "No import (Not a SCAN-B sample). Leave all tubes in the transport boxes."; |
7157 |
10 May 23 |
nicklas |
758 |
} |
7177 |
17 May 23 |
nicklas |
759 |
else |
7143 |
05 May 23 |
nicklas |
760 |
{ |
7177 |
17 May 23 |
nicklas |
761 |
if (s.errors.size() == 0) |
7177 |
17 May 23 |
nicklas |
762 |
{ |
7177 |
17 May 23 |
nicklas |
// The mapping is OK |
7177 |
17 May 23 |
nicklas |
764 |
s.canImport = true; |
7177 |
17 May 23 |
nicklas |
765 |
s.action = "Create a new Specimen, Lysate, RNA, DNA and FT (not linked to any Patient)."; |
7177 |
17 May 23 |
nicklas |
766 |
} |
7143 |
05 May 23 |
nicklas |
767 |
} |
7143 |
05 May 23 |
nicklas |
768 |
|
7157 |
10 May 23 |
nicklas |
769 |
return s.errors.size() == 0; |
7143 |
05 May 23 |
nicklas |
770 |
} |
7143 |
05 May 23 |
nicklas |
771 |
|
7143 |
05 May 23 |
nicklas |
772 |
/** |
7139 |
27 Apr 23 |
nicklas |
Get a mapper for a required column. If the column doesn't exists |
7139 |
27 Apr 23 |
nicklas |
an error message is logged and null is returned. |
7139 |
27 Apr 23 |
nicklas |
775 |
*/ |
7139 |
27 Apr 23 |
nicklas |
776 |
private Mapper getRequiredMapper(FlatFileParser ffp, String col, String fileAndLine) |
7139 |
27 Apr 23 |
nicklas |
777 |
{ |
7139 |
27 Apr 23 |
nicklas |
778 |
Mapper mapper = null; |
7139 |
27 Apr 23 |
nicklas |
779 |
if (ffp.getColumnHeaderIndex(col) == null) |
7139 |
27 Apr 23 |
nicklas |
780 |
{ |
7139 |
27 Apr 23 |
nicklas |
781 |
addErrorMessage(fileAndLine+"Column '" + col + "' not found in column headers."); |
7139 |
27 Apr 23 |
nicklas |
782 |
} |
7139 |
27 Apr 23 |
nicklas |
783 |
else |
7139 |
27 Apr 23 |
nicklas |
784 |
{ |
7139 |
27 Apr 23 |
nicklas |
785 |
mapper = ffp.getMapper("\\" + col + "\\"); |
7139 |
27 Apr 23 |
nicklas |
786 |
} |
7139 |
27 Apr 23 |
nicklas |
787 |
return mapper; |
7139 |
27 Apr 23 |
nicklas |
788 |
} |
7139 |
27 Apr 23 |
nicklas |
789 |
|
7139 |
27 Apr 23 |
nicklas |
790 |
/** |
7139 |
27 Apr 23 |
nicklas |
Get a mapper for an optional column. If the column doesn't exists |
7139 |
27 Apr 23 |
nicklas |
a warning message is logged (unless 'fileAndLine' is null) |
7139 |
27 Apr 23 |
nicklas |
and mapper that always return null is returned. |
7139 |
27 Apr 23 |
nicklas |
794 |
*/ |
7139 |
27 Apr 23 |
nicklas |
795 |
private Mapper getOptionalMapper(FlatFileParser ffp, String col, String fileAndLine) |
7139 |
27 Apr 23 |
nicklas |
796 |
{ |
7139 |
27 Apr 23 |
nicklas |
797 |
Mapper mapper = null; |
7139 |
27 Apr 23 |
nicklas |
798 |
if (ffp.getColumnHeaderIndex(col) == null) |
7139 |
27 Apr 23 |
nicklas |
799 |
{ |
7139 |
27 Apr 23 |
nicklas |
800 |
if (fileAndLine != null) |
7139 |
27 Apr 23 |
nicklas |
801 |
{ |
7139 |
27 Apr 23 |
nicklas |
802 |
addWarningMessage(fileAndLine+"Column '" + col + "' not found in column headers."); |
7139 |
27 Apr 23 |
nicklas |
803 |
} |
7139 |
27 Apr 23 |
nicklas |
804 |
mapper = new ConstantMapper((String)null); |
7139 |
27 Apr 23 |
nicklas |
805 |
} |
7139 |
27 Apr 23 |
nicklas |
806 |
else |
7139 |
27 Apr 23 |
nicklas |
807 |
{ |
7139 |
27 Apr 23 |
nicklas |
808 |
mapper = ffp.getMapper("\\" + col + "\\"); |
7139 |
27 Apr 23 |
nicklas |
809 |
} |
7139 |
27 Apr 23 |
nicklas |
810 |
return mapper; |
7139 |
27 Apr 23 |
nicklas |
811 |
} |
7139 |
27 Apr 23 |
nicklas |
812 |
|
7191 |
23 May 23 |
nicklas |
813 |
public static class Box |
7191 |
23 May 23 |
nicklas |
814 |
{ |
7191 |
23 May 23 |
nicklas |
815 |
final String name; |
7191 |
23 May 23 |
nicklas |
816 |
int numSamples; |
7191 |
23 May 23 |
nicklas |
817 |
|
7191 |
23 May 23 |
nicklas |
818 |
public Box(String name) |
7191 |
23 May 23 |
nicklas |
819 |
{ |
7191 |
23 May 23 |
nicklas |
820 |
this.name = name; |
7191 |
23 May 23 |
nicklas |
821 |
} |
7191 |
23 May 23 |
nicklas |
822 |
|
7191 |
23 May 23 |
nicklas |
823 |
public JSONObject toJSONObject() |
7191 |
23 May 23 |
nicklas |
824 |
{ |
7191 |
23 May 23 |
nicklas |
825 |
JSONObject json = new JSONObject(); |
7191 |
23 May 23 |
nicklas |
826 |
json.put("name", name); |
7191 |
23 May 23 |
nicklas |
827 |
json.put("numSamples", numSamples); |
7191 |
23 May 23 |
nicklas |
828 |
return json; |
7191 |
23 May 23 |
nicklas |
829 |
} |
7191 |
23 May 23 |
nicklas |
830 |
} |
7191 |
23 May 23 |
nicklas |
831 |
|
7139 |
27 Apr 23 |
nicklas |
832 |
public static class SampleEntry |
7139 |
27 Apr 23 |
nicklas |
833 |
{ |
7176 |
17 May 23 |
nicklas |
834 |
final String line; |
7139 |
27 Apr 23 |
nicklas |
835 |
final String fileAndLine; |
7139 |
27 Apr 23 |
nicklas |
836 |
final int lineNo; |
7139 |
27 Apr 23 |
nicklas |
837 |
String clarityId; |
7139 |
27 Apr 23 |
nicklas |
838 |
String scanBId; |
7139 |
27 Apr 23 |
nicklas |
839 |
String pad; |
7140 |
28 Apr 23 |
nicklas |
840 |
String transportBox; |
7141 |
02 May 23 |
nicklas |
841 |
|
7142 |
04 May 23 |
nicklas |
842 |
Patient patient; |
7142 |
04 May 23 |
nicklas |
843 |
Case theCase; |
7143 |
05 May 23 |
nicklas |
844 |
Blood blood; |
7140 |
28 Apr 23 |
nicklas |
845 |
BioWell well; |
7142 |
04 May 23 |
nicklas |
846 |
SpecimenTube specimen; |
7142 |
04 May 23 |
nicklas |
847 |
NoSpecimen noSpecimen; |
7142 |
04 May 23 |
nicklas |
848 |
Lysate lysate; |
7142 |
04 May 23 |
nicklas |
849 |
Rna rna; |
7142 |
04 May 23 |
nicklas |
850 |
Dna dna; |
7142 |
04 May 23 |
nicklas |
851 |
FlowThrough flowThrough; |
7139 |
27 Apr 23 |
nicklas |
852 |
|
7143 |
05 May 23 |
nicklas |
853 |
boolean canImport; |
7148 |
08 May 23 |
nicklas |
854 |
boolean noConsent; |
7164 |
12 May 23 |
nicklas |
855 |
boolean flag; |
7143 |
05 May 23 |
nicklas |
856 |
MeasuredBioMaterial mappedTo; |
7159 |
11 May 23 |
nicklas |
857 |
String comment; |
7159 |
11 May 23 |
nicklas |
858 |
String otherPathNote; |
7143 |
05 May 23 |
nicklas |
859 |
String action; |
7158 |
10 May 23 |
nicklas |
860 |
String alternateAction; |
7158 |
10 May 23 |
nicklas |
861 |
boolean alternateIsDefault; |
7141 |
02 May 23 |
nicklas |
862 |
final List<String> errors; |
7141 |
02 May 23 |
nicklas |
863 |
final List<String> warnings; |
7144 |
05 May 23 |
nicklas |
864 |
final List<String> debug; |
7139 |
27 Apr 23 |
nicklas |
865 |
|
7176 |
17 May 23 |
nicklas |
866 |
public SampleEntry(String line, String fileAndLine, int lineNo) |
7139 |
27 Apr 23 |
nicklas |
867 |
{ |
7176 |
17 May 23 |
nicklas |
868 |
this.line = line; |
7139 |
27 Apr 23 |
nicklas |
869 |
this.fileAndLine = fileAndLine; |
7139 |
27 Apr 23 |
nicklas |
870 |
this.lineNo = lineNo; |
7141 |
02 May 23 |
nicklas |
871 |
this.errors = new ArrayList<>(); |
7141 |
02 May 23 |
nicklas |
872 |
this.warnings = new ArrayList<>(); |
7144 |
05 May 23 |
nicklas |
873 |
this.debug = new ArrayList<>(); |
7139 |
27 Apr 23 |
nicklas |
874 |
} |
7139 |
27 Apr 23 |
nicklas |
875 |
|
7141 |
02 May 23 |
nicklas |
876 |
public void addError(String error) |
7141 |
02 May 23 |
nicklas |
877 |
{ |
7141 |
02 May 23 |
nicklas |
878 |
this.errors.add(error); |
7141 |
02 May 23 |
nicklas |
879 |
} |
7141 |
02 May 23 |
nicklas |
880 |
|
7141 |
02 May 23 |
nicklas |
881 |
public void addWarning(String warning) |
7141 |
02 May 23 |
nicklas |
882 |
{ |
7141 |
02 May 23 |
nicklas |
883 |
this.warnings.add(warning); |
7141 |
02 May 23 |
nicklas |
884 |
} |
7141 |
02 May 23 |
nicklas |
885 |
|
7144 |
05 May 23 |
nicklas |
886 |
public void addDebug(String msg) |
7144 |
05 May 23 |
nicklas |
887 |
{ |
7144 |
05 May 23 |
nicklas |
888 |
this.debug.add(msg); |
7144 |
05 May 23 |
nicklas |
889 |
} |
7144 |
05 May 23 |
nicklas |
890 |
|
7139 |
27 Apr 23 |
nicklas |
891 |
public JSONObject toJSONObject() |
7139 |
27 Apr 23 |
nicklas |
892 |
{ |
7139 |
27 Apr 23 |
nicklas |
893 |
JSONObject json = new JSONObject(); |
7176 |
17 May 23 |
nicklas |
894 |
json.put("line", line); |
7139 |
27 Apr 23 |
nicklas |
895 |
json.put("lineNo", lineNo); |
7139 |
27 Apr 23 |
nicklas |
896 |
json.put("clarityId", clarityId); |
7139 |
27 Apr 23 |
nicklas |
897 |
json.put("scanBId", scanBId); |
7139 |
27 Apr 23 |
nicklas |
898 |
json.put("pad", pad); |
7140 |
28 Apr 23 |
nicklas |
899 |
json.put("transportBox", transportBox); |
7140 |
28 Apr 23 |
nicklas |
900 |
if (well != null) json.put("well", JsonUtil.getBioWellAsJSON(well, true)); |
7140 |
28 Apr 23 |
nicklas |
901 |
|
7148 |
08 May 23 |
nicklas |
902 |
json.put("noConsent", noConsent); |
7143 |
05 May 23 |
nicklas |
903 |
json.put("canImport", canImport); |
7143 |
05 May 23 |
nicklas |
904 |
json.put("action", action); |
7158 |
10 May 23 |
nicklas |
905 |
json.put("alternateAction", alternateAction); |
7158 |
10 May 23 |
nicklas |
906 |
json.put("alternateIsDefault", alternateIsDefault); |
7159 |
11 May 23 |
nicklas |
907 |
json.put("comment", comment); |
7159 |
11 May 23 |
nicklas |
908 |
json.put("otherPathNote", otherPathNote); |
7143 |
05 May 23 |
nicklas |
909 |
if (mappedTo != null) |
7143 |
05 May 23 |
nicklas |
910 |
{ |
7143 |
05 May 23 |
nicklas |
911 |
JSONObject jsonMapped = new JSONObject(); |
7143 |
05 May 23 |
nicklas |
912 |
jsonMapped.put("name", mappedTo.getName()); |
7143 |
05 May 23 |
nicklas |
913 |
jsonMapped.put("id", mappedTo.getId()); |
7143 |
05 May 23 |
nicklas |
914 |
jsonMapped.put("itemType", mappedTo.getItemSubtype().getName()); |
7143 |
05 May 23 |
nicklas |
915 |
json.put("mappedTo", jsonMapped); |
7143 |
05 May 23 |
nicklas |
916 |
} |
7143 |
05 May 23 |
nicklas |
917 |
|
7141 |
02 May 23 |
nicklas |
918 |
if (errors.size() > 0) |
7141 |
02 May 23 |
nicklas |
919 |
{ |
7141 |
02 May 23 |
nicklas |
920 |
JSONArray jsonErrors = new JSONArray(); |
7141 |
02 May 23 |
nicklas |
921 |
jsonErrors.addAll(errors); |
7141 |
02 May 23 |
nicklas |
922 |
json.put("errors", jsonErrors); |
7141 |
02 May 23 |
nicklas |
923 |
} |
7141 |
02 May 23 |
nicklas |
924 |
if (warnings.size() > 0) |
7141 |
02 May 23 |
nicklas |
925 |
{ |
7141 |
02 May 23 |
nicklas |
926 |
JSONArray jsonWarnings = new JSONArray(); |
7141 |
02 May 23 |
nicklas |
927 |
jsonWarnings.addAll(warnings); |
7141 |
02 May 23 |
nicklas |
928 |
json.put("warnings", jsonWarnings); |
7141 |
02 May 23 |
nicklas |
929 |
} |
7139 |
27 Apr 23 |
nicklas |
930 |
return json; |
7139 |
27 Apr 23 |
nicklas |
931 |
} |
7141 |
02 May 23 |
nicklas |
932 |
|
7161 |
11 May 23 |
nicklas |
933 |
void updateFromRequestParameters(JSONObject json) |
7161 |
11 May 23 |
nicklas |
934 |
{ |
7161 |
11 May 23 |
nicklas |
935 |
if (json == null) return; |
7161 |
11 May 23 |
nicklas |
936 |
if (!clarityId.equals(json.get("clarityId"))) |
7161 |
11 May 23 |
nicklas |
937 |
{ |
7161 |
11 May 23 |
nicklas |
938 |
throw new InvalidDataException("Clarity ID mismatch: "+clarityId+"<>"+json.get("clarityId")); |
7161 |
11 May 23 |
nicklas |
939 |
} |
7161 |
11 May 23 |
nicklas |
940 |
|
7161 |
11 May 23 |
nicklas |
941 |
String comment = Values.getStringOrNull((String)json.get("comment")); |
7161 |
11 May 23 |
nicklas |
942 |
if (comment != null) this.comment = comment; |
7161 |
11 May 23 |
nicklas |
943 |
|
7161 |
11 May 23 |
nicklas |
944 |
if (alternateAction != null && !Boolean.TRUE.equals(json.get("alternateAction"))) |
7161 |
11 May 23 |
nicklas |
945 |
{ |
7161 |
11 May 23 |
nicklas |
// Reset the alternate action |
7161 |
11 May 23 |
nicklas |
947 |
alternateAction = null; |
7161 |
11 May 23 |
nicklas |
948 |
} |
7161 |
11 May 23 |
nicklas |
949 |
} |
7161 |
11 May 23 |
nicklas |
950 |
|
7141 |
02 May 23 |
nicklas |
951 |
/** |
7141 |
02 May 23 |
nicklas |
Try to find an existing Specimen item with EXTERNA_REF=cmd:Clarity ID |
7141 |
02 May 23 |
nicklas |
Return TRUE if a single match was found, FALSE otherwise. |
7141 |
02 May 23 |
nicklas |
954 |
*/ |
7141 |
02 May 23 |
nicklas |
955 |
boolean findSpecimenByClarityId(DbControl dc) |
7141 |
02 May 23 |
nicklas |
956 |
{ |
7141 |
02 May 23 |
nicklas |
957 |
if (clarityId == null) return false; |
7141 |
02 May 23 |
nicklas |
958 |
|
7141 |
02 May 23 |
nicklas |
959 |
ItemQuery<Sample> findSpecimen = Sample.getQuery(); |
7141 |
02 May 23 |
nicklas |
960 |
Subtype.SPECIMEN.addFilter(dc, findSpecimen); |
7141 |
02 May 23 |
nicklas |
961 |
findSpecimen.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
7141 |
02 May 23 |
nicklas |
962 |
findSpecimen.join(Annotations.innerJoin(Annotationtype.EXTERNAL_REF.get(dc), "cid")); |
7141 |
02 May 23 |
nicklas |
963 |
findSpecimen.restrict(Restrictions.eq(Hql.alias("cid"), Expressions.string("cmd:"+clarityId))); |
7141 |
02 May 23 |
nicklas |
964 |
|
7141 |
02 May 23 |
nicklas |
965 |
List<Sample> samples = findSpecimen.list(dc); |
7141 |
02 May 23 |
nicklas |
966 |
if (samples.size() > 1) |
7141 |
02 May 23 |
nicklas |
967 |
{ |
7141 |
02 May 23 |
nicklas |
// This should *never* happen |
7141 |
02 May 23 |
nicklas |
969 |
addError("Found " + samples.size() + " Specimen with Clarity ID: "+clarityId); |
7141 |
02 May 23 |
nicklas |
970 |
} |
7141 |
02 May 23 |
nicklas |
// In most cases we will find a matching Specimen, but |
7141 |
02 May 23 |
nicklas |
// no match is not an error condition (until we have checked other possibilities) |
7141 |
02 May 23 |
nicklas |
973 |
if (samples.size() == 1) |
7141 |
02 May 23 |
nicklas |
974 |
{ |
7142 |
04 May 23 |
nicklas |
975 |
specimen = SpecimenTube.get(samples.get(0)); |
7143 |
05 May 23 |
nicklas |
976 |
theCase = specimen.getCase(); |
7141 |
02 May 23 |
nicklas |
977 |
} |
7141 |
02 May 23 |
nicklas |
978 |
return specimen != null; |
7141 |
02 May 23 |
nicklas |
979 |
} |
7141 |
02 May 23 |
nicklas |
980 |
|
7158 |
10 May 23 |
nicklas |
981 |
|
7158 |
10 May 23 |
nicklas |
982 |
Sample findSampleByPad(DbControl dc, String otherPad) |
7158 |
10 May 23 |
nicklas |
983 |
{ |
7158 |
10 May 23 |
nicklas |
984 |
int sep = otherPad.indexOf('-'); |
7158 |
10 May 23 |
nicklas |
985 |
if (sep > 0) otherPad = otherPad.substring(0, sep); |
7158 |
10 May 23 |
nicklas |
986 |
|
7158 |
10 May 23 |
nicklas |
987 |
ItemQuery<Sample> query = Sample.getQuery(); |
7158 |
10 May 23 |
nicklas |
988 |
query.restrict(Restrictions.or( |
7158 |
10 May 23 |
nicklas |
989 |
Subtype.SPECIMEN.restriction(dc, null), |
7158 |
10 May 23 |
nicklas |
990 |
Subtype.NO_SPECIMEN.restriction(dc, null) |
7158 |
10 May 23 |
nicklas |
991 |
)); |
7158 |
10 May 23 |
nicklas |
992 |
query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
7158 |
10 May 23 |
nicklas |
993 |
query.restrict(new AnnotationSimpleRestriction(null, Annotationtype.PAD.get(dc), Operator.EQ, otherPad, new AnnotationRestriction.Options())); |
7158 |
10 May 23 |
nicklas |
994 |
List<Sample> other = query.list(dc); |
7158 |
10 May 23 |
nicklas |
995 |
|
7158 |
10 May 23 |
nicklas |
996 |
return other.size() > 0 ? other.get(0) : null; |
7158 |
10 May 23 |
nicklas |
997 |
} |
7158 |
10 May 23 |
nicklas |
998 |
|
7142 |
04 May 23 |
nicklas |
999 |
/** |
7142 |
04 May 23 |
nicklas |
Try to find an existing NoSpecimen item with EXTERNAL_SPECIMEN_EXISTS=Yes |
7142 |
04 May 23 |
nicklas |
1001 |
*/ |
7141 |
02 May 23 |
nicklas |
1002 |
boolean findNoSpecimenByScanBId(DbControl dc) |
7141 |
02 May 23 |
nicklas |
1003 |
{ |
7141 |
02 May 23 |
nicklas |
1004 |
if (scanBId == null) return false; |
7141 |
02 May 23 |
nicklas |
1005 |
|
7141 |
02 May 23 |
nicklas |
1006 |
List<NoSpecimen> nsList = NoSpecimen.findByCaseName(dc, scanBId, true); |
7141 |
02 May 23 |
nicklas |
1007 |
for (NoSpecimen ns : nsList) |
7141 |
02 May 23 |
nicklas |
1008 |
{ |
7141 |
02 May 23 |
nicklas |
1009 |
if ("Yes".equals(Annotationtype.EXTERNAL_SPECIMEN_EXISTS.getAnnotationValue(dc, ns.getItem()))) |
7141 |
02 May 23 |
nicklas |
1010 |
{ |
7142 |
04 May 23 |
nicklas |
1011 |
noSpecimen = ns; |
7141 |
02 May 23 |
nicklas |
1012 |
break; |
7141 |
02 May 23 |
nicklas |
1013 |
} |
7141 |
02 May 23 |
nicklas |
1014 |
} |
7143 |
05 May 23 |
nicklas |
1015 |
if (noSpecimen != null) |
7143 |
05 May 23 |
nicklas |
1016 |
{ |
7143 |
05 May 23 |
nicklas |
1017 |
theCase = noSpecimen.getCase(); |
7143 |
05 May 23 |
nicklas |
1018 |
} |
7141 |
02 May 23 |
nicklas |
1019 |
return noSpecimen != null; |
7141 |
02 May 23 |
nicklas |
1020 |
} |
7141 |
02 May 23 |
nicklas |
1021 |
|
7141 |
02 May 23 |
nicklas |
1022 |
/** |
7143 |
05 May 23 |
nicklas |
Try to find an existing Case either directly or via another |
7143 |
05 May 23 |
nicklas |
Specimen/NoSpecimen item. |
7143 |
05 May 23 |
nicklas |
1025 |
*/ |
7143 |
05 May 23 |
nicklas |
1026 |
boolean findCaseByScanBId(DbControl dc) |
7143 |
05 May 23 |
nicklas |
1027 |
{ |
7143 |
05 May 23 |
nicklas |
1028 |
if (scanBId == null) return false; |
7143 |
05 May 23 |
nicklas |
1029 |
theCase = Case.findByName(dc, scanBId); |
7143 |
05 May 23 |
nicklas |
1030 |
return theCase != null; |
7143 |
05 May 23 |
nicklas |
1031 |
} |
7143 |
05 May 23 |
nicklas |
1032 |
|
7143 |
05 May 23 |
nicklas |
1033 |
/** |
7143 |
05 May 23 |
nicklas |
Try to find an existing Blood item. If more than |
7143 |
05 May 23 |
nicklas |
one is found we simply take the first one since we are |
7143 |
05 May 23 |
nicklas |
mainly interested in the patient. |
7143 |
05 May 23 |
nicklas |
1037 |
*/ |
7143 |
05 May 23 |
nicklas |
1038 |
boolean findBloodByScanBId(DbControl dc) |
7143 |
05 May 23 |
nicklas |
1039 |
{ |
7143 |
05 May 23 |
nicklas |
1040 |
if (scanBId == null) return false; |
7143 |
05 May 23 |
nicklas |
1041 |
List<Blood> list = Blood.findAllByCaseName(dc, scanBId); |
7143 |
05 May 23 |
nicklas |
1042 |
if (list.size() > 0) blood = list.get(0); |
7144 |
05 May 23 |
nicklas |
1043 |
if (blood != null) |
7144 |
05 May 23 |
nicklas |
1044 |
{ |
7144 |
05 May 23 |
nicklas |
1045 |
patient = Patient.findByBlood(dc, blood); |
7144 |
05 May 23 |
nicklas |
1046 |
} |
7143 |
05 May 23 |
nicklas |
1047 |
return blood != null; |
7143 |
05 May 23 |
nicklas |
1048 |
} |
7143 |
05 May 23 |
nicklas |
1049 |
|
7143 |
05 May 23 |
nicklas |
1050 |
/** |
7141 |
02 May 23 |
nicklas |
Find a matching Lysate item that is a child item to the current Specimen. |
7141 |
02 May 23 |
nicklas |
It must find exactly one item otherwise it is an error. |
7141 |
02 May 23 |
nicklas |
1053 |
*/ |
7141 |
02 May 23 |
nicklas |
1054 |
boolean findLysate(DbControl dc) |
7141 |
02 May 23 |
nicklas |
1055 |
{ |
7142 |
04 May 23 |
nicklas |
1056 |
lysate = Lysate.get(findChild(dc, specimen, Subtype.LYSATE)); |
7142 |
04 May 23 |
nicklas |
1057 |
return lysate != null; |
7141 |
02 May 23 |
nicklas |
1058 |
} |
7141 |
02 May 23 |
nicklas |
1059 |
|
7141 |
02 May 23 |
nicklas |
1060 |
/** |
7141 |
02 May 23 |
nicklas |
Find a matching RNA item that is a child item to the current Lysate. |
7141 |
02 May 23 |
nicklas |
It must find exactly one item otherwise it is an error. |
7141 |
02 May 23 |
nicklas |
1063 |
*/ |
7141 |
02 May 23 |
nicklas |
1064 |
boolean findRna(DbControl dc) |
7141 |
02 May 23 |
nicklas |
1065 |
{ |
7142 |
04 May 23 |
nicklas |
1066 |
rna = Rna.get(findChild(dc, lysate, Subtype.RNA)); |
7142 |
04 May 23 |
nicklas |
1067 |
return rna != null; |
7142 |
04 May 23 |
nicklas |
1068 |
} |
7142 |
04 May 23 |
nicklas |
1069 |
|
7142 |
04 May 23 |
nicklas |
1070 |
/** |
7142 |
04 May 23 |
nicklas |
Find a matching DNA item that is a child item to the current Lysate. |
7142 |
04 May 23 |
nicklas |
It must find exactly one item otherwise it is an error. |
7142 |
04 May 23 |
nicklas |
1073 |
*/ |
7142 |
04 May 23 |
nicklas |
1074 |
boolean findDna(DbControl dc) |
7142 |
04 May 23 |
nicklas |
1075 |
{ |
7142 |
04 May 23 |
nicklas |
1076 |
dna = Dna.get(findChild(dc, lysate, Subtype.DNA)); |
7142 |
04 May 23 |
nicklas |
1077 |
return dna != null; |
7142 |
04 May 23 |
nicklas |
1078 |
} |
7142 |
04 May 23 |
nicklas |
1079 |
|
7142 |
04 May 23 |
nicklas |
1080 |
/** |
7142 |
04 May 23 |
nicklas |
Find a matching FlowThrough item that is a child item to the current Lysate. |
7142 |
04 May 23 |
nicklas |
It must find exactly one item otherwise it is an error. |
7142 |
04 May 23 |
nicklas |
1083 |
*/ |
7142 |
04 May 23 |
nicklas |
1084 |
boolean findFlowThrough(DbControl dc) |
7142 |
04 May 23 |
nicklas |
1085 |
{ |
7142 |
04 May 23 |
nicklas |
1086 |
flowThrough = FlowThrough.get(findChild(dc, lysate, Subtype.FLOW_THROUGH)); |
7142 |
04 May 23 |
nicklas |
1087 |
return flowThrough != null; |
7142 |
04 May 23 |
nicklas |
1088 |
} |
7142 |
04 May 23 |
nicklas |
1089 |
|
7142 |
04 May 23 |
nicklas |
1090 |
private Extract findChild(DbControl dc, ReggieItem<? extends MeasuredBioMaterial> parent, Subtype childType) |
7142 |
04 May 23 |
nicklas |
1091 |
{ |
7142 |
04 May 23 |
nicklas |
1092 |
if (parent == null) return null; |
7141 |
02 May 23 |
nicklas |
1093 |
|
7142 |
04 May 23 |
nicklas |
1094 |
ItemQuery<Extract> find = Extract.getQuery(); |
7142 |
04 May 23 |
nicklas |
1095 |
childType.addFilter(dc, find); |
7142 |
04 May 23 |
nicklas |
1096 |
find.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
7142 |
04 May 23 |
nicklas |
1097 |
find.join(Hql.innerJoin("parent", "p")); |
7142 |
04 May 23 |
nicklas |
1098 |
find.restrict(Restrictions.eq(Hql.alias("p"), Hql.entity(parent.getItem()))); |
7141 |
02 May 23 |
nicklas |
1099 |
|
7142 |
04 May 23 |
nicklas |
1100 |
List<Extract> items = find.list(dc); |
7141 |
02 May 23 |
nicklas |
1101 |
if (items.size() == 0) |
7141 |
02 May 23 |
nicklas |
1102 |
{ |
7142 |
04 May 23 |
nicklas |
1103 |
addError("Could not find child "+childType.getName()+" for: "+lysate.getName()); |
7142 |
04 May 23 |
nicklas |
1104 |
return null; |
7141 |
02 May 23 |
nicklas |
1105 |
} |
7141 |
02 May 23 |
nicklas |
1106 |
else if (items.size() > 1) |
7141 |
02 May 23 |
nicklas |
1107 |
{ |
7142 |
04 May 23 |
nicklas |
1108 |
addError("Found " + items.size() + " "+childType.getName()+" for: "+lysate.getName()); |
7142 |
04 May 23 |
nicklas |
1109 |
return null; |
7141 |
02 May 23 |
nicklas |
1110 |
} |
7142 |
04 May 23 |
nicklas |
1111 |
return items.get(0); |
7141 |
02 May 23 |
nicklas |
1112 |
} |
7141 |
02 May 23 |
nicklas |
1113 |
|
7142 |
04 May 23 |
nicklas |
1114 |
/** |
7142 |
04 May 23 |
nicklas |
Check that the given item is not already stored in some place. |
7142 |
04 May 23 |
nicklas |
1116 |
*/ |
7142 |
04 May 23 |
nicklas |
1117 |
void checkStorage(ReggieItem<? extends MeasuredBioMaterial> item) |
7141 |
02 May 23 |
nicklas |
1118 |
{ |
7142 |
04 May 23 |
nicklas |
1119 |
if (item != null && item.getItem().isInWell()) |
7141 |
02 May 23 |
nicklas |
1120 |
{ |
7142 |
04 May 23 |
nicklas |
1121 |
addError(item.getItem().getItemSubtype().getName()+ |
7142 |
04 May 23 |
nicklas |
1122 |
" is already stored: "+getStorageLocation(item.getItem().getBioWell())); |
7141 |
02 May 23 |
nicklas |
1123 |
} |
7141 |
02 May 23 |
nicklas |
1124 |
} |
7141 |
02 May 23 |
nicklas |
1125 |
|
7142 |
04 May 23 |
nicklas |
1126 |
/** |
7142 |
04 May 23 |
nicklas |
Get the name of the storage location (eg. name of box+coordinates) |
7142 |
04 May 23 |
nicklas |
1128 |
*/ |
7141 |
02 May 23 |
nicklas |
1129 |
String getStorageLocation(BioWell well) |
7141 |
02 May 23 |
nicklas |
1130 |
{ |
7141 |
02 May 23 |
nicklas |
1131 |
if (well == null) return null; |
7141 |
02 May 23 |
nicklas |
1132 |
BioPlate plate = well.getPlate(); |
7141 |
02 May 23 |
nicklas |
1133 |
return plate.getName()+" "+well.getCoordinate(); |
7141 |
02 May 23 |
nicklas |
1134 |
} |
7141 |
02 May 23 |
nicklas |
1135 |
|
7142 |
04 May 23 |
nicklas |
1136 |
/** |
7142 |
04 May 23 |
nicklas |
If we could not map to existing items, they need to be created and |
7142 |
04 May 23 |
nicklas |
properly linked to whatever information we have. We must ensure that |
7142 |
04 May 23 |
nicklas |
a Specimen, Lysate, RNA, DNA and FlowThrough always exists. If |
7142 |
04 May 23 |
nicklas |
a new Specimen is needed we will also try to link to an existing |
7142 |
04 May 23 |
nicklas |
Patient or Case. |
7142 |
04 May 23 |
nicklas |
1142 |
*/ |
7162 |
12 May 23 |
nicklas |
1143 |
void createMissingItems(DbControl dc, Stats stats) |
7142 |
04 May 23 |
nicklas |
1144 |
{ |
7142 |
04 May 23 |
nicklas |
1145 |
|
7144 |
05 May 23 |
nicklas |
1146 |
if (theCase == null) |
7144 |
05 May 23 |
nicklas |
1147 |
{ |
7144 |
05 May 23 |
nicklas |
// We may need to create a Case but only if it can be linked to a patient |
7144 |
05 May 23 |
nicklas |
1149 |
if (patient != null) |
7144 |
05 May 23 |
nicklas |
1150 |
{ |
7144 |
05 May 23 |
nicklas |
1151 |
Sample c = Sample.getNew(dc); |
7144 |
05 May 23 |
nicklas |
1152 |
c.setItemSubtype(Subtype.CASE.get(dc)); |
7144 |
05 May 23 |
nicklas |
1153 |
c.setExternalId(Case.getNextExternalId(dc)); |
7144 |
05 May 23 |
nicklas |
1154 |
c.setName(scanBId.substring(0, 7)); // It may hava suffix |
7144 |
05 May 23 |
nicklas |
1155 |
BioMaterialEvent ce = c.getCreationEvent(); |
7144 |
05 May 23 |
nicklas |
1156 |
ce.setSource(patient.getItem()); |
7144 |
05 May 23 |
nicklas |
1157 |
ce.setProtocol(null); |
7144 |
05 May 23 |
nicklas |
1158 |
ce.setHardware(null); |
7144 |
05 May 23 |
nicklas |
1159 |
if (blood != null) // It shouldn't be since the case can only be null if we found the patient via blood |
7144 |
05 May 23 |
nicklas |
1160 |
{ |
7144 |
05 May 23 |
nicklas |
// Copy consent |
7144 |
05 May 23 |
nicklas |
1162 |
Consent.copyConsentAnnotations(dc, blood.getItem(), c, false); |
7144 |
05 May 23 |
nicklas |
1163 |
} |
7144 |
05 May 23 |
nicklas |
1164 |
dc.saveItem(c); |
7145 |
05 May 23 |
nicklas |
1165 |
theCase = Case.get(c); |
7144 |
05 May 23 |
nicklas |
1166 |
addDebug("Created new Case: "+c.getName()); |
7144 |
05 May 23 |
nicklas |
1167 |
} |
7144 |
05 May 23 |
nicklas |
1168 |
} |
7145 |
05 May 23 |
nicklas |
1169 |
else |
7145 |
05 May 23 |
nicklas |
1170 |
{ |
7145 |
05 May 23 |
nicklas |
1171 |
addDebug("Using existing Case: "+theCase.getName()); |
7145 |
05 May 23 |
nicklas |
1172 |
} |
7144 |
05 May 23 |
nicklas |
1173 |
|
7142 |
04 May 23 |
nicklas |
1174 |
if (specimen == null) |
7142 |
04 May 23 |
nicklas |
1175 |
{ |
7142 |
04 May 23 |
nicklas |
1176 |
Sample sp = null; |
7161 |
11 May 23 |
nicklas |
1177 |
if (noSpecimen != null && alternateAction == null) |
7142 |
04 May 23 |
nicklas |
1178 |
{ |
7142 |
04 May 23 |
nicklas |
1179 |
sp = noSpecimen.getItem(); |
7142 |
04 May 23 |
nicklas |
1180 |
noSpecimen = null; |
7144 |
05 May 23 |
nicklas |
1181 |
addDebug("Converting NoSpecimen to Specimen: "+sp.getName()); |
7162 |
12 May 23 |
nicklas |
1182 |
stats.convertedNoSpecimen++; |
7142 |
04 May 23 |
nicklas |
1183 |
} |
7142 |
04 May 23 |
nicklas |
1184 |
else |
7142 |
04 May 23 |
nicklas |
1185 |
{ |
7144 |
05 May 23 |
nicklas |
1186 |
sp = Sample.getNew(dc); |
7144 |
05 May 23 |
nicklas |
1187 |
sp.setExternalId(SpecimenTube.getNextExternalId(dc, Subtype.SPECIMEN)); |
7144 |
05 May 23 |
nicklas |
1188 |
sp.setName(SpecimenTube.getNextSpecimenName(dc, scanBId, true)); |
7144 |
05 May 23 |
nicklas |
1189 |
BioMaterialEvent ce = sp.getCreationEvent(); |
7144 |
05 May 23 |
nicklas |
1190 |
if (theCase != null) |
7142 |
04 May 23 |
nicklas |
1191 |
{ |
7144 |
05 May 23 |
nicklas |
1192 |
ce.setSource(theCase.getItem()); |
7145 |
05 May 23 |
nicklas |
1193 |
Annotationtype.LATERALITY.copyAnnotationValues(dc, theCase.getItem(), sp, false); |
7142 |
04 May 23 |
nicklas |
1194 |
} |
7144 |
05 May 23 |
nicklas |
1195 |
ce.setProtocol(null); |
7144 |
05 May 23 |
nicklas |
1196 |
ce.setHardware(null); |
7142 |
04 May 23 |
nicklas |
1197 |
dc.saveItem(sp); |
7145 |
05 May 23 |
nicklas |
1198 |
if (scanBId.endsWith("C")) Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, sp, "SpecimenCoreBiopsy"); |
7145 |
05 May 23 |
nicklas |
1199 |
if (scanBId.endsWith("D")) Annotationtype.BIOPSY_TYPE.setAnnotationValue(dc, sp, "SpecimenCoreBiopsy2nd"); |
7144 |
05 May 23 |
nicklas |
1200 |
addDebug("Created new Specimen: "+sp.getName()); |
7162 |
12 May 23 |
nicklas |
1201 |
stats.newSpecimen++; |
7142 |
04 May 23 |
nicklas |
1202 |
} |
7142 |
04 May 23 |
nicklas |
1203 |
|
7142 |
04 May 23 |
nicklas |
1204 |
sp.setItemSubtype(Subtype.SPECIMEN.get(dc)); |
7142 |
04 May 23 |
nicklas |
1205 |
Annotationtype.TUBE_LABEL.setAnnotationValue(dc, sp, clarityId); |
7142 |
04 May 23 |
nicklas |
1206 |
Annotationtype.EXTERNAL_REF.setAnnotationValue(dc, sp, "cmd:"+clarityId); |
7163 |
12 May 23 |
nicklas |
1207 |
Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, sp, "Disable"); |
7144 |
05 May 23 |
nicklas |
1208 |
if (pad != null && !Annotationtype.PAD.hasAnnotation(dc, sp)) |
7144 |
05 May 23 |
nicklas |
1209 |
{ |
7144 |
05 May 23 |
nicklas |
1210 |
Annotationtype.PAD.setAnnotationValue(dc, sp, pad); |
7144 |
05 May 23 |
nicklas |
1211 |
} |
7142 |
04 May 23 |
nicklas |
1212 |
specimen = SpecimenTube.get(sp); |
7164 |
12 May 23 |
nicklas |
1213 |
flag = true; |
7142 |
04 May 23 |
nicklas |
1214 |
} |
7144 |
05 May 23 |
nicklas |
1215 |
else |
7144 |
05 May 23 |
nicklas |
1216 |
{ |
7144 |
05 May 23 |
nicklas |
1217 |
addDebug("Using existing Specimen: "+specimen.getName()); |
7162 |
12 May 23 |
nicklas |
1218 |
stats.mappedExistingSpecimen++; |
7144 |
05 May 23 |
nicklas |
1219 |
} |
7142 |
04 May 23 |
nicklas |
1220 |
|
7161 |
11 May 23 |
nicklas |
// Update comment |
7161 |
11 May 23 |
nicklas |
1222 |
if (comment != null) specimen.getItem().setDescription(comment); |
7161 |
11 May 23 |
nicklas |
1223 |
|
7142 |
04 May 23 |
nicklas |
1224 |
if (lysate == null) |
7142 |
04 May 23 |
nicklas |
1225 |
{ |
7142 |
04 May 23 |
nicklas |
1226 |
Extract lys = createChildExtract(dc, specimen, Subtype.LYSATE); |
7142 |
04 May 23 |
nicklas |
1227 |
Annotationtype.TUBE_LABEL.setAnnotationValue(dc, lys, clarityId+"-Lys"); |
7142 |
04 May 23 |
nicklas |
1228 |
lysate = Lysate.get(lys); |
7144 |
05 May 23 |
nicklas |
1229 |
addDebug("Created new Lysate: "+lys.getName()); |
7142 |
04 May 23 |
nicklas |
1230 |
} |
7142 |
04 May 23 |
nicklas |
1231 |
|
7142 |
04 May 23 |
nicklas |
1232 |
if (rna == null) |
7142 |
04 May 23 |
nicklas |
1233 |
{ |
7142 |
04 May 23 |
nicklas |
1234 |
Extract r = createChildExtract(dc, lysate, Subtype.RNA); |
7142 |
04 May 23 |
nicklas |
1235 |
Annotationtype.TUBE_LABEL.setAnnotationValue(dc, r, clarityId+"-RNA"); |
7142 |
04 May 23 |
nicklas |
1236 |
rna = Rna.get(r); |
7144 |
05 May 23 |
nicklas |
1237 |
addDebug("Created new RNA: "+r.getName()); |
7142 |
04 May 23 |
nicklas |
1238 |
} |
7142 |
04 May 23 |
nicklas |
1239 |
|
7142 |
04 May 23 |
nicklas |
1240 |
if (dna == null) |
7142 |
04 May 23 |
nicklas |
1241 |
{ |
7142 |
04 May 23 |
nicklas |
1242 |
Extract d = createChildExtract(dc, lysate, Subtype.DNA); |
7142 |
04 May 23 |
nicklas |
1243 |
Annotationtype.TUBE_LABEL.setAnnotationValue(dc, d, clarityId+"-DNA"); |
7142 |
04 May 23 |
nicklas |
1244 |
dna = Dna.get(d); |
7144 |
05 May 23 |
nicklas |
1245 |
addDebug("Created new DNA: "+d.getName()); |
7142 |
04 May 23 |
nicklas |
1246 |
} |
7142 |
04 May 23 |
nicklas |
1247 |
|
7142 |
04 May 23 |
nicklas |
1248 |
if (flowThrough == null) |
7142 |
04 May 23 |
nicklas |
1249 |
{ |
7142 |
04 May 23 |
nicklas |
1250 |
Extract ft = createChildExtract(dc, lysate, Subtype.FLOW_THROUGH); |
7142 |
04 May 23 |
nicklas |
1251 |
Annotationtype.TUBE_LABEL.setAnnotationValue(dc, ft, clarityId+"-Prot"); |
7142 |
04 May 23 |
nicklas |
1252 |
flowThrough = FlowThrough.get(ft); |
7144 |
05 May 23 |
nicklas |
1253 |
addDebug("Created new FlowThough: "+ft.getName()); |
7142 |
04 May 23 |
nicklas |
1254 |
} |
7142 |
04 May 23 |
nicklas |
1255 |
} |
7142 |
04 May 23 |
nicklas |
1256 |
|
7142 |
04 May 23 |
nicklas |
1257 |
private Extract createChildExtract(DbControl dc, ReggieItem<? extends MeasuredBioMaterial> parent, Subtype subtype) |
7142 |
04 May 23 |
nicklas |
1258 |
{ |
7142 |
04 May 23 |
nicklas |
1259 |
Extract e = Extract.getNew(dc); |
7142 |
04 May 23 |
nicklas |
1260 |
e.setItemSubtype(subtype.get(dc)); |
7142 |
04 May 23 |
nicklas |
1261 |
e.setName(ReggieItem.getNextChildItemName(dc, parent.getName(), null, subtype.getItemSuffix(), true)); |
7142 |
04 May 23 |
nicklas |
1262 |
BioMaterialEvent createEvent = e.getCreationEvent(); |
7142 |
04 May 23 |
nicklas |
1263 |
createEvent.setSource(parent.getItem()); |
7142 |
04 May 23 |
nicklas |
1264 |
createEvent.setProtocol(null); |
7142 |
04 May 23 |
nicklas |
1265 |
createEvent.setHardware(null); |
7163 |
12 May 23 |
nicklas |
1266 |
Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, e, "Disable"); |
7142 |
04 May 23 |
nicklas |
1267 |
dc.saveItem(e); |
7142 |
04 May 23 |
nicklas |
1268 |
return e; |
7142 |
04 May 23 |
nicklas |
1269 |
} |
7142 |
04 May 23 |
nicklas |
1270 |
|
7142 |
04 May 23 |
nicklas |
1271 |
/** |
7142 |
04 May 23 |
nicklas |
Place existing items in storage boxes. |
7142 |
04 May 23 |
nicklas |
1273 |
*/ |
7142 |
04 May 23 |
nicklas |
1274 |
void placeInStorageBoxes(DbControl dc) |
7142 |
04 May 23 |
nicklas |
1275 |
{ |
7142 |
04 May 23 |
nicklas |
1276 |
specimen.getItem().setBioWell(well); |
7142 |
04 May 23 |
nicklas |
1277 |
BioWell lysWell = StoragePlate.getChildBioWell(dc, well, "E-Sp", "E-Lys"); |
7142 |
04 May 23 |
nicklas |
1278 |
lysate.getItem().setBioWell(lysWell); |
7142 |
04 May 23 |
nicklas |
1279 |
rna.getItem().setBioWell(StoragePlate.getChildBioWell(dc, lysWell, "E-Lys", "E-RNA")); |
7142 |
04 May 23 |
nicklas |
1280 |
dna.getItem().setBioWell(StoragePlate.getChildBioWell(dc, lysWell, "E-Lys", "E-DNA")); |
7142 |
04 May 23 |
nicklas |
1281 |
flowThrough.getItem().setBioWell(StoragePlate.getChildBioWell(dc, lysWell, "E-Lys", "E-FT")); |
7142 |
04 May 23 |
nicklas |
1282 |
|
7145 |
05 May 23 |
nicklas |
// Set/Update EXTERNAL_STORAGE annotation and EXTERNAL_SPECIMEN_EXISTS |
7145 |
05 May 23 |
nicklas |
1284 |
Annotationtype.EXTERNAL_SPECIMEN_EXISTS.setAnnotationValue(dc, specimen.getItem(), "Yes"); |
7142 |
04 May 23 |
nicklas |
1285 |
String extStorage = "Transport box: " + transportBox; |
7142 |
04 May 23 |
nicklas |
1286 |
Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, specimen.getItem(), extStorage); |
7142 |
04 May 23 |
nicklas |
1287 |
Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, lysate.getItem(), extStorage); |
7142 |
04 May 23 |
nicklas |
1288 |
Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, rna.getItem(), extStorage); |
7142 |
04 May 23 |
nicklas |
1289 |
Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, dna.getItem(), extStorage); |
7142 |
04 May 23 |
nicklas |
1290 |
Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, flowThrough.getItem(), extStorage); |
7142 |
04 May 23 |
nicklas |
1291 |
} |
7142 |
04 May 23 |
nicklas |
1292 |
|
7142 |
04 May 23 |
nicklas |
1293 |
/** |
7142 |
04 May 23 |
nicklas |
Add items to the item lists that are used for the lab protocol. |
7142 |
04 May 23 |
nicklas |
1295 |
*/ |
7164 |
12 May 23 |
nicklas |
1296 |
void addToItemLists(DbControl dc, ListSet ls, Stats stats) |
7142 |
04 May 23 |
nicklas |
1297 |
{ |
7142 |
04 May 23 |
nicklas |
1298 |
ls.specimenList.add(specimen.getItem()); |
7142 |
04 May 23 |
nicklas |
1299 |
ls.lysateList.add(lysate.getItem()); |
7142 |
04 May 23 |
nicklas |
1300 |
ls.rnaList.add(rna.getItem()); |
7142 |
04 May 23 |
nicklas |
1301 |
ls.dnaList.add(dna.getItem()); |
7142 |
04 May 23 |
nicklas |
1302 |
ls.flowThroughList.add(flowThrough.getItem()); |
7164 |
12 May 23 |
nicklas |
1303 |
if (flag) |
7164 |
12 May 23 |
nicklas |
1304 |
{ |
7164 |
12 May 23 |
nicklas |
1305 |
if (ls.flaggedExternalSpecimen.add(specimen.getItem())) |
7164 |
12 May 23 |
nicklas |
1306 |
{ |
7164 |
12 May 23 |
nicklas |
1307 |
stats.flagged++; |
7164 |
12 May 23 |
nicklas |
1308 |
} |
7164 |
12 May 23 |
nicklas |
1309 |
|
7164 |
12 May 23 |
nicklas |
1310 |
} |
7142 |
04 May 23 |
nicklas |
1311 |
} |
7166 |
12 May 23 |
nicklas |
1312 |
|
7166 |
12 May 23 |
nicklas |
1313 |
/** |
7166 |
12 May 23 |
nicklas |
Add all warnings to the ImportWarnings annotation. |
7166 |
12 May 23 |
nicklas |
1315 |
*/ |
7166 |
12 May 23 |
nicklas |
1316 |
@SuppressWarnings("unchecked") |
7166 |
12 May 23 |
nicklas |
1317 |
void appendWarnings(DbControl dc) |
7166 |
12 May 23 |
nicklas |
1318 |
{ |
7166 |
12 May 23 |
nicklas |
1319 |
if (warnings.size() > 0) |
7166 |
12 May 23 |
nicklas |
1320 |
{ |
7166 |
12 May 23 |
nicklas |
1321 |
List<String> existingWarnings = (List<String>)Annotationtype.IMPORT_WARNINGS.getAnnotationValues(dc, specimen.getItem()); |
7166 |
12 May 23 |
nicklas |
1322 |
List<String> all = new ArrayList<>(existingWarnings); |
7166 |
12 May 23 |
nicklas |
1323 |
all.addAll(warnings); |
7166 |
12 May 23 |
nicklas |
1324 |
Annotationtype.IMPORT_WARNINGS.setAnnotationValues(dc, mappedTo, all); |
7166 |
12 May 23 |
nicklas |
1325 |
} |
7166 |
12 May 23 |
nicklas |
1326 |
} |
7139 |
27 Apr 23 |
nicklas |
1327 |
} |
7139 |
27 Apr 23 |
nicklas |
1328 |
|
7142 |
04 May 23 |
nicklas |
1329 |
/** |
7142 |
04 May 23 |
nicklas |
Hold the 5 different ItemList items that are |
7142 |
04 May 23 |
nicklas |
related to a single transport box. |
7142 |
04 May 23 |
nicklas |
1332 |
*/ |
7142 |
04 May 23 |
nicklas |
1333 |
public static class ListSet |
7142 |
04 May 23 |
nicklas |
1334 |
{ |
7142 |
04 May 23 |
nicklas |
1335 |
final String boxName; |
7185 |
22 May 23 |
nicklas |
1336 |
final File importedFrom; |
7191 |
23 May 23 |
nicklas |
1337 |
final JSONObject jsonInfo; |
7142 |
04 May 23 |
nicklas |
1338 |
|
7168 |
12 May 23 |
nicklas |
1339 |
final List<String> transportMessages; |
7164 |
12 May 23 |
nicklas |
1340 |
final ItemList flaggedExternalSpecimen; |
7142 |
04 May 23 |
nicklas |
1341 |
final ItemList specimenList; |
7142 |
04 May 23 |
nicklas |
1342 |
final ItemList lysateList; |
7142 |
04 May 23 |
nicklas |
1343 |
final ItemList rnaList; |
7142 |
04 May 23 |
nicklas |
1344 |
final ItemList dnaList; |
7142 |
04 May 23 |
nicklas |
1345 |
final ItemList flowThroughList; |
7142 |
04 May 23 |
nicklas |
1346 |
|
7191 |
23 May 23 |
nicklas |
1347 |
ListSet(DbControl dc, String boxName, File importedFrom, JSONObject jsonInfo) |
7142 |
04 May 23 |
nicklas |
1348 |
{ |
7142 |
04 May 23 |
nicklas |
1349 |
this.boxName = boxName; |
7185 |
22 May 23 |
nicklas |
1350 |
this.importedFrom = importedFrom; |
7191 |
23 May 23 |
nicklas |
1351 |
this.jsonInfo = jsonInfo; |
7168 |
12 May 23 |
nicklas |
1352 |
this.transportMessages = new ArrayList<>(); |
7164 |
12 May 23 |
nicklas |
1353 |
flaggedExternalSpecimen = BiomaterialList.FLAGGED_EXERNAL_SPECIMEN.get(dc); |
7142 |
04 May 23 |
nicklas |
1354 |
specimenList = create(dc, Subtype.SPECIMEN); |
7142 |
04 May 23 |
nicklas |
1355 |
lysateList = create(dc, Subtype.LYSATE); |
7142 |
04 May 23 |
nicklas |
1356 |
rnaList = create(dc, Subtype.RNA); |
7142 |
04 May 23 |
nicklas |
1357 |
dnaList = create(dc, Subtype.DNA); |
7142 |
04 May 23 |
nicklas |
1358 |
flowThroughList = create(dc, Subtype.FLOW_THROUGH); |
7142 |
04 May 23 |
nicklas |
1359 |
} |
7142 |
04 May 23 |
nicklas |
1360 |
|
7142 |
04 May 23 |
nicklas |
1361 |
private ItemList create(DbControl dc, Subtype subtype) |
7142 |
04 May 23 |
nicklas |
1362 |
{ |
7142 |
04 May 23 |
nicklas |
1363 |
ItemList list = ItemList.getNew(dc, subtype.getMainType()); |
7142 |
04 May 23 |
nicklas |
1364 |
list.setItemSubtype(subtype.get(dc)); |
7142 |
04 May 23 |
nicklas |
1365 |
list.setExternalId(WORK_LIST_ID); |
7142 |
04 May 23 |
nicklas |
1366 |
list.setName("Transport box: "+boxName + " ("+subtype.getName()+")"); |
7191 |
23 May 23 |
nicklas |
1367 |
list.setDescription((String)jsonInfo.get("comment")); |
7174 |
17 May 23 |
nicklas |
1368 |
Annotationtype.EXTERNAL_REF.setAnnotationValue(dc, list, boxName); |
7142 |
04 May 23 |
nicklas |
1369 |
dc.saveItem(list); |
7185 |
22 May 23 |
nicklas |
1370 |
|
7185 |
22 May 23 |
nicklas |
1371 |
AnyToAny link = AnyToAny.getNewOrExisting(dc, list, "Imported from", importedFrom, true); |
7185 |
22 May 23 |
nicklas |
1372 |
dc.saveItem(link); |
7185 |
22 May 23 |
nicklas |
1373 |
|
7142 |
04 May 23 |
nicklas |
1374 |
return list; |
7142 |
04 May 23 |
nicklas |
1375 |
} |
7168 |
12 May 23 |
nicklas |
1376 |
|
7168 |
12 May 23 |
nicklas |
1377 |
public void addTransportMessages(DbControl dc) |
7168 |
12 May 23 |
nicklas |
1378 |
{ |
7168 |
12 May 23 |
nicklas |
1379 |
if (transportMessages.size() > 0) |
7168 |
12 May 23 |
nicklas |
1380 |
{ |
7168 |
12 May 23 |
nicklas |
1381 |
Annotationtype.TRANSPORT_MESSAGES.setAnnotationValues(dc, specimenList, transportMessages); |
7168 |
12 May 23 |
nicklas |
1382 |
Annotationtype.TRANSPORT_MESSAGES.setAnnotationValues(dc, lysateList, transportMessages); |
7168 |
12 May 23 |
nicklas |
1383 |
Annotationtype.TRANSPORT_MESSAGES.setAnnotationValues(dc, rnaList, transportMessages); |
7168 |
12 May 23 |
nicklas |
1384 |
Annotationtype.TRANSPORT_MESSAGES.setAnnotationValues(dc, dnaList, transportMessages); |
7168 |
12 May 23 |
nicklas |
1385 |
Annotationtype.TRANSPORT_MESSAGES.setAnnotationValues(dc, flowThroughList, transportMessages); |
7168 |
12 May 23 |
nicklas |
1386 |
} |
7168 |
12 May 23 |
nicklas |
1387 |
} |
7142 |
04 May 23 |
nicklas |
1388 |
} |
7142 |
04 May 23 |
nicklas |
1389 |
|
7162 |
12 May 23 |
nicklas |
1390 |
|
7162 |
12 May 23 |
nicklas |
1391 |
public static class Stats |
7162 |
12 May 23 |
nicklas |
1392 |
{ |
7162 |
12 May 23 |
nicklas |
1393 |
int mappedExistingSpecimen = 0; |
7162 |
12 May 23 |
nicklas |
1394 |
int convertedNoSpecimen = 0; |
7162 |
12 May 23 |
nicklas |
1395 |
int newSpecimen = 0; |
7162 |
12 May 23 |
nicklas |
1396 |
int skipped = 0; |
7162 |
12 May 23 |
nicklas |
1397 |
int placeInBoxes = 0; |
7164 |
12 May 23 |
nicklas |
1398 |
int flagged = 0; |
7162 |
12 May 23 |
nicklas |
1399 |
} |
7139 |
27 Apr 23 |
nicklas |
1400 |
} |