create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / material / Material.java
1 package net.sf.openrocket.material;
2
3 import net.sf.openrocket.l10n.Translator;
4 import net.sf.openrocket.startup.Application;
5 import net.sf.openrocket.unit.Unit;
6 import net.sf.openrocket.unit.UnitGroup;
7 import net.sf.openrocket.util.MathUtil;
8
9 /**
10  * A class for different material types.  Each material has a name and density.
11  * The interpretation of the density depends on the material type.  For
12  * {@link Type#BULK} it is kg/m^3, for {@link Type#SURFACE} km/m^2.
13  * <p>
14  * Objects of this type are immutable.
15  * 
16  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
17  */
18
19 public abstract class Material implements Comparable<Material> {
20         
21         private static final Translator trans = Application.getTranslator();
22         
23         public enum Type {
24                 LINE("Databases.materials.types.Line", UnitGroup.UNITS_DENSITY_LINE),
25                 SURFACE("Databases.materials.types.Surface", UnitGroup.UNITS_DENSITY_SURFACE),
26                 BULK("Databases.materials.types.Bulk", UnitGroup.UNITS_DENSITY_BULK);
27                 
28                 private final String name;
29                 private final UnitGroup units;
30                 
31                 private Type(String nameKey, UnitGroup units) {
32                         this.name = trans.get(nameKey);
33                         this.units = units;
34                 }
35                 
36                 public UnitGroup getUnitGroup() {
37                         return units;
38                 }
39                 
40                 @Override
41                 public String toString() {
42                         return name;
43                 }
44         }
45         
46         
47         /////  Definitions of different material types  /////
48         
49         public static class Line extends Material {
50                 Line(String name, double density, boolean userDefined) {
51                         super(name, density, userDefined);
52                 }
53                 
54                 @Override
55                 public Type getType() {
56                         return Type.LINE;
57                 }
58         }
59         
60         public static class Surface extends Material {
61                 
62                 Surface(String name, double density, boolean userDefined) {
63                         super(name, density, userDefined);
64                 }
65                 
66                 @Override
67                 public Type getType() {
68                         return Type.SURFACE;
69                 }
70                 
71                 @Override
72                 public String toStorableString() {
73                         return super.toStorableString();
74                 }
75         }
76         
77         public static class Bulk extends Material {
78                 Bulk(String name, double density, boolean userDefined) {
79                         super(name, density, userDefined);
80                 }
81                 
82                 @Override
83                 public Type getType() {
84                         return Type.BULK;
85                 }
86         }
87         
88         
89         
90         private final String name;
91         private final double density;
92         private final boolean userDefined;
93         
94         
95         /**
96          * Constructor for materials.
97          * 
98          * @param name ignored when defining system materials.
99          * @param key ignored when defining user materials.
100          * @param density
101          * @param userDefined true if this is a user defined material, false if it is a system material.
102          */
103         private Material(String name, double density, boolean userDefined) {
104                 this.name = name;
105                 this.userDefined = userDefined;
106                 this.density = density;
107         }
108         
109         public double getDensity() {
110                 return density;
111         }
112         
113         public String getName() {
114                 return name;
115         }
116         
117         public String getName(Unit u) {
118                 return name + " (" + u.toStringUnit(density) + ")";
119         }
120         
121         public boolean isUserDefined() {
122                 return userDefined;
123         }
124         
125         public abstract Type getType();
126         
127         @Override
128         public String toString() {
129                 return this.getName(this.getType().getUnitGroup().getDefaultUnit());
130         }
131         
132         
133         /**
134          * Compares this object to another object.  Material objects are equal if and only if
135          * their types, names and densities are identical.
136          */
137         @Override
138         public boolean equals(Object o) {
139                 if (o == null)
140                         return false;
141                 if (this.getClass() != o.getClass())
142                         return false;
143                 Material m = (Material) o;
144                 return ((m.name.equals(this.name)) && MathUtil.equals(m.density, this.density));
145         }
146         
147         
148         /**
149          * A hashCode() method giving a hash code compatible with the equals() method.
150          */
151         @Override
152         public int hashCode() {
153                 return name.hashCode() + (int) (density * 1000);
154         }
155         
156         
157         /**
158          * Order the materials according to their name, secondarily according to density.
159          */
160         @Override
161         public int compareTo(Material o) {
162                 int c = this.name.compareTo(o.name);
163                 if (c != 0) {
164                         return c;
165                 } else {
166                         return (int) ((this.density - o.density) * 1000);
167                 }
168         }
169         
170         
171         /**
172          * Return a new material.  The name is used as-is, without any translation.
173          * 
174          * @param type                  the material type
175          * @param name                  the material name
176          * @param density               the material density
177          * @param userDefined   whether the material is user-defined or not
178          * @return                              the new material
179          */
180         public static Material newMaterial(Type type, String name, double density, boolean userDefined) {
181                 switch (type) {
182                 case LINE:
183                         return new Material.Line(name, density, userDefined);
184                         
185                 case SURFACE:
186                         return new Material.Surface(name, density, userDefined);
187                         
188                 case BULK:
189                         return new Material.Bulk(name, density, userDefined);
190                         
191                 default:
192                         throw new IllegalArgumentException("Unknown material type: " + type);
193                 }
194         }
195         
196         public String toStorableString() {
197                 return getType().name() + "|" + name.replace('|', ' ') + '|' + density;
198         }
199         
200         
201         /**
202          * Return a material defined by the provided string.
203          * 
204          * @param str                   the material storage string.
205          * @param userDefined   whether the created material is user-defined.
206          * @return                              a new <code>Material</code> object.
207          * @throws IllegalArgumentException             if <code>str</code> is invalid or null.
208          */
209         public static Material fromStorableString(String str, boolean userDefined) {
210                 if (str == null)
211                         throw new IllegalArgumentException("Material string is null");
212                 
213                 String[] split = str.split("\\|", 3);
214                 if (split.length < 3)
215                         throw new IllegalArgumentException("Illegal material string: " + str);
216                 
217                 Type type = null;
218                 String name;
219                 double density;
220                 
221                 try {
222                         type = Type.valueOf(split[0]);
223                 } catch (Exception e) {
224                         throw new IllegalArgumentException("Illegal material string: " + str, e);
225                 }
226                 
227                 name = split[1];
228                 
229                 try {
230                         density = Double.parseDouble(split[2]);
231                 } catch (NumberFormatException e) {
232                         throw new IllegalArgumentException("Illegal material string: " + str, e);
233                 }
234                 
235                 switch (type) {
236                 case BULK:
237                         return new Material.Bulk(name, density, userDefined);
238                         
239                 case SURFACE:
240                         return new Material.Surface(name, density, userDefined);
241                         
242                 case LINE:
243                         return new Material.Line(name, density, userDefined);
244                         
245                 default:
246                         throw new IllegalArgumentException("Illegal material string: " + str);
247                 }
248         }
249         
250 }