1 package emissary.pickup;
2
3 import emissary.util.xml.SaferJDOMUtil;
4
5 import org.jdom2.Document;
6 import org.jdom2.Element;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 import java.io.DataInputStream;
11 import java.io.DataOutputStream;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.UUID;
17 import javax.annotation.Nullable;
18
19
20
21
22
23
24
25
26
27
28 public final class WorkBundle implements Comparable<WorkBundle> {
29
30 private static final Logger logger = LoggerFactory.getLogger(WorkBundle.class);
31
32 static final int MAX_UNITS = 1024;
33
34
35 String bundleId;
36
37
38 String outputRoot;
39
40
41 String eatPrefix;
42
43
44 @Nullable
45 String caseId = null;
46
47
48 int priority = Priority.DEFAULT;
49
50
51 boolean simpleMode = false;
52
53 List<WorkUnit> workUnitList = new ArrayList<>();
54
55
56 String sentTo;
57
58
59 int errorCount = 0;
60
61
62
63
64 long oldestFileModificationTime = Long.MAX_VALUE;
65
66
67
68
69 long youngestFileModificationTime = Long.MIN_VALUE;
70
71
72 long totalFileSize = 0L;
73
74
75
76
77 public WorkBundle() {
78 bundleId = generateId();
79 }
80
81
82
83
84
85
86
87 public WorkBundle(String outputRoot, String eatPrefix) {
88 bundleId = generateId();
89 this.outputRoot = outputRoot;
90 this.eatPrefix = eatPrefix;
91 }
92
93
94
95
96
97
98
99 public WorkBundle(WorkBundle that) {
100 this.bundleId = that.bundleId;
101 this.outputRoot = that.getOutputRoot();
102 this.eatPrefix = that.getEatPrefix();
103 this.caseId = that.getCaseId();
104 this.sentTo = that.sentTo;
105 this.errorCount = that.errorCount;
106 this.priority = that.getPriority();
107 this.simpleMode = that.getSimpleMode();
108 this.oldestFileModificationTime = that.oldestFileModificationTime;
109 this.youngestFileModificationTime = that.youngestFileModificationTime;
110 this.totalFileSize = that.totalFileSize;
111 if (!that.getWorkUnitList().isEmpty()) {
112 this.addWorkUnits(that.getWorkUnitList());
113 }
114 resetBundleId();
115 }
116
117
118
119
120
121
122
123
124
125 public static WorkBundle readFromStream(DataInputStream in) throws IOException {
126 WorkBundle wb = new WorkBundle();
127 wb.bundleId = readUtfOrNull(in);
128 wb.outputRoot = readUtfOrNull(in);
129 wb.eatPrefix = readUtfOrNull(in);
130 wb.caseId = readUtfOrNull(in);
131 wb.sentTo = readUtfOrNull(in);
132 wb.errorCount = in.readInt();
133 wb.priority = in.readInt();
134 wb.simpleMode = in.readBoolean();
135 wb.oldestFileModificationTime = in.readLong();
136 wb.youngestFileModificationTime = in.readLong();
137 wb.totalFileSize = in.readLong();
138 int workUnitSize = in.readInt();
139 if (workUnitSize > MAX_UNITS) {
140 throw new IOException(
141 "Exception when reading: WorkBundle may not contain more then " + MAX_UNITS + " WorkUnits (saw: " + workUnitSize + ").");
142 }
143 for (int i = 0; i < workUnitSize; i++) {
144 wb.addWorkUnit(WorkUnit.readFromStream(in));
145 }
146 return wb;
147 }
148
149
150
151
152
153
154
155 public void writeToStream(DataOutputStream out) throws IOException {
156 writeUtfOrNull(bundleId, out);
157 writeUtfOrNull(outputRoot, out);
158 writeUtfOrNull(eatPrefix, out);
159 writeUtfOrNull(caseId, out);
160 writeUtfOrNull(sentTo, out);
161 out.writeInt(errorCount);
162 out.writeInt(priority);
163 out.writeBoolean(simpleMode);
164 out.writeLong(oldestFileModificationTime);
165 out.writeLong(youngestFileModificationTime);
166 out.writeLong(totalFileSize);
167 out.writeInt(workUnitList.size());
168 if (workUnitList.size() > MAX_UNITS) {
169 throw new IOException(
170 "Exception when writing: WorkBundle may not contain more then " + MAX_UNITS + " WorkUnits (saw: " + workUnitList.size() + ").");
171 }
172 for (WorkUnit u : workUnitList) {
173 u.writeToStream(out);
174 }
175 }
176
177 @Nullable
178 static String readUtfOrNull(DataInputStream in) throws IOException {
179 if (in.readBoolean()) {
180 return in.readUTF();
181 }
182 return null;
183 }
184
185 static void writeUtfOrNull(@Nullable String s, DataOutputStream out) throws IOException {
186 out.writeBoolean(s != null);
187 if (s != null) {
188 out.writeUTF(s);
189 }
190 }
191
192
193
194
195
196
197 public void setBundleId(String val) {
198 this.bundleId = val;
199 }
200
201
202
203
204
205
206 public String resetBundleId() {
207 bundleId = generateId();
208 return bundleId;
209 }
210
211
212
213
214 public String getBundleId() {
215 return bundleId;
216 }
217
218
219
220
221
222
223 static String generateId() {
224 return UUID.randomUUID().toString();
225 }
226
227
228
229
230
231
232 public String getOutputRoot() {
233 return this.outputRoot;
234 }
235
236
237
238
239
240
241 public void setOutputRoot(@Nullable String argOutputRoot) {
242 this.outputRoot = argOutputRoot;
243 }
244
245
246
247
248
249
250 public String getEatPrefix() {
251 return this.eatPrefix;
252 }
253
254
255
256
257
258
259 public void setEatPrefix(@Nullable String argEatPrefix) {
260 this.eatPrefix = argEatPrefix;
261 }
262
263
264
265
266
267
268 public List<WorkUnit> getWorkUnitList() {
269 return new ArrayList<>(workUnitList);
270 }
271
272
273
274
275
276
277 public Iterator<WorkUnit> getWorkUnitIterator() {
278 return workUnitList.iterator();
279 }
280
281
282
283
284
285
286
287
288
289 public int addWorkUnit(WorkUnit workUnit) {
290 if (workUnitList.size() >= MAX_UNITS) {
291 throw new IllegalStateException("WorkBundle may not contain more than " + MAX_UNITS + " WorkUnits.");
292 }
293 workUnitList.add(workUnit);
294 return size();
295 }
296
297
298
299
300
301
302
303
304
305
306
307 public int addWorkUnit(WorkUnit workUnit, long fileModificationTimeInMillis, long fileSize) {
308 addWorkUnit(workUnit);
309
310 if (fileModificationTimeInMillis < oldestFileModificationTime) {
311 oldestFileModificationTime = fileModificationTimeInMillis;
312 }
313 if (fileModificationTimeInMillis > youngestFileModificationTime) {
314 youngestFileModificationTime = fileModificationTimeInMillis;
315 }
316 totalFileSize += fileSize;
317 return size();
318 }
319
320
321
322
323
324
325
326
327
328 int addWorkUnits(List<WorkUnit> list) {
329 if (workUnitList.size() + list.size() > MAX_UNITS) {
330 throw new IllegalStateException("WorkBundle may not contain more than " + MAX_UNITS + " WorkUnits.");
331 }
332 workUnitList.addAll(list);
333 return workUnitList.size();
334 }
335
336
337
338
339
340
341 public List<String> getFileNameList() {
342 ArrayList<String> fileNameList = new ArrayList<>(workUnitList.size());
343 for (WorkUnit workUnit : workUnitList) {
344 fileNameList.add(workUnit.getFileName());
345 }
346
347 return fileNameList;
348 }
349
350
351
352
353
354
355 public Iterator<String> getFileNameIterator() {
356 return getFileNameList().iterator();
357 }
358
359
360
361
362
363
364
365
366
367 public int addFileName(String file) {
368 return addWorkUnit(new WorkUnit(file));
369 }
370
371
372
373
374
375
376
377
378
379
380
381 public int addFileName(String file, long fileModificationTimeInMillis, long fileSize) {
382 return addWorkUnit(new WorkUnit(file), fileModificationTimeInMillis, fileSize);
383 }
384
385
386
387
388
389
390
391
392
393 int addFileNames(String[] file) {
394 for (String f : file) {
395 addWorkUnit(new WorkUnit(f));
396 }
397 return size();
398 }
399
400
401
402
403
404
405
406
407 int addFileNames(List<String> list) {
408
409 for (String file : list) {
410 addWorkUnit(new WorkUnit(file));
411 }
412 return size();
413 }
414
415
416
417
418 public int size() {
419 return workUnitList.size();
420 }
421
422
423
424
425 void clearFiles() {
426
427 workUnitList.clear();
428 oldestFileModificationTime = Long.MAX_VALUE;
429 youngestFileModificationTime = Long.MIN_VALUE;
430 totalFileSize = 0L;
431 }
432
433
434
435
436
437
438 public String getCaseId() {
439 return this.caseId;
440 }
441
442
443
444
445
446
447 public void setCaseId(@Nullable String argCaseId) {
448 this.caseId = argCaseId;
449 }
450
451
452
453
454 public void setSentTo(@Nullable String place) {
455 this.sentTo = place;
456 }
457
458
459
460
461 public String getSentTo() {
462 return sentTo;
463 }
464
465
466
467
468 public int getErrorCount() {
469 return errorCount;
470 }
471
472
473
474
475
476
477 public int incrementErrorCount() {
478 return ++errorCount;
479 }
480
481
482
483
484 public void setErrorCount(int val) {
485 errorCount = val;
486 }
487
488
489
490
491 public void setPriority(int val) {
492 priority = val;
493 }
494
495
496
497
498 public int getPriority() {
499 return priority;
500 }
501
502
503
504
505
506
507 public void setSimpleMode(boolean val) {
508 simpleMode = val;
509 }
510
511
512
513
514 public boolean getSimpleMode() {
515 return simpleMode;
516 }
517
518 public long getOldestFileModificationTime() {
519 return oldestFileModificationTime;
520 }
521
522 public void setOldestFileModificationTime(long oldestFileModificationTime) {
523 this.oldestFileModificationTime = oldestFileModificationTime;
524 }
525
526 public long getYoungestFileModificationTime() {
527 return youngestFileModificationTime;
528 }
529
530 public void setYoungestFileModificationTime(long youngestFileModificationTime) {
531 this.youngestFileModificationTime = youngestFileModificationTime;
532 }
533
534 public long getTotalFileSize() {
535 return totalFileSize;
536 }
537
538 public void setTotalFileSize(long totalFileSize) {
539 this.totalFileSize = totalFileSize;
540 }
541
542
543
544
545
546 @Override
547 public int compareTo(WorkBundle that) {
548 if (this.getPriority() < that.getPriority()) {
549 return -1;
550 } else if (that.getPriority() < this.getPriority()) {
551 return 1;
552 } else {
553 return 0;
554 }
555 }
556
557
558
559
560 @Override
561 public String toString() {
562 return "WorkBundle[id=" + getBundleId() + ", pri=" + getPriority() + ", files=" + getFileNameList().toString() + ", eatPrefix="
563 + getEatPrefix()
564 + ", outputRoot=" + getOutputRoot() + ", sentTo=" + getSentTo() + ", errorCount=" + getErrorCount() + ", totalFileSize="
565 + getTotalFileSize() + ", oldestModTime=" + getOldestFileModificationTime() + ", youngModTime=" + getYoungestFileModificationTime()
566 + ", simple=" + getSimpleMode() + ", caseId=" + getCaseId() + ", size=" + size() + "]";
567 }
568
569 public String toXml() {
570 Element root = new Element("workBundle");
571 root.addContent(SaferJDOMUtil.simpleElement("bundleId", getBundleId()));
572 root.addContent(SaferJDOMUtil.simpleElement("outputRoot", getOutputRoot()));
573 root.addContent(SaferJDOMUtil.simpleElement("eatPrefix", getEatPrefix()));
574 root.addContent(SaferJDOMUtil.simpleElement("caseId", getCaseId()));
575 root.addContent(SaferJDOMUtil.simpleElement("sentTo", getSentTo()));
576 root.addContent(SaferJDOMUtil.simpleElement("errorCount", getErrorCount()));
577 root.addContent(SaferJDOMUtil.simpleElement("priority", getPriority()));
578 root.addContent(SaferJDOMUtil.simpleElement("simpleMode", getSimpleMode()));
579 root.addContent(SaferJDOMUtil.simpleElement("oldestFileModificationTime", getOldestFileModificationTime()));
580 root.addContent(SaferJDOMUtil.simpleElement("youngestFileModificationTime", getYoungestFileModificationTime()));
581 root.addContent(SaferJDOMUtil.simpleElement("totalFileSize", getTotalFileSize()));
582
583 for (WorkUnit wu : workUnitList) {
584 Element workunit = new Element("workUnit");
585 workunit.addContent(SaferJDOMUtil.simpleElement("workFileName", wu.getFileName()));
586 if (wu.getTransactionId() != null) {
587 workunit.addContent(SaferJDOMUtil.simpleElement("transactionId", wu.getTransactionId()));
588 }
589 workunit.addContent(SaferJDOMUtil.simpleElement("failedToParse", wu.failedToParse()));
590 workunit.addContent(SaferJDOMUtil.simpleElement("failedToProcess", wu.failedToProcess()));
591
592 root.addContent(workunit);
593 }
594
595 Document jdom = new Document(root);
596 return SaferJDOMUtil.toString(jdom);
597 }
598
599
600
601
602
603
604
605 @Nullable
606 public static WorkBundle buildWorkBundle(String xml) {
607 Document jdoc;
608 try {
609 jdoc = SaferJDOMUtil.createDocument(xml);
610 return buildWorkBundle(jdoc);
611 } catch (Exception ex) {
612 logger.error("Cannot make WorkBundle from " + xml, ex);
613 return null;
614 }
615 }
616
617
618
619
620
621
622
623 @Nullable
624 private static WorkBundle buildWorkBundle(Document jdom) {
625 Element root = jdom.getRootElement();
626 if (root == null) {
627 logger.error("Document does not have a root element!");
628 return null;
629 }
630
631 WorkBundle wb = new WorkBundle();
632 wb.setBundleId(root.getChildTextTrim("bundleId"));
633 String s = root.getChildTextTrim("outputRoot");
634 if (s != null && s.length() > 0) {
635 wb.setOutputRoot(s);
636 } else {
637 wb.setOutputRoot(null);
638 }
639
640 s = root.getChildTextTrim("eatPrefix");
641 if (s != null && s.length() > 0) {
642 wb.setEatPrefix(s);
643 } else {
644 wb.setEatPrefix(null);
645 }
646
647 s = root.getChildTextTrim("caseId");
648 if (s != null && s.length() > 0) {
649 wb.setCaseId(s);
650 } else {
651 wb.setCaseId(null);
652 }
653
654 s = root.getChildTextTrim("sentTo");
655 if (s != null && s.length() > 0) {
656 wb.setSentTo(s);
657 } else {
658 wb.setSentTo(null);
659 }
660
661 wb.setPriority(SaferJDOMUtil.getChildIntValue(root, "priority"));
662 wb.setSimpleMode(SaferJDOMUtil.getChildBooleanValue(root, "simpleMode"));
663 wb.setOldestFileModificationTime(SaferJDOMUtil.getChildLongValue(root, "oldestFileModificationTime"));
664 wb.setYoungestFileModificationTime(SaferJDOMUtil.getChildLongValue(root, "youngestFileModificationTime"));
665 wb.setTotalFileSize(SaferJDOMUtil.getChildLongValue(root, "totalFileSize"));
666 String serr = root.getChildTextTrim("errorCount");
667 if (serr != null && serr.length() > 0) {
668 wb.setErrorCount(Integer.parseInt(serr));
669 }
670
671 for (Element wu : root.getChildren("workUnit")) {
672 String filename = wu.getChildTextTrim("workFileName");
673 String transactionId = wu.getChildTextTrim("transactionId");
674 boolean failedToParse = Boolean.parseBoolean(wu.getChildTextTrim("failedToParse"));
675 boolean failedToProcess = Boolean.parseBoolean(wu.getChildTextTrim("failedToProcess"));
676 wb.addWorkUnit(new WorkUnit(filename, transactionId, failedToParse, failedToProcess));
677 }
678
679 return wb;
680 }
681 }