updates for 0.9.4
[debian/openrocket] / src / net / sf / openrocket / database / Databases.java
1 package net.sf.openrocket.database;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URL;
6 import java.util.ArrayList;
7
8 import net.sf.openrocket.file.GeneralMotorLoader;
9 import net.sf.openrocket.material.Material;
10 import net.sf.openrocket.material.MaterialStorage;
11 import net.sf.openrocket.motor.Motor;
12 import net.sf.openrocket.util.JarUtil;
13 import net.sf.openrocket.util.MathUtil;
14 import net.sf.openrocket.util.Prefs;
15
16
17 /**
18  * A class that contains single instances of {@link Database} for specific purposes.
19  * 
20  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
21  */
22 public class Databases {
23
24         /* Static implementations of specific databases: */
25         /**
26          * The motor database.
27          */
28         public static final Database<Motor> MOTOR = new Database<Motor>(new GeneralMotorLoader());
29         
30         
31         /**
32          * A database of bulk materials (with bulk densities).
33          */
34         public static final Database<Material> BULK_MATERIAL = new Database<Material>();
35         /**
36          * A database of surface materials (with surface densities).
37          */
38         public static final Database<Material> SURFACE_MATERIAL = new Database<Material>();
39         /**
40          * A database of linear material (with length densities).
41          */
42         public static final Database<Material> LINE_MATERIAL = new Database<Material>();
43         
44         
45
46         // TODO: HIGH: loading the thrust curves and other databases
47         static {
48                 
49                 try {
50                         MOTOR.loadJarDirectory("datafiles/thrustcurves/", ".*\\.[eE][nN][gG]$");
51                 } catch (IOException e) {
52                         System.out.println("Could not read thrust curves from JAR: "+e.getMessage());
53                         
54                         // Try to find directory as a system resource
55                         File dir;
56                         URL url = ClassLoader.getSystemResource("datafiles/thrustcurves/");
57                         
58                         try {
59                                 dir = JarUtil.urlToFile(url);
60                         } catch (Exception e1) {
61                                 dir = new File("datafiles/thrustcurves/");
62                         }
63                                 
64                         try {
65                                 MOTOR.loadDirectory(dir, ".*\\.[eE][nN][gG]$");
66                         } catch (IOException e1) {
67                                 System.out.println("Could not read thrust curves from directory either.");
68                                 throw new RuntimeException(e1);
69                         }
70                 }
71         }
72         
73         static {
74                 
75                 // Add default materials
76                 BULK_MATERIAL.add(new Material.Bulk("Acrylic",          1190, false));
77                 BULK_MATERIAL.add(new Material.Bulk("Balsa",             170, false));
78                 BULK_MATERIAL.add(new Material.Bulk("Birch",             670, false));
79                 BULK_MATERIAL.add(new Material.Bulk("Cardboard",         680, false));
80                 BULK_MATERIAL.add(new Material.Bulk("Carbon fiber",     1780, false));
81                 BULK_MATERIAL.add(new Material.Bulk("Cork",                      240, false));
82                 BULK_MATERIAL.add(new Material.Bulk("Depron",             40, false));
83                 BULK_MATERIAL.add(new Material.Bulk("Fiberglass",       1850, false));
84                 BULK_MATERIAL.add(new Material.Bulk("Kraft phenolic",950, false));
85                 BULK_MATERIAL.add(new Material.Bulk("Maple",             755, false));
86                 BULK_MATERIAL.add(new Material.Bulk("Paper (office)",820, false));
87                 BULK_MATERIAL.add(new Material.Bulk("Pine",                      530, false));
88                 BULK_MATERIAL.add(new Material.Bulk("Plywood (birch)",630, false));
89                 BULK_MATERIAL.add(new Material.Bulk("Polycarbonate (Lexan)",1200, false));
90                 BULK_MATERIAL.add(new Material.Bulk("Polystyrene",  1050, false));
91                 BULK_MATERIAL.add(new Material.Bulk("PVC",                      1390, false));
92                 BULK_MATERIAL.add(new Material.Bulk("Spruce",            450, false));
93                 // TODO: CRITICAL: Add styrofoam
94                 BULK_MATERIAL.add(new Material.Bulk("Quantum tubing",1050, false));
95                 
96                 SURFACE_MATERIAL.add(new Material.Surface("Ripstop nylon",                      0.067, false));
97                 SURFACE_MATERIAL.add(new Material.Surface("Mylar",                                      0.021, false));
98                 SURFACE_MATERIAL.add(new Material.Surface("Polyethylene (thin)",        0.015, false));
99                 SURFACE_MATERIAL.add(new Material.Surface("Polyethylene (heavy)",       0.040, false));
100                 SURFACE_MATERIAL.add(new Material.Surface("Silk",                                       0.060, false));
101                 SURFACE_MATERIAL.add(new Material.Surface("Paper (office)",                     0.080, false));
102                 SURFACE_MATERIAL.add(new Material.Surface("Cellophane",                         0.018, false));
103                 SURFACE_MATERIAL.add(new Material.Surface("Cr\u00eape paper",           0.025, false));
104                 
105                 LINE_MATERIAL.add(new Material.Line("Thread (heavy-duty)",                              0.0003, false));
106                 LINE_MATERIAL.add(new Material.Line("Elastic cord (round 2mm, 1/16 in)",0.0018, false));
107                 LINE_MATERIAL.add(new Material.Line("Elastic cord (flat  6mm, 1/4 in)", 0.0043, false));
108                 LINE_MATERIAL.add(new Material.Line("Elastic cord (flat 12mm, 1/2 in)", 0.008, false));
109                 LINE_MATERIAL.add(new Material.Line("Elastic cord (flat 19mm, 3/4 in)", 0.0012, false));
110                 LINE_MATERIAL.add(new Material.Line("Elastic cord (flat 25mm, 1 in)",   0.0016, false));
111                 LINE_MATERIAL.add(new Material.Line("Braided nylon (2 mm, 1/16 in)",    0.001, false));
112                 LINE_MATERIAL.add(new Material.Line("Braided nylon (3 mm, 1/8 in)",     0.0035, false));
113                 LINE_MATERIAL.add(new Material.Line("Tubular nylon (11 mm, 7/16 in)",   0.013, false));
114                 LINE_MATERIAL.add(new Material.Line("Tubular nylon (14 mm, 9/16 in)",   0.016, false));
115                 LINE_MATERIAL.add(new Material.Line("Tubular nylon (25 mm, 1 in)",              0.029, false));
116                 
117                 
118                 // Add user-defined materials
119                 for (Material m: Prefs.getUserMaterials()) {
120                         switch (m.getType()) {
121                         case LINE:
122                                 LINE_MATERIAL.add(m);
123                                 break;
124                                 
125                         case SURFACE:
126                                 SURFACE_MATERIAL.add(m);
127                                 break;
128                                 
129                         case BULK:
130                                 BULK_MATERIAL.add(m);
131                                 break;
132                                 
133                         default:
134                                 System.err.println("ERROR: Unknown material type " + m);
135                         }
136                 }
137                 
138                 // Add database storage listener
139                 MaterialStorage listener = new MaterialStorage();
140                 LINE_MATERIAL.addDatabaseListener(listener);
141                 SURFACE_MATERIAL.addDatabaseListener(listener);
142                 BULK_MATERIAL.addDatabaseListener(listener);
143         }
144         
145         
146         /*
147          * Used just for ensuring initialization of the class.
148          */
149         public static void fakeMethod() {
150                 
151         }
152         
153         
154         /**
155          * Find a material from the database with the specified type and name.  Returns
156          * <code>null</code> if the specified material could not be found.
157          * 
158          * @param type  the material type.
159          * @param name  the material name in the database.
160          * @return              the material, or <code>null</code> if not found.
161          */
162         public static Material findMaterial(Material.Type type, String name) {
163                 Database<Material> db;
164                 switch (type) {
165                 case BULK:
166                         db = BULK_MATERIAL;
167                         break;
168                 case SURFACE:
169                         db = SURFACE_MATERIAL;
170                         break;
171                 case LINE:
172                         db = LINE_MATERIAL;
173                         break;
174                 default:
175                         throw new IllegalArgumentException("Illegal material type: "+type);
176                 }
177                 
178                 for (Material m: db) {
179                         if (m.getName().equalsIgnoreCase(name)) {
180                                 return m;
181                         }
182                 }
183                 return null;
184         }
185         
186         
187         /**
188          * Find a material from the database or return a new material if the specified
189          * material with the specified density is not found.
190          * 
191          * @param type                  the material type.
192          * @param name                  the material name.
193          * @param density               the density of the material.
194          * @param userDefined   whether a newly created material should be user-defined.
195          * @return                              the material object from the database or a new material.
196          */
197         public static Material findMaterial(Material.Type type, String name, double density,
198                         boolean userDefined) {
199                 Database<Material> db;
200                 switch (type) {
201                 case BULK:
202                         db = BULK_MATERIAL;
203                         break;
204                 case SURFACE:
205                         db = SURFACE_MATERIAL;
206                         break;
207                 case LINE:
208                         db = LINE_MATERIAL;
209                         break;
210                 default:
211                         throw new IllegalArgumentException("Illegal material type: "+type);
212                 }
213
214                 for (Material m: db) {
215                         if (m.getName().equalsIgnoreCase(name) && MathUtil.equals(m.getDensity(), density)) {
216                                 return m;
217                         }
218                 }
219                 return Material.newMaterial(type, name, density, userDefined);
220         }       
221         
222         
223
224         /**
225          * Return all motor in the database matching a search criteria.  Any search criteria that
226          * is null or NaN is ignored.
227          * 
228          * @param type                  the motor type, or null.
229          * @param manufacturer  the manufacturer, or null.
230          * @param designation   the designation, or null.
231          * @param diameter              the diameter, or NaN.
232          * @param length                the length, or NaN.
233          * @return                              an array of all the matching motors.
234          */
235         public static Motor[] findMotors(Motor.Type type, String manufacturer, String designation, double diameter, double length) {
236                 ArrayList<Motor> results = new ArrayList<Motor>();
237                 
238                 for (Motor m: MOTOR) {
239                         boolean match = true;
240                         if (type != null  &&  type != m.getMotorType())
241                                 match = false;
242                         else if (manufacturer != null  &&  !m.getManufacturer().matches(manufacturer))
243                                 match = false;
244                         else if (designation != null  &&  !designation.equalsIgnoreCase(m.getDesignation()))
245                                 match = false;
246                         else if (!Double.isNaN(diameter)  &&  (Math.abs(diameter - m.getDiameter()) > 0.0015))
247                                 match = false;
248                         else if (!Double.isNaN(length) && (Math.abs(length - m.getLength()) > 0.0015))
249                                 match = false;
250                         
251                         if (match)
252                                 results.add(m);
253                 }
254                 
255                 return results.toArray(new Motor[0]);
256         }
257
258 }