1 package net.sf.openrocket.material;
3 import net.sf.openrocket.database.Databases;
4 import net.sf.openrocket.l10n.Translator;
5 import net.sf.openrocket.startup.Application;
6 import net.sf.openrocket.unit.Unit;
7 import net.sf.openrocket.unit.UnitGroup;
8 import net.sf.openrocket.util.MathUtil;
11 * A class for different material types. Each material has a name and density.
12 * The interpretation of the density depends on the material type. For
13 * {@link Type#BULK} it is kg/m^3, for {@link Type#SURFACE} km/m^2.
15 * Objects of this type are immutable.
17 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
20 public abstract class Material implements Comparable<Material> {
22 private static final Translator trans = Application.getTranslator();
25 LINE("Line", UnitGroup.UNITS_DENSITY_LINE),
26 SURFACE("Surface", UnitGroup.UNITS_DENSITY_SURFACE),
27 BULK("Bulk", UnitGroup.UNITS_DENSITY_BULK);
29 private final String name;
30 private final UnitGroup units;
32 private Type(String name, UnitGroup units) {
33 this.name = trans.get ("Databases.materials.types." + name);
37 public UnitGroup getUnitGroup() {
42 public String toString() {
48 ///// Definitions of different material types /////
50 public static class Line extends Material {
51 Line(String name, String key, double density, boolean userDefined) {
52 super(name, key, density, userDefined);
56 public Type getType() {
61 public static class Surface extends Material {
63 Surface(String name, String key, double density, boolean userDefined) {
64 super(name, key, density, userDefined);
68 public Type getType() {
73 public String toStorableString() {
74 return super.toStorableString();
78 public static class Bulk extends Material {
79 Bulk(String name, String key, double density, boolean userDefined) {
80 super(name, key, density, userDefined);
84 public Type getType() {
91 private final String name;
92 private final String key;
93 private final double density;
94 private final boolean userDefined;
98 * Constructor for materials.
100 * @param name ignored when defining system materials.
101 * @param key ignored when defining user materials.
103 * @param userDefined true if this is a user defined material, false if it is a system material.
105 private Material(String name, String key, double density, boolean userDefined) {
107 this.key = "UserDefined."+name;
111 this.name = trans.get("Databases.materials." + key);
113 this.userDefined = userDefined;
114 this.density = density;
117 public String getKey() {
121 public double getDensity() {
125 public String getName() {
129 public String getName(Unit u) {
130 return name + " (" + u.toStringUnit(density) + ")";
133 public boolean isUserDefined() {
137 public abstract Type getType();
140 public String toString() {
141 return this.getName(this.getType().getUnitGroup().getDefaultUnit());
146 * Compares this object to another object. Material objects are equal if and only if
147 * their types, names and densities are identical.
150 public boolean equals(Object o) {
153 if (this.getClass() != o.getClass())
155 Material m = (Material) o;
156 return ((m.name.equals(this.name)) && MathUtil.equals(m.density, this.density));
161 * A hashCode() method giving a hash code compatible with the equals() method.
164 public int hashCode() {
165 return name.hashCode() + (int) (density * 1000);
170 * Order the materials according to their name, secondarily according to density.
173 public int compareTo(Material o) {
174 int c = this.name.compareTo(o.name);
178 return (int) ((this.density - o.density) * 1000);
183 public static Material newSystemMaterial(Type type, String key, double density ) {
186 return new Material.Line(null, key, density, false);
189 return new Material.Surface(null,key, density, false);
192 return new Material.Bulk(null, key, density, false);
195 throw new IllegalArgumentException("Unknown material type: " + type);
200 * Return a new user defined material of the specified type.
202 public static Material newUserMaterial(Type type, String name, double density) {
205 return new Material.Line(name, null, density, true);
208 return new Material.Surface(name, null, density, true);
211 return new Material.Bulk(name, null, density, true);
214 throw new IllegalArgumentException("Unknown material type: " + type);
219 * Return a new user defined material of the specified type and localizable key.
221 public static Material newUserMaterialWithKey(Type type, String key, String name, double density) {
224 return new Material.Line(name, key, density, true);
227 return new Material.Surface(name, key, density, true);
230 return new Material.Bulk(name, key, density, true);
233 throw new IllegalArgumentException("Unknown material type: " + type);
239 public String toStorableString() {
240 return getType().name() + "|" + key + "|" + name.replace('|', ' ') + '|' + density;
245 * Return a material defined by the provided string.
247 * @param str the material storage string.
248 * @param userDefined whether the created material is user-defined.
249 * @return a new <code>Material</code> object.
250 * @throws IllegalArgumentException if <code>str</code> is invalid or null.
252 public static Material fromStorableString(String str) {
254 throw new IllegalArgumentException("Material string is null");
256 String[] split = str.split("\\|");
257 if (split.length < 3)
258 throw new IllegalArgumentException("Illegal material string: " + str);
263 String densityString;
266 type = Type.valueOf(split[0]);
267 } catch (Exception e) {
268 throw new IllegalArgumentException("Illegal material string: " + str, e);
271 if ( split.length == 3 ) {
273 densityString =split[2];
277 densityString=split[3];
284 density = Double.parseDouble(densityString);
285 } catch (NumberFormatException e) {
286 throw new IllegalArgumentException("Illegal material string: " + str, e);
289 return Databases.findMaterial(type, key, name, density);