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