From b7085203640ff4fae2e6558955ebe88950969208 Mon Sep 17 00:00:00 2001 From: Luiz Victor Linhares Rocha Date: Mon, 17 Oct 2016 16:41:17 -0200 Subject: [PATCH 1/2] adds documentation and refactoring for many files --- .../sf/openrocket/appearance/Appearance.java | 4 +- .../net/sf/openrocket/appearance/Decal.java | 47 ++- .../sf/openrocket/appearance/DecalImage.java | 24 ++ .../defaults/DefaultAppearance.java | 40 ++ .../defaults/ResourceDecalImage.java | 11 +- .../openrocket/communication/UpdateInfo.java | 14 +- .../communication/UpdateInfoRetriever.java | 352 +++++++++++++----- .../database/AsynchronousDatabaseLoader.java | 32 +- .../database/ComponentPresetDao.java | 37 +- .../net/sf/openrocket/database/Database.java | 31 +- .../openrocket/database/DatabaseListener.java | 15 + .../net/sf/openrocket/database/Databases.java | 58 ++- .../database/motor/ThrustCurveMotorSet.java | 230 ++++++++---- .../sf/openrocket/document/Attachment.java | 19 + .../sf/openrocket/document/DecalRegistry.java | 9 + .../rocketcomponent/AxialStage.java | 40 +- .../rocketcomponent/RocketComponent.java | 8 +- 17 files changed, 744 insertions(+), 227 deletions(-) diff --git a/core/src/net/sf/openrocket/appearance/Appearance.java b/core/src/net/sf/openrocket/appearance/Appearance.java index 385256bb6..e9271491c 100644 --- a/core/src/net/sf/openrocket/appearance/Appearance.java +++ b/core/src/net/sf/openrocket/appearance/Appearance.java @@ -23,9 +23,7 @@ public class Appearance { } public Appearance(final Color paint, final double shine) { - this.paint = paint; - this.shine = MathUtil.clamp(shine, 0, 1); - this.texture = null; + this(paint,shine,null); } public Color getPaint() { diff --git a/core/src/net/sf/openrocket/appearance/Decal.java b/core/src/net/sf/openrocket/appearance/Decal.java index 5e5461188..412cdcd3d 100644 --- a/core/src/net/sf/openrocket/appearance/Decal.java +++ b/core/src/net/sf/openrocket/appearance/Decal.java @@ -4,12 +4,17 @@ import net.sf.openrocket.startup.Application; 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 */ public class Decal { + /** + * enum to flag what happens on edge in a decal + * + * + */ public static enum EdgeMode { REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker"); private final String transName; @@ -29,6 +34,16 @@ public class Decal { private final DecalImage image; 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, final DecalImage image, final EdgeMode mode) { this.offset = offset; @@ -39,26 +54,56 @@ public class Decal { this.mode = mode; } + /** + * returns the offset, in coordinates object format + * + * @return offset coordinates of the decal + */ public Coordinate getOffset() { return offset; } + /** + * return the center, in coordinates object format + * + * @return The center coordinates of the decal + */ public Coordinate getCenter() { return center; } + /** + * return the scaling of the decal, in coordinate format + * + * @return the scale coordinates of the decal + */ public Coordinate getScale() { return scale; } + /** + * returns the rotation of the decal, in radians + * + * @return the rotation of the decal, in radians + */ public double getRotation() { return rotation; } + /** + * return the edge behaviour of the decal + * + * @return the edge behaviour of the decal + */ public EdgeMode getEdgeMode() { return mode; } + /** + * returns the image of the decal itself + * + * @return the image of the decal itself + */ public DecalImage getImage() { return image; } diff --git a/core/src/net/sf/openrocket/appearance/DecalImage.java b/core/src/net/sf/openrocket/appearance/DecalImage.java index 544eda8b3..77a74010f 100644 --- a/core/src/net/sf/openrocket/appearance/DecalImage.java +++ b/core/src/net/sf/openrocket/appearance/DecalImage.java @@ -7,13 +7,37 @@ import java.io.InputStream; import net.sf.openrocket.util.ChangeSource; +/** + * Interface to handle image files for declas + * + */ public interface DecalImage extends ChangeSource, Comparable { + /** + * returns the name of the file path of the image + * @return name of file path + */ 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; + /** + * exports an image into the File + * @param file The File handler object + * @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); } diff --git a/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java b/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java index 38806be53..bd57cc94a 100644 --- a/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java +++ b/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java @@ -23,8 +23,22 @@ import net.sf.openrocket.rocketcomponent.TubeFinSet; import net.sf.openrocket.util.Color; import net.sf.openrocket.util.Coordinate; +/** + * + * Class defining the default images of the application + * + */ 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) { return new Appearance( new Color(1, 1, 1), @@ -37,6 +51,14 @@ public class DefaultAppearance { 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) { return new Appearance( base, @@ -69,6 +91,12 @@ public class DefaultAppearance { private static HashMap plastics = new HashMap(); + /** + * 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) { if (!plastics.containsKey(c)) { plastics.put(c, new Appearance(c, .3)); @@ -76,6 +104,12 @@ public class DefaultAppearance { 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) { if (c instanceof BodyTube) return ESTES_BT; @@ -100,6 +134,12 @@ public class DefaultAppearance { 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) { if (m instanceof ThrustCurveMotor) { ThrustCurveMotor tcm = (ThrustCurveMotor) m; diff --git a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java index 630cf3639..6c70470ce 100644 --- a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java +++ b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java @@ -8,11 +8,20 @@ import java.io.InputStream; import net.sf.openrocket.appearance.DecalImage; import net.sf.openrocket.util.StateChangeListener; - +/** + * + * Default implementation class of DecalImage + * + */ public class ResourceDecalImage implements DecalImage { + /** File path to the image*/ final String resource; + /** + * main constructor, stores the file path given + * @param resource + */ public ResourceDecalImage(final String resource) { this.resource = resource; } diff --git a/core/src/net/sf/openrocket/communication/UpdateInfo.java b/core/src/net/sf/openrocket/communication/UpdateInfo.java index 78458b812..f4d296e75 100644 --- a/core/src/net/sf/openrocket/communication/UpdateInfo.java +++ b/core/src/net/sf/openrocket/communication/UpdateInfo.java @@ -6,18 +6,30 @@ import net.sf.openrocket.util.ArrayList; import net.sf.openrocket.util.BuildProperties; import net.sf.openrocket.util.ComparablePair; + /** + * + * class that stores the update information of the application + * + */ public class UpdateInfo { private final String latestVersion; private final ArrayList> updates; - + /** + * loads the default information + */ public UpdateInfo() { this.latestVersion = BuildProperties.getVersion(); this.updates = new ArrayList>(); } + /** + * 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> updates) { this.latestVersion = version; this.updates = new ArrayList>(updates); diff --git a/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java b/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java index 16d51456b..654ac0a93 100644 --- a/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java +++ b/core/src/net/sf/openrocket/communication/UpdateInfoRetriever.java @@ -41,10 +41,11 @@ public class UpdateInfoRetriever { * Check whether the update info fetching is still in progress. * * @return true if the communication is still in progress. + * @throws IllegalStateException if {@link #startFetchUpdateInfo()} has not been called */ public boolean isRunning() { if (fetcher == null) { - throw new IllegalStateException("startFetchUpdateInfo() has not been called"); + throw new IllegalStateException("startFetchUpdateInfo() has not been called"); } return fetcher.isAlive(); } @@ -81,43 +82,76 @@ public class UpdateInfoRetriever { */ /* package-private */ static UpdateInfo parseUpdateInput(Reader r) throws IOException { - BufferedReader reader; - if (r instanceof BufferedReader) { - reader = (BufferedReader) r; - } else { - reader = new BufferedReader(r); - } - - + BufferedReader reader = convertToBufferedReader(r); String version = null; + ArrayList> updates = new ArrayList>(); String str = reader.readLine(); 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(); - } else if (str.matches("^[0-9]+:\\p{Print}+$")) { - int index = str.indexOf(':'); - int value = Integer.parseInt(str.substring(0, index)); - String desc = str.substring(index + 1).trim(); - if (!desc.equals("")) { - updates.add(new ComparablePair(value, desc)); - } + } else if (isUpdateToken(str)) { + ComparablePair update = parseUpdateToken(str); + if(update != null) + updates.add(update); } - // Ignore anything else str = reader.readLine(); } - if (version != null) { - return new UpdateInfo(version, updates); - } else { + if (version == 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 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(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. * @@ -137,11 +171,193 @@ public class UpdateInfoRetriever { } } - + /** + * Establishes a connection with data of previous updates + * @throws IOException + */ private void doConnection() throws IOException { - String url = Communicator.UPDATE_INFO_URL + "?" + Communicator.VERSION_PARAM + "=" - + Communicator.encode(BuildProperties.getVersion()); + HttpURLConnection connection = getConnection(getUrl()); + 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> updates = + new ArrayList>(); + + 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 parseUpdateInfo(String line){ + String[] split = line.split(":", 2); + int n = Integer.parseInt(split[0]); + return new ComparablePair(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); connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT); @@ -165,80 +381,16 @@ public class UpdateInfoRetriever { connection.setRequestProperty("X-OpenRocket-Locale", Communicator.encode(Locale.getDefault().toString())); connection.setRequestProperty("X-OpenRocket-CPUs", "" + Runtime.getRuntime().availableProcessors()); - - InputStream is = null; - try { - connection.connect(); - - log.debug("Update response code: " + connection.getResponseCode()); - - if (connection.getResponseCode() == Communicator.UPDATE_INFO_NO_UPDATE_CODE) { - // No updates are available - log.info("No updates available"); - 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> updates = - new ArrayList>(); - - 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(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(); - } - } + return connection; + } + + /** + * builds the default url for fetching updates + * @return the string with an url for fethcing updates + */ + private String getUrl() { + return Communicator.UPDATE_INFO_URL + "?" + Communicator.VERSION_PARAM + "=" + + Communicator.encode(BuildProperties.getVersion()); } } } diff --git a/core/src/net/sf/openrocket/database/AsynchronousDatabaseLoader.java b/core/src/net/sf/openrocket/database/AsynchronousDatabaseLoader.java index 71bda4757..a8aed6f5c 100644 --- a/core/src/net/sf/openrocket/database/AsynchronousDatabaseLoader.java +++ b/core/src/net/sf/openrocket/database/AsynchronousDatabaseLoader.java @@ -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() { return endedLoading; @@ -86,10 +86,27 @@ public abstract class AsynchronousDatabaseLoader { } } - + /** + * + */ private void doLoad() { // 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; while (!inUse && System.currentTimeMillis() < startLoading) { 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(); diff --git a/core/src/net/sf/openrocket/database/ComponentPresetDao.java b/core/src/net/sf/openrocket/database/ComponentPresetDao.java index a27a7f5d4..aaa66bf1d 100644 --- a/core/src/net/sf/openrocket/database/ComponentPresetDao.java +++ b/core/src/net/sf/openrocket/database/ComponentPresetDao.java @@ -6,10 +6,23 @@ import net.sf.openrocket.preset.ComponentPreset; public interface ComponentPresetDao { + /** + * return a list all components + * @return list of all components + */ public List listAll(); + /** + * insert a component preset into a database + * @param preset the component to be inserted into the database + */ 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 listForType( ComponentPreset.Type type ); /** @@ -21,13 +34,35 @@ public interface ComponentPresetDao { * @return */ public List 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 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 listForTypes( List 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 ); + /** + * 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 find( String manufacturer, String partNo ); } \ No newline at end of file diff --git a/core/src/net/sf/openrocket/database/Database.java b/core/src/net/sf/openrocket/database/Database.java index 3f16e818a..df513ea21 100644 --- a/core/src/net/sf/openrocket/database/Database.java +++ b/core/src/net/sf/openrocket/database/Database.java @@ -19,6 +19,7 @@ import net.sf.openrocket.database.DatabaseListener; */ public class Database> extends AbstractSet { + /** the list that contains the data from the database itself*/ protected final List list = new ArrayList(); private final ArrayList> listeners = new ArrayList>(); @@ -33,6 +34,10 @@ public class Database> extends AbstractSet { return list.size(); } + /** + * {@inheritDoc} + * fires add event + */ @Override public boolean add(T element) { int index; @@ -71,17 +76,27 @@ public class Database> extends AbstractSet { return list.indexOf(m); } - + /** + * adds a listener for database changes + * @param listener the listener + */ public void addDatabaseListener(DatabaseListener listener) { listeners.add(listener); } + /** + * removes a listener from the list os listeners + * @param listener + */ public void removeChangeListener(DatabaseListener listener) { listeners.remove(listener); } - + /** + * wake up call for database listeners for when elements are added + * @param element the element added + */ @SuppressWarnings("unchecked") protected void fireAddEvent(T element) { Object[] array = listeners.toArray(); @@ -90,6 +105,10 @@ public class Database> extends AbstractSet { } } + /** + * wake up call for database listeners when elements are removed + * @param element the removed element + */ @SuppressWarnings("unchecked") protected void fireRemoveEvent(T element) { Object[] array = listeners.toArray(); @@ -98,10 +117,6 @@ public class Database> extends AbstractSet { } } - - - - /** * Iterator class implementation that fires changes if remove() is called. */ @@ -120,6 +135,10 @@ public class Database> extends AbstractSet { return current; } + /** + * {@inheritDoc} + * fires remove event + */ @Override public void remove() { iterator.remove(); diff --git a/core/src/net/sf/openrocket/database/DatabaseListener.java b/core/src/net/sf/openrocket/database/DatabaseListener.java index a24b2ddeb..54438f163 100644 --- a/core/src/net/sf/openrocket/database/DatabaseListener.java +++ b/core/src/net/sf/openrocket/database/DatabaseListener.java @@ -1,9 +1,24 @@ package net.sf.openrocket.database; +/** + * interface defining listeners for database + * + * @param type stored in the database + */ public interface DatabaseListener> { + /** + * 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 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 source); } diff --git a/core/src/net/sf/openrocket/database/Databases.java b/core/src/net/sf/openrocket/database/Databases.java index ffe3628eb..d28e92ac0 100644 --- a/core/src/net/sf/openrocket/database/Databases.java +++ b/core/src/net/sf/openrocket/database/Databases.java @@ -117,7 +117,13 @@ public class Databases { 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) { String name = trans.get("material", baseName); return Material.newMaterial(type, name, density, false); @@ -145,21 +151,7 @@ public class Databases { * @return the material, or null if not found. */ public static Material findMaterial(Material.Type type, String baseName) { - Database db; - 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); - } - + Database db = getDatabase(type); String name = trans.get("material", baseName); for (Material m : db) { @@ -170,6 +162,24 @@ public class Databases { 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 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 @@ -184,21 +194,7 @@ public class Databases { * @return the material object from the database or a new material. */ public static Material findMaterial(Material.Type type, String baseName, double density) { - Database db; - 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); - } - + Database db = getDatabase(type); String name = trans.get("material", baseName); for (Material m : db) { diff --git a/core/src/net/sf/openrocket/database/motor/ThrustCurveMotorSet.java b/core/src/net/sf/openrocket/database/motor/ThrustCurveMotorSet.java index bbdc628b1..72da33d01 100644 --- a/core/src/net/sf/openrocket/database/motor/ThrustCurveMotorSet.java +++ b/core/src/net/sf/openrocket/database/motor/ThrustCurveMotorSet.java @@ -45,31 +45,128 @@ public class ThrustCurveMotorSet implements Comparable { 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) { - // Check for first insertion - if (motors.isEmpty()) { - manufacturer = motor.getManufacturer(); - designation = motor.getDesignation(); - simplifiedDesignation = simplifyDesignation(designation); - diameter = motor.getDiameter(); - length = motor.getLength(); - totalImpulse = Math.round((motor.getTotalImpulseEstimate())); + checkFirstInsertion(motor); + verifyMotor(motor); + updateType(motor); + checkChangeSimplifiedDesignation(motor); + addStandardDelay(motor); + if(!checkMotorOverwrite(motor)){ + motors.add(motor); + 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; + } + } } - - // Verify that the motor can be added - 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); + return false; + } + + + /** + * get a description from a motor + * @param motor the motor + * @return the description of the 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); + } } - - // Update the type if now known + Collections.sort(delays); + } + + /** + * 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) { type = motor.getMotorType(); // Add "Plugged" option if hybrid @@ -79,56 +176,45 @@ public class ThrustCurveMotorSet implements Comparable { } } } - - // 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); - if (!delays.contains(d)) { - delays.add(d); - } + } + + /** + * check if the given motor is the first one, and sets attributes according to it + * @param motor + */ + 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) { if (motors.isEmpty()) return true; @@ -153,12 +239,18 @@ public class ThrustCurveMotorSet implements Comparable { return true; } - + /** + * returns a new list with the stored motors + * @return list + */ public List getMotors() { return motors.clone(); } - + /** + * + * @return number of motor in the set + */ public int getMotorCount() { return motors.size(); } diff --git a/core/src/net/sf/openrocket/document/Attachment.java b/core/src/net/sf/openrocket/document/Attachment.java index 6ac927495..ec9fd2769 100644 --- a/core/src/net/sf/openrocket/document/Attachment.java +++ b/core/src/net/sf/openrocket/document/Attachment.java @@ -7,19 +7,38 @@ import java.io.InputStream; import net.sf.openrocket.util.AbstractChangeSource; import net.sf.openrocket.util.ChangeSource; +/** + * + * Class handler of documents attachments + * + */ public abstract class Attachment extends AbstractChangeSource implements Comparable, ChangeSource { private final String name; + /** + * default constructor + * @param name the name of attachment + */ public Attachment(String name) { super(); this.name = name; } + /** + * returns the name of attachment + * @return name of attachment + */ public String getName() { 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; @Override diff --git a/core/src/net/sf/openrocket/document/DecalRegistry.java b/core/src/net/sf/openrocket/document/DecalRegistry.java index b96cafba9..dec64c8a2 100644 --- a/core/src/net/sf/openrocket/document/DecalRegistry.java +++ b/core/src/net/sf/openrocket/document/DecalRegistry.java @@ -25,11 +25,20 @@ import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.FileUtils; import net.sf.openrocket.util.StateChangeListener; +/** + * + * Class that handles decal usage registration + * + */ public class DecalRegistry { + /** + * default constructor + */ DecalRegistry() { } + /** the decal usage map*/ private Map registeredDecals = new HashMap(); public DecalImage makeUniqueImage(DecalImage original) { diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java index d27c07da1..4d481a676 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java @@ -12,16 +12,24 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC private static final Translator trans = Application.getTranslator(); //private static final Logger log = LoggerFactory.getLogger(AxialStage.class); + /** list of separations to be happening*/ protected FlightConfigurableParameterSet separations; - + /** number of stages */ protected int stageNumber; + /** + * default constructor, builds a rocket with zero stages + */ public AxialStage(){ this.separations = new FlightConfigurableParameterSet( new StageSeparationConfiguration()); this.relativePosition = Position.AFTER; this.stageNumber = 0; } + /** + * {@inheritDoc} + * AxialStage will always accept children + */ @Override public boolean allowsChildren() { return true; @@ -33,6 +41,10 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return trans.get("Stage.Stage"); } + /** + * gets the separation configuration of the rocket + * @return the separation configuration of the rocket + */ public FlightConfigurableParameterSet getSeparationConfigurations() { return separations; } @@ -42,7 +54,10 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC 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 public Collection getComponentBounds() { Collection bounds = new ArrayList(8); @@ -110,16 +125,28 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return this.stageNumber; } + /** + * {@inheritDoc} + * axialStage is always after + */ @Override public boolean isAfter(){ return true; } + /** + * returns if the object is a launch stage + * @return if the object is a launch stage + */ public boolean isLaunchStage(){ return ( this instanceof ParallelStage ) ||( getRocket().getBottomCoreStage().equals(this)); } + /** + * sets the stage number + * @param newStageNumber + */ public void setStageNumber(final int newStageNumber) { this.stageNumber = newStageNumber; } @@ -138,12 +165,21 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return buf; } + /** + * method used for debugging separation + * @return a string that represents the debug message of separation + */ public String toDebugSeparation() { StringBuilder buff = new StringBuilder(); buff.append( this.separations.toDebug() ); 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() { if( this instanceof ParallelStage ){ return (AxialStage) this.parent; diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 6fda14f90..6f2413d97 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -30,7 +30,11 @@ import net.sf.openrocket.util.SafetyMutex; import net.sf.openrocket.util.StateChangeListener; 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 { @SuppressWarnings("unused") 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(); - /* + /** * Text is suitable to the form * Position relative to: */ From 9f10b8cec176d2839100efc0a6673e7ac651f145 Mon Sep 17 00:00:00 2001 From: Luiz Victor Linhares Rocha <luizvlrocha@uol.com.br> Date: Wed, 19 Oct 2016 15:22:28 -0200 Subject: [PATCH 2/2] adds documentation to some document package and rocketcomponents --- .../sf/openrocket/document/Attachment.java | 6 +- .../sf/openrocket/document/DecalRegistry.java | 92 ++++-- .../document/OpenRocketDocument.java | 283 ++++++++++++++---- .../attachments/FileSystemAttachment.java | 21 +- .../FlightConfigurationId.java | 66 +++- .../rocketcomponent/RocketComponent.java | 9 + 6 files changed, 392 insertions(+), 85 deletions(-) diff --git a/core/src/net/sf/openrocket/document/Attachment.java b/core/src/net/sf/openrocket/document/Attachment.java index ec9fd2769..a46d6300f 100644 --- a/core/src/net/sf/openrocket/document/Attachment.java +++ b/core/src/net/sf/openrocket/document/Attachment.java @@ -18,7 +18,7 @@ public abstract class Attachment extends AbstractChangeSource implements Compara /** * default constructor - * @param name the name of attachment + * @param name the attachment name */ public Attachment(String name) { super(); @@ -41,6 +41,10 @@ public abstract class Attachment extends AbstractChangeSource implements Compara */ public abstract InputStream getBytes() throws FileNotFoundException, IOException; + /** + * {@inheritDoc} + * considers only the name to equals + */ @Override public int compareTo(Attachment o) { return this.name.compareTo(o.name); diff --git a/core/src/net/sf/openrocket/document/DecalRegistry.java b/core/src/net/sf/openrocket/document/DecalRegistry.java index dec64c8a2..591676cdf 100644 --- a/core/src/net/sf/openrocket/document/DecalRegistry.java +++ b/core/src/net/sf/openrocket/document/DecalRegistry.java @@ -33,7 +33,7 @@ import net.sf.openrocket.util.StateChangeListener; public class DecalRegistry { /** - * default constructor + * default constructor, does nothing */ DecalRegistry() { } @@ -41,6 +41,12 @@ public class DecalRegistry { /** the decal usage map*/ private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>(); + /** + * returns a new decal with the same image but with unique names + * supports only classes and subclasses of DecalImageImpl + * @param original the decal to be made unique + * @return + */ public DecalImage makeUniqueImage(DecalImage original) { if (!(original instanceof DecalImageImpl)) { @@ -66,6 +72,11 @@ public class DecalRegistry { } + /** + * get the image from an attachment + * @param attachment + * @return + */ public DecalImage getDecalImage(Attachment attachment) { String decalName = attachment.getName(); DecalImageImpl d; @@ -175,6 +186,10 @@ public class DecalRegistry { } } + /** + * + * @return + */ File getFileSystemLocation() { return fileSystemLocation; } @@ -214,6 +229,11 @@ public class DecalRegistry { } + /** + * sercha + * @param file + * @return + */ private DecalImageImpl findDecalForFile(File file) { for (DecalImageImpl d : registeredDecals.values()) { @@ -249,28 +269,25 @@ public class DecalRegistry { private static final int NUMBER_INDEX = 3; private static final int EXTENSION_INDEX = 4; + /** + * Makes a unique name for saving decal files in case the name already exists + * @param name the name of the decal + * @return the name formated and unique + */ private String makeUniqueName(String name) { - String newName = name; - if (!newName.startsWith("decals/")) { - newName = "decals/" + name; - } - String basename = ""; - String extension = ""; - Matcher nameMatcher = fileNamePattern.matcher(newName); - if (nameMatcher.matches()) { - basename = nameMatcher.group(BASE_NAME_INDEX); - extension = nameMatcher.group(EXTENSION_INDEX); - } + String newName = checkPathConsistency(name); + String basename = getGroup(BASE_NAME_INDEX,fileNamePattern.matcher(newName)); + String extension = getGroup(EXTENSION_INDEX,fileNamePattern.matcher(newName)); Set<Integer> counts = new TreeSet<Integer>(); boolean needsRewrite = false; - + for (DecalImageImpl d : registeredDecals.values()) { Matcher m = fileNamePattern.matcher(d.getName()); if (m.matches()) { - if (basename.equals(m.group(BASE_NAME_INDEX)) && extension.equals(m.group(EXTENSION_INDEX))) { + if (isofSameBaseAndExtension(m, basename, extension)) { String intString = m.group(NUMBER_INDEX); if (intString != null) { Integer i = Integer.parseInt(intString); @@ -287,13 +304,54 @@ public class DecalRegistry { return newName; } - // find a missing integer; + return MessageFormat.format("{0} ({1}).{2}", basename, findMissingInteger(counts),extension); + } + + /** + * Searches the count for a new Integer + * @param counts the count set + * @return a unique integer in the count + */ + private Integer findMissingInteger(Set<Integer> counts) { Integer newIndex = 1; while (counts.contains(newIndex)) { newIndex++; } - - return MessageFormat.format("{0} ({1}).{2}", basename, newIndex, extension); + return newIndex; + } + + /** + * Tests if a matcher has the same basename and extension + * @param m the matcher being tested + * @param basename the basename + * @param extension the extension + * @return + */ + private boolean isofSameBaseAndExtension(Matcher m, String basename, String extension) { + return basename.equals(m.group(BASE_NAME_INDEX)) && extension.equals(m.group(EXTENSION_INDEX)); + } + + /** + * gets the String group from a matcher + * @param index the index of the group to + * @param matcher the matcher for the search + * @return the String according with the group, empty if there's no match + */ + private String getGroup(int index, Matcher matcher) { + if (matcher.matches()) + return matcher.group(index); + return ""; + } + + /** + * checks if the name starts with "decals/" + * @param name the name being checked + * @return the name complete with the starting folder + */ + private String checkPathConsistency(String name){ + if (name.startsWith("decals/")) + return name; + return "decals/" + name; } } diff --git a/core/src/net/sf/openrocket/document/OpenRocketDocument.java b/core/src/net/sf/openrocket/document/OpenRocketDocument.java index 4feb45cac..8efe1460e 100644 --- a/core/src/net/sf/openrocket/document/OpenRocketDocument.java +++ b/core/src/net/sf/openrocket/document/OpenRocketDocument.java @@ -102,36 +102,56 @@ public class OpenRocketDocument implements ComponentChangeListener { private final List<DocumentChangeListener> listeners = new ArrayList<DocumentChangeListener>(); + /** + * main constructor, enable events in the rocket + * and initializes the document + * @param rocket the rocket to be used in the document + */ OpenRocketDocument(Rocket rocket) { this.rocket = rocket; rocket.enableEvents(); init(); } + /** + * initializes the document, clearing the undo cache and + * setting itself as a listener for changes in the rocket + */ private void init() { clearUndo(); - rocket.addComponentChangeListener(this); } + /** + * adds a customExpression into the list + * @param expression the expression to be added + */ public void addCustomExpression(CustomExpression expression) { if (customExpressions.contains(expression)) { log.info(Markers.USER_MARKER, "Could not add custom expression " + expression.getName() + " to document as document alerady has a matching expression."); - } else { - customExpressions.add(expression); - } + } + customExpressions.add(expression); } + /** + * remves + * @param expression + */ public void removeCustomExpression(CustomExpression expression) { customExpressions.remove(expression); } + //TODO:LOW:this leaves the object custom expression exposed, is it supposed to be like that? + /** + * + * @return + */ public List<CustomExpression> getCustomExpressions() { return customExpressions; } - /* - * Returns a set of all the flight data types defined or available in any way in the rocket document + /** + * @returns a set of all the flight data types defined or available in any way in the rocket document */ public Set<FlightDataType> getFlightDataTypes() { Set<FlightDataType> allTypes = new LinkedHashSet<FlightDataType>(); @@ -158,28 +178,50 @@ public class OpenRocketDocument implements ComponentChangeListener { return allTypes; } - + /** + * gets the rocket in the document + * @return the rocket in the document + */ public Rocket getRocket() { return rocket; } - + /** + * returns the selected configuration from the rocket + * @return selected configuration from the rocket + */ public FlightConfiguration getSelectedConfiguration() { return rocket.getSelectedConfiguration(); } + /** + * returns the File handler object for the document + * @return the File handler object for the document + */ public File getFile() { return file; } + /** + * set the file handler object for the document + * @param file the new file handler object + */ public void setFile(File file) { this.file = file; } + /** + * returns if the current rocket is saved + * @return if the current rocket is saved + */ public boolean isSaved() { return rocket.getModID() == savedID; } + /** + * sets the current rocket as saved, and none if false is given + * @param saved if the current rocket or none will be set to save + */ public void setSaved(boolean saved) { if (saved == false) this.savedID = -1; @@ -197,33 +239,57 @@ public class OpenRocketDocument implements ComponentChangeListener { } + /** + * returns the decal list used in the document + * @return the decal list registered in the document + */ public Collection<DecalImage> getDecalList() { return decalRegistry.getDecalList(); } + /** + * returns the number of times the given decal was used + * @param img the decal to be counted + * @return the number of times + */ public int countDecalUsage(DecalImage img) { int count = 0; Iterator<RocketComponent> it = rocket.iterator(); while (it.hasNext()) { - RocketComponent comp = it.next(); - Appearance a = comp.getAppearance(); - if (a == null) { - continue; - } - Decal d = a.getTexture(); - if (d == null) { - continue; - } - if (img.equals(d.getImage())) { + if(hasDecal(it.next(),img)) count++; - } } return count; } + //TODO: LOW: move this method to rocketComponent, Appearance and decal + //I see 3 layers of object accessed, seems unsafe + /** + * checks if a rocket component has the given decalImage + * @param comp the RocketComponent to be searched + * @param img the DecalImage to be checked + * @return if the comp has img + */ + private boolean hasDecal(RocketComponent comp, DecalImage img){ + Appearance a = comp.getAppearance(); + if(a == null) + return false; + Decal d = a.getTexture(); + if(d == null) + return false; + if(img.equals(d.getImage())) + return true; + return false; + } + + /** + * gets a unique identification for the given decal + * @param img the decal to be made unique + * @return the new unique decal + */ public DecalImage makeUniqueDecal(DecalImage img) { if (countDecalUsage(img) <= 1) { return img; @@ -231,26 +297,54 @@ public class OpenRocketDocument implements ComponentChangeListener { return decalRegistry.makeUniqueImage(img); } + /** + * gets the decal image from an attachment + * @param a the attachment + * @return the image from the attachment + */ public DecalImage getDecalImage(Attachment a) { return decalRegistry.getDecalImage(a); } + /** + * gets a list of simulations in the document + * @return the simulations in the document + */ public List<Simulation> getSimulations() { return simulations.clone(); } + /** + * gets the number of simulations in the document + * @return the number of simulations in the document + */ public int getSimulationCount() { return simulations.size(); } + /** + * the the Nth simulation from the document + * @param n simulation index + * @return the Nth simulation from the document, null if there's none + */ public Simulation getSimulation(int n) { return simulations.get(n); } + /** + * gets the index of the given simulation + * @param simulation the simulation being searched + * @return the index of the simulation in the document + */ public int getSimulationIndex(Simulation simulation) { return simulations.indexOf(simulation); } + /** + * adds simulation into the document + * fires document change event + * @param simulation the simulation to be added + */ public void addSimulation(Simulation simulation) { simulations.add(simulation); FlightConfigurationId simId = simulation.getId(); @@ -260,33 +354,61 @@ public class OpenRocketDocument implements ComponentChangeListener { fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); } + /** + * adds the simulation to the Nth index, overwriting if there is already one + * fires change document event + * @param simulation the simulation to be added + * @param n the index to be added + */ public void addSimulation(Simulation simulation, int n) { simulations.add(n, simulation); fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); } + /** + * removes the specific simulation from the list + * @param simulation the simulation to be removed + */ public void removeSimulation(Simulation simulation) { simulations.remove(simulation); fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); } + /** + * removes the Nth simulation from the document + * fires document change event + * @param n the Nth simulation + * @return the removed simulation + */ public Simulation removeSimulation(int n) { Simulation simulation = simulations.remove(n); fireDocumentChangeEvent(new SimulationChangeEvent(simulation)); return simulation; } + /** + * removes the flight configuration and simulation with the specific id + * @param configId + */ public void removeFlightConfigurationAndSimulations(FlightConfigurationId configId) { if (configId == null) { return; } + removeSimulations(configId); + rocket.removeFlightConfiguration(configId); + } + + /** + * removes all simulations with the specific configId + * @param configId the Flight Configuration Id that dictates which simulations shoul be removed + */ + private void removeSimulations(FlightConfigurationId configId) { for (Simulation s : getSimulations()) { // Assumes modifiable collection - which it is if (configId.equals(s.getId())) { removeSimulation(s); } } - rocket.removeFlightConfiguration(configId); } @@ -331,42 +453,22 @@ public class OpenRocketDocument implements ComponentChangeListener { */ public void addUndoPosition(String description) { - if (storedDescription != null) { - logUndoError("addUndoPosition called while storedDescription=" + storedDescription + - " description=" + description); - } + checkDescription(description); // Check whether modifications have been done since last call - if (isCleanState()) { - // No modifications - log.info("Adding undo position '" + description + "' to " + this + ", document was in clean state"); - nextDescription = description; + if(isCheckNoModification(description)) return; - } - log.info("Adding undo position '" + description + "' to " + this + ", document is in unclean state"); + checkUndoPositionConsistency(); + addStateToUndoHistory(description); - /* - * Modifications have been made to the rocket. We should be at the end of the - * undo history, but check for consistency and try to recover. - */ - if (undoPosition != undoHistory.size() - 1) { - logUndoError("undo position inconsistency"); - } - while (undoPosition < undoHistory.size() - 1) { - undoHistory.removeLast(); - undoDescription.removeLast(); - } - - - // Add the current state to the undo history - undoHistory.add(rocket.copyWithOriginalID()); - undoDescription.add(null); - nextDescription = description; - undoPosition++; - - - // Maintain maximum undo size + maintainMaximumUndoSize(); + } + + /** + * + */ + private void maintainMaximumUndoSize() { if (undoHistory.size() > UNDO_LEVELS + UNDO_MARGIN && undoPosition > UNDO_MARGIN) { for (int i = 0; i < UNDO_MARGIN; i++) { undoHistory.removeFirst(); @@ -375,6 +477,57 @@ public class OpenRocketDocument implements ComponentChangeListener { } } } + + /** + * @param description + */ + private void addStateToUndoHistory(String description) { + // Add the current state to the undo history + undoHistory.add(rocket.copyWithOriginalID()); + undoDescription.add(null); + nextDescription = description; + undoPosition++; + } + + /** + * checks if there was or not modification, and logs + * + * @param description the description to be used in the log + * @return if there was or not modification + */ + private boolean isCheckNoModification(String description){ + if (isCleanState()) { + // No modifications + log.info("Adding undo position '" + description + "' to " + this + ", document was in clean state"); + nextDescription = description; + return true; + } + return false; + } + + /** + * checks if the document already has a stored undo description + * logs if it has + * + * @param description undo description to be logged + */ + private void checkDescription(String description) { + if (storedDescription != null) { + logUndoError("addUndoPosition called while storedDescription=" + storedDescription + + " description=" + description); + } + } + + /** + * If modifications have been made to the rocket. We should be at the end of the + * undo history, but check for consistency and try to recover. + */ + private void checkUndoPositionConsistency() { + if (undoPosition != undoHistory.size() - 1) { + logUndoError("undo position inconsistency"); + } + removeRedoInfo(); + } /** @@ -436,18 +589,29 @@ public class OpenRocketDocument implements ComponentChangeListener { " undoPosition=" + undoPosition + " undoHistory.size=" + undoHistory.size() + " isClean=" + isCleanState()); } - // Remove any redo information if available - while (undoPosition < undoHistory.size() - 1) { - undoHistory.removeLast(); - undoDescription.removeLast(); - } - - // Set the latest description - undoDescription.set(undoPosition, nextDescription); + removeRedoInfo(); + setLatestDescription(); } fireUndoRedoChangeEvent(); } + + /** + * Sets the latest description + */ + private void setLatestDescription() { + undoDescription.set(undoPosition, nextDescription); + } + + /** + * Removes any redo information if available + */ + private void removeRedoInfo() { + while (undoPosition < undoHistory.size() - 1) { + undoHistory.removeLast(); + undoDescription.removeLast(); + } + } /** @@ -610,6 +774,7 @@ public class OpenRocketDocument implements ComponentChangeListener { undoRedoListeners.remove(listener); } + private void fireUndoRedoChangeEvent() { UndoRedoListener[] array = undoRedoListeners.toArray(new UndoRedoListener[0]); for (UndoRedoListener l : array) { diff --git a/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java b/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java index 28d737e44..763aa92e2 100644 --- a/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java +++ b/core/src/net/sf/openrocket/document/attachments/FileSystemAttachment.java @@ -8,19 +8,38 @@ import java.io.InputStream; import net.sf.openrocket.document.Attachment; +/** + * + * defines a file system attachment + * stores the attachment location + */ public class FileSystemAttachment extends Attachment { - + /** the file location*/ private final File location; + /** + * main constructor, + * + * @param name name of attachment + * @param location File location of attachment + */ public FileSystemAttachment(String name, File location) { super(name); this.location = location; } + /** + * + * @return the File object with the attachment location + */ public File getLocation() { return location; } + /** + * {@inheritDoc} + * creates the stream based on the location passed while building + */ @Override public InputStream getBytes() throws FileNotFoundException, IOException { return new FileInputStream(location); diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfigurationId.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfigurationId.java index 1e6ab1938..258fd7fe5 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfigurationId.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfigurationId.java @@ -2,7 +2,7 @@ package net.sf.openrocket.rocketcomponent; import java.util.UUID; -/* +/** * FlightConfigurationID is a very minimal wrapper class used to identify a given flight configuration for various components and options. * It is intended to provide better visibility and traceability by more specific type safety -- this class replaces a * straight-up <code>String</code> Key in previous implementations. @@ -19,10 +19,17 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati public final static FlightConfigurationId ERROR_FCID = new FlightConfigurationId( FlightConfigurationId.ERROR_UUID); public final static FlightConfigurationId DEFAULT_VALUE_FCID = new FlightConfigurationId( FlightConfigurationId.DEFAULT_VALUE_UUID ); + /** + * default constructor, builds with an unique random ID + */ public FlightConfigurationId() { this(UUID.randomUUID()); } + /** + * builds the id with the given String + * @param _str te string to be made into the id + */ public FlightConfigurationId(final String _str) { UUID candidate; if(_str == null || "".equals(_str)){ @@ -37,6 +44,10 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati this.key = candidate; } + /** + * builds he id with the given UUID object + * @param _val the UUID to be made into the id + */ public FlightConfigurationId(final UUID _val) { if (null == _val){ this.key = FlightConfigurationId.ERROR_UUID; @@ -45,6 +56,10 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati } } + /** + * {@inheritDoc} + * considers equals ids with the same key + */ @Override public boolean equals(Object anObject) { if (!(anObject instanceof FlightConfigurationId)) { @@ -55,32 +70,65 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati return this.key.equals(otherFCID.key); } + /** + * + * @return + */ public String toShortKey(){ - if( hasError() ){ + if( hasError() ) return FlightConfigurationId.ERROR_KEY_NAME; - }else if( this.key == FlightConfigurationId.DEFAULT_VALUE_UUID){ + if( isDefaultId()) return FlightConfigurationId.DEFAULT_VALUE_NAME; - }else{ - return this.key.toString().substring(0,8); - } + return this.key.toString().substring(0,8); + + } + + //extracted this method because maybe, just maybe, this info could be used somewhere else + /** + * gets if the id is the default + * @return if the id is default + */ + private boolean isDefaultId() { + return this.key == FlightConfigurationId.DEFAULT_VALUE_UUID; } + /** + * returns the whole key in the id + * @return the full key of the id + */ public String toFullKey(){ - return this.key.toString(); + return this.toString(); } + /** + * {@inheritDoc} + * uses the key hash code + */ @Override public int hashCode() { return this.key.hashCode(); } + /** + * checks if the key is the ERROR_UUID flag + * @return if the id has error + */ public boolean hasError(){ return (ERROR_UUID == this.key); } + + /** + * checks if the key from the id is valid + * @return if the id is valid or not + */ public boolean isValid() { return !hasError(); } + /** + * {@inheritDoc} + * same as get full id + */ @Override public String toString() { return this.key.toString(); @@ -91,6 +139,10 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati return this.key.compareTo( other.key); } + /** + * used for debuggin, gets the short key + * @return the short key version of the id + */ public String toDebug(){ return this.toShortKey(); } diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 6f2413d97..50c45a61e 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -355,6 +355,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab } } + /** + * appends the debug string of the component into the passed builder + * @param sb String builder to be appended + */ private void toDebugString(StringBuilder sb) { sb.append(this.getClass().getSimpleName()).append('@').append(System.identityHashCode(this)); sb.append("[\"").append(this.getName()).append('"'); @@ -962,6 +966,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab return result; } + /** + * returns the axial offset of the component + * @return + */ public double getAxialOffset() { mutex.verify(); return this.asPositionValue(this.relativePosition); @@ -2085,6 +2093,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab } } + /// debug functions public String toDebugName(){ return this.getName()+"<"+this.getClass().getSimpleName()+">("+this.getID().substring(0,8)+")"; }