package jcgp.backend.parameters; import javafx.beans.property.Property; import javafx.beans.property.ReadOnlyProperty; /** * Specifies an abstract model of a module parameter. *

* 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. *

* {@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. *

* 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 Module, ParameterStatus * @author Eduardo Pedroni * @param the data type stored in the parameter. */ public abstract class Parameter { private boolean monitor, critical; protected ParameterStatus status = ParameterStatus.VALID; protected String name; protected Property 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 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; } }