Cleanup
[debian/openrocket] / core / src / net / sf / openrocket / preset / xml / OpenRocketComponentSaver.java
1 package net.sf.openrocket.preset.xml;
2
3 import net.sf.openrocket.logging.LogHelper;
4 import net.sf.openrocket.material.Material;
5 import net.sf.openrocket.preset.ComponentPreset;
6 import net.sf.openrocket.preset.InvalidComponentPresetException;
7 import net.sf.openrocket.startup.Application;
8
9 import javax.xml.bind.JAXBContext;
10 import javax.xml.bind.JAXBException;
11 import javax.xml.bind.Marshaller;
12 import javax.xml.bind.Unmarshaller;
13 import java.io.BufferedWriter;
14 import java.io.IOException;
15 import java.io.OutputStream;
16 import java.io.OutputStreamWriter;
17 import java.io.Reader;
18 import java.io.StringWriter;
19 import java.util.List;
20
21 /**
22  * The active manager class that is the entry point for writing *.orc files.
23  */
24 public class OpenRocketComponentSaver {
25
26     /**
27      * The logger.
28      */
29     private static final LogHelper log = Application.getLogger();
30
31     /**
32      * This method marshals an OpenRocketDocument (OR design) to Rocksim-compliant XML.
33      *
34      * @param theMaterialList the list of materials to be included
35      * @param thePresetList   the list of presets to be included
36      *
37      * @return ORC-compliant XML
38      */
39     public String marshalToOpenRocketComponent(List<Material> theMaterialList, List<ComponentPreset> thePresetList) {
40
41         try {
42             JAXBContext binder = JAXBContext.newInstance(OpenRocketComponentDTO.class);
43             Marshaller marshaller = binder.createMarshaller();
44             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
45             StringWriter sw = new StringWriter();
46
47             marshaller.marshal(toOpenRocketComponentDTO(theMaterialList, thePresetList), sw);
48             return sw.toString();
49         }
50         catch (Exception e) {
51             log.error("Could not marshal a preset list. " + e.getMessage());
52         }
53
54         return null;
55     }
56
57     /**
58      * This method unmarshals from a Reader that is presumed to be open on an XML file in .orc format.
59      *
60      * @param is an open reader; StringBufferInputStream could not be used because it's deprecated and does not handle
61      *           UTF characters correctly
62      *
63      * @return a list of ComponentPresets
64      *
65      * @throws InvalidComponentPresetException
66      *
67      */
68     public List<ComponentPreset> unmarshalFromOpenRocketComponent(Reader is) throws InvalidComponentPresetException {
69         return fromOpenRocketComponent(is).asComponentPresets();
70     }
71
72     /**
73      * Write an XML representation of a list of presets.
74      *
75      * @param dest            the stream to write the data to
76      * @param theMaterialList the list of materials to be included
77      * @param thePresetList   the list of presets to be included
78      *
79      * @throws IOException thrown if the stream could not be written
80      */
81     public void save(OutputStream dest, List<Material> theMaterialList, List<ComponentPreset> thePresetList) throws
82                                                                                                              IOException {
83         log.info("Saving .orc file");
84
85         BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, "UTF-8"));
86         writer.write(marshalToOpenRocketComponent(theMaterialList, thePresetList));
87         writer.flush();
88         writer.close();
89     }
90
91     /**
92      * Read from an open Reader instance XML in .orc format and reconstruct an OpenRocketComponentDTO instance.
93      *
94      * @param is an open Reader; assumed to be opened on a file of XML in .orc format
95      *
96      * @return the OpenRocketComponentDTO that is a POJO representation of the XML; null if the data could not be read
97      *         or was in an invalid format
98      */
99     private OpenRocketComponentDTO fromOpenRocketComponent(Reader is) {
100         try {
101             JAXBContext bind = JAXBContext.newInstance(OpenRocketComponentDTO.class);
102             Unmarshaller unmarshaller = bind.createUnmarshaller();
103             return (OpenRocketComponentDTO) unmarshaller.unmarshal(is);
104         }
105         catch (JAXBException e) {
106             log.error("Could not unmarshal the .orc file. ", e);
107         }
108         return null;
109     }
110
111     /**
112      * Root conversion method.  It iterates over all subcomponents.
113      *
114      * @return a corresponding ORC representation
115      */
116     private OpenRocketComponentDTO toOpenRocketComponentDTO(List<Material> theMaterialList, List<ComponentPreset> thePresetList) {
117         OpenRocketComponentDTO rsd = new OpenRocketComponentDTO();
118
119         if (theMaterialList != null) {
120             for (Material material : theMaterialList) {
121                 rsd.addMaterial(new MaterialDTO(material));
122             }
123         }
124
125         if (thePresetList != null) {
126             for (ComponentPreset componentPreset : thePresetList) {
127                 rsd.addComponent(toComponentDTO(componentPreset));
128             }
129         }
130         return rsd;
131     }
132
133     /**
134      * Factory method that maps a preset to the corresponding DTO handler.
135      *
136      * @param thePreset the preset for which a handler will be found
137      *
138      * @return a subclass of BaseComponentDTO that can be used for marshalling/unmarshalling a preset; null if not found
139      *         for the preset type
140      */
141     private static BaseComponentDTO toComponentDTO(ComponentPreset thePreset) {
142         switch (thePreset.getType()) {
143             case BODY_TUBE:
144                 return new BodyTubeDTO(thePreset);
145             case TUBE_COUPLER:
146                 return new TubeCouplerDTO(thePreset);
147             case NOSE_CONE:
148                 return new NoseConeDTO(thePreset);
149             case TRANSITION:
150                 return new TransitionDTO(thePreset);
151             case BULK_HEAD:
152                 return new BulkHeadDTO(thePreset);
153             case CENTERING_RING:
154                 return new CenteringRingDTO(thePreset);
155             case ENGINE_BLOCK:
156                 return new EngineBlockDTO(thePreset);
157         }
158
159         return null;
160     }
161 }