create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / optimization / rocketoptimization / modifiers / GenericModifier.java
1 package net.sf.openrocket.optimization.rocketoptimization.modifiers;
2
3 import java.util.Locale;
4
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;
13
14 /**
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.
18  * 
19  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
20  */
21 public abstract class GenericModifier<T> extends AbstractSimulationModifier {
22         private static final LogHelper log = Application.getLogger();
23         
24         private final double multiplier;
25         
26         private final Class<? extends T> modifiedClass;
27         private final String methodName;
28         
29         private final Method getter;
30         private final Method setter;
31         
32         
33         /**
34          * Sole constructor.
35          * 
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")
44          */
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;
49                 
50                 this.modifiedClass = modifiedClass;
51                 this.methodName = methodName;
52                 
53                 if (MathUtil.equals(multiplier, 0)) {
54                         throw new IllegalArgumentException("multiplier is zero");
55                 }
56                 
57                 try {
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);
65                 }
66         }
67         
68         
69         
70         @Override
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");
75                 }
76                 return ((Double) getter.invoke(modifiable)) * multiplier;
77         }
78         
79         
80         @Override
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");
85                 }
86                 double siValue = toBaseValue(scaledValue) / multiplier;
87                 log.verbose("Setting setter=" + setter + " modifiable=" + modifiable + " siValue=" + siValue + "scaledValue=" + scaledValue);
88                 setter.invoke(modifiable, siValue);
89         }
90         
91         
92         /**
93          * Return the object from the simulation that will be modified.
94          * @param simulation    the simulation
95          * @return                              the object to modify
96          * 
97          * @throws OptimizationException        if the object cannot be found
98          */
99         protected abstract T getModifiedObject(Simulation simulation) throws OptimizationException;
100         
101         
102         
103         @Override
104         public String toString() {
105                 return "GenericModifier[modifiedClass=" + modifiedClass.getCanonicalName() + ", methodName=" + methodName + ", multiplier=" + multiplier + "]";
106         }
107         
108 }