3488 |
16 Sep 15 |
nicklas |
1 |
package net.sf.basedb.reggie.servlet; |
3488 |
16 Sep 15 |
nicklas |
2 |
|
3488 |
16 Sep 15 |
nicklas |
3 |
import java.io.IOException; |
4512 |
31 May 17 |
nicklas |
4 |
import java.io.InputStream; |
4806 |
14 May 18 |
nicklas |
5 |
import java.io.OutputStream; |
4806 |
14 May 18 |
nicklas |
6 |
import java.io.OutputStreamWriter; |
3916 |
02 May 16 |
nicklas |
7 |
import java.util.Collections; |
3488 |
16 Sep 15 |
nicklas |
8 |
import java.util.Date; |
4512 |
31 May 17 |
nicklas |
9 |
import java.util.HashMap; |
4512 |
31 May 17 |
nicklas |
10 |
import java.util.HashSet; |
4806 |
14 May 18 |
nicklas |
11 |
import java.util.LinkedHashSet; |
4512 |
31 May 17 |
nicklas |
12 |
import java.util.List; |
4512 |
31 May 17 |
nicklas |
13 |
import java.util.Map; |
4512 |
31 May 17 |
nicklas |
14 |
import java.util.Set; |
4512 |
31 May 17 |
nicklas |
15 |
import java.util.regex.Matcher; |
4512 |
31 May 17 |
nicklas |
16 |
import java.util.regex.Pattern; |
3488 |
16 Sep 15 |
nicklas |
17 |
|
3488 |
16 Sep 15 |
nicklas |
18 |
import javax.servlet.ServletException; |
3488 |
16 Sep 15 |
nicklas |
19 |
import javax.servlet.http.HttpServlet; |
3488 |
16 Sep 15 |
nicklas |
20 |
import javax.servlet.http.HttpServletRequest; |
3488 |
16 Sep 15 |
nicklas |
21 |
import javax.servlet.http.HttpServletResponse; |
3488 |
16 Sep 15 |
nicklas |
22 |
|
3488 |
16 Sep 15 |
nicklas |
23 |
import org.json.simple.JSONArray; |
3488 |
16 Sep 15 |
nicklas |
24 |
import org.json.simple.JSONObject; |
3488 |
16 Sep 15 |
nicklas |
25 |
|
4512 |
31 May 17 |
nicklas |
26 |
|
3916 |
02 May 16 |
nicklas |
27 |
import net.sf.basedb.core.AnnotationBatcher; |
3916 |
02 May 16 |
nicklas |
28 |
import net.sf.basedb.core.AnnotationBatcher.Change; |
4512 |
31 May 17 |
nicklas |
29 |
import net.sf.basedb.core.query.Annotations; |
4512 |
31 May 17 |
nicklas |
30 |
import net.sf.basedb.core.query.Expressions; |
4512 |
31 May 17 |
nicklas |
31 |
import net.sf.basedb.core.query.Hql; |
4512 |
31 May 17 |
nicklas |
32 |
import net.sf.basedb.core.query.Restrictions; |
3916 |
02 May 16 |
nicklas |
33 |
import net.sf.basedb.core.AnnotationType; |
4512 |
31 May 17 |
nicklas |
34 |
import net.sf.basedb.core.BaseException; |
3488 |
16 Sep 15 |
nicklas |
35 |
import net.sf.basedb.core.DbControl; |
3488 |
16 Sep 15 |
nicklas |
36 |
import net.sf.basedb.core.File; |
3916 |
02 May 16 |
nicklas |
37 |
import net.sf.basedb.core.Item; |
4512 |
31 May 17 |
nicklas |
38 |
import net.sf.basedb.core.ItemQuery; |
3488 |
16 Sep 15 |
nicklas |
39 |
import net.sf.basedb.core.Path; |
3488 |
16 Sep 15 |
nicklas |
40 |
import net.sf.basedb.core.Sample; |
3488 |
16 Sep 15 |
nicklas |
41 |
import net.sf.basedb.core.SessionControl; |
3916 |
02 May 16 |
nicklas |
42 |
import net.sf.basedb.core.SimpleProgressReporter; |
4512 |
31 May 17 |
nicklas |
43 |
import net.sf.basedb.core.Type; |
4512 |
31 May 17 |
nicklas |
44 |
import net.sf.basedb.core.snapshot.SnapshotManager; |
3488 |
16 Sep 15 |
nicklas |
45 |
import net.sf.basedb.reggie.JsonUtil; |
3975 |
26 May 16 |
nicklas |
46 |
import net.sf.basedb.reggie.Reggie; |
5634 |
01 Oct 19 |
nicklas |
47 |
import net.sf.basedb.reggie.activity.ActivityDef; |
3488 |
16 Sep 15 |
nicklas |
48 |
import net.sf.basedb.reggie.counter.CounterService; |
3488 |
16 Sep 15 |
nicklas |
49 |
import net.sf.basedb.reggie.dao.Annotationtype; |
3488 |
16 Sep 15 |
nicklas |
50 |
import net.sf.basedb.reggie.dao.Case; |
3488 |
16 Sep 15 |
nicklas |
51 |
import net.sf.basedb.reggie.dao.ReggieRole; |
4512 |
31 May 17 |
nicklas |
52 |
import net.sf.basedb.reggie.dao.Subtype; |
5631 |
27 Sep 19 |
nicklas |
53 |
import net.sf.basedb.reggie.plugins.ExternalRNAImporter; |
5631 |
27 Sep 19 |
nicklas |
54 |
import net.sf.basedb.reggie.plugins.ExternalRNAImporter.AliquotPlate; |
3488 |
16 Sep 15 |
nicklas |
55 |
import net.sf.basedb.util.FileUtil; |
5631 |
27 Sep 19 |
nicklas |
56 |
import net.sf.basedb.util.Values; |
4806 |
14 May 18 |
nicklas |
57 |
import net.sf.basedb.util.encode.ToSpaceEncoderDecoder; |
3488 |
16 Sep 15 |
nicklas |
58 |
import net.sf.basedb.util.error.ThrowableUtil; |
4806 |
14 May 18 |
nicklas |
59 |
import net.sf.basedb.util.export.TableWriter; |
4512 |
31 May 17 |
nicklas |
60 |
import net.sf.basedb.util.parser.FlatFileParser; |
4806 |
14 May 18 |
nicklas |
61 |
import net.sf.basedb.util.parser.FlatFileParser.LineType; |
4806 |
14 May 18 |
nicklas |
62 |
import net.sf.basedb.util.parser.Mapper; |
3488 |
16 Sep 15 |
nicklas |
63 |
|
3488 |
16 Sep 15 |
nicklas |
64 |
|
3488 |
16 Sep 15 |
nicklas |
65 |
public class ImportServlet |
3488 |
16 Sep 15 |
nicklas |
66 |
extends HttpServlet |
3488 |
16 Sep 15 |
nicklas |
67 |
{ |
3488 |
16 Sep 15 |
nicklas |
68 |
|
3488 |
16 Sep 15 |
nicklas |
69 |
private static final long serialVersionUID = 2550233926528990677L; |
3488 |
16 Sep 15 |
nicklas |
70 |
|
3488 |
16 Sep 15 |
nicklas |
71 |
public ImportServlet() |
3488 |
16 Sep 15 |
nicklas |
72 |
{} |
3488 |
16 Sep 15 |
nicklas |
73 |
|
3488 |
16 Sep 15 |
nicklas |
74 |
@Override |
3488 |
16 Sep 15 |
nicklas |
75 |
protected void doPost(HttpServletRequest req, HttpServletResponse resp) |
3488 |
16 Sep 15 |
nicklas |
76 |
throws ServletException, IOException |
3488 |
16 Sep 15 |
nicklas |
77 |
{ |
3488 |
16 Sep 15 |
nicklas |
78 |
String cmd = req.getParameter("cmd"); |
3488 |
16 Sep 15 |
nicklas |
79 |
JsonUtil.setJsonResponseHeaders(resp); |
3488 |
16 Sep 15 |
nicklas |
80 |
|
3488 |
16 Sep 15 |
nicklas |
81 |
JSONObject json = new JSONObject(); |
3488 |
16 Sep 15 |
nicklas |
82 |
json.put("status", "ok"); |
3488 |
16 Sep 15 |
nicklas |
83 |
|
3488 |
16 Sep 15 |
nicklas |
84 |
JSONArray jsonMessages = new JSONArray(); |
3975 |
26 May 16 |
nicklas |
85 |
final SessionControl sc = Reggie.getSessionControl(req); |
3916 |
02 May 16 |
nicklas |
86 |
String progressName = req.getParameter("progressbar"); |
3916 |
02 May 16 |
nicklas |
87 |
SimpleProgressReporter progress = null; |
3916 |
02 May 16 |
nicklas |
88 |
if (progressName != null) |
3916 |
02 May 16 |
nicklas |
89 |
{ |
3916 |
02 May 16 |
nicklas |
90 |
progress = new SimpleProgressReporter(null); |
3916 |
02 May 16 |
nicklas |
91 |
sc.setSessionSetting(progressName, progress); |
3916 |
02 May 16 |
nicklas |
92 |
} |
3916 |
02 May 16 |
nicklas |
93 |
|
3488 |
16 Sep 15 |
nicklas |
94 |
DbControl dc = null; |
3488 |
16 Sep 15 |
nicklas |
95 |
try |
3488 |
16 Sep 15 |
nicklas |
96 |
{ |
3488 |
16 Sep 15 |
nicklas |
97 |
if ("ImportFrozenTissueDate".equals(cmd)) |
3488 |
16 Sep 15 |
nicklas |
98 |
{ |
6336 |
16 Jun 21 |
nicklas |
99 |
dc = sc.newDbControl(":Import frozen tissue date"); |
3488 |
16 Sep 15 |
nicklas |
100 |
|
3488 |
16 Sep 15 |
nicklas |
101 |
ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR); |
3488 |
16 Sep 15 |
nicklas |
102 |
|
3488 |
16 Sep 15 |
nicklas |
103 |
String path = req.getParameter("file"); |
3488 |
16 Sep 15 |
nicklas |
104 |
File f = File.getByPath(dc, new Path(path, Path.Type.FILE), false); |
3488 |
16 Sep 15 |
nicklas |
105 |
|
3488 |
16 Sep 15 |
nicklas |
106 |
String charset = f.getCharacterSet(); |
3488 |
16 Sep 15 |
nicklas |
107 |
if (charset == null) charset = "UTF-8"; |
3488 |
16 Sep 15 |
nicklas |
108 |
|
4512 |
31 May 17 |
nicklas |
109 |
InputStream in = null; |
3488 |
16 Sep 15 |
nicklas |
110 |
Date frozenTissueDate = new Date(); |
3488 |
16 Sep 15 |
nicklas |
111 |
int numUpdated = 0; |
3488 |
16 Sep 15 |
nicklas |
112 |
int numCreated = 0; |
3916 |
02 May 16 |
nicklas |
113 |
int noChange = 0; |
4512 |
31 May 17 |
nicklas |
114 |
|
4512 |
31 May 17 |
nicklas |
115 |
SnapshotManager manager = new SnapshotManager(); |
4512 |
31 May 17 |
nicklas |
116 |
FlatFileParser ffp = new FlatFileParser(); |
4512 |
31 May 17 |
nicklas |
117 |
ffp.setDataSplitterRegexp(Pattern.compile("\\t")); |
4815 |
17 May 18 |
nicklas |
118 |
ffp.setDataHeaderRegexp(Pattern.compile(".*ProvID.*")); |
5112 |
20 Nov 18 |
nicklas |
119 |
ffp.setIgnoreRegexp(Pattern.compile("^\\s*$")); // Ignore blank lines |
4512 |
31 May 17 |
nicklas |
120 |
|
4512 |
31 May 17 |
nicklas |
// Since we are using an AnnotationBatcher to update the cases |
4512 |
31 May 17 |
nicklas |
// we can't load the Consent annotation the normal way. |
4512 |
31 May 17 |
nicklas |
// Instead, we use a query to check load all items that has a consent that is not "Yes" |
4512 |
31 May 17 |
nicklas |
124 |
ItemQuery<Sample> verifyConsent = Sample.getQuery(); |
4512 |
31 May 17 |
nicklas |
125 |
verifyConsent.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
4512 |
31 May 17 |
nicklas |
126 |
verifyConsent.join(Annotations.innerJoin(Annotationtype.CONSENT.get(dc), "c")); |
4512 |
31 May 17 |
nicklas |
127 |
verifyConsent.restrict( |
4512 |
31 May 17 |
nicklas |
128 |
Restrictions.neq(Hql.alias("c"), Expressions.string("Yes")) |
4512 |
31 May 17 |
nicklas |
129 |
); |
4512 |
31 May 17 |
nicklas |
130 |
Set<Integer> noConsent = new HashSet<>(verifyConsent.idList(dc)); |
3488 |
16 Sep 15 |
nicklas |
131 |
|
4512 |
31 May 17 |
nicklas |
132 |
ItemQuery<Sample> findByPAD = Sample.getQuery(); |
4512 |
31 May 17 |
nicklas |
133 |
findByPAD.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT); |
4512 |
31 May 17 |
nicklas |
134 |
Subtype.CASE.addFilter(dc, findByPAD); |
4512 |
31 May 17 |
nicklas |
135 |
findByPAD.join(Hql.innerJoin("childCreationEvents", "cce")); |
4512 |
31 May 17 |
nicklas |
136 |
findByPAD.join(Hql.innerJoin("cce", "event", "evt")); |
4512 |
31 May 17 |
nicklas |
137 |
findByPAD.join(Hql.innerJoin("evt", "bioMaterial", "sp")); // 'sp' should now reference a specimen tube/nospecimen |
6510 |
03 Dec 21 |
nicklas |
// Restrict to 'Specimen' or 'NoSpecimen' child items |
6510 |
03 Dec 21 |
nicklas |
139 |
findByPAD.restrict(Restrictions.or(Subtype.SPECIMEN.restriction(dc, "sp"), Subtype.NO_SPECIMEN.restriction(dc, "sp"))); |
4512 |
31 May 17 |
nicklas |
140 |
|
4512 |
31 May 17 |
nicklas |
141 |
findByPAD.join(Annotations.leftJoin("sp", Annotationtype.PAD.get(dc), "pad")); |
4805 |
14 May 18 |
nicklas |
142 |
findByPAD.restrict(Restrictions.or( |
4805 |
14 May 18 |
nicklas |
143 |
Restrictions.eq(Hql.alias("pad"), Expressions.parameter("pad")), |
4805 |
14 May 18 |
nicklas |
144 |
Restrictions.eq(Hql.alias("pad"), Expressions.parameter("pad2")) // pad2 = pad with spaces removed |
4805 |
14 May 18 |
nicklas |
145 |
)); |
4512 |
31 May 17 |
nicklas |
146 |
|
4806 |
14 May 18 |
nicklas |
147 |
Set<FrozenTissueWarning> oldWarnings = new LinkedHashSet<>(); |
4806 |
14 May 18 |
nicklas |
148 |
Set<FrozenTissueWarning> allWarnings = new LinkedHashSet<>(); |
4806 |
14 May 18 |
nicklas |
149 |
File oldWarningsFile = importOldWarnings(dc, "/home/SCANB/FrozenTissueFiles/last-import-warnings.csv", oldWarnings); |
3488 |
16 Sep 15 |
nicklas |
150 |
try |
3488 |
16 Sep 15 |
nicklas |
151 |
{ |
3916 |
02 May 16 |
nicklas |
152 |
long fileSize = f.getSize(); |
4512 |
31 May 17 |
nicklas |
153 |
in = f.getDownloadStream(0); |
4512 |
31 May 17 |
nicklas |
154 |
ffp.setInputStream(in, charset); |
3916 |
02 May 16 |
nicklas |
155 |
|
4512 |
31 May 17 |
nicklas |
156 |
FlatFileParser.LineType lineType = ffp.parseHeaders(); |
4815 |
17 May 18 |
nicklas |
157 |
if (lineType != FlatFileParser.LineType.DATA_HEADER || ffp.getColumnHeaderIndex("ProvID") == null) |
4512 |
31 May 17 |
nicklas |
158 |
{ |
4512 |
31 May 17 |
nicklas |
159 |
throw new BaseException("Could not find header line containing 'ProvID' column"); |
4512 |
31 May 17 |
nicklas |
160 |
} |
4512 |
31 May 17 |
nicklas |
161 |
|
4512 |
31 May 17 |
nicklas |
162 |
int idIndex = ffp.getColumnHeaderIndex("ProvID"); |
4512 |
31 May 17 |
nicklas |
163 |
Integer commentIndex = ffp.getColumnHeaderIndex("Kommentar"); // Optional column that may contain useful information for some samples |
4512 |
31 May 17 |
nicklas |
164 |
|
3916 |
02 May 16 |
nicklas |
165 |
AnnotationType frozenDate = Annotationtype.FROZEN_TISSUE_DATE.get(dc); |
3916 |
02 May 16 |
nicklas |
166 |
AnnotationBatcher batcher = new AnnotationBatcher(dc, Item.SAMPLE); |
3916 |
02 May 16 |
nicklas |
167 |
batcher.addAnnotationTypes(Collections.singleton(frozenDate)); |
3916 |
02 May 16 |
nicklas |
168 |
|
4512 |
31 May 17 |
nicklas |
// Pattern for matching various SCAN-B ID formats: |
4512 |
31 May 17 |
nicklas |
// 1234567, 12-34567, 1234567C, 12-34567D |
4512 |
31 May 17 |
nicklas |
171 |
Pattern cleanup = Pattern.compile("(\\d{2})-?(\\d{5})(C|D)?"); |
4512 |
31 May 17 |
nicklas |
172 |
|
4512 |
31 May 17 |
nicklas |
// Keep track of found items for duplicate reporting |
4512 |
31 May 17 |
nicklas |
174 |
Map<String, Integer> usedIds = new HashMap<>(); |
4512 |
31 May 17 |
nicklas |
175 |
|
4512 |
31 May 17 |
nicklas |
176 |
while (ffp.hasMoreData()) |
3488 |
16 Sep 15 |
nicklas |
177 |
{ |
4512 |
31 May 17 |
nicklas |
178 |
FlatFileParser.Data data = ffp.nextData(); |
5364 |
16 Apr 19 |
nicklas |
179 |
String provId = data.getString(idIndex); |
5364 |
16 Apr 19 |
nicklas |
180 |
String comment = commentIndex == null ? null : data.getString(commentIndex); |
4512 |
31 May 17 |
nicklas |
181 |
|
4512 |
31 May 17 |
nicklas |
182 |
int lineNo = ffp.getParsedLines(); |
4512 |
31 May 17 |
nicklas |
183 |
|
4512 |
31 May 17 |
nicklas |
184 |
if (lineNo % 10 == 0 && progress != null) |
3916 |
02 May 16 |
nicklas |
185 |
{ |
4512 |
31 May 17 |
nicklas |
186 |
progress.display((int)((95* ffp.getParsedBytes()) / fileSize), "Processing " + f.getName() + " (" + lineNo + " lines)..."); |
3916 |
02 May 16 |
nicklas |
187 |
} |
3488 |
16 Sep 15 |
nicklas |
188 |
|
4512 |
31 May 17 |
nicklas |
// Remove '-', 'C' and 'D' |
4512 |
31 May 17 |
nicklas |
190 |
Matcher m = cleanup.matcher(provId); |
4512 |
31 May 17 |
nicklas |
191 |
Case theCase = null; |
4512 |
31 May 17 |
nicklas |
192 |
if (m.matches()) |
3488 |
16 Sep 15 |
nicklas |
193 |
{ |
4512 |
31 May 17 |
nicklas |
194 |
String scanbId = m.group(1) + m.group(2); |
4512 |
31 May 17 |
nicklas |
195 |
theCase = Case.findByName(dc, scanbId); |
3488 |
16 Sep 15 |
nicklas |
196 |
} |
3488 |
16 Sep 15 |
nicklas |
197 |
else |
3488 |
16 Sep 15 |
nicklas |
198 |
{ |
4512 |
31 May 17 |
nicklas |
199 |
findByPAD.setParameter("pad", provId, Type.STRING); |
4805 |
14 May 18 |
nicklas |
200 |
findByPAD.setParameter("pad2", provId.replace(" ", ""), Type.STRING); |
4512 |
31 May 17 |
nicklas |
201 |
List<Sample> result = findByPAD.list(dc); |
4512 |
31 May 17 |
nicklas |
202 |
if (result.size() > 1) |
3488 |
16 Sep 15 |
nicklas |
203 |
{ |
4806 |
14 May 18 |
nicklas |
204 |
allWarnings.add(new FrozenTissueWarning(lineNo, provId, null, "Found " + result.size() + " cases", comment)); |
4512 |
31 May 17 |
nicklas |
205 |
continue; |
3916 |
02 May 16 |
nicklas |
206 |
} |
4512 |
31 May 17 |
nicklas |
207 |
else if (result.size() == 1) |
3916 |
02 May 16 |
nicklas |
208 |
{ |
4512 |
31 May 17 |
nicklas |
209 |
theCase = Case.get(result.get(0)); |
3488 |
16 Sep 15 |
nicklas |
210 |
} |
3488 |
16 Sep 15 |
nicklas |
211 |
} |
3488 |
16 Sep 15 |
nicklas |
212 |
|
4512 |
31 May 17 |
nicklas |
213 |
if (theCase == null) |
4512 |
31 May 17 |
nicklas |
214 |
{ |
4806 |
14 May 18 |
nicklas |
215 |
allWarnings.add(new FrozenTissueWarning(lineNo, provId, null, "Not found", comment)); |
4512 |
31 May 17 |
nicklas |
216 |
continue; |
4512 |
31 May 17 |
nicklas |
217 |
} |
4512 |
31 May 17 |
nicklas |
218 |
|
4512 |
31 May 17 |
nicklas |
219 |
String caseName = theCase.getName(); |
4512 |
31 May 17 |
nicklas |
220 |
Sample s = theCase.getItem(); |
4512 |
31 May 17 |
nicklas |
221 |
if (noConsent.contains(s.getId())) |
4512 |
31 May 17 |
nicklas |
222 |
{ |
4806 |
14 May 18 |
nicklas |
223 |
allWarnings.add(new FrozenTissueWarning(lineNo, provId, caseName, "No consent", comment)); |
4512 |
31 May 17 |
nicklas |
224 |
continue; |
4512 |
31 May 17 |
nicklas |
225 |
} |
4804 |
14 May 18 |
nicklas |
226 |
|
4804 |
14 May 18 |
nicklas |
// Do not process the same item twice (will cause exception in AnnotationBatcher) |
4804 |
14 May 18 |
nicklas |
228 |
if (usedIds.containsKey(caseName)) continue; |
4804 |
14 May 18 |
nicklas |
229 |
usedIds.put(caseName, lineNo); |
4512 |
31 May 17 |
nicklas |
230 |
|
4512 |
31 May 17 |
nicklas |
231 |
batcher.setCurrentItem(s); |
4512 |
31 May 17 |
nicklas |
232 |
AnnotationBatcher.Change change = batcher.setValue(frozenDate, frozenTissueDate, null, false); |
4512 |
31 May 17 |
nicklas |
233 |
if (change == Change.ADDED) |
4512 |
31 May 17 |
nicklas |
234 |
{ |
4512 |
31 May 17 |
nicklas |
235 |
numCreated++; |
4512 |
31 May 17 |
nicklas |
236 |
} |
4512 |
31 May 17 |
nicklas |
237 |
else if (change == Change.UPDATED) |
4512 |
31 May 17 |
nicklas |
238 |
{ |
4512 |
31 May 17 |
nicklas |
239 |
numUpdated++; |
4512 |
31 May 17 |
nicklas |
240 |
} |
4512 |
31 May 17 |
nicklas |
241 |
else |
4512 |
31 May 17 |
nicklas |
242 |
{ |
4512 |
31 May 17 |
nicklas |
243 |
noChange++; |
4512 |
31 May 17 |
nicklas |
244 |
} |
3488 |
16 Sep 15 |
nicklas |
245 |
} |
3488 |
16 Sep 15 |
nicklas |
246 |
} |
3488 |
16 Sep 15 |
nicklas |
247 |
finally |
3488 |
16 Sep 15 |
nicklas |
248 |
{ |
3488 |
16 Sep 15 |
nicklas |
249 |
FileUtil.close(in); |
3488 |
16 Sep 15 |
nicklas |
250 |
} |
4512 |
31 May 17 |
nicklas |
251 |
|
3488 |
16 Sep 15 |
nicklas |
252 |
jsonMessages.add("Created FrozenTissueDate annotation on " + numCreated + " cases"); |
3488 |
16 Sep 15 |
nicklas |
253 |
jsonMessages.add("Updated FrozenTissueDate annotation on " + numUpdated + " cases"); |
3916 |
02 May 16 |
nicklas |
254 |
jsonMessages.add("No change on " + noChange + " cases"); |
4806 |
14 May 18 |
nicklas |
255 |
if (allWarnings.size() > 0) |
3488 |
16 Sep 15 |
nicklas |
256 |
{ |
4806 |
14 May 18 |
nicklas |
257 |
JSONArray jsonWarnings = new JSONArray(); |
4806 |
14 May 18 |
nicklas |
258 |
OutputStream out = null; |
4806 |
14 May 18 |
nicklas |
259 |
int numNewWarnings = 0; |
4806 |
14 May 18 |
nicklas |
260 |
try |
4806 |
14 May 18 |
nicklas |
261 |
{ |
4806 |
14 May 18 |
nicklas |
262 |
out = oldWarningsFile.getUploadStream(false); |
4806 |
14 May 18 |
nicklas |
263 |
oldWarningsFile.setCharacterSet("UTF-8"); |
4806 |
14 May 18 |
nicklas |
264 |
oldWarningsFile.setMimeType("text/csv"); |
4806 |
14 May 18 |
nicklas |
265 |
TableWriter oldWarningsOut = new TableWriter(new OutputStreamWriter(out, "UTF-8")); |
4806 |
14 May 18 |
nicklas |
266 |
oldWarningsOut.setEncoder(new ToSpaceEncoderDecoder()); |
4806 |
14 May 18 |
nicklas |
267 |
oldWarningsOut.tablePrintData("Line", "ProvID", "CaseName", "Reason", "Comment"); |
4806 |
14 May 18 |
nicklas |
268 |
for (FrozenTissueWarning ftw : allWarnings) |
4806 |
14 May 18 |
nicklas |
269 |
{ |
4806 |
14 May 18 |
nicklas |
270 |
oldWarningsOut.tablePrintData(ftw.lineNo, ftw.provId, ftw.caseName, ftw.reason, ftw.comment); |
4806 |
14 May 18 |
nicklas |
271 |
JSONObject jsonFtw = ftw.asJSONObject(); |
4806 |
14 May 18 |
nicklas |
272 |
jsonWarnings.add(jsonFtw); |
4806 |
14 May 18 |
nicklas |
273 |
if (!oldWarnings.contains(ftw)) |
4806 |
14 May 18 |
nicklas |
274 |
{ |
4806 |
14 May 18 |
nicklas |
275 |
numNewWarnings++; |
4806 |
14 May 18 |
nicklas |
276 |
jsonFtw.put("isNew", 1); |
4806 |
14 May 18 |
nicklas |
277 |
} |
4806 |
14 May 18 |
nicklas |
278 |
} |
4806 |
14 May 18 |
nicklas |
279 |
oldWarningsOut.flush(); |
4806 |
14 May 18 |
nicklas |
280 |
oldWarningsOut.close(); |
4806 |
14 May 18 |
nicklas |
281 |
out.flush(); |
4806 |
14 May 18 |
nicklas |
282 |
} |
4806 |
14 May 18 |
nicklas |
283 |
finally |
4806 |
14 May 18 |
nicklas |
284 |
{ |
4806 |
14 May 18 |
nicklas |
285 |
FileUtil.close(out); |
4806 |
14 May 18 |
nicklas |
286 |
} |
4806 |
14 May 18 |
nicklas |
287 |
|
4806 |
14 May 18 |
nicklas |
288 |
int numOldWarnings = jsonWarnings.size() - numNewWarnings; |
4806 |
14 May 18 |
nicklas |
289 |
if (numNewWarnings == 0) |
4806 |
14 May 18 |
nicklas |
290 |
{ |
4806 |
14 May 18 |
nicklas |
291 |
jsonMessages.add("No new warnings, " + numOldWarnings + " old warnings"); |
4806 |
14 May 18 |
nicklas |
292 |
} |
4806 |
14 May 18 |
nicklas |
293 |
else |
4806 |
14 May 18 |
nicklas |
294 |
{ |
4806 |
14 May 18 |
nicklas |
295 |
jsonMessages.add("[Warning]" + numNewWarnings + " new warnings, " + numOldWarnings + " old warnings"); |
4806 |
14 May 18 |
nicklas |
296 |
} |
4512 |
31 May 17 |
nicklas |
297 |
json.put("warnings", jsonWarnings); |
3488 |
16 Sep 15 |
nicklas |
298 |
} |
3488 |
16 Sep 15 |
nicklas |
299 |
|
3916 |
02 May 16 |
nicklas |
300 |
if (progress != null) |
3916 |
02 May 16 |
nicklas |
301 |
{ |
4512 |
31 May 17 |
nicklas |
302 |
progress.display(100, "Done; " + ffp.getParsedLines() + " lines was processed."); |
3916 |
02 May 16 |
nicklas |
303 |
} |
3488 |
16 Sep 15 |
nicklas |
304 |
dc.commit(); |
3488 |
16 Sep 15 |
nicklas |
305 |
} |
5631 |
27 Sep 19 |
nicklas |
306 |
else if ("PreValidateRNAImportFile".equals(cmd) || "ImportRNAFromFile".equals(cmd)) |
5631 |
27 Sep 19 |
nicklas |
307 |
{ |
5631 |
27 Sep 19 |
nicklas |
308 |
String path = Values.getStringOrNull(req.getParameter("path")); |
5631 |
27 Sep 19 |
nicklas |
309 |
String sheet = Values.getStringOrNull(req.getParameter("sheet")); |
5631 |
27 Sep 19 |
nicklas |
310 |
String prefix = Values.getStringOrNull(req.getParameter("prefix")); |
5631 |
27 Sep 19 |
nicklas |
311 |
boolean validateOnly = "PreValidateRNAImportFile".equals(cmd); |
5631 |
27 Sep 19 |
nicklas |
312 |
|
6336 |
16 Jun 21 |
nicklas |
313 |
dc = sc.newDbControl(":Import external RNA"); |
5631 |
27 Sep 19 |
nicklas |
314 |
if (!validateOnly) |
5631 |
27 Sep 19 |
nicklas |
315 |
{ |
5631 |
27 Sep 19 |
nicklas |
316 |
ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.LIBRARY_PLATE_DESIGNER, ReggieRole.ADMINISTRATOR); |
5631 |
27 Sep 19 |
nicklas |
317 |
} |
5631 |
27 Sep 19 |
nicklas |
318 |
|
5631 |
27 Sep 19 |
nicklas |
319 |
File importFile = File.getByPath(dc, new Path(path, Path.Type.FILE), false); |
5631 |
27 Sep 19 |
nicklas |
320 |
sc.setUserClientSetting("reggie.rna.last-import-prefix", prefix); |
5631 |
27 Sep 19 |
nicklas |
321 |
|
5631 |
27 Sep 19 |
nicklas |
322 |
ExternalRNAImporter importer = new ExternalRNAImporter(); |
5631 |
27 Sep 19 |
nicklas |
323 |
importer.setNamePrefix(prefix); |
5631 |
27 Sep 19 |
nicklas |
324 |
InputStream in = null; |
5631 |
27 Sep 19 |
nicklas |
325 |
boolean fileIsValidForImport = false; |
5631 |
27 Sep 19 |
nicklas |
326 |
List<String> sheetNames = null; |
5631 |
27 Sep 19 |
nicklas |
327 |
JSONObject jsonImportFile = new JSONObject(); |
5631 |
27 Sep 19 |
nicklas |
328 |
try |
5631 |
27 Sep 19 |
nicklas |
329 |
{ |
5631 |
27 Sep 19 |
nicklas |
330 |
String fileName = importFile.getName(); |
5631 |
27 Sep 19 |
nicklas |
331 |
in = importFile.getDownloadStream(0); |
5631 |
27 Sep 19 |
nicklas |
332 |
fileIsValidForImport = importer.doImport(dc, in, sheet, validateOnly, fileName); |
5631 |
27 Sep 19 |
nicklas |
333 |
sheetNames = importer.getWorksheets(); |
5631 |
27 Sep 19 |
nicklas |
334 |
if (sheetNames != null) fileName += "/" + importer.getParsedWorksheet(); |
5631 |
27 Sep 19 |
nicklas |
335 |
jsonImportFile.put("filename", fileName); |
5631 |
27 Sep 19 |
nicklas |
336 |
} |
5631 |
27 Sep 19 |
nicklas |
337 |
finally |
5631 |
27 Sep 19 |
nicklas |
338 |
{ |
5631 |
27 Sep 19 |
nicklas |
339 |
FileUtil.close(in); |
5631 |
27 Sep 19 |
nicklas |
340 |
} |
5631 |
27 Sep 19 |
nicklas |
341 |
|
5631 |
27 Sep 19 |
nicklas |
342 |
jsonImportFile.put("valid", fileIsValidForImport); |
5631 |
27 Sep 19 |
nicklas |
343 |
jsonImportFile.put("warnings", importer.getWarningMessages().size()); |
5631 |
27 Sep 19 |
nicklas |
344 |
jsonImportFile.put("errors", importer.getErrorMessages().size()); |
5631 |
27 Sep 19 |
nicklas |
345 |
jsonImportFile.put("numAliquots", importer.getNumAliquots()); |
5631 |
27 Sep 19 |
nicklas |
346 |
if (sheetNames != null) jsonImportFile.put("sheetNames", sheetNames); |
5631 |
27 Sep 19 |
nicklas |
347 |
json.put("importFile", jsonImportFile); |
5631 |
27 Sep 19 |
nicklas |
348 |
|
5631 |
27 Sep 19 |
nicklas |
349 |
JSONArray jsonPlates = new JSONArray(); |
5631 |
27 Sep 19 |
nicklas |
350 |
for (AliquotPlate ap : importer.getPlates()) |
5631 |
27 Sep 19 |
nicklas |
351 |
{ |
5631 |
27 Sep 19 |
nicklas |
352 |
jsonPlates.add(ap.toJSONObject()); |
5631 |
27 Sep 19 |
nicklas |
353 |
if (!validateOnly && fileIsValidForImport) |
5631 |
27 Sep 19 |
nicklas |
354 |
{ |
5635 |
01 Oct 19 |
nicklas |
355 |
if (ap.getBioPlate().isInDatabase()) |
5635 |
01 Oct 19 |
nicklas |
356 |
{ |
5635 |
01 Oct 19 |
nicklas |
357 |
jsonMessages.add("Added " + ap.getNumAliquots() + " aliquots to storage box '" + ap.getName() + "'"); |
5635 |
01 Oct 19 |
nicklas |
358 |
} |
5635 |
01 Oct 19 |
nicklas |
359 |
else |
5635 |
01 Oct 19 |
nicklas |
360 |
{ |
5635 |
01 Oct 19 |
nicklas |
361 |
jsonMessages.add("Created storage box '" + ap.getName() + "' with " + ap.getNumAliquots() + " aliquots."); |
5635 |
01 Oct 19 |
nicklas |
362 |
} |
5631 |
27 Sep 19 |
nicklas |
363 |
} |
5631 |
27 Sep 19 |
nicklas |
364 |
} |
5631 |
27 Sep 19 |
nicklas |
365 |
jsonImportFile.put("plates", jsonPlates); |
5631 |
27 Sep 19 |
nicklas |
366 |
jsonImportFile.put("numPlates", jsonPlates.size()); |
5631 |
27 Sep 19 |
nicklas |
367 |
|
5631 |
27 Sep 19 |
nicklas |
368 |
if (fileIsValidForImport) |
5631 |
27 Sep 19 |
nicklas |
369 |
{ |
5631 |
27 Sep 19 |
nicklas |
370 |
if (importer.hasWarning()) |
5631 |
27 Sep 19 |
nicklas |
371 |
{ |
5631 |
27 Sep 19 |
nicklas |
372 |
jsonMessages.addAll(importer.getWarningMessages()); |
5631 |
27 Sep 19 |
nicklas |
373 |
} |
5631 |
27 Sep 19 |
nicklas |
374 |
} |
5631 |
27 Sep 19 |
nicklas |
375 |
else |
5631 |
27 Sep 19 |
nicklas |
376 |
{ |
5631 |
27 Sep 19 |
nicklas |
377 |
jsonMessages.addAll(importer.getErrorMessages()); |
5631 |
27 Sep 19 |
nicklas |
378 |
if (importer.hasWarning()) |
5631 |
27 Sep 19 |
nicklas |
379 |
{ |
5631 |
27 Sep 19 |
nicklas |
380 |
jsonMessages.addAll(importer.getWarningMessages()); |
5631 |
27 Sep 19 |
nicklas |
381 |
} |
5631 |
27 Sep 19 |
nicklas |
382 |
} |
5631 |
27 Sep 19 |
nicklas |
383 |
if (!validateOnly && fileIsValidForImport) |
5631 |
27 Sep 19 |
nicklas |
384 |
{ |
5634 |
01 Oct 19 |
nicklas |
385 |
ActivityDef.IMPORTED_RNA_ALIQUOTS.merge(dc, importer.getNumImportedAliquots()); |
5634 |
01 Oct 19 |
nicklas |
386 |
dc.commit(); |
5631 |
27 Sep 19 |
nicklas |
387 |
} |
5631 |
27 Sep 19 |
nicklas |
388 |
} |
5631 |
27 Sep 19 |
nicklas |
389 |
|
3488 |
16 Sep 15 |
nicklas |
390 |
json.put("messages", jsonMessages); |
3488 |
16 Sep 15 |
nicklas |
391 |
CounterService.getInstance().setForceCount(); |
3488 |
16 Sep 15 |
nicklas |
392 |
} |
3488 |
16 Sep 15 |
nicklas |
393 |
catch (Throwable t) |
3488 |
16 Sep 15 |
nicklas |
394 |
{ |
3488 |
16 Sep 15 |
nicklas |
395 |
t.printStackTrace(); |
3488 |
16 Sep 15 |
nicklas |
396 |
json.clear(); |
3488 |
16 Sep 15 |
nicklas |
397 |
json.put("status", "error"); |
3488 |
16 Sep 15 |
nicklas |
398 |
json.put("message", t.getMessage()); |
3488 |
16 Sep 15 |
nicklas |
399 |
json.put("stacktrace", ThrowableUtil.stackTraceToString(t)); |
3488 |
16 Sep 15 |
nicklas |
400 |
} |
3488 |
16 Sep 15 |
nicklas |
401 |
finally |
3488 |
16 Sep 15 |
nicklas |
402 |
{ |
3488 |
16 Sep 15 |
nicklas |
403 |
if (dc != null) dc.close(); |
3916 |
02 May 16 |
nicklas |
404 |
if (progressName != null && sc != null) |
3916 |
02 May 16 |
nicklas |
405 |
{ |
3916 |
02 May 16 |
nicklas |
406 |
sc.setSessionSetting(progressName, null); |
3916 |
02 May 16 |
nicklas |
407 |
} |
3488 |
16 Sep 15 |
nicklas |
408 |
json.writeJSONString(resp.getWriter()); |
3488 |
16 Sep 15 |
nicklas |
409 |
} |
3488 |
16 Sep 15 |
nicklas |
410 |
|
3488 |
16 Sep 15 |
nicklas |
411 |
} |
3488 |
16 Sep 15 |
nicklas |
412 |
|
4806 |
14 May 18 |
nicklas |
413 |
private File importOldWarnings(DbControl dc, String file, Set<FrozenTissueWarning> oldWarnings) |
4806 |
14 May 18 |
nicklas |
414 |
throws IOException |
4806 |
14 May 18 |
nicklas |
415 |
{ |
4806 |
14 May 18 |
nicklas |
416 |
Path p = new Path(file, Path.Type.FILE); |
4806 |
14 May 18 |
nicklas |
417 |
File f = File.getByPath(dc, p, true); |
4806 |
14 May 18 |
nicklas |
418 |
if (f.isInDatabase()) |
4806 |
14 May 18 |
nicklas |
419 |
{ |
4806 |
14 May 18 |
nicklas |
420 |
InputStream old = null; |
4806 |
14 May 18 |
nicklas |
421 |
try |
4806 |
14 May 18 |
nicklas |
422 |
{ |
4806 |
14 May 18 |
nicklas |
423 |
old = f.getDownloadStream(0); |
4806 |
14 May 18 |
nicklas |
424 |
FlatFileParser ffp = new FlatFileParser(); |
4806 |
14 May 18 |
nicklas |
425 |
ffp.setDataHeaderRegexp(Pattern.compile("Line\tProvID\t.*")); |
4806 |
14 May 18 |
nicklas |
426 |
ffp.setDataSplitterRegexp(Pattern.compile("\t")); |
4806 |
14 May 18 |
nicklas |
427 |
ffp.setInputStream(old, f.getCharacterSet()); |
4806 |
14 May 18 |
nicklas |
428 |
|
4806 |
14 May 18 |
nicklas |
429 |
LineType lineType = ffp.parseHeaders(); |
4806 |
14 May 18 |
nicklas |
430 |
if (lineType == LineType.DATA_HEADER) |
4806 |
14 May 18 |
nicklas |
431 |
{ |
4806 |
14 May 18 |
nicklas |
432 |
Mapper lineNo = ffp.getMapper("\\Line\\"); |
4806 |
14 May 18 |
nicklas |
433 |
Mapper provId = ffp.getMapper("\\ProvID\\"); |
4806 |
14 May 18 |
nicklas |
434 |
Mapper caseName = ffp.getMapper("\\CaseName\\"); |
4806 |
14 May 18 |
nicklas |
435 |
Mapper reason = ffp.getMapper("\\Reason\\"); |
4806 |
14 May 18 |
nicklas |
436 |
Mapper comment = ffp.getMapper("\\Comment\\"); |
4806 |
14 May 18 |
nicklas |
437 |
while (ffp.hasMoreData()) |
4806 |
14 May 18 |
nicklas |
438 |
{ |
4806 |
14 May 18 |
nicklas |
439 |
FlatFileParser.Data data = ffp.nextData(); |
5364 |
16 Apr 19 |
nicklas |
440 |
oldWarnings.add(new FrozenTissueWarning(lineNo.getInt(data), provId.getString(data), caseName.getString(data), reason.getString(data), comment.getString(data))); |
4806 |
14 May 18 |
nicklas |
441 |
} |
4806 |
14 May 18 |
nicklas |
442 |
} |
4806 |
14 May 18 |
nicklas |
443 |
} |
4806 |
14 May 18 |
nicklas |
444 |
finally |
4806 |
14 May 18 |
nicklas |
445 |
{ |
4806 |
14 May 18 |
nicklas |
446 |
FileUtil.close(old); |
4806 |
14 May 18 |
nicklas |
447 |
} |
4806 |
14 May 18 |
nicklas |
448 |
} |
4806 |
14 May 18 |
nicklas |
449 |
else |
4806 |
14 May 18 |
nicklas |
450 |
{ |
4806 |
14 May 18 |
nicklas |
451 |
f.setDescription( |
4806 |
14 May 18 |
nicklas |
452 |
"This file is used by the \"Frozen Tissue Date\" wizard to keep track of warnings from the last import. " + |
4806 |
14 May 18 |
nicklas |
453 |
"This information is used the next time the wizard is used to hide warnings that has already been reported."); |
4806 |
14 May 18 |
nicklas |
454 |
dc.saveItem(f); |
4806 |
14 May 18 |
nicklas |
455 |
} |
4806 |
14 May 18 |
nicklas |
456 |
return f; |
4806 |
14 May 18 |
nicklas |
457 |
} |
3488 |
16 Sep 15 |
nicklas |
458 |
|
4806 |
14 May 18 |
nicklas |
459 |
static class FrozenTissueWarning |
4512 |
31 May 17 |
nicklas |
460 |
{ |
4806 |
14 May 18 |
nicklas |
461 |
|
4806 |
14 May 18 |
nicklas |
462 |
private final int lineNo; |
4806 |
14 May 18 |
nicklas |
463 |
private final String provId; |
4806 |
14 May 18 |
nicklas |
464 |
private final String caseName; |
4806 |
14 May 18 |
nicklas |
465 |
private final String reason; |
4806 |
14 May 18 |
nicklas |
466 |
private final String comment; |
4806 |
14 May 18 |
nicklas |
467 |
|
4806 |
14 May 18 |
nicklas |
468 |
FrozenTissueWarning(int lineNo, String provId, String caseName, String reason, String comment) |
4806 |
14 May 18 |
nicklas |
469 |
{ |
4806 |
14 May 18 |
nicklas |
470 |
this.lineNo = lineNo; |
4806 |
14 May 18 |
nicklas |
471 |
this.provId = provId; |
4806 |
14 May 18 |
nicklas |
472 |
this.caseName = caseName; |
4806 |
14 May 18 |
nicklas |
473 |
this.reason = reason; |
4806 |
14 May 18 |
nicklas |
474 |
this.comment = comment; |
4806 |
14 May 18 |
nicklas |
475 |
} |
4806 |
14 May 18 |
nicklas |
476 |
|
4806 |
14 May 18 |
nicklas |
477 |
@Override |
4806 |
14 May 18 |
nicklas |
478 |
public boolean equals(Object obj) |
4806 |
14 May 18 |
nicklas |
479 |
{ |
4806 |
14 May 18 |
nicklas |
480 |
if (!(obj instanceof FrozenTissueWarning)) return false; |
4806 |
14 May 18 |
nicklas |
481 |
FrozenTissueWarning o = (FrozenTissueWarning)obj; |
4806 |
14 May 18 |
nicklas |
482 |
return o.lineNo == lineNo && o.provId.equals(provId); |
4806 |
14 May 18 |
nicklas |
483 |
} |
4806 |
14 May 18 |
nicklas |
484 |
|
4806 |
14 May 18 |
nicklas |
485 |
@Override |
4806 |
14 May 18 |
nicklas |
486 |
public int hashCode() |
4806 |
14 May 18 |
nicklas |
487 |
{ |
4806 |
14 May 18 |
nicklas |
488 |
return lineNo + provId.hashCode(); |
4806 |
14 May 18 |
nicklas |
489 |
} |
4806 |
14 May 18 |
nicklas |
490 |
|
4806 |
14 May 18 |
nicklas |
491 |
JSONObject asJSONObject() |
4806 |
14 May 18 |
nicklas |
492 |
{ |
4806 |
14 May 18 |
nicklas |
493 |
JSONObject json = new JSONObject(); |
4806 |
14 May 18 |
nicklas |
494 |
json.put("line", lineNo); |
4806 |
14 May 18 |
nicklas |
495 |
json.put("provId", provId); |
4806 |
14 May 18 |
nicklas |
496 |
json.put("caseName", caseName); |
4806 |
14 May 18 |
nicklas |
497 |
json.put("reason", reason); |
4806 |
14 May 18 |
nicklas |
498 |
json.put("comment", comment); |
4806 |
14 May 18 |
nicklas |
499 |
return json; |
4806 |
14 May 18 |
nicklas |
500 |
} |
4806 |
14 May 18 |
nicklas |
501 |
|
4512 |
31 May 17 |
nicklas |
502 |
} |
4512 |
31 May 17 |
nicklas |
503 |
|
3488 |
16 Sep 15 |
nicklas |
504 |
} |