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 that is not user-defined.
159          */
160         public static Material newMaterial(Type type, String name, double density) {
161                 return newMaterial(type, name, density, false);
162         }
163
164         /**
165          * Return a new material of the specified type.
166          */
167         public static Material newMaterial(Type type, String name, double density, 
168                         boolean userDefined) {
169                 switch (type) {
170                 case LINE:
171                         return new Material.Line(name, density, userDefined);
172                         
173                 case SURFACE:
174                         return new Material.Surface(name, density, userDefined);
175                         
176                 case BULK:
177                         return new Material.Bulk(name, density, userDefined);
178                         
179                 default:
180                         throw new IllegalArgumentException("Unknown material type: "+type);
181                 }
182         }
183         
184         
185         public String toStorableString() {
186                 return getType().name() + "|" + name.replace('|', ' ') + '|' + density;
187         }
188         
189         public static Material fromStorableString(String str, boolean userDefined) {
190                 String[] split = str.split("\\|",3);
191                 if (split.length < 3)
192                         throw new IllegalArgumentException("Illegal material string: "+str);
193
194                 Type type = null;
195                 String name;
196                 double density;
197                 
198                 try {
199                         type = Type.valueOf(split[0]);
200                 } catch (Exception e) {
201                         throw new IllegalArgumentException("Illegal material string: "+str, e);
202                 }
203
204                 name = split[1];
205                 
206                 try {
207                         density = Double.parseDouble(split[2]);
208                 } catch (NumberFormatException e) {
209                         throw new IllegalArgumentException("Illegal material string: "+str, e);
210                 }
211                 
212                 switch (type) {
213                 case BULK:
214                         return new Material.Bulk(name, density, userDefined);
215                         
216                 case SURFACE:
217                         return new Material.Surface(name, density, userDefined);
218                         
219                 case LINE:
220                         return new Material.Line(name, density, userDefined);
221                         
222                 default:
223                         throw new IllegalArgumentException("Illegal material string: "+str);
224                 }
225         }
226
227 }