1 package net.sf.openrocket.preset.loader;
3 import au.com.bytecode.opencsv.CSVReader;
4 import net.sf.openrocket.database.Databases;
5 import net.sf.openrocket.file.preset.ColumnDefinition;
6 import net.sf.openrocket.file.rocksim.RocksimNoseConeCode;
7 import net.sf.openrocket.gui.print.PrintUnit;
8 import net.sf.openrocket.gui.util.SwingPreferences;
9 import net.sf.openrocket.material.Material;
10 import net.sf.openrocket.preset.ComponentPreset;
11 import net.sf.openrocket.preset.ComponentPresetFactory;
12 import net.sf.openrocket.preset.InvalidComponentPresetException;
13 import net.sf.openrocket.preset.TypedKey;
14 import net.sf.openrocket.preset.TypedPropertyMap;
15 import net.sf.openrocket.preset.xml.OpenRocketComponentSaver;
16 import net.sf.openrocket.startup.Application;
17 import net.sf.openrocket.unit.UnitGroup;
18 import net.sf.openrocket.util.ArrayList;
19 import net.sf.openrocket.util.BugException;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.StringReader;
28 import java.util.Collection;
29 import java.util.HashMap;
30 import java.util.List;
35 * Primary entry point for parsing component CSV files that are in Rocksim format.
37 public class RocksimComponentFileLoader {
40 * Common unit of measure key. Rocksim format allows different types of units.
42 public final static TypedKey<String> UNITS_OF_MEASURE = new TypedKey<String>("Units", String.class);
45 * Read a comma separated component file and return the parsed contents as a list of string arrays. Not for
46 * production use - just here for smoke testing.
48 * @param type the type of component file to read; uses the default file name
49 * @return a list (guaranteed never to be null) of string arrays. Each element of the list represents a row in the
50 * component data file; the element in the list itself is an array of String, where each item in the array
51 * is a column (cell) in the row. The string array is in sequential order as it appeared in the file.
53 public static List<String[]> load(RocksimComponentFileType type) {
54 return load(RocksimComponentFileLoader.class.getResourceAsStream("/giantleaprocketry/" + type.getDefaultFileName()));
58 * Read a comma separated component file and return the parsed contents as a list of string arrays.
60 * @param file the file to read and parse
61 * @return a list (guaranteed never to be null) of string arrays. Each element of the list represents a row in the
62 * component data file; the element in the list itself is an array of String, where each item in the array
63 * is a column (cell) in the row. The string array is in sequential order as it appeared in the file.
65 public static List<String[]> load(File file) throws FileNotFoundException {
66 return load(new FileInputStream(file));
70 * Read a comma separated component file and return the parsed contents as a list of string arrays.
72 * @param is the stream to read and parse
73 * @return a list (guaranteed never to be null) of string arrays. Each element of the list represents a row in the
74 * component data file; the element in the list itself is an array of String, where each item in the array
75 * is a column (cell) in the row. The string array is in sequential order as it appeared in the file.
77 public static List<String[]> load(InputStream is) {
79 return new ArrayList<String[]>();
81 InputStreamReader r = null;
83 r = new InputStreamReader(is);
85 // Create the CSV reader. Use comma separator.
86 CSVReader reader = new CSVReader(r, ',', '\'', '\\');
88 //Read and throw away the header row.
91 //Read the rest of the file as data rows.
92 return reader.readAll();
94 catch (IOException e) {
101 catch (IOException e) {
106 return new ArrayList<String[]>();
110 * Rocksim CSV units are either inches or mm. A value of 0 or "in." indicate inches. A value of 1 or "mm" indicate
113 * @param units the value from the file
114 * @return true if it's inches
116 private static boolean isInches(String units) {
117 String tmp = units.trim().toLowerCase();
118 return "0".equals(tmp) || tmp.startsWith("in");
122 * Convert inches or millimeters to meters.
124 * @param units a Rocksim CSV string representing the kind of units.
125 * @param value the original value within the CSV file
126 * @return the value in meters
128 private static double convertLength(String units, double value) {
129 if (isInches(units)) {
130 return PrintUnit.INCHES.toMeters(value);
133 return PrintUnit.MILLIMETERS.toMeters(value);
138 * Remove all occurrences of the given character. Note: this is done because some manufacturers embed double
139 * quotes in their descriptions or material names. Those are stripped away because they cause all sorts of
140 * matching/lookup issues.
142 * @param target the target string to be operated upon
143 * @param toBeRemoved the character to remove
144 * @return target, minus every occurrence of toBeRemoved
146 private static String stripAll(String target, Character toBeRemoved) {
147 StringBuilder sb = new StringBuilder();
148 for (int i = 0; i < target.length(); i++) {
149 Character c = target.charAt(i);
150 if (!c.equals(toBeRemoved)) {
154 return sb.toString();
158 * Convert all words in a given string to Camel Case (first letter capitalized). Words are assumed to be
159 * separated by a space. Note: this is done because some manufacturers define their material name in Camel Case
160 * but the component part references the material in lower case. That causes matching/lookup issues that's
161 * easiest handled this way (rather than converting everything to lower case.
163 * @param target the target string to be operated upon
164 * @return target, with the first letter of each word in uppercase
166 private static String toCamelCase(String target) {
167 StringBuilder sb = new StringBuilder();
168 String[] t = target.split("[ ]");
169 if (t != null && t.length > 0) {
170 for (String aT : t) {
172 s = s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
173 sb.append(s).append(" ");
175 return sb.toString().trim();
183 * The core loading method, shared by all component types.
185 * @param theData the data as read from the CSV file
186 * @param keyMap the list of typed keys that specify the preset's expected columns
187 * @param materialMap a map of material name to OR Material; this is sourced from a MATERIAL.CSV file that must
188 * accompany the component CSV file.
189 * @param type the kind of component
190 * @return a collection of preset's
192 private static Collection<ComponentPreset> commonLoader(final List<String[]> theData,
193 final List<TypedKey<?>> keyMap,
194 final Map<String, Material> materialMap,
195 final ComponentPreset.Type type) {
196 Collection<ComponentPreset> result = new ArrayList<ComponentPreset>();
197 List<TypedPropertyMap> templates = new java.util.ArrayList<TypedPropertyMap>();
198 Set<String> favorites = Application.getPreferences().getComponentFavorites();
201 ColumnDefinition[] columns = new ColumnDefinition[keyMap.size()];
202 for (int i = 0; i < keyMap.size(); i++) {
203 TypedKey key = keyMap.get(i);
205 columns[i] = new ColumnDefinition(key);
206 if (key.getName().equals("Units")) {
212 for (int i = 0; i < theData.size(); i++) {
213 String[] item = theData.get(i);
214 TypedPropertyMap preset = new TypedPropertyMap();
216 for (int j = 0; j < columns.length; j++) {
217 if (j < item.length) {
218 String value = item[j];
222 value = value.trim();
223 value = stripAll(value, '"');
224 if (value.length() == 0) {
227 final TypedKey typedKey = columns[j].getKey();
228 //If it's the material, then pull it out of our internal map. The map references the
229 //data from the associated MATERIAL.CSV file that is mandatory.
230 if (typedKey.equals(ComponentPreset.MATERIAL)) {
231 preset.put(ComponentPreset.MATERIAL, materialMap.get(value));
233 //The shape of a nosecone or transition must get mapped from Rocksim to OR.
234 else if (typedKey.equals(ComponentPreset.SHAPE)) {
235 preset.put(ComponentPreset.SHAPE, RocksimNoseConeCode.fromShapeNameOrCode(value).asOpenRocket());
238 //Rocksim allows different types of length units. They must be converted and normalized to OR.
239 final UnitGroup unitGroup = typedKey.getUnitGroup();
240 if (unitGroup != null && unitGroup.equals(UnitGroup.UNITS_LENGTH)) {
241 columns[j].setProperty(preset, convertLength(item[uom], Double.valueOf(value)));
244 columns[j].setProperty(preset, value);
249 //Set what kind of component this is.
250 preset.put(ComponentPreset.TYPE, type);
251 //Add to the collection.
252 templates.add(preset);
255 for (TypedPropertyMap o : templates) {
257 ComponentPreset preset = ComponentPresetFactory.create(o);
258 if (favorites.contains(preset.preferenceKey())) {
259 preset.setFavorite(true);
263 catch (InvalidComponentPresetException ex) {
264 throw new BugException(ex);
271 static class BodyTubeLoader {
272 private final static int MFG_INDEX = 0;
273 private final static int PART_NO_INDEX = 1;
274 private final static int DESCRIPTION_INDEX = 2;
275 private final static int UNITS_INDEX = 3;
276 private final static int ID_INDEX = 4;
277 private final static int OD_INDEX = 5;
278 private final static int LENGTH_INDEX = 6;
279 private final static int MATERIAL_INDEX = 7;
281 public final static List<TypedKey<?>> keyMap = new ArrayList<TypedKey<?>>(8);
284 keyMap.add(MFG_INDEX, ComponentPreset.MANUFACTURER);
285 keyMap.add(PART_NO_INDEX, ComponentPreset.PARTNO);
286 keyMap.add(DESCRIPTION_INDEX, ComponentPreset.DESCRIPTION);
287 keyMap.add(UNITS_INDEX, UNITS_OF_MEASURE);
288 keyMap.add(ID_INDEX, ComponentPreset.INNER_DIAMETER);
289 keyMap.add(OD_INDEX, ComponentPreset.OUTER_DIAMETER);
290 keyMap.add(LENGTH_INDEX, ComponentPreset.LENGTH);
291 keyMap.add(MATERIAL_INDEX, ComponentPreset.MATERIAL);
294 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
295 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.BODY_TUBE);
296 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.BODY_TUBE);
299 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
300 FileNotFoundException {
301 List<String[]> data = RocksimComponentFileLoader.load(file);
302 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.BODY_TUBE);
308 * Tube coupler parser. Although there are additional fields in the file, they are not used by
309 * most (any?) manufacturers so we ignore them entirely.
311 static class TubeCouplerLoader extends BodyTubeLoader {
312 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
313 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.TUBE_COUPLER);
314 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.TUBE_COUPLER);
317 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
318 FileNotFoundException {
319 List<String[]> data = RocksimComponentFileLoader.load(file);
320 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.TUBE_COUPLER);
325 * Engine block parser. Although there are additional fields in the file, they are not used by
326 * most (any?) manufacturers so we ignore them entirely.
328 static class EngineBlockLoader extends BodyTubeLoader {
329 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
330 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.ENGINE_BLOCK);
331 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.ENGINE_BLOCK);
334 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
335 FileNotFoundException {
336 List<String[]> data = RocksimComponentFileLoader.load(file);
337 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.ENGINE_BLOCK);
342 static class BulkheadLoader extends BodyTubeLoader {
343 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
344 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.BULKHEAD);
345 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.BULK_HEAD);
348 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
349 FileNotFoundException {
350 List<String[]> data = RocksimComponentFileLoader.load(file);
351 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.BULK_HEAD);
355 static class CenteringRingLoader extends BodyTubeLoader {
356 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
357 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.CENTERING_RING);
358 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.CENTERING_RING);
361 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
362 FileNotFoundException {
363 List<String[]> data = RocksimComponentFileLoader.load(file);
364 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.CENTERING_RING);
368 static class NoseConeLoader {
369 public static final int MFG_INDEX = 0;
370 public static final int PART_NO_INDEX = 1;
371 public static final int DESCRIPTION_INDEX = 2;
372 public static final int UNITS_INDEX = 3;
373 public static final int LENGTH_INDEX = 4;
374 public static final int OUTER_DIA_INDEX = 5;
375 public static final int LD_RATIO_INDEX = 6;
376 public static final int INSERT_LENGTH_INDEX = 7;
377 public static final int INSERT_OD_INDEX = 8;
378 public static final int THICKNESS_INDEX = 9;
379 public static final int SHAPE_INDEX = 10;
380 public static final int CONFIG_INDEX = 11;
381 public static final int MATERIAL_INDEX = 12;
382 public static final int CG_LOC_INDEX = 13;
383 public static final int MASS_UNITS_INDEX = 14;
384 public static final int MASS_INDEX = 15;
385 public static final int BASE_EXT_LEN_INDEX = 16;
387 public final static TypedKey<Double> LD_RATIO = new TypedKey<Double>("Len/Dia Ratio", Double.class);
388 public final static TypedKey<Double> BASE_EXT_LEN = new TypedKey<Double>("Base Ext Len", Double.class, UnitGroup.UNITS_LENGTH);
389 public final static TypedKey<String> CONFIG = new TypedKey<String>("Config", String.class);
390 public final static TypedKey<Double> CG_LOC = new TypedKey<Double>("CG Loc", Double.class, UnitGroup.UNITS_LENGTH);
391 public final static List<TypedKey<?>> keyMap = new ArrayList<TypedKey<?>>(17);
394 keyMap.add(MFG_INDEX, ComponentPreset.MANUFACTURER);
395 keyMap.add(PART_NO_INDEX, ComponentPreset.PARTNO);
396 keyMap.add(DESCRIPTION_INDEX, ComponentPreset.DESCRIPTION);
397 keyMap.add(UNITS_INDEX, UNITS_OF_MEASURE);
398 keyMap.add(LENGTH_INDEX, ComponentPreset.LENGTH);
399 keyMap.add(OUTER_DIA_INDEX, ComponentPreset.AFT_OUTER_DIAMETER);
400 keyMap.add(LD_RATIO_INDEX, LD_RATIO);
401 keyMap.add(INSERT_LENGTH_INDEX, ComponentPreset.AFT_SHOULDER_LENGTH);
402 keyMap.add(INSERT_OD_INDEX, ComponentPreset.AFT_SHOULDER_DIAMETER);
403 keyMap.add(THICKNESS_INDEX, ComponentPreset.THICKNESS);
404 keyMap.add(SHAPE_INDEX, ComponentPreset.SHAPE);
405 keyMap.add(CONFIG_INDEX, CONFIG);
406 keyMap.add(MATERIAL_INDEX, ComponentPreset.MATERIAL);
407 keyMap.add(CG_LOC_INDEX, CG_LOC);
408 keyMap.add(MASS_UNITS_INDEX, UNITS_OF_MEASURE);
409 keyMap.add(MASS_INDEX, ComponentPreset.MASS);
410 keyMap.add(BASE_EXT_LEN_INDEX, BASE_EXT_LEN);
413 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
414 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.NOSE_CONE);
415 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.NOSE_CONE);
418 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
419 FileNotFoundException {
420 List<String[]> data = RocksimComponentFileLoader.load(file);
421 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.NOSE_CONE);
425 static class TransitionLoader {
426 public static final int MFG_INDEX = 0;
427 public static final int PART_NO_INDEX = 1;
428 public static final int DESCRIPTION_INDEX = 2;
429 public static final int UNITS_INDEX = 3;
430 public static final int FRONT_INSERT_LENGTH_INDEX = 4;
431 public static final int FRONT_INSERT_OD_INDEX = 5;
432 public static final int FRONT_OD_INDEX = 6;
433 public static final int LENGTH_INDEX = 7;
434 public static final int REAR_OD_INDEX = 8;
435 public static final int CORE_DIA_INDEX = 9;
436 public static final int REAR_INSERT_LENGTH_INDEX = 10;
437 public static final int REAR_INSERT_OD_INDEX = 11;
438 public static final int THICKNESS_INDEX = 12;
439 public static final int CONFIG_INDEX = 13;
440 public static final int MATERIAL_INDEX = 14;
441 public static final int CG_LOC_INDEX = 15;
442 public static final int MASS_UNITS_INDEX = 16;
443 public static final int MASS_INDEX = 17;
444 public static final int SHAPE_INDEX = 18;
446 public final static TypedKey<String> CONFIG = new TypedKey<String>("Config", String.class);
447 public final static TypedKey<String> IGNORE = new TypedKey<String>("Ignore", String.class);
448 public final static TypedKey<Double> CG_LOC = new TypedKey<Double>("CG Loc", Double.class, UnitGroup.UNITS_LENGTH);
449 public final static List<TypedKey<?>> keyMap = new ArrayList<TypedKey<?>>(19);
452 keyMap.add(MFG_INDEX, ComponentPreset.MANUFACTURER);
453 keyMap.add(PART_NO_INDEX, ComponentPreset.PARTNO);
454 keyMap.add(DESCRIPTION_INDEX, ComponentPreset.DESCRIPTION);
455 keyMap.add(UNITS_INDEX, UNITS_OF_MEASURE);
456 keyMap.add(FRONT_INSERT_LENGTH_INDEX, ComponentPreset.FORE_SHOULDER_LENGTH);
457 keyMap.add(FRONT_INSERT_OD_INDEX, ComponentPreset.FORE_SHOULDER_DIAMETER);
458 keyMap.add(FRONT_OD_INDEX, ComponentPreset.FORE_OUTER_DIAMETER);
459 keyMap.add(LENGTH_INDEX, ComponentPreset.LENGTH);
460 keyMap.add(REAR_OD_INDEX, ComponentPreset.AFT_OUTER_DIAMETER);
461 keyMap.add(CORE_DIA_INDEX, IGNORE);
462 keyMap.add(REAR_INSERT_LENGTH_INDEX, ComponentPreset.AFT_SHOULDER_LENGTH);
463 keyMap.add(REAR_INSERT_OD_INDEX, ComponentPreset.AFT_SHOULDER_DIAMETER);
464 keyMap.add(THICKNESS_INDEX, ComponentPreset.THICKNESS);
465 keyMap.add(CONFIG_INDEX, CONFIG);
466 keyMap.add(MATERIAL_INDEX, ComponentPreset.MATERIAL);
467 keyMap.add(CG_LOC_INDEX, CG_LOC);
468 keyMap.add(MASS_UNITS_INDEX, UNITS_OF_MEASURE);
469 keyMap.add(MASS_INDEX, ComponentPreset.MASS);
470 keyMap.add(SHAPE_INDEX, ComponentPreset.SHAPE);
473 public Collection<ComponentPreset> load(Map<String, Material> materialMap) {
474 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.TRANSITION);
475 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.TRANSITION);
478 public Collection<ComponentPreset> load(Map<String, Material> materialMap, File file) throws
479 FileNotFoundException {
480 List<String[]> data = RocksimComponentFileLoader.load(file);
481 return commonLoader(data, keyMap, materialMap, ComponentPreset.Type.TRANSITION);
485 static class MaterialLoader {
486 private final static int MATERIAL_INDEX = 0;
487 private final static int UNITS_INDEX = 1;
488 private final static int DENSITY_INDEX = 2;
489 private final static int LOW_INDEX = 3;
490 private final static int HIGH_INDEX = 4;
491 private final static int CLASS_INDEX = 5;
492 private final static int ROCKETRY_USE_INDEX = 6;
493 private final static int BODY_TUBES_INDEX = 7;
494 public static final int FIN_SETS_INDEX = 8;
495 public static final int LAUNCH_LUGS_INDEX = 9;
496 public static final int CORDS_INDEX = 10;
497 public static final int NOSE_INDEX = 11;
498 public static final int PARACHUTE_INDEX = 12;
499 public static final int STREAMER_INDEX = 13;
500 public static final int TRANSITION_INDEX = 14;
501 public static final int RING_INDEX = 15;
502 public static final int BULKHEAD_INDEX = 16;
503 public static final int ENGINE_BLOCK_INDEX = 17;
504 public static final int SLEEVE_INDEX = 18;
505 public static final int TUBE_COUPLER_INDEX = 19;
506 public static final int KNOWN_DIM_TYPE_INDEX = 27;
507 public static final int KNOWN_DIM_UNITS_INDEX = 28;
508 public static final int KNOWN_DIM_VALUE_INDEX = 29;
510 public final static List<TypedKey<?>> keyMap = new ArrayList<TypedKey<?>>(8);
511 public final static TypedKey<String> MATERIAL_NAME = new TypedKey<String>("Material Name", String.class);
512 public final static TypedKey<Double> DENSITY = new TypedKey<Double>("Density", Double.class);
514 static class MaterialAdapter {
516 double conversionFactor;
518 MaterialAdapter(Material.Type theType, double cf) {
520 conversionFactor = cf;
524 private final static Map<String, MaterialAdapter> materialAdapterMap = new HashMap<String, MaterialAdapter>();
527 materialAdapterMap.put("g/cm", new MaterialAdapter(Material.Type.LINE, 0.1d));
528 materialAdapterMap.put("g/cm2", new MaterialAdapter(Material.Type.SURFACE, 10.0d));
529 materialAdapterMap.put("g/cm3", new MaterialAdapter(Material.Type.BULK, 1000.0d));
530 materialAdapterMap.put("kg/m3", new MaterialAdapter(Material.Type.BULK, 1d));
531 materialAdapterMap.put("lb/ft3", new MaterialAdapter(Material.Type.BULK, 16.0184634d));
532 materialAdapterMap.put("oz/in", new MaterialAdapter(Material.Type.LINE, 1.11612296d));
533 materialAdapterMap.put("oz/in2", new MaterialAdapter(Material.Type.SURFACE, 43.9418487));
535 keyMap.add(MATERIAL_INDEX, MATERIAL_NAME);
536 keyMap.add(UNITS_INDEX, UNITS_OF_MEASURE);
537 keyMap.add(DENSITY_INDEX, DENSITY);
540 static Map<String, Material> load() {
541 List<String[]> data = RocksimComponentFileLoader.load(RocksimComponentFileType.MATERIAL);
542 Map<String, Material> materialMap = new HashMap<String, Material>();
544 for (int i = 0; i < data.size(); i++) {
546 String[] strings = data.get(i);
547 MaterialAdapter ma = materialAdapterMap.get(strings[UNITS_INDEX]);
548 double metricDensity = ma.conversionFactor * Double.parseDouble(strings[DENSITY_INDEX]);
549 final String cleanedMaterialName = stripAll(strings[MATERIAL_INDEX], '"').trim();
550 final Material material = Databases.findMaterial(ma.type, cleanedMaterialName,
551 metricDensity, true);
552 materialMap.put(cleanedMaterialName, material);
553 materialMap.put(cleanedMaterialName.toLowerCase(), material);
554 materialMap.put(toCamelCase(cleanedMaterialName), material);
556 catch (Exception e) {
557 //Trap a bad row and move on
558 //TODO: log it? Display to user?
565 public static void main(String[] args) {
566 Application.setPreferences(new SwingPreferences());
567 Map<String, Material> materialMap = MaterialLoader.load();
568 Collection<ComponentPreset> presetNC = new NoseConeLoader().load(materialMap);
569 Collection<ComponentPreset> presetBC = new BodyTubeLoader().load(materialMap);
570 Collection<ComponentPreset> presetBH = new BulkheadLoader().load(materialMap);
571 Collection<ComponentPreset> presetCR = new CenteringRingLoader().load(materialMap);
572 Collection<ComponentPreset> presetTC = new TubeCouplerLoader().load(materialMap);
573 Collection<ComponentPreset> presetTR = new TransitionLoader().load(materialMap);
574 Collection<ComponentPreset> presetEB = new EngineBlockLoader().load(materialMap);
576 for (Iterator<ComponentPreset> iterator = presetNC.iterator(); iterator.hasNext(); ) {
577 ComponentPreset next = iterator.next();
578 System.err.println(next);
580 for (Iterator<ComponentPreset> iterator = presetBC.iterator(); iterator.hasNext(); ) {
581 ComponentPreset next = iterator.next();
582 System.err.println(next);
584 for (Iterator<ComponentPreset> iterator = presetBH.iterator(); iterator.hasNext(); ) {
585 ComponentPreset next = iterator.next();
586 System.err.println(next);
588 for (Iterator<ComponentPreset> iterator = presetCR.iterator(); iterator.hasNext(); ) {
589 ComponentPreset next = iterator.next();
590 System.err.println(next);
592 for (Iterator<ComponentPreset> iterator = presetTC.iterator(); iterator.hasNext(); ) {
593 ComponentPreset next = iterator.next();
594 System.err.println(next);
596 for (Iterator<ComponentPreset> iterator = presetTR.iterator(); iterator.hasNext(); ) {
597 ComponentPreset next = iterator.next();
598 System.err.println(next);
600 for (Iterator<ComponentPreset> iterator = presetEB.iterator(); iterator.hasNext(); ) {
601 ComponentPreset next = iterator.next();
602 System.err.println(next);
605 List<ComponentPreset> allPresets = new ArrayList<ComponentPreset>();
606 allPresets.addAll(presetBC);
607 allPresets.addAll(presetBH);
608 allPresets.addAll(presetCR);
609 allPresets.addAll(presetEB);
610 allPresets.addAll(presetNC);
611 allPresets.addAll(presetTC);
612 allPresets.addAll(presetTR);
614 String xml = new OpenRocketComponentSaver().marshalToOpenRocketComponent(new ArrayList<Material>(materialMap.values()), allPresets);
615 System.err.println(xml);
617 List<ComponentPreset> presets = new OpenRocketComponentSaver().unmarshalFromOpenRocketComponent(new StringReader(xml));
619 catch (InvalidComponentPresetException e) {
626 //The oddities I've found thus far in the stock Rocksim data:
627 //1. BTDATA.CSV - Totally Tubular goofed up their part no. and description columns (They messed up TCDATA also)
628 //2. NCDATA.CSV - Estes Balsa nose cones are classified as G10 Fiberglass
629 //3. TRDATA.CSV - Apogee Saturn LEM Transition has no part number; Balsa Machining transitions have blank diameter