1 package net.sf.openrocket.optimization.rocketoptimization.modifiers;
3 import java.util.Locale;
5 import net.sf.openrocket.document.Simulation;
6 import net.sf.openrocket.logging.LogHelper;
7 import net.sf.openrocket.optimization.general.OptimizationException;
8 import net.sf.openrocket.startup.Application;
9 import net.sf.openrocket.unit.UnitGroup;
10 import net.sf.openrocket.util.BugException;
11 import net.sf.openrocket.util.MathUtil;
12 import net.sf.openrocket.util.Reflection.Method;
15 * A generic SimulationModifier that uses reflection to get and set a double value.
16 * Implementations need to implement the {@link #getModifiedObject(Simulation)} method
17 * to return which object is modified.
19 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
21 public abstract class GenericModifier<T> extends AbstractSimulationModifier {
22 private static final LogHelper log = Application.getLogger();
24 private final double multiplier;
26 private final Class<? extends T> modifiedClass;
27 private final String methodName;
29 private final Method getter;
30 private final Method setter;
36 * @param modifierName the name of this modifier (returned by {@link #getName()})
37 * @param modifierDescription the description of this modifier (returned by {@link #getDescription()})
38 * @param relatedObject the related object (returned by {@link #getRelatedObject()})
39 * @param unitGroup the unit group (returned by {@link #getUnitGroup()})
40 * @param multiplier the multiplier by which the value returned by the getter is multiplied
41 * to obtain the desired value
42 * @param modifiedClass the class type that {@link #getModifiedObject(Simulation)} returns
43 * @param methodName the base name of the getter/setter methods (without "get"/"set")
45 public GenericModifier(String modifierName, String modifierDescription, Object relatedObject, UnitGroup unitGroup,
46 double multiplier, Class<? extends T> modifiedClass, String methodName) {
47 super(modifierName, modifierDescription, relatedObject, unitGroup);
48 this.multiplier = multiplier;
50 this.modifiedClass = modifiedClass;
51 this.methodName = methodName;
53 if (MathUtil.equals(multiplier, 0)) {
54 throw new IllegalArgumentException("multiplier is zero");
58 methodName = methodName.substring(0, 1).toUpperCase(Locale.ENGLISH) + methodName.substring(1);
59 getter = new Method(modifiedClass.getMethod("get" + methodName));
60 setter = new Method(modifiedClass.getMethod("set" + methodName, double.class));
61 } catch (SecurityException e) {
62 throw new BugException("Trying to find method get/set" + methodName + " in class " + modifiedClass, e);
63 } catch (NoSuchMethodException e) {
64 throw new BugException("Trying to find method get/set" + methodName + " in class " + modifiedClass, e);
71 public double getCurrentSIValue(Simulation simulation) throws OptimizationException {
72 T modifiable = getModifiedObject(simulation);
73 if (modifiable == null) {
74 throw new OptimizationException("BUG: getModifiedObject() returned null");
76 return ((Double) getter.invoke(modifiable)) * multiplier;
81 public void modify(Simulation simulation, double scaledValue) throws OptimizationException {
82 T modifiable = getModifiedObject(simulation);
83 if (modifiable == null) {
84 throw new OptimizationException("BUG: getModifiedObject() returned null");
86 double siValue = toBaseValue(scaledValue) / multiplier;
87 log.verbose("Setting setter=" + setter + " modifiable=" + modifiable + " siValue=" + siValue + "scaledValue=" + scaledValue);
88 setter.invoke(modifiable, siValue);
93 * Return the object from the simulation that will be modified.
94 * @param simulation the simulation
95 * @return the object to modify
97 * @throws OptimizationException if the object cannot be found
99 protected abstract T getModifiedObject(Simulation simulation) throws OptimizationException;
104 public String toString() {
105 return "GenericModifier[modifiedClass=" + modifiedClass.getCanonicalName() + ", methodName=" + methodName + ", multiplier=" + multiplier + "]";