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