aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/parameters/Parameter.java
blob: c6051805c4f4a7c62ea2b8274c771ac354757c0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package jcgp.backend.parameters;

import javafx.beans.property.Property;
import javafx.beans.property.ReadOnlyProperty;

/**
 * Specifies an abstract model of a module parameter.
 * <br><br>
 * Parameters are values which control the operation of modules.
 * They can be freely modified and accessed by the module in which
 * they are declared. Additionally, the module may choose to expose
 * some of its parameters to a user interface, so that information
 * is displayed. If that is the case, the parameter can be made
 * read-only by setting the monitor flag (it becomes a parameter
 * monitor). In addition, settings the critical flag indicates to
 * the experiment that any changes to the parameter should result in
 * an experiment-wide reset.
 * <br><br>
 * {@code Parameter} is abstract. A typical implementation defines
 * the data type T and initialises the {@code valueProperty} field
 * with a suitable type. For the sake of clarity, it may not be ideal 
 * for a subclass constructor to expose an argument for the monitor
 * field. Instead, a different class should be created which constructs
 * the parameter as a monitor, so that the distinction between a regular
 * parameter and a parameter monitor is more apparent. The boolean, integer
 * and double implementations of parameter (and their associated monitors)
 * implement this pattern, refer to them for more details. 
 * <br><br>
 * The {@code status} field holds the current status of the parameter, 
 * which should change whenever the parameter value changes.
 * In order for this to happen, {@code validate()} is called whenever
 * the parameter status should be updated. This being the case, it should
 * be overridden on an instance-to-instance basis, as each parameter 
 * will likely have different validity criteria. The type of status is
 * {@link ParameterStatus}, an enum type defining all valid states.
 * 
 * @see jcgp.backend.modules.Module
 * @author Eduardo Pedroni
 * @param <T> the data type stored in the parameter.
 */
public abstract class Parameter<T> {
	
	private boolean monitor, critical;
	protected ParameterStatus status = ParameterStatus.VALID;
	protected String name;
	protected Property<T> valueProperty;
	
	/**
	 * For internal use only. This creates a new instance of the class
	 * requiring a name, monitor and critical information. It should be
	 * invoked using {@code super()} by any implementing constructors.
	 * 
	 * @param name the name of the parameter, to be used by GUIs (if in use).
	 * @param monitor true if the parameter is a monitor, meaning it is not editable via the GUI (if in use).
	 * @param critical true if any changes to this parameter should cause an experiment-wide reset.
	 */
	protected Parameter(String name, boolean monitor, boolean critical) {
		this.name = name;
		this.monitor = monitor;
		this.critical = critical;
	}
	
	/**
	 * @return true if the parameter is a monitor.
	 */
	public boolean isMonitor() {
		return monitor;
	}
	
	/**
	 * @return true if the parameter is critical.
	 */
	public boolean isCritical() {
		return critical;
	}
	
	/**
	 * @return the current status of the parameter.
	 */
	public ParameterStatus getStatus() {
		return status;
	}
		
	/**
	 * This method is intended for bindings only. Changes to the parameter
	 * value should be made using {@code set()}.
	 * 
	 * @return the property which holds the parameter value.
	 */
	public ReadOnlyProperty<T> valueProperty() {
		return valueProperty;
	}
	
	/**
	 * @return the parameter's current value.
	 */
	public T get() {
		return valueProperty.getValue();
	}
	
	/**
	 * Sets the parameter to the specified value, if the property
	 * is not bound.
	 * 
	 * @param newValue the new value for the parameter.
	 */
	public void set(T newValue) {
		if (!valueProperty.isBound()) {
			valueProperty.setValue(newValue);
		}
	}
	
	/**
	 * This is a callback method which gets called whenever changes
	 * to parameters (not only its own instance) are made. This method
	 * is intended to set the {@code status} field according to the
	 * new value, so that the user can be informed if any parameters
	 * are currently set to invalid values.
	 * 
	 * @param newValue the new value.
	 */
	public abstract void validate(T newValue);
	
	@Override
	public String toString() {
		return name;
	}
}