1 package net.sf.openrocket.motor;
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashSet;
7 import java.util.Locale;
9 import java.util.concurrent.ConcurrentHashMap;
12 * Class containing information about motor manufacturers.
14 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
16 public class Manufacturer {
18 private static class ManufacturerList extends ConcurrentHashMap<String,Manufacturer> {
20 void add( Manufacturer m ) {
21 for( String s : m.getSearchNames() ) {
22 Manufacturer previousRegistered;
23 if ( (previousRegistered = putIfAbsent( s, m )) != null ) {
24 throw new IllegalStateException("Manufacturer name clash between " +
25 "manufacturers " + previousRegistered + " and " + m + " name " + s);
31 private static ManufacturerList manufacturers = new ManufacturerList();
35 // AeroTech has many name combinations...
36 List<String> names = new ArrayList<String>();
37 for (String s : new String[] { "A", "AT", "AERO", "AEROT", "AEROTECH" }) {
39 names.add(s + "-RMS");
40 names.add(s + "-RCS");
41 names.add("RCS-" + s);
42 names.add(s + "-APOGEE");
46 // Aerotech has single-use, reload and hybrid motors
47 manufacturers.add(new Manufacturer("AeroTech", "AeroTech", Motor.Type.UNKNOWN,
48 names.toArray(new String[0])));
50 manufacturers.add(new Manufacturer("Alpha Hybrid Rocketry LLC", "Alpha Hybrid Rocketry", Motor.Type.HYBRID,
51 "AHR", "ALPHA", "ALPHA HYBRID", "ALPHA HYBRIDS", "ALPHA HYBRIDS ROCKETRY"));
53 // TODO: HIGH: AMW/ProX - how to classify?
55 manufacturers.add(new Manufacturer("Animal Motor Works", "Animal Motor Works", Motor.Type.RELOAD,
56 "AMW", "AW", "ANIMAL"));
58 manufacturers.add(new Manufacturer("Apogee", "Apogee", Motor.Type.SINGLE,
61 manufacturers.add(new Manufacturer("Cesaroni Technology Inc.", "Cesaroni Technology", Motor.Type.RELOAD,
62 "CES", "CESARONI", "CESARONI TECHNOLOGY INCORPORATED", "CTI",
63 "CS", "CSR", "PRO38", "ABC"));
65 manufacturers.add(new Manufacturer("Contrail Rockets", "Contrail Rockets", Motor.Type.HYBRID,
66 "CR", "CONTR", "CONTRAIL", "CONTRAIL ROCKET"));
68 manufacturers.add(new Manufacturer("Estes", "Estes", Motor.Type.SINGLE,
71 // Ellis Mountain has both single-use and reload motors
72 manufacturers.add(new Manufacturer("Ellis Mountain", "Ellis Mountain", Motor.Type.UNKNOWN,
73 "EM", "ELLIS", "ELLIS MOUNTAIN ROCKET", "ELLIS MOUNTAIN ROCKETS"));
75 manufacturers.add(new Manufacturer("Gorilla Rocket Motors", "Gorilla Rocket Motors", Motor.Type.RELOAD,
76 "GR", "GORILLA", "GORILLA ROCKET", "GORILLA ROCKETS", "GORILLA MOTOR",
77 "GORILLA MOTORS", "GORILLA ROCKET MOTOR"));
79 manufacturers.add(new Manufacturer("HyperTEK", "HyperTEK", Motor.Type.HYBRID,
82 manufacturers.add(new Manufacturer("Kosdon by AeroTech", "Kosdon by AeroTech", Motor.Type.RELOAD,
83 "K", "KBA", "K-AT", "KOS", "KOSDON", "KOSDON/AT", "KOSDON/AEROTECH"));
85 manufacturers.add(new Manufacturer("Loki Research", "Loki Research", Motor.Type.RELOAD,
88 manufacturers.add(new Manufacturer("Public Missiles, Ltd.", "Public Missiles", Motor.Type.SINGLE,
89 "PM", "PML", "PUBLIC MISSILES LIMITED"));
91 manufacturers.add(new Manufacturer("Propulsion Polymers", "Propulsion Polymers", Motor.Type.HYBRID,
92 "PP", "PROP", "PROPULSION"));
94 manufacturers.add(new Manufacturer("Quest", "Quest", Motor.Type.SINGLE,
97 manufacturers.add(new Manufacturer("RATT Works", "RATT Works", Motor.Type.HYBRID,
98 "RATT", "RT", "RTW"));
100 manufacturers.add(new Manufacturer("Roadrunner Rocketry", "Roadrunner Rocketry", Motor.Type.SINGLE,
101 "RR", "ROADRUNNER"));
103 manufacturers.add(new Manufacturer("Rocketvision", "Rocketvision", Motor.Type.SINGLE,
104 "RV", "ROCKET VISION"));
106 manufacturers.add(new Manufacturer("Sky Ripper Systems", "Sky Ripper Systems", Motor.Type.HYBRID,
107 "SR", "SRS", "SKYR", "SKYRIPPER", "SKY RIPPER", "SKYRIPPER SYSTEMS"));
109 manufacturers.add(new Manufacturer("West Coast Hybrids", "West Coast Hybrids", Motor.Type.HYBRID,
110 "WCH", "WCR", "WEST COAST", "WEST COAST HYBRID"));
112 // German WECO Feuerwerk, previously Sachsen Feuerwerk
113 manufacturers.add(new Manufacturer("WECO Feuerwerk", "WECO Feuerwerk", Motor.Type.SINGLE,
114 "WECO", "WECO FEUERWERKS", "SF", "SACHSEN", "SACHSEN FEUERWERK",
115 "SACHSEN FEUERWERKS"));
121 private final String displayName;
122 private final String simpleName;
123 private final Set<String> allNames;
124 private final Set<String> searchNames;
125 private final Motor.Type motorType;
128 private Manufacturer(String displayName, String simpleName, Motor.Type motorType, String... alternateNames) {
129 this.displayName = displayName;
130 this.simpleName = simpleName;
131 this.motorType = motorType;
132 if (motorType == null) {
133 throw new IllegalArgumentException("motorType cannot be null");
136 Set<String> all = new HashSet<String>();
137 Set<String> search = new HashSet<String>();
139 all.add(displayName);
141 search.add(generateSearchString(displayName));
142 search.add(generateSearchString(simpleName));
144 for (String name : alternateNames) {
146 search.add(generateSearchString(name));
149 this.allNames = Collections.unmodifiableSet(all);
150 this.searchNames = Collections.unmodifiableSet(search);
155 * Returns the display name of the manufacturer. This is the value that
156 * should be presented in the UI to the user.
158 * @return the display name
160 public String getDisplayName() {
166 * Returns the simple name of the manufacturer. This should be used for example
167 * when saving the manufacturer for compatibility.
169 * @return the simple name.
171 public String getSimpleName() {
177 * Return all names of the manufacturer. This includes all kinds of
178 * codes that correspond to the manufacturer (for example "A" for AeroTech).
180 * @return an unmodifiable set of the alternative names.
182 public Set<String> getAllNames() {
186 Set<String> getSearchNames() {
191 * Return the motor type that this manufacturer produces if it produces only one motor type.
192 * If the manufacturer manufactures multiple motor types or the type is unknown,
193 * type <code>UNKNOWN</code> is returned.
195 * @return the manufactured motor type, or <code>UNKNOWN</code>.
197 public Motor.Type getMotorType() {
203 * Check whether the display, simple or any of the alternative names matches the
204 * specified name. Matching is performed case insensitively and ignoring any
205 * non-letter and non-number characters.
207 * @param name the name to search for.
208 * @return whether this manufacturer matches the request.
210 public boolean matches(String name) {
213 return this.searchNames.contains(generateSearchString(name));
218 * Return the display name of the manufacturer.
221 public String toString() {
227 * Returns a manufacturer for the given name. The manufacturer is searched for
228 * within the manufacturers and if a match is found the corresponding
229 * object is returned. If not, a new manufacturer is returned with display and
230 * simple name the name specified. Subsequent requests for the same (or corresponding)
231 * manufacturer name will return the same object.
233 * @param name the manufacturer name to search for.
234 * @return the Manufacturer object corresponding the name.
236 public static Manufacturer getManufacturer(String name) {
237 String searchString = generateSearchString(name);
238 Manufacturer m = manufacturers.get(searchString);
243 m = new Manufacturer(name.trim(), name.trim(), Motor.Type.UNKNOWN);
245 // We need some additional external synchronization here so we lock on the manufacturers.
246 synchronized( manufacturers ) {
247 Manufacturer retest = manufacturers.get(searchString);
248 if ( retest != null ) {
252 manufacturers.add(m);
257 private static String generateSearchString(String str) {
258 return str.toLowerCase(Locale.getDefault()).replaceAll("[^a-zA-Z0-9]+", " ").trim();