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