1 package net.sf.openrocket.preset.xml;
3 import net.sf.openrocket.material.Material;
4 import net.sf.openrocket.preset.ComponentPreset;
5 import net.sf.openrocket.preset.InvalidComponentPresetException;
6 import net.sf.openrocket.startup.Application;
8 import javax.xml.bind.JAXBContext;
9 import javax.xml.bind.JAXBException;
10 import javax.xml.bind.Marshaller;
11 import javax.xml.bind.Unmarshaller;
12 import java.io.BufferedWriter;
13 import java.io.IOException;
14 import java.io.OutputStream;
15 import java.io.OutputStreamWriter;
16 import java.io.Reader;
17 import java.io.StringWriter;
18 import java.util.List;
21 * The active manager class that is the entry point for reading and writing *.orc files.
23 public class OpenRocketComponentSaver {
26 * The JAXBContext. JAXBContext is thread-safe.
28 private static JAXBContext context = null;
32 context = JAXBContext.newInstance(OpenRocketComponentDTO.class);
34 catch (JAXBException jaxb) {
35 Application.getLogger().error("Unable to create JAXBContext for loading of *.orc files.", jaxb);
40 * This method marshals a list of materials and ComponentPresets into an .orc formatted XML string.
42 * @param theMaterialList the list of materials to be included
43 * @param thePresetList the list of presets to be included
45 * @return ORC-compliant XML
47 * @throws JAXBException
49 public String marshalToOpenRocketComponent(List<Material> theMaterialList, List<ComponentPreset> thePresetList) throws
51 /** The context is thread-safe, but marshallers are not. Create a local one. */
52 Marshaller marshaller = context.createMarshaller();
53 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
54 StringWriter sw = new StringWriter();
56 marshaller.marshal(toOpenRocketComponentDTO(theMaterialList, thePresetList), sw);
62 * This method unmarshals from a Reader that is presumed to be open on an XML file in .orc format.
64 * @param is an open reader; StringBufferInputStream could not be used because it's deprecated and does not handle UTF
65 * characters correctly
67 * @return a list of ComponentPresets
69 * @throws InvalidComponentPresetException
72 public List<ComponentPreset> unmarshalFromOpenRocketComponent(Reader is) throws JAXBException,
73 InvalidComponentPresetException {
74 return fromOpenRocketComponent(is).asComponentPresets();
78 * Write an XML representation of a list of presets.
80 * @param dest the stream to write the data to
81 * @param theMaterialList the list of materials to be included
82 * @param thePresetList the list of presets to be included
84 * @throws JAXBException
85 * @throws IOException thrown if the stream could not be written
87 public void save(OutputStream dest, List<Material> theMaterialList, List<ComponentPreset> thePresetList) throws
90 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, "UTF-8"));
91 writer.write(marshalToOpenRocketComponent(theMaterialList, thePresetList));
97 * Read from an open Reader instance XML in .orc format and reconstruct an OpenRocketComponentDTO instance.
99 * @param is an open Reader; assumed to be opened on a file of XML in .orc format
101 * @return the OpenRocketComponentDTO that is a POJO representation of the XML; null if the data could not be read or
102 * was in an invalid format
104 private OpenRocketComponentDTO fromOpenRocketComponent(Reader is) throws JAXBException {
105 /** The context is thread-safe, but unmarshallers are not. Create a local one. */
106 Unmarshaller unmarshaller = context.createUnmarshaller();
107 return (OpenRocketComponentDTO) unmarshaller.unmarshal(is);
111 * Root conversion method. It iterates over all subcomponents.
113 * @return a corresponding ORC representation
115 private OpenRocketComponentDTO toOpenRocketComponentDTO(List<Material> theMaterialList, List<ComponentPreset> thePresetList) {
116 OpenRocketComponentDTO rsd = new OpenRocketComponentDTO();
118 if (theMaterialList != null) {
119 for (Material material : theMaterialList) {
120 rsd.addMaterial(new MaterialDTO(material));
124 if (thePresetList != null) {
125 for (ComponentPreset componentPreset : thePresetList) {
126 rsd.addComponent(toComponentDTO(componentPreset));
133 * Factory method that maps a preset to the corresponding DTO handler.
135 * @param thePreset the preset for which a handler will be found
137 * @return a subclass of BaseComponentDTO that can be used for marshalling/unmarshalling a preset; null if not found
138 * for the preset type
140 private static BaseComponentDTO toComponentDTO(ComponentPreset thePreset) {
141 switch (thePreset.getType()) {
143 return new BodyTubeDTO(thePreset);
145 return new TubeCouplerDTO(thePreset);
147 return new NoseConeDTO(thePreset);
149 return new TransitionDTO(thePreset);
151 return new BulkHeadDTO(thePreset);
153 return new CenteringRingDTO(thePreset);
155 return new EngineBlockDTO(thePreset);