Material localization support
[debian/openrocket] / core / src / net / sf / openrocket / preset / xml / BaseComponentDTO.java
1 package net.sf.openrocket.preset.xml;
2
3 import java.awt.image.BufferedImage;
4 import java.io.ByteArrayInputStream;
5 import java.io.ByteArrayOutputStream;
6 import java.io.IOException;
7 import java.util.List;
8
9 import javax.imageio.ImageIO;
10 import javax.xml.bind.DatatypeConverter;
11 import javax.xml.bind.annotation.XmlAccessType;
12 import javax.xml.bind.annotation.XmlAccessorType;
13 import javax.xml.bind.annotation.XmlAttribute;
14 import javax.xml.bind.annotation.XmlElement;
15 import javax.xml.bind.annotation.XmlInlineBinaryData;
16 import javax.xml.bind.annotation.XmlValue;
17 import javax.xml.bind.annotation.adapters.XmlAdapter;
18 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
19
20 import net.sf.openrocket.database.Databases;
21 import net.sf.openrocket.material.Material;
22 import net.sf.openrocket.motor.Manufacturer;
23 import net.sf.openrocket.preset.ComponentPreset;
24 import net.sf.openrocket.preset.InvalidComponentPresetException;
25 import net.sf.openrocket.preset.TypedPropertyMap;
26 import net.sf.openrocket.unit.UnitGroup;
27
28 /**
29  * Base class for the external representation of all component presets.
30  */
31 @XmlAccessorType(XmlAccessType.FIELD)
32 public abstract class BaseComponentDTO {
33         
34         @XmlElement(name = "Manufacturer")
35         private String manufacturer;
36         @XmlElement(name = "PartNumber")
37         private String partNo;
38         @XmlElement(name = "Description")
39         private String description;
40         @XmlElement(name = "Material")
41         private AnnotatedMaterialDTO material;
42         @XmlElement(name = "Mass")
43         private AnnotatedMassDTO mass;
44         @XmlElement(name = "Filled")
45         private Boolean filled;
46         @XmlInlineBinaryData
47         @XmlJavaTypeAdapter(Base64Adapter.class)
48         @XmlElement(name = "Thumbnail")
49         private byte[] image;
50         
51         /**
52          * Default constructor.
53          */
54         protected BaseComponentDTO() {
55         }
56         
57         /**
58          * Constructor.
59          *
60          * @param preset  the preset to use to pull data values out of
61          *
62          * @throws net.sf.openrocket.util.BugException thrown if the expected body tube keys are not in the preset
63          */
64         protected BaseComponentDTO(final ComponentPreset preset) {
65                 setManufacturer(preset.getManufacturer().getSimpleName());
66                 setPartNo(preset.getPartNo());
67                 if (preset.has(ComponentPreset.DESCRIPTION)) {
68                         setDescription(preset.get(ComponentPreset.DESCRIPTION));
69                 }
70                 if (preset.has(ComponentPreset.MATERIAL)) {
71                         setMaterial(new AnnotatedMaterialDTO(preset.get(ComponentPreset.MATERIAL)));
72                 }
73                 if (preset.has(ComponentPreset.MASS)) {
74                         setMass(preset.get(ComponentPreset.MASS));
75                 }
76                 if (preset.has(ComponentPreset.FILLED)) {
77                         setFilled(preset.get(ComponentPreset.FILLED));
78                 }
79                 if (preset.has(ComponentPreset.IMAGE)) {
80                         setImageData(preset.get(ComponentPreset.IMAGE));
81                 }
82         }
83         
84         public String getManufacturer() {
85                 return manufacturer;
86         }
87         
88         public void setManufacturer(final String theManufacturer) {
89                 manufacturer = theManufacturer;
90         }
91         
92         public String getPartNo() {
93                 return partNo;
94         }
95         
96         public void setPartNo(final String thePartNo) {
97                 partNo = thePartNo;
98         }
99         
100         public String getDescription() {
101                 return description;
102         }
103         
104         public void setDescription(final String theDescription) {
105                 description = theDescription;
106         }
107         
108         public AnnotatedMaterialDTO getMaterial() {
109                 return material;
110         }
111         
112         public void setMaterial(final AnnotatedMaterialDTO theMaterial) {
113                 material = theMaterial;
114         }
115         
116         public double getMass() {
117                 return mass.getValue();
118         }
119         
120         public void setMass(final AnnotatedMassDTO theMass) {
121                 mass = theMass;
122         }
123         
124         public void setMass(final double theMass) {
125                 mass = new AnnotatedMassDTO(theMass);
126         }
127         
128         public Boolean getFilled() {
129                 return filled;
130         }
131         
132         public void setFilled(Boolean filled) {
133                 this.filled = filled;
134         }
135         
136         public byte[] getImageData() {
137                 return image;
138         }
139         
140         public void setImageData(final byte[] theImage) {
141                 image = theImage;
142         }
143         
144         public BufferedImage getImage() throws IOException {
145                 if (image != null) {
146                         return ImageIO.read(new ByteArrayInputStream(image));
147                 }
148                 return null;
149         }
150         
151         public void setImage(BufferedImage theImage) throws IOException {
152                 if (theImage != null) {
153                         final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
154                         ImageIO.write(theImage, "png", byteArrayOutputStream);
155                         image = byteArrayOutputStream.toByteArray();
156                 }
157         }
158         
159         public abstract ComponentPreset asComponentPreset(List<MaterialDTO> materials) throws InvalidComponentPresetException;
160         
161         void addProps(TypedPropertyMap props, List<MaterialDTO> materialList) {
162                 props.put(ComponentPreset.MANUFACTURER, Manufacturer.getManufacturer(manufacturer));
163                 props.put(ComponentPreset.PARTNO, partNo);
164                 if (description != null) {
165                         props.put(ComponentPreset.DESCRIPTION, description);
166                 }
167                 Material m = find(materialList, material);
168                 if (m != null) {
169                         props.put(ComponentPreset.MATERIAL, find(materialList, material));
170                 }
171                 if (mass != null) {
172                         props.put(ComponentPreset.MASS, getMass());
173                 }
174                 if (filled != null) {
175                         props.put(ComponentPreset.FILLED, getFilled());
176                 }
177                 if (image != null) {
178                         props.put(ComponentPreset.IMAGE, image);
179                 }
180         }
181         
182         protected Material find(List<MaterialDTO> materialList, AnnotatedMaterialDTO dto) {
183                 if (dto == null) {
184                         return null;
185                 }
186                 for (int i = 0; i < materialList.size(); i++) {
187                         MaterialDTO materialDTO = materialList.get(i);
188                         if (materialDTO.getType().name().equals(dto.type) && materialDTO.getName().equals(dto.material)) {
189                                 return materialDTO.asMaterial();
190                         }
191                 }
192                 
193                 // Don't have one, first check OR's database
194                 Material m = Databases.findMaterial(dto.getORMaterialType(), dto.material);
195                 if (m != null) {
196                         return m;
197                 }
198                 
199                 return Databases.findMaterial(dto.getORMaterialType(), dto.material, 0.0);
200                 
201         }
202         
203         static class AnnotatedMaterialDTO {
204                 @XmlAttribute(name = "Type")
205                 private String type;
206                 @XmlValue
207                 private String material;
208                 
209                 AnnotatedMaterialDTO() {
210                 }
211                 
212                 AnnotatedMaterialDTO(Material theMaterial) {
213                         type = theMaterial.getType().name();
214                         material = theMaterial.getName();
215                 }
216                 
217                 public Material.Type getORMaterialType() {
218                         if ("BULK".equals(type)) {
219                                 return Material.Type.BULK;
220                         } else if ("SURFACE".equals(type)) {
221                                 return Material.Type.SURFACE;
222                         } else if ("LINE".equals(type)) {
223                                 return Material.Type.LINE;
224                         }
225                         throw new IllegalArgumentException("Inavlid material type " + type + " specified for Component");
226                 }
227         }
228         
229         static class AnnotatedLengthDTO {
230                 @XmlAttribute(name = "Unit", required = false)
231                 private String unitName = "m";
232                 @XmlValue
233                 private double length;
234                 
235                 AnnotatedLengthDTO() {
236                 }
237                 
238                 AnnotatedLengthDTO(double length) {
239                         this.length = length;
240                 }
241                 
242                 public double getValue() {
243                         return UnitGroup.UNITS_LENGTH.getUnit(unitName).fromUnit(length);
244                 }
245         }
246         
247         static class AnnotatedMassDTO {
248                 @XmlAttribute(name = "Unit", required = false)
249                 private String unitName = "kg";
250                 @XmlValue
251                 private double mass;
252                 
253                 AnnotatedMassDTO() {
254                 }
255                 
256                 AnnotatedMassDTO(double mass) {
257                         this.mass = mass;
258                 }
259                 
260                 public double getValue() {
261                         return UnitGroup.UNITS_MASS.getUnit(unitName).fromUnit(mass);
262                 }
263         }
264         
265         static class Base64Adapter extends XmlAdapter<String, byte[]> {
266                 @Override
267                 public byte[] unmarshal(String s) {
268                         if (s == null) {
269                                 return null;
270                         }
271                         return DatatypeConverter.parseBase64Binary(s);
272                 }
273                 
274                 @Override
275                 public String marshal(byte[] bytes) {
276                         if (bytes == null) {
277                                 return null;
278                         }
279                         return DatatypeConverter.printBase64Binary(bytes);
280                 }
281         }
282 }