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