1 package net.sf.openrocket.preset.xml;
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;
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;
22 * The active manager class that is the entry point for writing *.orc files.
24 public class OpenRocketComponentSaver {
29 private static final LogHelper log = Application.getLogger();
32 * This method marshals an OpenRocketDocument (OR design) to Rocksim-compliant XML.
34 * @param theMaterialList the list of materials to be included
35 * @param thePresetList the list of presets to be included
37 * @return ORC-compliant XML
39 public String marshalToOpenRocketComponent(List<Material> theMaterialList, List<ComponentPreset> thePresetList) {
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();
47 marshaller.marshal(toOpenRocketComponentDTO(theMaterialList, thePresetList), sw);
51 log.error("Could not marshal a preset list. " + e.getMessage());
58 * This method unmarshals from a Reader that is presumed to be open on an XML file in .orc format.
60 * @param is an open reader; StringBufferInputStream could not be used because it's deprecated and does not handle
61 * UTF characters correctly
63 * @return a list of ComponentPresets
65 * @throws InvalidComponentPresetException
68 public List<ComponentPreset> unmarshalFromOpenRocketComponent(Reader is) throws InvalidComponentPresetException {
69 return fromOpenRocketComponent(is).asComponentPresets();
73 * Write an XML representation of a list of presets.
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
79 * @throws IOException thrown if the stream could not be written
81 public void save(OutputStream dest, List<Material> theMaterialList, List<ComponentPreset> thePresetList) throws
83 log.info("Saving .orc file");
85 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, "UTF-8"));
86 writer.write(marshalToOpenRocketComponent(theMaterialList, thePresetList));
92 * Read from an open Reader instance XML in .orc format and reconstruct an OpenRocketComponentDTO instance.
94 * @param is an open Reader; assumed to be opened on a file of XML in .orc format
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
99 private OpenRocketComponentDTO fromOpenRocketComponent(Reader is) {
101 JAXBContext bind = JAXBContext.newInstance(OpenRocketComponentDTO.class);
102 Unmarshaller unmarshaller = bind.createUnmarshaller();
103 return (OpenRocketComponentDTO) unmarshaller.unmarshal(is);
105 catch (JAXBException e) {
106 log.error("Could not unmarshal the .orc file. ", e);
112 * Root conversion method. It iterates over all subcomponents.
114 * @return a corresponding ORC representation
116 private OpenRocketComponentDTO toOpenRocketComponentDTO(List<Material> theMaterialList, List<ComponentPreset> thePresetList) {
117 OpenRocketComponentDTO rsd = new OpenRocketComponentDTO();
119 if (theMaterialList != null) {
120 for (Material material : theMaterialList) {
121 rsd.addMaterial(new MaterialDTO(material));
125 if (thePresetList != null) {
126 for (ComponentPreset componentPreset : thePresetList) {
127 rsd.addComponent(toComponentDTO(componentPreset));
134 * Factory method that maps a preset to the corresponding DTO handler.
136 * @param thePreset the preset for which a handler will be found
138 * @return a subclass of BaseComponentDTO that can be used for marshalling/unmarshalling a preset; null if not found
139 * for the preset type
141 private static BaseComponentDTO toComponentDTO(ComponentPreset thePreset) {
142 switch (thePreset.getType()) {
144 return new BodyTubeDTO(thePreset);
146 return new TubeCouplerDTO(thePreset);
148 return new NoseConeDTO(thePreset);
150 return new TransitionDTO(thePreset);
152 return new BulkHeadDTO(thePreset);
154 return new CenteringRingDTO(thePreset);
156 return new EngineBlockDTO(thePreset);