adds documentation and refactoring for many files

This commit is contained in:
Luiz Victor Linhares Rocha 2016-10-17 16:41:17 -02:00
parent 05d439bd1e
commit b708520364
17 changed files with 744 additions and 227 deletions

View File

@ -23,9 +23,7 @@ public class Appearance {
} }
public Appearance(final Color paint, final double shine) { public Appearance(final Color paint, final double shine) {
this.paint = paint; this(paint,shine,null);
this.shine = MathUtil.clamp(shine, 0, 1);
this.texture = null;
} }
public Color getPaint() { public Color getPaint() {

View File

@ -4,12 +4,17 @@ import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
/** /**
* A texture that can be applied by an Appearance. This class is immutable. * A texture that can be applied by an Appearance. an object of this class is immutable.
* *
* @author Bill Kuker <bkuker@billkuker.com> * @author Bill Kuker <bkuker@billkuker.com>
*/ */
public class Decal { public class Decal {
/**
* enum to flag what happens on edge in a decal
*
*
*/
public static enum EdgeMode { public static enum EdgeMode {
REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker"); REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker");
private final String transName; private final String transName;
@ -29,6 +34,16 @@ public class Decal {
private final DecalImage image; private final DecalImage image;
private final EdgeMode mode; private final EdgeMode mode;
/**
* Builds a new decal with the given itens
*
* @param offset The offset of the decal, in coordinate obejct format
* @param center The position of the center of the decal, in coordinate object format
* @param scale The scale of the decal, in coordinate obejct format
* @param rotation Rotation of the decal, in radians
* @param image The image itself
* @param mode The description of Edge behaviour
*/
public Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation, public Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation,
final DecalImage image, final EdgeMode mode) { final DecalImage image, final EdgeMode mode) {
this.offset = offset; this.offset = offset;
@ -39,26 +54,56 @@ public class Decal {
this.mode = mode; this.mode = mode;
} }
/**
* returns the offset, in coordinates object format
*
* @return offset coordinates of the decal
*/
public Coordinate getOffset() { public Coordinate getOffset() {
return offset; return offset;
} }
/**
* return the center, in coordinates object format
*
* @return The center coordinates of the decal
*/
public Coordinate getCenter() { public Coordinate getCenter() {
return center; return center;
} }
/**
* return the scaling of the decal, in coordinate format
*
* @return the scale coordinates of the decal
*/
public Coordinate getScale() { public Coordinate getScale() {
return scale; return scale;
} }
/**
* returns the rotation of the decal, in radians
*
* @return the rotation of the decal, in radians
*/
public double getRotation() { public double getRotation() {
return rotation; return rotation;
} }
/**
* return the edge behaviour of the decal
*
* @return the edge behaviour of the decal
*/
public EdgeMode getEdgeMode() { public EdgeMode getEdgeMode() {
return mode; return mode;
} }
/**
* returns the image of the decal itself
*
* @return the image of the decal itself
*/
public DecalImage getImage() { public DecalImage getImage() {
return image; return image;
} }

View File

@ -7,13 +7,37 @@ import java.io.InputStream;
import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.ChangeSource;
/**
* Interface to handle image files for declas
*
*/
public interface DecalImage extends ChangeSource, Comparable<DecalImage> { public interface DecalImage extends ChangeSource, Comparable<DecalImage> {
/**
* returns the name of the file path of the image
* @return name of file path
*/
public String getName(); public String getName();
/**
* gets the Stream of bytes representing the image itself
*
* @return the Stream of bytes representing the image
* @throws FileNotFoundException
* @throws IOException
*/
public InputStream getBytes() throws FileNotFoundException, IOException; public InputStream getBytes() throws FileNotFoundException, IOException;
/**
* exports an image into the File
* @param file The File handler object
* @throws IOException
*/
public void exportImage(File file) throws IOException; public void exportImage(File file) throws IOException;
/**
* wake up call to listeners
* @param source The source of the wake up call
*/
public void fireChangeEvent(Object source); public void fireChangeEvent(Object source);
} }

View File

@ -23,8 +23,22 @@ import net.sf.openrocket.rocketcomponent.TubeFinSet;
import net.sf.openrocket.util.Color; import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Coordinate;
/**
*
* Class defining the default images of the application
*
*/
public class DefaultAppearance { public class DefaultAppearance {
/**
* returns a simple appearance with the image in the path with
* default color
* no shining
* no offset, origin center and scale 1
*
* @param resource the path file to the resource
* @return
*/
private static Appearance simple(String resource) { private static Appearance simple(String resource) {
return new Appearance( return new Appearance(
new Color(1, 1, 1), new Color(1, 1, 1),
@ -37,6 +51,14 @@ public class DefaultAppearance {
new ResourceDecalImage(resource), EdgeMode.REPEAT)); new ResourceDecalImage(resource), EdgeMode.REPEAT));
}; };
/**
* returns the image with custom color and shine
*
* @param base base color for the image
* @param shine the custom shine property
* @param resource the file path to the image
* @return The appearance with custom color and shine.
*/
private static Appearance simpleAlpha(Color base, float shine, String resource) { private static Appearance simpleAlpha(Color base, float shine, String resource) {
return new Appearance( return new Appearance(
base, base,
@ -69,6 +91,12 @@ public class DefaultAppearance {
private static HashMap<Color, Appearance> plastics = new HashMap<Color, Appearance>(); private static HashMap<Color, Appearance> plastics = new HashMap<Color, Appearance>();
/**
* gets the appearance correspondent to the plastic with the given color
* also caches the plastics
* @param c the color of the plastics
* @return The plastic appearance with the given color
*/
private static Appearance getPlastic(Color c) { private static Appearance getPlastic(Color c) {
if (!plastics.containsKey(c)) { if (!plastics.containsKey(c)) {
plastics.put(c, new Appearance(c, .3)); plastics.put(c, new Appearance(c, .3));
@ -76,6 +104,12 @@ public class DefaultAppearance {
return plastics.get(c); return plastics.get(c);
} }
/**
* gets the default based on the type of the rocket component
*
* @param c the rocket component
* @return the default appearance for that type of rocket component
*/
public static Appearance getDefaultAppearance(RocketComponent c) { public static Appearance getDefaultAppearance(RocketComponent c) {
if (c instanceof BodyTube) if (c instanceof BodyTube)
return ESTES_BT; return ESTES_BT;
@ -100,6 +134,12 @@ public class DefaultAppearance {
return Appearance.MISSING; return Appearance.MISSING;
} }
/**
* gets the default motor texture based on the manufacturer
* returns reusable motor texture as default
* @param m The motor object
* @return The default appearance for the motor
*/
public static Appearance getDefaultAppearance(Motor m) { public static Appearance getDefaultAppearance(Motor m) {
if (m instanceof ThrustCurveMotor) { if (m instanceof ThrustCurveMotor) {
ThrustCurveMotor tcm = (ThrustCurveMotor) m; ThrustCurveMotor tcm = (ThrustCurveMotor) m;

View File

@ -8,11 +8,20 @@ import java.io.InputStream;
import net.sf.openrocket.appearance.DecalImage; import net.sf.openrocket.appearance.DecalImage;
import net.sf.openrocket.util.StateChangeListener; import net.sf.openrocket.util.StateChangeListener;
/**
*
* Default implementation class of DecalImage
*
*/
public class ResourceDecalImage implements DecalImage { public class ResourceDecalImage implements DecalImage {
/** File path to the image*/
final String resource; final String resource;
/**
* main constructor, stores the file path given
* @param resource
*/
public ResourceDecalImage(final String resource) { public ResourceDecalImage(final String resource) {
this.resource = resource; this.resource = resource;
} }

View File

@ -6,18 +6,30 @@ import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.BuildProperties; import net.sf.openrocket.util.BuildProperties;
import net.sf.openrocket.util.ComparablePair; import net.sf.openrocket.util.ComparablePair;
/**
*
* class that stores the update information of the application
*
*/
public class UpdateInfo { public class UpdateInfo {
private final String latestVersion; private final String latestVersion;
private final ArrayList<ComparablePair<Integer, String>> updates; private final ArrayList<ComparablePair<Integer, String>> updates;
/**
* loads the default information
*/
public UpdateInfo() { public UpdateInfo() {
this.latestVersion = BuildProperties.getVersion(); this.latestVersion = BuildProperties.getVersion();
this.updates = new ArrayList<ComparablePair<Integer, String>>(); this.updates = new ArrayList<ComparablePair<Integer, String>>();
} }
/**
* loads a custom update information into the cache
* @param version String with the version
* @param updates The list of updates contained in the version
*/
public UpdateInfo(String version, List<ComparablePair<Integer, String>> updates) { public UpdateInfo(String version, List<ComparablePair<Integer, String>> updates) {
this.latestVersion = version; this.latestVersion = version;
this.updates = new ArrayList<ComparablePair<Integer, String>>(updates); this.updates = new ArrayList<ComparablePair<Integer, String>>(updates);

View File

@ -41,10 +41,11 @@ public class UpdateInfoRetriever {
* Check whether the update info fetching is still in progress. * Check whether the update info fetching is still in progress.
* *
* @return <code>true</code> if the communication is still in progress. * @return <code>true</code> if the communication is still in progress.
* @throws IllegalStateException if {@link #startFetchUpdateInfo()} has not been called
*/ */
public boolean isRunning() { public boolean isRunning() {
if (fetcher == null) { if (fetcher == null) {
throw new IllegalStateException("startFetchUpdateInfo() has not been called"); throw new IllegalStateException("startFetchUpdateInfo() has not been called");
} }
return fetcher.isAlive(); return fetcher.isAlive();
} }
@ -81,43 +82,76 @@ public class UpdateInfoRetriever {
*/ */
/* package-private */ /* package-private */
static UpdateInfo parseUpdateInput(Reader r) throws IOException { static UpdateInfo parseUpdateInput(Reader r) throws IOException {
BufferedReader reader; BufferedReader reader = convertToBufferedReader(r);
if (r instanceof BufferedReader) {
reader = (BufferedReader) r;
} else {
reader = new BufferedReader(r);
}
String version = null; String version = null;
ArrayList<ComparablePair<Integer, String>> updates = ArrayList<ComparablePair<Integer, String>> updates =
new ArrayList<ComparablePair<Integer, String>>(); new ArrayList<ComparablePair<Integer, String>>();
String str = reader.readLine(); String str = reader.readLine();
while (str != null) { while (str != null) {
if (str.matches("^Version: *[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9.-]* *$")) { if (isHeader(str)) {
version = str.substring(8).trim(); version = str.substring(8).trim();
} else if (str.matches("^[0-9]+:\\p{Print}+$")) { } else if (isUpdateToken(str)) {
int index = str.indexOf(':'); ComparablePair<Integer, String> update = parseUpdateToken(str);
int value = Integer.parseInt(str.substring(0, index)); if(update != null)
String desc = str.substring(index + 1).trim(); updates.add(update);
if (!desc.equals("")) {
updates.add(new ComparablePair<Integer, String>(value, desc));
}
} }
// Ignore anything else
str = reader.readLine(); str = reader.readLine();
} }
if (version != null) { if (version == null)
return new UpdateInfo(version, updates);
} else {
return null; return null;
} return new UpdateInfo(version, updates);
} }
/**
* parses a line of a connection content into the information of an update
* @param str the line of the connection
* @return the update information
*/
private static ComparablePair<Integer, String> parseUpdateToken(String str){
int index = str.indexOf(':');
int value = Integer.parseInt(str.substring(0, index));
String desc = str.substring(index + 1).trim();
if (desc.equals(""))
return null;
return new ComparablePair<Integer, String>(value, desc);
}
/**
* checks if a string contains and update information
* @param str the string itself
* @return true for when the string has an update
* false otherwise
*/
private static boolean isUpdateToken(String str) {
return str.matches("^[0-9]+:\\p{Print}+$");
}
/**
* check if the string is formated as an update list header
* @param str the string to be checked
* @return true if str is a header, false otherwise
*/
private static boolean isHeader(String str) {
return str.matches("^Version: *[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9.-]* *$");
}
/**
* convert, if not yet converted, a Reader into a buffered reader
* @param r the Reader object
* @return the Reader as a BufferedReader Object
*/
private static BufferedReader convertToBufferedReader(Reader r) {
if (r instanceof BufferedReader)
return (BufferedReader) r;
return new BufferedReader(r);
}
/** /**
* An asynchronous task that fetches and parses the update info. * An asynchronous task that fetches and parses the update info.
* *
@ -137,11 +171,193 @@ public class UpdateInfoRetriever {
} }
} }
/**
* Establishes a connection with data of previous updates
* @throws IOException
*/
private void doConnection() throws IOException { private void doConnection() throws IOException {
String url = Communicator.UPDATE_INFO_URL + "?" + Communicator.VERSION_PARAM + "=" HttpURLConnection connection = getConnection(getUrl());
+ Communicator.encode(BuildProperties.getVersion()); InputStream is = null;
try {
connection.connect();
if(!checkConnection(connection))
return;
if(!checkContentType(connection))
return;
is = new LimitedInputStream(connection.getInputStream(), Communicator.MAX_INPUT_BYTES);
parseUpdateInput(buildBufferedReader(connection,is));
} finally {
try {
if (is != null)
is.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Parses the data received in a buffered reader
* @param reader The reader object
* @throws IOException If anything bad happens
*/
private void parseUpdateInput(BufferedReader reader) throws IOException{
String version = null;
ArrayList<ComparablePair<Integer, String>> updates =
new ArrayList<ComparablePair<Integer, String>>();
String line = reader.readLine();
while (line != null) {
if (isHeader(line)) {
version = parseHeader(line);
} else if (isUpdateInfo(line)) {
updates.add(parseUpdateInfo(line));
}
line = reader.readLine();
}
if (isInvalidVersion(version)) {
log.warn("Invalid version received, ignoring.");
return;
}
info = new UpdateInfo(version, updates);
log.info("Found update: " + info);
}
/**
* parses a line into it's version name
* @param line the string of the header
* @return the version in it's right format
*/
private String parseHeader(String line) {
return line.substring(8).trim();
}
/**
* parses a line into it's correspondent update information
* @param line the line to be parsed
* @return update information from the line
*/
private ComparablePair<Integer,String> parseUpdateInfo(String line){
String[] split = line.split(":", 2);
int n = Integer.parseInt(split[0]);
return new ComparablePair<Integer, String>(n, split[1].trim());
}
/**
* checks if a line contains an update information
* @param line the line to be checked
* @return true if the line caontain an update information
* false otherwise
*/
private boolean isUpdateInfo(String line) {
return line.matches("^[0-9]{1,9}:\\P{Cntrl}{1,300}$");
}
/**
* checks if a line is a header of an update list
* @param line the line to be checked
* @return true if line is a header, false otherwise
*/
private boolean isHeader(String line) {
return line.matches("^Version:[a-zA-Z0-9._ -]{1,30}$");
}
/**
* checks if a String is a valid version
* @param version the String to be checked
* @return true if it's valid, false otherwise
*/
private boolean isInvalidVersion(String version) {
return version == null || version.length() == 0 ||
version.equalsIgnoreCase(BuildProperties.getVersion());
}
/**
* builds a buffered reader from an open connection and a stream
* @param connection The connection
* @param is The input stream
* @return The Buffered reader created
* @throws IOException
*/
private BufferedReader buildBufferedReader(HttpURLConnection connection, InputStream is) throws IOException {
String encoding = connection.getContentEncoding();
if (encoding == null || encoding.equals(""))
encoding = "UTF-8";
return new BufferedReader(new InputStreamReader(is, encoding));
}
/**
* check if the content of a connection is valid
* @param connection the connection to be checked
* @return true if the content is valid, false otherwise
*/
private boolean checkContentType(HttpURLConnection connection) {
String contentType = connection.getContentType();
if (contentType == null ||
contentType.toLowerCase(Locale.ENGLISH).indexOf(Communicator.UPDATE_INFO_CONTENT_TYPE) < 0) {
// Unknown response type
log.warn("Unknown Content-type received:" + contentType);
return false;
}
return true;
}
/**
* check if a connection is responsive and valid
* @param connection the connection to be checked
* @return true if connection is ok, false otherwise
* @throws IOException
*/
private boolean checkConnection(HttpURLConnection connection) throws IOException{
log.debug("Update response code: " + connection.getResponseCode());
if (noUpdatesAvailable(connection)) {
log.info("No updates available");
info = new UpdateInfo();
return false;
}
if (!updateAvailable(connection)) {
// Error communicating with server
log.warn("Unknown server response code: " + connection.getResponseCode());
return false;
}
return true;
}
/**
* checks if a connection sent an update available flag
* @param connection the connection to be checked
* @return true if the response was an update available flag
* false otherwise
* @throws IOException if anything goes wrong
*/
private boolean updateAvailable(HttpURLConnection connection) throws IOException {
return connection.getResponseCode() == Communicator.UPDATE_INFO_UPDATE_AVAILABLE;
}
/**
* checks if a connection sent an update unavailable flag
* @param connection the connection to be checked
* @return true if the response was an no update available flag
* false otherwise
* @throws IOException if anything goes wrong
*/
private boolean noUpdatesAvailable(HttpURLConnection connection) throws IOException {
return connection.getResponseCode() == Communicator.UPDATE_INFO_NO_UPDATE_CODE;
}
/**
* Builds a connection with the given url
* @param url the url
* @return connection base on the url
* @throws IOException
*/
private HttpURLConnection getConnection(String url) throws IOException{
HttpURLConnection connection = Communicator.connectionSource.getConnection(url); HttpURLConnection connection = Communicator.connectionSource.getConnection(url);
connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT); connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT);
@ -165,80 +381,16 @@ public class UpdateInfoRetriever {
connection.setRequestProperty("X-OpenRocket-Locale", connection.setRequestProperty("X-OpenRocket-Locale",
Communicator.encode(Locale.getDefault().toString())); Communicator.encode(Locale.getDefault().toString()));
connection.setRequestProperty("X-OpenRocket-CPUs", "" + Runtime.getRuntime().availableProcessors()); connection.setRequestProperty("X-OpenRocket-CPUs", "" + Runtime.getRuntime().availableProcessors());
return connection;
InputStream is = null; }
try {
connection.connect(); /**
* builds the default url for fetching updates
log.debug("Update response code: " + connection.getResponseCode()); * @return the string with an url for fethcing updates
*/
if (connection.getResponseCode() == Communicator.UPDATE_INFO_NO_UPDATE_CODE) { private String getUrl() {
// No updates are available return Communicator.UPDATE_INFO_URL + "?" + Communicator.VERSION_PARAM + "="
log.info("No updates available"); + Communicator.encode(BuildProperties.getVersion());
info = new UpdateInfo();
return;
}
if (connection.getResponseCode() != Communicator.UPDATE_INFO_UPDATE_AVAILABLE) {
// Error communicating with server
log.warn("Unknown server response code: " + connection.getResponseCode());
return;
}
String contentType = connection.getContentType();
if (contentType == null ||
contentType.toLowerCase(Locale.ENGLISH).indexOf(Communicator.UPDATE_INFO_CONTENT_TYPE) < 0) {
// Unknown response type
log.warn("Unknown Content-type received:" + contentType);
return;
}
// Update is available, parse input
is = connection.getInputStream();
is = new LimitedInputStream(is, Communicator.MAX_INPUT_BYTES);
String encoding = connection.getContentEncoding();
if (encoding == null || encoding.equals(""))
encoding = "UTF-8";
BufferedReader reader = new BufferedReader(new InputStreamReader(is, encoding));
String version = null;
ArrayList<ComparablePair<Integer, String>> updates =
new ArrayList<ComparablePair<Integer, String>>();
String line = reader.readLine();
while (line != null) {
if (line.matches("^Version:[a-zA-Z0-9._ -]{1,30}$")) {
version = line.substring(8).trim();
} else if (line.matches("^[0-9]{1,9}:\\P{Cntrl}{1,300}$")) {
String[] split = line.split(":", 2);
int n = Integer.parseInt(split[0]);
updates.add(new ComparablePair<Integer, String>(n, split[1].trim()));
}
// Ignore line otherwise
line = reader.readLine();
}
// Check version input
if (version == null || version.length() == 0 ||
version.equalsIgnoreCase(BuildProperties.getVersion())) {
// Invalid response
log.warn("Invalid version received, ignoring.");
return;
}
info = new UpdateInfo(version, updates);
log.info("Found update: " + info);
} finally {
try {
if (is != null)
is.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
} }
} }
} }

View File

@ -43,7 +43,7 @@ public abstract class AsynchronousDatabaseLoader {
/** /**
* Return whether loading the database has ended. * @return whether loading the database has ended.
*/ */
public boolean isLoaded() { public boolean isLoaded() {
return endedLoading; return endedLoading;
@ -86,10 +86,27 @@ public abstract class AsynchronousDatabaseLoader {
} }
} }
/**
*
*/
private void doLoad() { private void doLoad() {
// Pause for indicated startup time // Pause for indicated startup time
pauseForStartupTime();
loadDatabase();
synchronized (this) {
endedLoading = true;
this.notifyAll();
}
}
/**
* waits the startup time before loading the database
*/
private void pauseForStartupTime() {
long startLoading = System.currentTimeMillis() + startupDelay; long startLoading = System.currentTimeMillis() + startupDelay;
while (!inUse && System.currentTimeMillis() < startLoading) { while (!inUse && System.currentTimeMillis() < startLoading) {
synchronized (this) { synchronized (this) {
@ -99,16 +116,11 @@ public abstract class AsynchronousDatabaseLoader {
} }
} }
} }
loadDatabase();
synchronized (this) {
endedLoading = true;
this.notifyAll();
}
} }
/**
* method that actually load the database
*/
protected abstract void loadDatabase(); protected abstract void loadDatabase();

View File

@ -6,10 +6,23 @@ import net.sf.openrocket.preset.ComponentPreset;
public interface ComponentPresetDao { public interface ComponentPresetDao {
/**
* return a list all components
* @return list of all components
*/
public List<ComponentPreset> listAll(); public List<ComponentPreset> listAll();
/**
* insert a component preset into a database
* @param preset the component to be inserted into the database
*/
public void insert( ComponentPreset preset ); public void insert( ComponentPreset preset );
/**
* return all components preset matching the given type
* @param type the searched type
* @return the list of components matching the type
*/
public List<ComponentPreset> listForType( ComponentPreset.Type type ); public List<ComponentPreset> listForType( ComponentPreset.Type type );
/** /**
@ -21,13 +34,35 @@ public interface ComponentPresetDao {
* @return * @return
*/ */
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite ); public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite );
/**
* Returns a list of components presets of multiple types
* @param type the types to be searched for
* @return
*/
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type ); public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type );
/**
* Returns a list of components preset of each type in the list
* @param types the list of types to be searched for
* @return
*/
public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types ); public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types );
/**
* set or reset a component preset as favorite
* @param preset the preset to be set as favorite
* @param type the type of the preset
* @param favorite true to set, false to reset as favorite
*/
public void setFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite ); public void setFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite );
/**
* returns a list of components preset based on manufacturer and part number
* @param manufacturer the manufacturer to be searched for
* @param partNo the part number of the component
* @return the resulting list of the search
*/
public List<ComponentPreset> find( String manufacturer, String partNo ); public List<ComponentPreset> find( String manufacturer, String partNo );
} }

View File

@ -19,6 +19,7 @@ import net.sf.openrocket.database.DatabaseListener;
*/ */
public class Database<T extends Comparable<T>> extends AbstractSet<T> { public class Database<T extends Comparable<T>> extends AbstractSet<T> {
/** the list that contains the data from the database itself*/
protected final List<T> list = new ArrayList<T>(); protected final List<T> list = new ArrayList<T>();
private final ArrayList<DatabaseListener<T>> listeners = new ArrayList<DatabaseListener<T>>(); private final ArrayList<DatabaseListener<T>> listeners = new ArrayList<DatabaseListener<T>>();
@ -33,6 +34,10 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
return list.size(); return list.size();
} }
/**
* {@inheritDoc}
* fires add event
*/
@Override @Override
public boolean add(T element) { public boolean add(T element) {
int index; int index;
@ -71,17 +76,27 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
return list.indexOf(m); return list.indexOf(m);
} }
/**
* adds a listener for database changes
* @param listener the listener
*/
public void addDatabaseListener(DatabaseListener<T> listener) { public void addDatabaseListener(DatabaseListener<T> listener) {
listeners.add(listener); listeners.add(listener);
} }
/**
* removes a listener from the list os listeners
* @param listener
*/
public void removeChangeListener(DatabaseListener<T> listener) { public void removeChangeListener(DatabaseListener<T> listener) {
listeners.remove(listener); listeners.remove(listener);
} }
/**
* wake up call for database listeners for when elements are added
* @param element the element added
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void fireAddEvent(T element) { protected void fireAddEvent(T element) {
Object[] array = listeners.toArray(); Object[] array = listeners.toArray();
@ -90,6 +105,10 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
} }
} }
/**
* wake up call for database listeners when elements are removed
* @param element the removed element
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void fireRemoveEvent(T element) { protected void fireRemoveEvent(T element) {
Object[] array = listeners.toArray(); Object[] array = listeners.toArray();
@ -98,10 +117,6 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
} }
} }
/** /**
* Iterator class implementation that fires changes if remove() is called. * Iterator class implementation that fires changes if remove() is called.
*/ */
@ -120,6 +135,10 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
return current; return current;
} }
/**
* {@inheritDoc}
* fires remove event
*/
@Override @Override
public void remove() { public void remove() {
iterator.remove(); iterator.remove();

View File

@ -1,9 +1,24 @@
package net.sf.openrocket.database; package net.sf.openrocket.database;
/**
* interface defining listeners for database
*
* @param <T> type stored in the database
*/
public interface DatabaseListener<T extends Comparable<T>> { public interface DatabaseListener<T extends Comparable<T>> {
/**
* action for when elements are added
* @param element the element added
* @param source the database of which the element was added
*/
public void elementAdded(T element, Database<T> source); public void elementAdded(T element, Database<T> source);
/**
* action for when elements are removed
* @param element the removed element
* @param source the database on which the element was removed
*/
public void elementRemoved(T element, Database<T> source); public void elementRemoved(T element, Database<T> source);
} }

View File

@ -117,7 +117,13 @@ public class Databases {
BULK_MATERIAL.addDatabaseListener(listener); BULK_MATERIAL.addDatabaseListener(listener);
} }
/**
* builds a new material based on the parameters given
* @param type The type of material
* @param baseName the name of material
* @param density density
* @return a new onejct withe the material data
*/
private static Material newMaterial(Type type, String baseName, double density) { private static Material newMaterial(Type type, String baseName, double density) {
String name = trans.get("material", baseName); String name = trans.get("material", baseName);
return Material.newMaterial(type, name, density, false); return Material.newMaterial(type, name, density, false);
@ -145,21 +151,7 @@ public class Databases {
* @return the material, or <code>null</code> if not found. * @return the material, or <code>null</code> if not found.
*/ */
public static Material findMaterial(Material.Type type, String baseName) { public static Material findMaterial(Material.Type type, String baseName) {
Database<Material> db; Database<Material> db = getDatabase(type);
switch (type) {
case BULK:
db = BULK_MATERIAL;
break;
case SURFACE:
db = SURFACE_MATERIAL;
break;
case LINE:
db = LINE_MATERIAL;
break;
default:
throw new IllegalArgumentException("Illegal material type: " + type);
}
String name = trans.get("material", baseName); String name = trans.get("material", baseName);
for (Material m : db) { for (Material m : db) {
@ -170,6 +162,24 @@ public class Databases {
return null; return null;
} }
/**
* gets the specific database with the given type
* @param type the desired type
* @return the database of the type given
*/
private static Database<Material> getDatabase(Material.Type type){
switch (type) {
case BULK:
return BULK_MATERIAL;
case SURFACE:
return SURFACE_MATERIAL;
case LINE:
return LINE_MATERIAL;
default:
throw new IllegalArgumentException("Illegal material type: " + type);
}
}
/** /**
* Find a material from the database or return a new user defined material if the specified * Find a material from the database or return a new user defined material if the specified
@ -184,21 +194,7 @@ public class Databases {
* @return the material object from the database or a new material. * @return the material object from the database or a new material.
*/ */
public static Material findMaterial(Material.Type type, String baseName, double density) { public static Material findMaterial(Material.Type type, String baseName, double density) {
Database<Material> db; Database<Material> db = getDatabase(type);
switch (type) {
case BULK:
db = BULK_MATERIAL;
break;
case SURFACE:
db = SURFACE_MATERIAL;
break;
case LINE:
db = LINE_MATERIAL;
break;
default:
throw new IllegalArgumentException("Illegal material type: " + type);
}
String name = trans.get("material", baseName); String name = trans.get("material", baseName);
for (Material m : db) { for (Material m : db) {

View File

@ -45,31 +45,128 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
private Motor.Type type = Motor.Type.UNKNOWN; private Motor.Type type = Motor.Type.UNKNOWN;
/**
* adds a motor into the set,
* uses digest and designation to determinate if a motor is present or not
* @param motor the motor to be added
*/
public void addMotor(ThrustCurveMotor motor) { public void addMotor(ThrustCurveMotor motor) {
// Check for first insertion checkFirstInsertion(motor);
if (motors.isEmpty()) { verifyMotor(motor);
manufacturer = motor.getManufacturer(); updateType(motor);
designation = motor.getDesignation(); checkChangeSimplifiedDesignation(motor);
simplifiedDesignation = simplifyDesignation(designation); addStandardDelay(motor);
diameter = motor.getDiameter(); if(!checkMotorOverwrite(motor)){
length = motor.getLength(); motors.add(motor);
totalImpulse = Math.round((motor.getTotalImpulseEstimate())); digestMap.put(motor, motor.getDigest());
Collections.sort(motors, comparator);
}
}
/**
* checks whether a motor is present, overwriting it
* @param motor the motor to be checked
* @return if there was an overwrite or not
*/
private boolean checkMotorOverwrite(ThrustCurveMotor motor) {
// Check whether to add as new motor or overwrite existing
final String digest = motor.getDigest();
for (int index = 0; index < motors.size(); index++) {
Motor m = motors.get(index);
if (isMotorPresent(motor, digest, m)) {
String newCmt = getFormattedDescription(motor);
String oldCmt = getFormattedDescription(m);
if (isNewDescriptionIrrelevant(newCmt, oldCmt)) {
return true;
} else if (oldCmt.length() == 0) {
replaceMotor(motor, digest, index);
return true;
}
}
} }
return false;
// Verify that the motor can be added }
if (!matches(motor)) {
throw new IllegalArgumentException("Motor does not match the set:" +
" manufacturer=" + manufacturer + /**
" designation=" + designation + * get a description from a motor
" diameter=" + diameter + * @param motor the motor
" length=" + length + * @return the description of the motor
" set_size=" + motors.size() + */
" motor=" + motor); private String getFormattedDescription(Motor motor) {
return motor.getDescription().replaceAll("\\s+", " ").trim();
}
/**
* checks if a motor is in the maps
* @param motor the motor to be checked
* @param digest the digest of the motor
* @param m the current motor being checked with
* @return wheter the motor is or no
*/
private boolean isMotorPresent(ThrustCurveMotor motor, final String digest, Motor m) {
return digest.equals(digestMap.get(m)) &&
motor.getDesignation().equals(m.getDesignation());
}
/**
* replace a motor into the given index
* @param motor
* @param digest
* @param index
*/
private void replaceMotor(ThrustCurveMotor motor, final String digest, int index) {
motors.set(index, motor);
digestMap.put(motor, digest);
}
/**
* checks if the new commit message is empty or equals to the old commit
* @param newCmt the new commit message
* @param oldCmt the old commit message
* @return whether the new commit is empty or equals to the old commit
*/
private boolean isNewDescriptionIrrelevant(String newCmt, String oldCmt) {
return newCmt.length() == 0 || newCmt.equals(oldCmt);
}
/**
* adds the standard delay if aplicable
* @param motor the motor to be considered
*/
private void addStandardDelay(ThrustCurveMotor motor) {
for (double d : motor.getStandardDelays()) {
d = Math.rint(d);
if (!delays.contains(d)) {
delays.add(d);
}
} }
Collections.sort(delays);
// Update the type if now known }
/**
* checks if simplified designation should be changed with the given motor
* @param motor the motor to be checked with
*/
private void checkChangeSimplifiedDesignation(ThrustCurveMotor motor) {
if (!designation.equalsIgnoreCase(motor.getDesignation().trim())) {
designation = simplifiedDesignation;
}
}
/**
* checks if the cached type should be changed with the given motor
* if it's hybrid, delays will be added
* @param motor the motor to be checked with
*/
private void updateType(ThrustCurveMotor motor) {
if (type == Motor.Type.UNKNOWN) { if (type == Motor.Type.UNKNOWN) {
type = motor.getMotorType(); type = motor.getMotorType();
// Add "Plugged" option if hybrid // Add "Plugged" option if hybrid
@ -79,56 +176,45 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
} }
} }
} }
}
// Change the simplified designation if necessary
if (!designation.equalsIgnoreCase(motor.getDesignation().trim())) { /**
designation = simplifiedDesignation; * verifies if a motor is valid
* @param motor
*/
private void verifyMotor(ThrustCurveMotor motor) {
if (!matches(motor)) {
throw new IllegalArgumentException("Motor does not match the set:" +
" manufacturer=" + manufacturer +
" designation=" + designation +
" diameter=" + diameter +
" length=" + length +
" set_size=" + motors.size() +
" motor=" + motor);
} }
}
// Add the standard delays
for (double d : motor.getStandardDelays()) { /**
d = Math.rint(d); * check if the given motor is the first one, and sets attributes according to it
if (!delays.contains(d)) { * @param motor
delays.add(d); */
} private void checkFirstInsertion(ThrustCurveMotor motor) {
if (motors.isEmpty()) {
manufacturer = motor.getManufacturer();
designation = motor.getDesignation();
simplifiedDesignation = simplifyDesignation(designation);
diameter = motor.getDiameter();
length = motor.getLength();
totalImpulse = Math.round((motor.getTotalImpulseEstimate()));
} }
Collections.sort(delays);
// Check whether to add as new motor or overwrite existing
final String digest = motor.getDigest();
for (int index = 0; index < motors.size(); index++) {
Motor m = motors.get(index);
if (digest.equals(digestMap.get(m)) &&
motor.getDesignation().equals(m.getDesignation())) {
// Match found, check which one to keep (or both) based on comment
String newCmt = motor.getDescription().replaceAll("\\s+", " ").trim();
String oldCmt = m.getDescription().replaceAll("\\s+", " ").trim();
if (newCmt.length() == 0 || newCmt.equals(oldCmt)) {
// Do not replace and do not add
return;
} else if (oldCmt.length() == 0) {
// Replace existing motor
motors.set(index, motor);
digestMap.put(motor, digest);
return;
}
// else continue search and add both
}
}
// Motor not present, add it
motors.add(motor);
digestMap.put(motor, digest);
Collections.sort(motors, comparator);
} }
/**
* Checks if a motor can be added with the set
* A set contains motors of same manufacturer, diameter, length and type
* @param m the motor to be checked with
* @return if the motor passed the test or not
*/
public boolean matches(ThrustCurveMotor m) { public boolean matches(ThrustCurveMotor m) {
if (motors.isEmpty()) if (motors.isEmpty())
return true; return true;
@ -153,12 +239,18 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
return true; return true;
} }
/**
* returns a new list with the stored motors
* @return list
*/
public List<ThrustCurveMotor> getMotors() { public List<ThrustCurveMotor> getMotors() {
return motors.clone(); return motors.clone();
} }
/**
*
* @return number of motor in the set
*/
public int getMotorCount() { public int getMotorCount() {
return motors.size(); return motors.size();
} }

View File

@ -7,19 +7,38 @@ import java.io.InputStream;
import net.sf.openrocket.util.AbstractChangeSource; import net.sf.openrocket.util.AbstractChangeSource;
import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.ChangeSource;
/**
*
* Class handler of documents attachments
*
*/
public abstract class Attachment extends AbstractChangeSource implements Comparable<Attachment>, ChangeSource { public abstract class Attachment extends AbstractChangeSource implements Comparable<Attachment>, ChangeSource {
private final String name; private final String name;
/**
* default constructor
* @param name the name of attachment
*/
public Attachment(String name) { public Attachment(String name) {
super(); super();
this.name = name; this.name = name;
} }
/**
* returns the name of attachment
* @return name of attachment
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* returns the stream of bytes representing the attachment
* @return the stream of bytes representing the attachment
* @throws FileNotFoundException
* @throws IOException
*/
public abstract InputStream getBytes() throws FileNotFoundException, IOException; public abstract InputStream getBytes() throws FileNotFoundException, IOException;
@Override @Override

View File

@ -25,11 +25,20 @@ import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.FileUtils; import net.sf.openrocket.util.FileUtils;
import net.sf.openrocket.util.StateChangeListener; import net.sf.openrocket.util.StateChangeListener;
/**
*
* Class that handles decal usage registration
*
*/
public class DecalRegistry { public class DecalRegistry {
/**
* default constructor
*/
DecalRegistry() { DecalRegistry() {
} }
/** the decal usage map*/
private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>(); private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>();
public DecalImage makeUniqueImage(DecalImage original) { public DecalImage makeUniqueImage(DecalImage original) {

View File

@ -12,16 +12,24 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
private static final Translator trans = Application.getTranslator(); private static final Translator trans = Application.getTranslator();
//private static final Logger log = LoggerFactory.getLogger(AxialStage.class); //private static final Logger log = LoggerFactory.getLogger(AxialStage.class);
/** list of separations to be happening*/
protected FlightConfigurableParameterSet<StageSeparationConfiguration> separations; protected FlightConfigurableParameterSet<StageSeparationConfiguration> separations;
/** number of stages */
protected int stageNumber; protected int stageNumber;
/**
* default constructor, builds a rocket with zero stages
*/
public AxialStage(){ public AxialStage(){
this.separations = new FlightConfigurableParameterSet<StageSeparationConfiguration>( new StageSeparationConfiguration()); this.separations = new FlightConfigurableParameterSet<StageSeparationConfiguration>( new StageSeparationConfiguration());
this.relativePosition = Position.AFTER; this.relativePosition = Position.AFTER;
this.stageNumber = 0; this.stageNumber = 0;
} }
/**
* {@inheritDoc}
* AxialStage will always accept children
*/
@Override @Override
public boolean allowsChildren() { public boolean allowsChildren() {
return true; return true;
@ -33,6 +41,10 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
return trans.get("Stage.Stage"); return trans.get("Stage.Stage");
} }
/**
* gets the separation configuration of the rocket
* @return the separation configuration of the rocket
*/
public FlightConfigurableParameterSet<StageSeparationConfiguration> getSeparationConfigurations() { public FlightConfigurableParameterSet<StageSeparationConfiguration> getSeparationConfigurations() {
return separations; return separations;
} }
@ -42,7 +54,10 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
separations.reset(fcid); separations.reset(fcid);
} }
// not strictly accurate, but this should provide an acceptable estimate for total vehicle size /**
* {@inheritDoc}
* not strictly accurate, but this should provide an acceptable estimate for total vehicle size
*/
@Override @Override
public Collection<Coordinate> getComponentBounds() { public Collection<Coordinate> getComponentBounds() {
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8); Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
@ -110,16 +125,28 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
return this.stageNumber; return this.stageNumber;
} }
/**
* {@inheritDoc}
* axialStage is always after
*/
@Override @Override
public boolean isAfter(){ public boolean isAfter(){
return true; return true;
} }
/**
* returns if the object is a launch stage
* @return if the object is a launch stage
*/
public boolean isLaunchStage(){ public boolean isLaunchStage(){
return ( this instanceof ParallelStage ) return ( this instanceof ParallelStage )
||( getRocket().getBottomCoreStage().equals(this)); ||( getRocket().getBottomCoreStage().equals(this));
} }
/**
* sets the stage number
* @param newStageNumber
*/
public void setStageNumber(final int newStageNumber) { public void setStageNumber(final int newStageNumber) {
this.stageNumber = newStageNumber; this.stageNumber = newStageNumber;
} }
@ -138,12 +165,21 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
return buf; return buf;
} }
/**
* method used for debugging separation
* @return a string that represents the debug message of separation
*/
public String toDebugSeparation() { public String toDebugSeparation() {
StringBuilder buff = new StringBuilder(); StringBuilder buff = new StringBuilder();
buff.append( this.separations.toDebug() ); buff.append( this.separations.toDebug() );
return buff.toString(); return buff.toString();
} }
/**
* gets the previous stage installed in the rockets
* returns null if this is the first stage
* @return the previous stage in the rocket
*/
public AxialStage getPreviousStage() { public AxialStage getPreviousStage() {
if( this instanceof ParallelStage ){ if( this instanceof ParallelStage ){
return (AxialStage) this.parent; return (AxialStage) this.parent;

View File

@ -30,7 +30,11 @@ import net.sf.openrocket.util.SafetyMutex;
import net.sf.openrocket.util.StateChangeListener; import net.sf.openrocket.util.StateChangeListener;
import net.sf.openrocket.util.UniqueID; import net.sf.openrocket.util.UniqueID;
/**
* Master class that defines components of rockets
* almost all hardware from the rocket extends from this abstract class
*
*/
public abstract class RocketComponent implements ChangeSource, Cloneable, Iterable<RocketComponent> { public abstract class RocketComponent implements ChangeSource, Cloneable, Iterable<RocketComponent> {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final Logger log = LoggerFactory.getLogger(RocketComponent.class); private static final Logger log = LoggerFactory.getLogger(RocketComponent.class);
@ -41,7 +45,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
//private static final Translator trans = Application.getTranslator(); //private static final Translator trans = Application.getTranslator();
/* /**
* Text is suitable to the form * Text is suitable to the form
* Position relative to: <title> * Position relative to: <title>
*/ */