This commit is contained in:
Gianpaolo Coro 2012-02-29 10:40:05 +00:00
parent b535042c7f
commit f71ad8be21
12 changed files with 790 additions and 1 deletions

View File

@ -26,7 +26,6 @@
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/rapidMiner.jar"/> <classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/rapidMiner.jar"/>
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/slf4j-api-1.6.0.jar"/> <classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/slf4j-api-1.6.0.jar"/>
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/slf4j-log4j12-1.6.0.jar"/> <classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/slf4j-log4j12-1.6.0.jar"/>
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/TChartSupport.jar"/>
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/TGGraphLayout.jar"/> <classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/TGGraphLayout.jar"/>
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/xpp3_min-1.1.4c.jar"/> <classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/xpp3_min-1.1.4c.jar"/>
<classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/xstream-1.3.1.jar"/> <classpathentry kind="lib" path="/StatisticalLibSupportLibraries/lib/EcologicalEngine/xstream-1.3.1.jar"/>

View File

@ -0,0 +1,65 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: Assertion.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.assertions;
import java.io.Serializable;
/**
* General purpose assertion handler.
* Assertion can be generalized to check a boolean expression and
* to raise an exception in correspondence to a failure happening
* during checking.
* <pre>
* <b>Example:</b>
*
* <b>Assertion</b>&lt;<i>TheExceptionType</i>&gt; assertion = new Assertion&lt;ParamException&gt; ();
* assertion.<b>validate</b> (param != null, new <i>TheExceptionType</i>("invalid parameter null"));
*
* <b>or</b>, in a more compact form:
* <i>// The exception to throw in case of failure
* // during the evaluation of the expected condition</i>
* new <b>Assertion</b>&lt;<i>TheExceptionType</i>&gt;().<b>validate</b>(
* i>5, <i>// The expected boolean <b>condition</b></i>
* new <i>TheExceptionType</i>("Parameter must be greater than 5")); <i>//The <b>error</b> message</i>
*
* </pre>
*
* @author Daniele Strollo (ISTI-CNR)
*/
public class Assertion <T extends Throwable> implements Serializable {
private static final long serialVersionUID = -2007903339251667541L;
/**
* Makes an assertion and if the expression evaluation fails, throws an
* exception of type T.
* <pre>
* Example:
* new Assertion&lt;MyException&gt;().validate(whatExpected, new MyException("guard failed"));
* </pre>
* @param assertion the boolean expression to evaluate
* @param exc the exception to throw if the condition does not hold
* @throws T the exception extending {@link java.lang.Throwable}
*/
public final void validate(final boolean assertion, final T exc)
throws T {
// TOCHECK junit.framework.Assert.assertTrue(assertion);
if (!assertion) {
throw exc;
}
}
}

View File

@ -0,0 +1,38 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: InvalidParameterException.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.exceptions;
/**
* @author Daniele Strollo (ISTI-CNR)
*
*/
public class InvalidParameterException extends Exception {
private static final long serialVersionUID = -9108485633158199338L;
public InvalidParameterException() {
super();
}
public InvalidParameterException(final String message) {
super(message);
}
public InvalidParameterException(final Throwable cause) {
super(cause);
}
public InvalidParameterException(final String message, final Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,91 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: ColumnDescr.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.tablemodel;
import java.io.Serializable;
import org.gcube.portlets.user.timeseries.charts.support.assertions.Assertion;
import org.gcube.portlets.user.timeseries.charts.support.exceptions.InvalidParameterException;
/**
* @author Daniele Strollo (ISTI-CNR)
*
*/
public final class FieldDescr implements Serializable {
private static final long serialVersionUID = 532149221570962514L;
private String alias = null;
private String rawname = null;
private FieldDescr() {
// for serialization only
}
public FieldDescr(final String rawname) throws InvalidParameterException {
this(null, rawname, FieldType.ND);
}
public FieldDescr(final String rawname, final FieldType type) throws InvalidParameterException {
this(null, rawname, type);
}
public FieldDescr(final String alias, final String rawname) throws InvalidParameterException {
this(alias, rawname, FieldType.ND);
this.setAlias(alias);
this.setRawName(rawname);
}
public FieldDescr(final String alias, final String rawname, final FieldType type) throws InvalidParameterException {
this();
this.setAlias(alias);
this.setRawName(rawname);
}
/**
* The alias name is the label used to identify the column.
* It can be null and in this case the getAlias will return the rawName.
* @param alias
* @throws InvalidParameterException
*/
public void setAlias(final String alias) {
if (alias != null && alias.trim().length() > 0) {
this.alias = alias.trim();
}
}
/**
* The rawName identifies the name of column on the table.
* It cannot be null.
* @param rawName
*/
public void setRawName(final String rawName) throws InvalidParameterException {
Assertion<InvalidParameterException> checker = new Assertion<InvalidParameterException>();
checker.validate(rawName != null && rawName.trim().length() > 0, new InvalidParameterException("The raw name cannot be null or empty."));
this.rawname = rawName.trim();
}
public String getRawName() {
return this.rawname;
}
public String getAlias() {
if (this.alias != null) {
return this.alias;
}
return this.rawname;
}
}

View File

@ -0,0 +1,41 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: ColumnType.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.tablemodel;
import java.io.Serializable;
/**
* @author Daniele Strollo (ISTI-CNR)
*
*/
public enum FieldType implements Serializable {
ND("not defined"),
STRING("string"),
NUMERIC("int"),
QUANTITY("quantity"),
DATE("date");
private String typeName = null;
private FieldType(final String typeName) {
this.typeName = typeName;
}
public final String getTypeName() {
return this.typeName;
}
}

View File

@ -0,0 +1,80 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: TableDescr.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.tablemodel;
import java.io.Serializable;
import java.util.List;
import java.util.Vector;
import org.gcube.portlets.user.timeseries.charts.support.assertions.Assertion;
import org.gcube.portlets.user.timeseries.charts.support.exceptions.InvalidParameterException;
/**
* @author Daniele Strollo (ISTI-CNR)
*
*/
public final class TableDescr implements Serializable {
private static final long serialVersionUID = -4850971456321479627L;
private String name = null;
private String alias = null;
private List<FieldDescr> fields = new Vector<FieldDescr>();
private TableDescr() {
// for serialization only
}
public TableDescr(final String name) throws InvalidParameterException {
this();
this.setName(name);
}
public TableDescr(final String name, final String alias) throws InvalidParameterException {
this(name);
this.setAlias(alias);
}
public String getName() {
return this.name;
}
public void setName(final String name) throws InvalidParameterException {
Assertion<InvalidParameterException> checker = new Assertion<InvalidParameterException>();
checker.validate(name != null && name.trim().length() > 0, new InvalidParameterException("The table name cannot be null or empty."));
this.name = name.trim();
}
public void setAlias(final String alias) {
if (alias != null && alias.trim().length() > 0) {
this.alias = alias.trim();
}
}
public String getAlias() {
if (alias != null) {
return alias;
}
return name;
}
public List<FieldDescr> getFields() {
return this.fields;
}
public void addFields(final FieldDescr... fields) {
if (fields == null) {
return;
}
for (FieldDescr field : fields) {
this.fields.add(field);
}
}
}

View File

@ -0,0 +1,93 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: GenerateDataTest.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.tests;
import java.util.List;
import java.util.Vector;
import org.gcube.portlets.user.timeseries.charts.support.exceptions.InvalidParameterException;
import org.gcube.portlets.user.timeseries.charts.support.types.GraphData;
import org.gcube.portlets.user.timeseries.charts.support.types.GraphGroups;
import org.gcube.portlets.user.timeseries.charts.support.types.Point;
import org.gcube.portlets.user.timeseries.charts.support.types.ValueEntry;
/**
* @author Daniele Strollo (ISTI-CNR)
*
*/
public class GenerateDataTest {
@SuppressWarnings("unchecked")
public static GraphGroups populateData(final int groupNum) {
final boolean REVERSE = true;
GraphGroups retval = new GraphGroups();
for (int g = 0; g < groupNum; g++) {
List<Point<? extends Number, ? extends Number>> points =
new Vector<Point<? extends Number, ? extends Number>>();
if (!REVERSE) {
try {
Point<Double, Double> xLine = new Point<Double, Double>("Tilapias and other cichlids", 1d);
for (int i = 2005; i < 2020; i++) {
xLine.addEntry(new ValueEntry<Double>(String.valueOf(i), Math.random() * 2000));
}
points.add(xLine);
xLine = new Point<Double, Double>("Trupians", 2d);
for (int i = 2005; i < 2020; i++) {
xLine.addEntry(new ValueEntry<Double>(String.valueOf(i), Math.random() * 2000));
}
points.add(xLine);
xLine = new Point<Double, Double>("Salmons", 3d);
for (int i = 2005; i < 2020; i++) {
xLine.addEntry(new ValueEntry<Double>(String.valueOf(i), Math.random() * 2000));
}
points.add(xLine);
} catch (Exception e) {}
} else {
for (int i = 2005; i < 2020; i++) {
try {
points.add(
new Point<Double, Double>(String.valueOf(i),
new Double(i),
new ValueEntry<Double>("Salmons, trouts, smelts", Math.random() * 2024),
new ValueEntry<Double>("Trupians", Math.random() * 1024),
new ValueEntry<Double>("Tilapias and other cichlids", Math.random() * 2000)
)
);
} catch (Exception e) {
e.printStackTrace();
}
}
}
try {
retval.addGraph("Group #" + g, new GraphData(points, REVERSE));
} catch (InvalidParameterException e) {
e.printStackTrace();
}
}
return retval;
}
public static final void main(final String[] args) {
GenerateDataTest.populateData(3);
}
}

View File

@ -0,0 +1,9 @@
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<source path='assertions'/>
<source path='exceptions'/>
<source path='types'/>
<source path='tablemodel'/>
</module>

View File

@ -0,0 +1,112 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: GraphData.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.types;
import java.io.Serializable;
import java.util.List;
import java.util.Vector;
import org.gcube.portlets.user.timeseries.charts.support.assertions.Assertion;
import org.gcube.portlets.user.timeseries.charts.support.exceptions.InvalidParameterException;
/**
* All the data needed to represent a single graph.
*
* @author Daniele Strollo (ISTI-CNR)
*
*/
public class GraphData implements Serializable {
private static final long serialVersionUID = 930654337632116093L;
private List<Point<? extends Number, ? extends Number>> data = null;
private Number minY = 0;
private Number maxY = 50000;
@SuppressWarnings("unused")
private GraphData() {
// for serialization issues only
}
public GraphData(
final List<Point<? extends Number, ? extends Number>> data,
final boolean invertAxis) throws InvalidParameterException {
Assertion<InvalidParameterException> checker = new Assertion<InvalidParameterException>();
checker.validate(data != null && data.size() > 0,
new InvalidParameterException(
"Invalid data. Null and empty not allowed"));
if (invertAxis) {
this.data = this.invertAxis(data);
} else {
this.data = data;
}
}
public final List<Point<? extends Number, ? extends Number>> getData() {
return this.data;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private List<Point<? extends Number, ? extends Number>> invertAxis(
final List<Point<? extends Number, ? extends Number>> points) {
List<Point<? extends Number, ? extends Number>> retval = new Vector<Point<? extends Number, ? extends Number>>();
int linesNum = points.get(0).getEntries().size();
// Prepare lines - labels of groups
for (int i = 0; i < linesNum; i++) {
try {
retval.add(new Point<Double, Double>(points.get(0).getEntries()
.get(i).getLabel(), Double.valueOf(points.get(0)
.getEntries().get(i).getValue().toString())));
} catch (InvalidParameterException e) {
e.printStackTrace();
}
}
// Insert values inside groups
for (Point<? extends Number, ? extends Number> xPoint : points) {
for (int i = 0; i < linesNum; i++) {
try {
retval.get(i).addEntry(
new ValueEntry(xPoint.getLabel(), Double
.valueOf(xPoint.getEntries().get(i)
.getValue().toString())));
} catch (InvalidParameterException e) {
e.printStackTrace();
}
}
}
return retval;
}
public final void setMaxY(final Number maxY) {
this.maxY = maxY;
}
public final void setMinY(final Number minY) {
this.minY = minY;
}
public final Number getMinY() {
return minY;
}
public final Number getMaxY() {
return maxY;
}
}

View File

@ -0,0 +1,41 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: GraphGroups.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.types;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author Daniele Strollo (ISTI-CNR)
*
*/
public class GraphGroups implements Serializable {
private static final long serialVersionUID = -466243452417462863L;
private Map<String, GraphData> graphs = new LinkedHashMap<String, GraphData>();
public GraphGroups() {
}
public final void addGraph(final String key, final GraphData graph) {
this.graphs.put(key, graph);
}
public final Map<String, GraphData> getGraphs() {
return this.graphs;
}
}

View File

@ -0,0 +1,141 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: Point.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.types;
import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;
import org.gcube.portlets.user.timeseries.charts.support.assertions.Assertion;
import org.gcube.portlets.user.timeseries.charts.support.exceptions.InvalidParameterException;
/**
* The Point consists of a single entry in the graph system.
* Since to each point multiple values can be related,
* a point essentially consists of a String (its label),
* and a list of {@link ValueEntry} couples (String, Value).
* <p>
* The type <b>T</b> declares the number format of entries (e.g. int, double...).
* </p>
* <p><b>Usage:</b><br/>
* <pre>
* <i>// Here a point is represented by integer values on the
* // X axis and floats on the relative Y axis values.</i>
* new <b>Point</b>&lt;Integer, Float&gt;("Avg 2010",
* 2010, <i>// The value of column entry</i>
* <i>// The rows associated to this column</i>
* new <b>ValueEntry</b>&lt;Float&gt;("Entry1", 500.34f),
* new <b>ValueEntry</b>&lt;Float&gt;("Entry2", 230.56f));
* </pre>
* </p>
* @author Daniele Strollo (ISTI-CNR)
*
*/
public class Point<S extends Number, T extends Number> implements Serializable {
private static final long serialVersionUID = 6164075295272357264L;
private String label = null;
private S value = null;
private List<ValueEntry<T>> entries = new Vector<ValueEntry<T>>();
@SuppressWarnings("unused")
private Point() {
// for serialization only
}
public Point(final S value)
throws InvalidParameterException {
this.setValue(value);
}
public Point(final String label, final S value)
throws InvalidParameterException {
this(value);
this.setLabel(label);
}
public Point(final S value, final ValueEntry<T>... entries)
throws InvalidParameterException {
this(value);
this.setEntries(entries);
}
public Point(final String label, final S value, final ValueEntry<T>... entries)
throws InvalidParameterException {
this(label, value);
this.setEntries(entries);
}
public final void setLabel(final String label) {
if (label != null) {
this.label = label.trim();
}
}
public final void setValue(final S value) throws InvalidParameterException {
Assertion<InvalidParameterException> checker = new Assertion<InvalidParameterException>();
checker.validate(
value != null,
new InvalidParameterException("Invalid parameter value. Null not allowed."));
this.value = value;
}
public final S getValue() {
return this.value;
}
public final void addEntry(final ValueEntry<T> entry) {
this.entries.add(entry);
}
public final void setEntries(final ValueEntry<T>... entries) {
if (entries != null) {
for (ValueEntry<T> t : entries) {
this.entries.add(t);
}
}
}
public final void sortEntries() {
Collections.sort(entries, new Comparator<ValueEntry<T>>() {
public int compare(final ValueEntry<T> o1, final ValueEntry<T> o2) {
o1.getValue().doubleValue();
return 0;
};
});
}
public final List<ValueEntry<T>> getEntries() {
return this.entries;
}
public final String getLabel() {
return this.label;
}
@Override
public final String toString() {
StringBuilder retval = new StringBuilder("[" + (this.label != null ? this.label : "N/D") + "] {");
for (ValueEntry<T> yValue : this.getEntries()) {
retval.append(yValue.toString() + " ");
}
retval.append("}");
return retval.toString();
}
}

View File

@ -0,0 +1,79 @@
/****************************************************************************
* This software is part of the gCube Project.
* Site: http://www.gcube-system.org/
****************************************************************************
* The gCube/gCore software is licensed as Free Open Source software
* conveying to the EUPL (http://ec.europa.eu/idabc/eupl).
* The software and documentation is provided by its authors/distributors
* "as is" and no expressed or
* implied warranty is given for its use, quality or fitness for a
* particular case.
****************************************************************************
* Filename: ValueEntry.java
****************************************************************************
* @author <a href="mailto:daniele.strollo@isti.cnr.it">Daniele Strollo</a>
***************************************************************************/
package org.gcube.portlets.user.timeseries.charts.support.types;
import java.io.Serializable;
import org.gcube.portlets.user.timeseries.charts.support.assertions.Assertion;
import org.gcube.portlets.user.timeseries.charts.support.exceptions.InvalidParameterException;
/**
* Each value entry in a graph is identified by its numerical value and
* possibly its label.
* <p>
* <b>Note:</b> the type <b>T</b> must be numerical (int, double, etc.).
* The label is not mandatory.
* </p>
* @author Daniele Strollo (ISTI-CNR)
*/
public class ValueEntry<T extends Number> implements Serializable {
private static final long serialVersionUID = -6765421417425929840L;
private String label = null;
private T value = null;
@SuppressWarnings("unused")
private ValueEntry() {
// for serialization only
}
public ValueEntry(final T value) throws InvalidParameterException {
this.setValue(value);
}
public ValueEntry(final String label, final T value) throws InvalidParameterException {
this(value);
this.setLabel(label);
}
public final void setLabel(final String label) {
if (label != null) {
this.label = label.trim();
}
}
public final void setValue(final T value) throws InvalidParameterException {
Assertion<InvalidParameterException> checker = new Assertion<InvalidParameterException>();
checker.validate(
value != null,
new InvalidParameterException("Invalid parameter value. Null not allowed."));
this.value = value;
}
public final String getLabel() {
return this.label;
}
public final T getValue() {
return this.value;
}
@Override
public final String toString() {
return (this.label != null ? this.label : "N/D") + " -> " + this.getValue();
}
}