1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package p3j.misc;
17
18 import java.beans.XMLDecoder;
19 import java.beans.XMLEncoder;
20 import java.io.BufferedInputStream;
21 import java.io.BufferedOutputStream;
22 import java.io.FileInputStream;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.io.OutputStream;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import java.util.logging.Level;
37 import java.util.zip.GZIPInputStream;
38 import java.util.zip.GZIPOutputStream;
39
40 import org.jamesii.SimSystem;
41 import org.jamesii.core.util.misc.Strings;
42
43 import p3j.database.IP3MDatabase;
44 import p3j.gui.P3J;
45 import p3j.gui.dialogs.ShowWarningAfterProjectionLoadingDialog;
46 import p3j.gui.dialogs.execstatus.SimpleProgressDialog;
47 import p3j.misc.gui.GUI;
48 import p3j.pppm.ProjectionModel;
49 import p3j.pppm.SubPopulation;
50 import p3j.pppm.SubPopulationModel;
51 import p3j.pppm.parameters.Parameter;
52 import p3j.pppm.parameters.ParameterAssignment;
53 import p3j.pppm.parameters.ParameterAssignmentSet;
54 import p3j.pppm.parameters.ParameterInstance;
55 import p3j.pppm.sets.Set;
56 import p3j.pppm.sets.SetType;
57
58
59
60
61
62
63
64
65
66
67
68
69 public class Serializer {
70
71
72
73
74
75 private boolean usingXML = true;
76
77
78
79
80 private boolean usingCompression = false;
81
82
83
84
85
86
87
88
89
90
91
92
93 public Object load(String file) throws IOException, ClassNotFoundException {
94 if (usingXML) {
95 return loadFromXML(file);
96 }
97 return loadFromBinary(file);
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111 public Object loadFromBinary(String file) throws IOException,
112 ClassNotFoundException {
113 ObjectInputStream input = new ObjectInputStream(getInputStream(file));
114 Object o = input.readObject();
115 input.close();
116 return o;
117 }
118
119
120
121
122
123
124
125
126
127
128 public Object loadFromXML(String file) throws IOException {
129 XMLDecoder xmlDecoder = new XMLDecoder(getInputStream(file));
130 Object object = xmlDecoder.readObject();
131 xmlDecoder.close();
132 return object;
133 }
134
135
136
137
138
139
140
141
142
143
144 protected InputStream getInputStream(String file) throws IOException {
145 InputStream in = new BufferedInputStream(new FileInputStream(file));
146 if (isUsingCompression()) {
147 in = new GZIPInputStream(in);
148 }
149 return in;
150 }
151
152
153
154
155
156
157
158
159
160
161 protected OutputStream getOutputStream(String file) throws IOException {
162 OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
163 if (isUsingCompression()) {
164 out = new GZIPOutputStream(out);
165 }
166 return out;
167 }
168
169
170
171
172
173
174
175
176
177
178
179 public void save(ProjectionModel pm, String file) throws IOException {
180 ProjectionModel modelToSave = copyProjection(pm);
181 if (usingXML) {
182 saveToXML(modelToSave, file);
183 } else {
184 saveToBinary(modelToSave, file);
185 }
186 }
187
188
189
190
191
192
193
194
195
196
197
198 public void saveToBinary(Object object, String file) throws IOException {
199 ObjectOutputStream output = new ObjectOutputStream(getOutputStream(file));
200 output.writeObject(object);
201 output.close();
202 }
203
204
205
206
207
208
209
210
211
212
213
214 public void saveToXML(Object object, String file) throws IOException {
215 XMLEncoder xmlEncoder = new XMLEncoder(getOutputStream(file));
216 xmlEncoder.writeObject(object);
217 xmlEncoder.close();
218 }
219
220 public boolean isUsingXML() {
221 return usingXML;
222 }
223
224 public void setUsingXML(boolean usingXML) {
225 this.usingXML = usingXML;
226 }
227
228 public boolean isUsingCompression() {
229 return usingCompression;
230 }
231
232 public void setUsingCompression(boolean usingCompression) {
233 this.usingCompression = usingCompression;
234 }
235
236
237
238
239
240
241
242
243
244
245
246 private ProjectionModel copyProjection(ProjectionModel original) {
247 ProjectionModel copy = new ProjectionModel();
248
249 IProgressObserver progress = SimpleProgressDialog.showDialog(
250 P3J.getInstance(), "Saving projection '" + original.getName() + "'",
251 "", 6, false);
252 progress.incrementProgress("General properties...");
253 copySimpleFields(original, copy);
254 progress.incrementProgress("Parameter instances...");
255 Map<ParameterInstance, ParameterInstance> paramInstances = copyParameterInstances(
256 original, copy);
257 progress.incrementProgress("Sets...");
258 Map<Set, Set> sets = copySets(original, copy, paramInstances);
259 progress.incrementProgress("Set Types...");
260 Map<SetType, SetType> setTypes = copySetTypes(original, copy,
261 paramInstances, sets);
262 progress.incrementProgress("Set Type Mapping...");
263 copyParamInstToSetTypeMapping(original, copy, paramInstances, setTypes);
264 progress.incrementProgress("Done");
265 progress.taskFinished();
266 return copy;
267 }
268
269
270
271
272
273
274
275
276
277 private void copySimpleFields(ProjectionModel original, ProjectionModel copy) {
278 copy.setName(original.getName());
279 copy.setDescription(original.getDescription());
280 copy.setJumpOffYear(original.getJumpOffYear());
281 copy.setMaximumAge(original.getMaximumAge());
282 copy.setYears(original.getYears());
283 copy.setGenerations(original.getGenerations());
284 copy.setSubPopulationModel(copySubPopulationModel(original
285 .getSubPopulationModel()));
286 }
287
288
289
290
291
292
293
294
295 private SubPopulationModel copySubPopulationModel(SubPopulationModel original) {
296 SubPopulationModel copy = new SubPopulationModel();
297 for (SubPopulation subPop : original.getSubPopulations())
298 copy.getSubPopulations()
299 .add(
300 new SubPopulation(subPop.getName(), subPop.isJumpOffPopulation(),
301 subPop.isAdditive(), subPop
302 .isConsistingOfDescendantGenerations()));
303 return copy;
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317
318 private Map<ParameterInstance, ParameterInstance> copyParameterInstances(
319 ProjectionModel original, ProjectionModel copy) {
320 Map<ParameterInstance, ParameterInstance> paramInstances = new HashMap<>();
321 List<ParameterInstance> listOfNewParamInstances = new ArrayList<>();
322 for (ParameterInstance paramInstance : original.getAllParameterInstances()) {
323 ParameterInstance piCopy = copyParameterInstance(paramInstance);
324 paramInstances.put(paramInstance, piCopy);
325 listOfNewParamInstances.add(piCopy);
326 }
327 copy.setAllParameterInstances(listOfNewParamInstances);
328 return paramInstances;
329 }
330
331
332
333
334
335
336
337
338
339
340
341
342
343 private Map<Set, Set> copySets(ProjectionModel original,
344 ProjectionModel copy,
345 Map<ParameterInstance, ParameterInstance> paramInstances) {
346 Map<Set, Set> sets = new HashMap<>();
347 Set newDefaultSet = copySet(original.getDefaultSet(), paramInstances);
348 copy.setDefaultSet(newDefaultSet);
349 sets.put(original.getDefaultSet(), newDefaultSet);
350 for (SetType setType : original.getAllSetTypes())
351 for (Set set : setType.getSets()) {
352 Set setCopy = copySet(set, paramInstances);
353 sets.put(set, setCopy);
354 }
355 return sets;
356 }
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 private Map<SetType, SetType> copySetTypes(ProjectionModel original,
375 ProjectionModel copy,
376 Map<ParameterInstance, ParameterInstance> paramInstances,
377 Map<Set, Set> sets) {
378 Map<SetType, SetType> setTypes = new HashMap<>();
379 SetType newDefaultSetType = copySetType(original.getDefaultSetType(),
380 paramInstances, sets);
381 copy.setDefaultType(newDefaultSetType);
382 setTypes.put(original.getDefaultSetType(), newDefaultSetType);
383 List<SetType> listOfNewUserDefSetTypes = new ArrayList<>();
384 for (SetType setType : original.getUserDefinedTypes()) {
385 SetType stCopy = copySetType(setType, paramInstances, sets);
386 setTypes.put(setType, stCopy);
387 listOfNewUserDefSetTypes.add(stCopy);
388 }
389 copy.setUserDefinedTypes(listOfNewUserDefSetTypes);
390 return setTypes;
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406 private void copyParamInstToSetTypeMapping(ProjectionModel original,
407 ProjectionModel copy,
408 Map<ParameterInstance, ParameterInstance> paramInstances,
409 Map<SetType, SetType> setTypes) {
410 Map<ParameterInstance, SetType> newInstanceSetTypesMap = new HashMap<>();
411 for (Entry<ParameterInstance, SetType> instSetTypeEntry : original
412 .getInstanceSetTypes().entrySet()) {
413 newInstanceSetTypesMap.put(paramInstances.get(instSetTypeEntry.getKey()),
414 setTypes.get(instSetTypeEntry.getValue()));
415 }
416 copy.setInstanceSetTypes(newInstanceSetTypesMap);
417 }
418
419
420
421
422
423
424
425
426 private ParameterInstance copyParameterInstance(
427 ParameterInstance paramInstance) {
428 Parameter param = paramInstance.getParameter();
429 return new ParameterInstance(paramInstance.getComparisonIndex(),
430 new Parameter(param.getID(), param.isGenerationDependent(),
431 param.getName(), param.getValueHeight(), param.getValueWidth(),
432 param.getPopulation()), paramInstance.getGeneration());
433 }
434
435
436
437
438
439
440
441
442
443
444 private Set copySet(Set set,
445 Map<ParameterInstance, ParameterInstance> paramInstances) {
446 Set copy = new Set();
447 copy.setName(set.getName());
448 copy.setDescription(set.getDescription());
449 copy.setProbability(set.getProbability());
450
451 Map<ParameterInstance, ParameterAssignmentSet> copyOfSetData = new HashMap<>();
452 for (Entry<ParameterInstance, ParameterAssignmentSet> setDataEntry : set
453 .getSetData().entrySet()) {
454 copyOfSetData.put(paramInstances.get(setDataEntry.getKey()),
455 copyParamAssignmentSet(setDataEntry.getValue(), paramInstances));
456 }
457
458 copy.setSetData(copyOfSetData);
459 return copy;
460 }
461
462
463
464
465
466
467
468
469
470
471 private ParameterAssignmentSet copyParamAssignmentSet(
472 ParameterAssignmentSet paramAssignmentSet,
473 Map<ParameterInstance, ParameterInstance> paramInstances) {
474 ParameterAssignmentSet copy = new ParameterAssignmentSet();
475 for (ParameterAssignment assignment : paramAssignmentSet.getAssignments()) {
476 copy.add(new ParameterAssignment(paramInstances.get(assignment
477 .getParamInstance()), assignment.getName(), assignment
478 .getDescription(), assignment.getProbability(), assignment
479 .getDeviation(), assignment.getMatrix().copy()));
480 }
481 return copy;
482 }
483
484
485
486
487
488
489
490
491
492
493
494
495 private SetType copySetType(SetType setType,
496 Map<ParameterInstance, ParameterInstance> paramInstances,
497 Map<Set, Set> sets) {
498 SetType copy = new SetType(setType.getName(), setType.getDescription());
499
500 List<ParameterInstance> copyDefinedParameters = new ArrayList<>();
501 for (ParameterInstance paramInstance : setType.getDefinedParameters())
502 copyDefinedParameters.add(paramInstances.get(paramInstance));
503 List<Set> copySets = new ArrayList<>();
504 for (Set set : setType.getSets())
505 copySets.add(sets.get(set));
506
507 copy.setDefinedParameters(copyDefinedParameters);
508 copy.setSets(copySets);
509
510 return copy;
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529 public ProjectionModel loadProjection(String absolutePath,
530 IP3MDatabase database) throws ClassNotFoundException, IOException,
531 LoadedProjectionFormatException {
532 ProjectionModel newProjection = new ProjectionModel();
533
534 try {
535 List<String> warnings = new ArrayList<>();
536 ProjectionModel loadedProjection = (ProjectionModel) load(absolutePath);
537
538 copySimpleFields(loadedProjection, newProjection);
539 database.newProjection(newProjection);
540
541 Map<ParameterInstance, ParameterInstance> paramInstances = matchParameterInstances(
542 loadedProjection, newProjection, warnings);
543 Map<SetType, SetType> setTypes = saveSetTypes(loadedProjection,
544 newProjection, paramInstances);
545 database.saveProjection(newProjection);
546 saveSets(loadedProjection, newProjection, paramInstances, setTypes,
547 database);
548
549 database.saveProjection(newProjection);
550
551 if (!warnings.isEmpty())
552 new ShowWarningAfterProjectionLoadingDialog(P3J.getInstance(), warnings)
553 .setVisible(true);
554 } catch (Exception ex) {
555 GUI.printErrorMessage("Loading the projection failed", ex);
556 }
557
558 return newProjection;
559 }
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574 private Map<ParameterInstance, ParameterInstance> matchParameterInstances(
575 ProjectionModel loadedProjection, ProjectionModel newProjection,
576 List<String> warnings) throws LoadedProjectionFormatException {
577
578 Map<ParameterInstance, ParameterInstance> matching = new HashMap<>();
579 List<ParameterInstance> oldInstances = new ArrayList<>(
580 loadedProjection.getAllParameterInstances());
581
582 for (final ParameterInstance newInstance : newProjection
583 .getAllParameterInstances()) {
584
585 List<ParameterInstance> matchCandidates = new ArrayList<>();
586
587 for (ParameterInstance oldInstance : oldInstances)
588 if (newInstance.toString().equals(oldInstance.toString())
589 && newInstance.getGeneration() == oldInstance.getGeneration()
590 && newInstance.getValueHeight() == oldInstance.getValueHeight()
591 && newInstance.getValueWidth() == oldInstance.getValueWidth()
592 && newInstance.getParameter().isGenerationDependent() == oldInstance
593 .getParameter().isGenerationDependent()) {
594 matchCandidates.add(oldInstance);
595 }
596
597 if (matchCandidates.isEmpty())
598 throw new LoadedProjectionFormatException(
599 "No match found for parameter instance " + newInstance);
600
601 oldInstances.remove(matchParameterInstances(matching, newInstance,
602 matchCandidates, warnings));
603 }
604
605 return matching;
606 }
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623 private ParameterInstance matchParameterInstances(
624 Map<ParameterInstance, ParameterInstance> matching,
625 final ParameterInstance targetInstance,
626 List<ParameterInstance> matchCandidates, List<String> warnings) {
627
628 ParameterInstance bestMatch = Collections.min(matchCandidates,
629 new Comparator<ParameterInstance>() {
630 final String targetName = targetInstance.getParameter().getName();
631
632 @Override
633 public int compare(ParameterInstance inst1, ParameterInstance inst2) {
634 return Integer.compare(Strings.getLevenshteinDistance(inst1
635 .getParameter().getName(), targetName), Strings
636 .getLevenshteinDistance(inst2.getParameter().getName(),
637 targetName));
638 }
639 });
640
641 matching.put(bestMatch, targetInstance);
642 SimSystem.report(Level.INFO, "Matched '" + bestMatch + "' to '"
643 + targetInstance + "'.");
644 if (!bestMatch.getParameter().getName()
645 .equals(targetInstance.getParameter().getName()))
646 warnings.add("Could not find perfect match for parameter '"
647 + targetInstance.getParameter() + "', using best match '"
648 + bestMatch.getParameter());
649
650 return bestMatch;
651 }
652
653
654
655
656
657
658
659
660
661
662
663
664 private Map<SetType, SetType> saveSetTypes(ProjectionModel loadedProjection,
665 ProjectionModel newProjection,
666 Map<ParameterInstance, ParameterInstance> paramInstances) {
667
668 Map<SetType, SetType> setTypes = new HashMap<>();
669
670 setTypes.put(loadedProjection.getDefaultSetType(),
671 newProjection.getDefaultSetType());
672
673 for (SetType loadedSetType : loadedProjection.getUserDefinedTypes()) {
674 SetType newSetType = newProjection.createSetType(loadedSetType.getName(),
675 loadedSetType.getDescription());
676 setTypes.put(loadedSetType, newSetType);
677 for (ParameterInstance paramInst : loadedSetType.getDefinedParameters())
678 newProjection.assignParameterInstance(paramInstances.get(paramInst),
679 newSetType, false);
680 }
681
682 return setTypes;
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699 private void saveSets(ProjectionModel loadedProjection,
700 ProjectionModel newProjection,
701 Map<ParameterInstance, ParameterInstance> paramInstances,
702 Map<SetType, SetType> setTypes, IP3MDatabase database) {
703
704 int numAssignments = loadedProjection.countNumberOfParameterAssignments();
705 IProgressObserver progress = SimpleProgressDialog.showDialog(
706 P3J.getInstance(), "Loading projection '" + loadedProjection.getName()
707 + "'", "Loading " + numAssignments + " parameter assignments:",
708 numAssignments, false);
709
710 for (SetType loadedSetType : loadedProjection.getAllSetTypes()) {
711 SetType newSetType = setTypes.get(loadedSetType);
712 for (Set loadedSet : loadedSetType.getSets()) {
713 Set newSet = loadedSet != loadedProjection.getDefaultSet() ? newSetType
714 .createSet(loadedSet.getName(), loadedSet.getDescription(),
715 loadedSet.getProbability()) : newProjection.getDefaultSet();
716 saveSet(loadedSet, newSet, loadedSetType, paramInstances, database,
717 progress);
718 }
719 }
720 progress.taskFinished();
721 }
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739 private void saveSet(Set loadedSet, Set newSet, SetType loadedSetType,
740 Map<ParameterInstance, ParameterInstance> paramInstances,
741 IP3MDatabase database, IProgressObserver progress) {
742 for (ParameterInstance paramInst : loadedSetType.getDefinedParameters()) {
743 ParameterAssignmentSet paramAssignSet = loadedSet
744 .getParameterAssignments(paramInst);
745 for (ParameterAssignment paramAssign : paramAssignSet.getAssignments()) {
746 ParameterAssignment newParamAssign = database.newParameterAssignment(
747 paramInstances.get(paramInst), paramAssign.getName(),
748 paramAssign.getDescription(), paramAssign.getProbability(),
749 paramAssign.getDeviation(), paramAssign.getMatrixValue());
750 newSet.addParameterAssignment(newParamAssign);
751 progress.incrementProgress("Assignment '" + newParamAssign.getName()
752 + "'");
753 }
754 }
755 }
756
757 }