package net.sf.openrocket.preset.xml;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlValue;
-
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.preset.TypedPropertyMap;
import net.sf.openrocket.unit.UnitGroup;
+import javax.imageio.ImageIO;
+import javax.xml.bind.DatatypeConverter;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlInlineBinaryData;
+import javax.xml.bind.annotation.XmlValue;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+
/**
* Base class for the external representation of all component presets.
*/
private AnnotatedMassDTO mass;
@XmlElement(name="Filled")
private Boolean filled;
+ @XmlInlineBinaryData
+ @XmlJavaTypeAdapter(Base64Adapter.class)
+ @XmlElement(name = "Thumbnail")
+ private byte[] image;
/**
* Default constructor.
this.filled = filled;
}
- public abstract ComponentPreset asComponentPreset(List<MaterialDTO> materials) throws InvalidComponentPresetException;
+ public byte[] getImageData() {
+ return image;
+ }
+
+ public void setImageData(final byte[] theImage) {
+ image = theImage;
+ }
+
+ public BufferedImage getImage() throws IOException {
+ if (image != null) {
+ return ImageIO.read(new ByteArrayInputStream(image));
+ }
+ return null;
+ }
+
+ public void setImage(BufferedImage theImage) throws IOException {
+ if (theImage != null) {
+ final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ImageIO.write(theImage, "png", byteArrayOutputStream);
+ image = byteArrayOutputStream.toByteArray();
+ }
+ }
+
+ public abstract ComponentPreset asComponentPreset(List<MaterialDTO> materials) throws InvalidComponentPresetException;
void addProps(TypedPropertyMap props, List<MaterialDTO> materialList) {
props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(manufacturer));
material = theMaterial.getName();
}
}
-
+
static class AnnotatedLengthDTO {
@XmlAttribute(name="Unit", required=false)
private String unitName = "m";
@XmlValue
private double length;
-
+
AnnotatedLengthDTO() {}
-
+
AnnotatedLengthDTO( double length ) {
this.length = length;
}
return UnitGroup.UNITS_LENGTH.getUnit(unitName).fromUnit(length);
}
}
-
+
static class AnnotatedMassDTO {
@XmlAttribute(name="Unit", required=false)
private String unitName = "kg";
@XmlValue
private double mass;
-
+
AnnotatedMassDTO() {}
-
+
AnnotatedMassDTO( double mass ) {
this.mass = mass;
}
-
+
public double getValue() {
return UnitGroup.UNITS_MASS.getUnit(unitName).fromUnit(mass);
}
}
+
+ static class Base64Adapter extends XmlAdapter<String, byte[]> {
+ public byte[] unmarshal(String s) {
+ if (s == null) {
+ return null;
+ }
+ return DatatypeConverter.parseBase64Binary(s);
+ }
+
+ public String marshal(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ return DatatypeConverter.printBase64Binary(bytes);
+ }
+ }
}
import net.sf.openrocket.material.Material;
import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.preset.InvalidComponentPresetException;
+import net.sf.openrocket.startup.Application;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
*/
public class OpenRocketComponentSaver {
+ /**
+ * The JAXBContext. JAXBContext is thread-safe.
+ */
+ private static JAXBContext context = null;
+
+ static {
+ try {
+ context = JAXBContext.newInstance(OpenRocketComponentDTO.class);
+ }
+ catch (JAXBException jaxb) {
+ Application.getLogger().error("Unable to create JAXBContext for loading of *.orc files.", jaxb);
+ }
+ }
+
/**
* This method marshals a list of materials and ComponentPresets into an .orc formatted XML string.
*
*/
public String marshalToOpenRocketComponent(List<Material> theMaterialList, List<ComponentPreset> thePresetList) throws
JAXBException {
-
- JAXBContext binder = JAXBContext.newInstance(OpenRocketComponentDTO.class);
- Marshaller marshaller = binder.createMarshaller();
+ /** The context is thread-safe, but marshallers are not. Create a local one. */
+ Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter sw = new StringWriter();
* was in an invalid format
*/
private OpenRocketComponentDTO fromOpenRocketComponent(Reader is) throws JAXBException {
- JAXBContext bind = JAXBContext.newInstance(OpenRocketComponentDTO.class);
- Unmarshaller unmarshaller = bind.createUnmarshaller();
+ /** The context is thread-safe, but unmarshallers are not. Create a local one. */
+ Unmarshaller unmarshaller = context.createUnmarshaller();
return (OpenRocketComponentDTO) unmarshaller.unmarshal(is);
}
--- /dev/null
+package net.sf.openrocket.preset.xml;
+
+import net.sf.openrocket.motor.Manufacturer;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.ComponentPresetFactory;
+import net.sf.openrocket.preset.TypedPropertyMap;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.imageio.ImageIO;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+/**
+ */
+public class BaseComponentDTOTest {
+
+
+ @Test
+ public void testImage() throws Exception {
+ TypedPropertyMap presetspec = new TypedPropertyMap();
+ presetspec.put(ComponentPreset.TYPE, ComponentPreset.Type.BODY_TUBE);
+ presetspec.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer("manufacturer"));
+ presetspec.put(ComponentPreset.PARTNO, "partno");
+ presetspec.put(ComponentPreset.LENGTH, 2.0);
+ presetspec.put(ComponentPreset.OUTER_DIAMETER, 2.0);
+ presetspec.put(ComponentPreset.INNER_DIAMETER, 1.0);
+ presetspec.put(ComponentPreset.MASS, 100.0);
+ ComponentPreset preset = ComponentPresetFactory.create(presetspec);
+
+ //Convert the presets to a BodyTubeDTO
+ BodyTubeDTO dto = new BodyTubeDTO(preset);
+
+ //Add an image to the DTO.
+ BufferedImage image = ImageIO.read(this.getClass().getResourceAsStream("or_launcher.png"));
+ dto.setImage(image);
+
+ JAXBContext binder = JAXBContext.newInstance(OpenRocketComponentDTO.class);
+ Marshaller marshaller = binder.createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ StringWriter sw = new StringWriter();
+
+ //Serialize the dto to XML
+ marshaller.marshal(dto, sw);
+ String xml = sw.toString();
+
+ //Read the XML back to create the dto again
+ Unmarshaller unmarshaller = binder.createUnmarshaller();
+ BodyTubeDTO redone = (BodyTubeDTO) unmarshaller.unmarshal(new StringReader(xml));
+
+ //Compare the image.
+ Assert.assertArrayEquals(((DataBufferByte) image.getData().getDataBuffer()).getData(),
+ ((DataBufferByte) redone.getImage().getData().getDataBuffer()).getData());
+
+ //Assert the rest of the attributes.
+ Assert.assertEquals(dto.getInsideDiameter(), redone.getInsideDiameter(), 0.00001);
+ Assert.assertEquals(dto.getLength(), redone.getLength(), 0.00001);
+ Assert.assertEquals(dto.getOutsideDiameter(), redone.getOutsideDiameter(), 0.00001);
+ Assert.assertEquals(dto.getDescription(), redone.getDescription());
+ Assert.assertEquals(dto.getManufacturer(), redone.getManufacturer());
+ Assert.assertEquals(dto.getMass(), redone.getMass(), 0.00001);
+ Assert.assertEquals(dto.getPartNo(), redone.getPartNo());
+
+ //Uncomment if you want to write the image to a file to view it.
+// ImageIO.write(redone.getImage(), "png", new FileOutputStream("redone.png"));
+ }
+}
--- /dev/null
+package net.sf.openrocket.preset.xml;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+* OpenRocketComponentSaver Tester.
+*
+*/
+public class OpenRocketComponentSaverTest {
+
+ @Before
+ public void before() throws Exception {
+ }
+
+ @After
+ public void after() throws Exception {
+ }
+
+ /**
+ *
+ * Method: marshalToOpenRocketComponent(List<Material> theMaterialList, List<ComponentPreset> thePresetList)
+ *
+ */
+ @Test
+ public void testMarshalToOpenRocketComponent() throws Exception {
+ //TODO: Test goes here...
+ }
+
+ /**
+ *
+ * Method: unmarshalFromOpenRocketComponent(Reader is)
+ *
+ */
+ @Test
+ public void testUnmarshalFromOpenRocketComponent() throws Exception {
+ //TODO: Test goes here...
+ }
+
+ /**
+ *
+ * Method: save(OutputStream dest, List<Material> theMaterialList, List<ComponentPreset> thePresetList)
+ *
+ */
+ @Test
+ public void testSave() throws Exception {
+ //TODO: Test goes here...
+ }
+
+
+ /**
+ *
+ * Method: fromOpenRocketComponent(Reader is)
+ *
+ */
+ @Test
+ public void testFromOpenRocketComponent() throws Exception {
+ //TODO: Test goes here...
+/*
+try {
+ Method method = OpenRocketComponentSaver.getClass().getMethod("fromOpenRocketComponent", Reader.class);
+ method.setAccessible(true);
+ method.invoke(<Object>, <Parameters>);
+} catch(NoSuchMethodException e) {
+} catch(IllegalAccessException e) {
+} catch(InvocationTargetException e) {
+}
+*/
+ }
+
+ /**
+ *
+ * Method: toOpenRocketComponentDTO(List<Material> theMaterialList, List<ComponentPreset> thePresetList)
+ *
+ */
+ @Test
+ public void testToOpenRocketComponentDTO() throws Exception {
+ //TODO: Test goes here...
+/*
+try {
+ Method method = OpenRocketComponentSaver.getClass().getMethod("toOpenRocketComponentDTO", List<Material>.class, List<ComponentPreset>.class);
+ method.setAccessible(true);
+ method.invoke(<Object>, <Parameters>);
+} catch(NoSuchMethodException e) {
+} catch(IllegalAccessException e) {
+} catch(InvocationTargetException e) {
+}
+*/
+ }
+
+ /**
+ *
+ * Method: toComponentDTO(ComponentPreset thePreset)
+ *
+ */
+ @Test
+ public void testToComponentDTO() throws Exception {
+ //TODO: Test goes here...
+/*
+try {
+ Method method = OpenRocketComponentSaver.getClass().getMethod("toComponentDTO", ComponentPreset.class);
+ method.setAccessible(true);
+ method.invoke(<Object>, <Parameters>);
+} catch(NoSuchMethodException e) {
+} catch(IllegalAccessException e) {
+} catch(InvocationTargetException e) {
+}
+*/
+ }
+
+}