Initial commit
[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) {
27                         super(name, density);
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) {
44                         super(name, density);
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) {
65                         super(name, density);
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         
84         
85         public Material(String name, double density) {
86                 this.name = name;
87                 this.density = density;
88         }
89         
90         
91         
92         public double getDensity() {
93                 return density;
94         }
95         
96         public String getName() {
97                 return name;
98         }
99         
100         public String getName(Unit u) {
101                 return name + " (" + u.toStringUnit(density) + ")";
102         }
103         
104         public abstract UnitGroup getUnitGroup();
105         public abstract Type getType();
106         
107         @Override
108         public String toString() {
109                 return getName(getUnitGroup().getDefaultUnit());
110         }
111         
112
113         /**
114          * Compares this object to another object.  Material objects are equal if and only if
115          * their types, names and densities are identical.
116          */
117         @Override
118         public boolean equals(Object o) {
119                 if (o == null)
120                         return false;
121                 if (this.getClass() != o.getClass())
122                         return false;
123                 Material m = (Material)o;
124                 return ((m.name.equals(this.name)) && 
125                                 MathUtil.equals(m.density, this.density)); 
126         }
127
128
129         /**
130          * A hashCode() method giving a hash code compatible with the equals() method.
131          */
132         @Override
133         public int hashCode() {
134                 return name.hashCode() + (int)(density*1000);
135         }
136
137         
138         /**
139          * Order the materials according to their name, secondarily according to density.
140          */
141         public int compareTo(Material o) {
142                 int c = this.name.compareTo(o.name);
143                 if (c != 0) {
144                         return c;
145                 } else {
146                         return (int)((this.density - o.density)*1000);
147                 }
148         }
149         
150         
151         
152         public static Material newMaterial(Type type, String name, double density) {
153                 switch (type) {
154                 case LINE:
155                         return new Material.Line(name, density);
156                         
157                 case SURFACE:
158                         return new Material.Surface(name, density);
159                         
160                 case BULK:
161                         return new Material.Bulk(name, density);
162                         
163                 default:
164                         throw new IllegalArgumentException("Unknown material type: "+type);
165                 }
166         }
167         
168         
169         public String toStorableString() {
170                 return getType().name() + "|" + name.replace('|', ' ') + '|' + density;
171         }
172         
173         public static Material fromStorableString(String str) {
174                 String[] split = str.split("\\|",3);
175                 if (split.length < 3)
176                         throw new IllegalArgumentException("Illegal material string: "+str);
177
178                 Type type = null;
179                 String name;
180                 double density;
181                 
182                 try {
183                         type = Type.valueOf(split[0]);
184                 } catch (Exception e) {
185                         throw new IllegalArgumentException("Illegal material string: "+str, e);
186                 }
187
188                 name = split[1];
189                 
190                 try {
191                         density = Double.parseDouble(split[2]);
192                 } catch (NumberFormatException e) {
193                         throw new IllegalArgumentException("Illegal material string: "+str, e);
194                 }
195                 
196                 switch (type) {
197                 case BULK:
198                         return new Material.Bulk(name, density);
199                         
200                 case SURFACE:
201                         return new Material.Surface(name, density);
202                         
203                 case LINE:
204                         return new Material.Line(name, density);
205                         
206                 default:
207                         throw new IllegalArgumentException("Illegal material string: "+str);
208                 }
209         }
210
211 }