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