View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
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   * Class that stores and loads serializable classes. Needed to store and load
61   * parameter files.
62   * 
63   * Created on February 12, 2007
64   * 
65   * @author Christina Bohk
66   * @author Roland Ewald
67   * 
68   */
69  public class Serializer {
70  
71    /**
72     * Flag that indicates whether objects should be stored in XML or in binary
73     * encoding.
74     */
75    private boolean usingXML = true;
76  
77    /**
78     * Flag that indicates whether GZIP compression (LZW) is used.
79     */
80    private boolean usingCompression = false;
81  
82    /**
83     * Loads object from file.
84     * 
85     * @param file
86     *          path to file with the object to be loaded
87     * @return object the object that has been loaded
88     * @throws IOException
89     *           if file was not found, file input failed, etc.
90     * @throws ClassNotFoundException
91     *           if class of persistent object could not be found
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    * Load object from a binary file.
102    * 
103    * @param file
104    *          path and file name
105    * @return deserialised object
106    * @throws IOException
107    *           if file was not found, etc.
108    * @throws ClassNotFoundException
109    *           if class of persistent object could not be found
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    * Load object from XML file.
121    * 
122    * @param file
123    *          path and file name
124    * @return deserialised object
125    * @throws IOException
126    *           if file was not found, a read error occurred, etc.
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    * Create an input stream.
137    * 
138    * @param file
139    *          source file
140    * @return input stream from file
141    * @throws IOException
142    *           if stream creation fails
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    * Create an output stream.
154    * 
155    * @param file
156    *          target file
157    * @return output stream to file
158    * @throws IOException
159    *           if stream creation fails
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    * Save object to file.
171    * 
172    * @param object
173    *          the object to be saved in the file
174    * @param file
175    *          the file
176    * @throws IOException
177    *           if outputting went wrong
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    * Save object to binary file.
190    * 
191    * @param object
192    *          the object to be written
193    * @param file
194    *          the target file
195    * @throws IOException
196    *           if writing fails
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    * Save object to XML file.
206    * 
207    * @param object
208    *          the object to be written
209    * @param file
210    *          the target file
211    * @throws IOException
212    *           if writing fails
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    * Creates a full, deep copy of this projection model. This is necessary for
238    * serialization, because hibernate is used with lazy evaluation, so that
239    * non-serializable hibernate-specific collections are used internally. The
240    * copy only relies on serializable collections, so it can be serialized
241    * easily.
242    * 
243    * @return a full copy of the projection model, including copies of all
244    *         sub-elements (set types, matrices, etc.)
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    * Copies all simple fields of the projection model.
271    * 
272    * @param original
273    *          the original
274    * @param copy
275    *          the copy
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    * Copies the sub-population model.
290    * 
291    * @param original
292    *          the original sub population model
293    * @return the copy
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    * Copies parameter instances (and parameters) from the original projection to
308    * the copy.
309    * 
310    * @param original
311    *          the original
312    * @param copy
313    *          the copy
314    * @return mapping from old parameter instances to their corresponding new
315    *         parameter instances, which is necessary for creating sets and set
316    *         types with the same structure
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    * Copies all sets of the original model to the copy.
333    * 
334    * @param original
335    *          the original
336    * @param copy
337    *          the copy
338    * @param paramInstances
339    *          the mapping from old to new parameter instances
340    * @return the mapping from old sets to their corresponding copies, which is
341    *         necessary to construct set types with the same structure
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    * Copies set types from the original projection to the copy.
360    * 
361    * @param original
362    *          the original
363    * @param copy
364    *          the copy
365    * @param paramInstances
366    *          the mapping from old to new parameter instances
367    * @param sets
368    *          the mapping from old to new sets
369    * @return the mapping from old to new set types, required to correctly update
370    *         the internal structure of the projection (see
371    *         {@link Serializer#copyParamInstToSetTypeMapping(ProjectionModel, ProjectionModel, Map, Map)}
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    * Copies the mapping from parameter instances to the set types that manage
395    * them from the original projection to the copy.
396    * 
397    * @param copy
398    *          the copy
399    * @param original
400    *          the original
401    * @param paramInstances
402    *          the mapping from old to new parameter instances
403    * @param setTypes
404    *          the mapping from old to new set types
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    * Copies a parameter instance.
421    * 
422    * @param paramInstance
423    *          the original parameter instance
424    * @return the copy
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    * Copies a set.
437    * 
438    * @param set
439    *          the original set
440    * @param paramInstances
441    *          the mapping from old to new parameter instances
442    * @return the copy
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    * Copies a parameter assignment set.
464    * 
465    * @param paramAssignmentSet
466    *          the original parameter assignment set
467    * @param paramInstances
468    *          the map from old to new parameter instances
469    * @return the copy
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    * Copies a set type.
486    * 
487    * @param setType
488    *          the original set type
489    * @param paramInstances
490    *          the mapping from old to new parameter instances
491    * @param sets
492    *          the mapping from old to new sets
493    * @return the copy
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    * Loads a projection into the database. In some sense, this method is the
515    * inverse of @link {@link Serializer#copyProjection(ProjectionModel)}, as it
516    * makes sure that the newly loaded projection model is properly managed by
517    * hibernate. The easiest way to do so is by storing it as a new projection.
518    * 
519    * @param absolutePath
520    *          the absolute path
521    * @param database
522    *          the database
523    * @return the projection model
524    * @throws ClassNotFoundException
525    *           the class not found exception
526    * @throws IOException
527    *           Signals that an I/O exception has occurred.
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    * Matches loaded parameter instances to those stored in the database.
563    * 
564    * @param loadedProjection
565    *          the loaded projection
566    * @param newProjection
567    *          the new projection
568    * @param warnings
569    *          the list of warnings to be handed over to the user
570    * @return the map
571    * @throws LoadedProjectionFormatException
572    *           in case no exact one-to-one matching could be found
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    * Match parameter instances. Sort potential matches by smallest Levenshtein
610    * distance to parameter name. If there is no exact matching, a line is added
611    * to the warnings.
612    * 
613    * @param matching
614    *          the mapping from old to new parameter instance, representing the
615    *          current matching
616    * @param targetInstance
617    *          the parameter instance to be matched
618    * @param matchCandidates
619    *          the match candidates that have been found
620    * @param warnings
621    *          the list of all warnings
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    * Save set types.
655    * 
656    * @param loadedProjection
657    *          the loaded projection
658    * @param newProjection
659    *          the new projection
660    * @param paramInstances
661    *          the mapping from old to new parameter instances
662    * @return the mapping from old to new set types
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    * Save sets.
687    * 
688    * @param loadedProjection
689    *          the loaded projection
690    * @param newProjection
691    *          the new projection
692    * @param paramInstances
693    *          the mapping from old to new parameter instances
694    * @param setTypes
695    *          the mapping from old to new set types
696    * @param database
697    *          the database
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    * Save single set.
725    * 
726    * @param loadedSet
727    *          the loaded set
728    * @param newSet
729    *          the new set
730    * @param loadedSetType
731    *          the set type
732    * @param paramInstances
733    *          the mapping from old to new parameter instances
734    * @param database
735    *          the database
736    * @param progress
737    *          the dialog to show the progress
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 }