2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU General Public License for more details.
12
* You should have received a copy of the GNU General Public License
13
* along with this program; if not, write to the Free Software
14
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
* Copyright (C) 2006 Robert Jung
23
package weka.gui.ensembleLibraryEditor.tree;
25
import java.math.BigDecimal;
26
import java.text.NumberFormat;
28
import javax.swing.tree.DefaultMutableTreeNode;
31
* This subclass is responsible for allowing users to specify either a minimum,
32
* maximum, or iterator value for Integer attributes. It stores a value that is
33
* of type java.lang.Number to accomodate the many different number types used
34
* by Weka classifiers.
36
* @author Robert Jung (mrbobjung@gmail.com)
37
* @version $Revision: 1.1 $
39
public class NumberNode
40
extends DefaultMutableTreeNode {
42
/** for serialization */
43
private static final long serialVersionUID = -2505599954089243851L;
45
/** the enumerated value indicating a node is not an iterator */
46
public static final int NOT_ITERATOR = 0;
48
/** the enumerated value indicating a node is a *= iterator */
49
public static final int TIMES_EQUAL = 1;
51
/** the enumerated value indicating a node is a += iterator */
52
public static final int PLUS_EQUAL = 2;
54
/** the name of the node to be displayed */
55
private String m_Name;
57
/** the iterator type, NOT_ITERATOR, TIMES_EQUAL, or PLUS_EQUAL */
58
private int m_IteratorType;
60
/** this stores whether or not this node should have a checkbox */
61
private boolean m_Checkable;
63
/** this stores the node's selected state */
64
private boolean m_Selected;
66
/** the node's tipText */
67
private String m_ToolTipText;
70
* This method rounds a double to the number of decimal places defined by
73
* @param a the value to round
74
* @return the rounded value
76
public static double roundDouble(double a) {
77
return new BigDecimal("" + a).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
81
* This method rounds a float to the number of decimal places defined by
84
* @param a the value to round
85
* @return the rounded value
87
public static float roundFloat(float a) {
88
return new BigDecimal("" + a).setScale(scale, BigDecimal.ROUND_HALF_UP).floatValue();
92
* this defines the number of decimal places we care about, we arbitrarily
93
* chose 7 thinking that anything beyond this is overkill
95
public static final int scale = 7;
98
* This is the maximum floating point value that we care about when testing
101
public static final double epsilon = 0.000001;
104
* The constructor simply initializes all of the member variables
106
* @param text the name
107
* @param value the actual value
108
* @param iteratorType the iterator type
109
* @param checkable true if it's checkable
110
* @param toolTipText the tooltip to use
112
public NumberNode(String text, Number value, int iteratorType,
113
boolean checkable, String toolTipText) {
117
this.m_IteratorType = iteratorType;
118
this.m_Checkable = checkable;
119
this.m_Selected = false;
120
this.m_ToolTipText = toolTipText;
124
* getter for the node selected state
126
* @return whether or not this node is selected
128
public boolean getSelected() {
133
* setter for the node selected state
136
* the new selected state
138
public void setSelected(boolean newValue) {
139
m_Selected = newValue;
143
* getter for this node's object
145
* @return the current value
147
public Number getValue() {
148
return (Number) getUserObject();
152
* setter for this nodes object
154
* @param newValue the new value to use
156
public void setValue(Number newValue) {
157
userObject = newValue;
161
* getter for this node's iteratorType which will be one of the three
164
* @return the iterator type
166
public int getIteratorType() {
167
return m_IteratorType;
171
* setter for this nodes iteratorType which should be one of the three
174
* @param newValue the new iterator type to use
176
public void setIteratorType(int newValue) {
177
m_IteratorType = newValue;
181
* returns whether or not this node can be toggled on and off
183
* @return true if it's checkable
185
public boolean getCheckable() {
190
* returns the text to be displayed for this node
194
public String getText() {
199
* getter for the tooltip text
201
* @return tooltip text
203
public String getToolTipText() {
204
return m_ToolTipText;
208
* this is a simple filter for the setUserObject method. We basically don't
209
* want null values to be passed in.
211
* @param o the user object
213
public void setUserObject(Object o) {
215
super.setUserObject(o);
219
* returns a string representation
221
* @return a string representation
223
public String toString() {
224
return getClass().getName() + "[" + m_Name + ": "
225
+ getUserObject().toString() + "]";
228
// *************** IMPORTANT!!! ***********************
229
// I could not figure out a graceful way to deal with this!
230
// we have a requirement here to add, multiply, and test for
231
// equality various subclasses of java.lang.number the
232
// following eight methods are extremely redundant and are
233
// a horrible example cutting/pasting. However, this
234
// is what I've ended up with and its very clunky looking.
235
// If anyone knows a better way to do this then please be my
236
// guest by all means!
238
// I really can't beleive there's not some slick way of handling
239
// this stuff built into the language
242
* figures out the class of this node's object and returns a new instance of
243
* it initialized with the value of "0".
245
* @return 0 as object
246
* @throws NumberClassNotFoundException if number class not supported
248
public Number getZeroValue() throws NumberClassNotFoundException {
250
Number value = getValue();
253
if (value instanceof Double)
254
zero = new Double(0.0);
255
else if (value instanceof Integer)
256
zero = new Integer(0);
257
else if (value instanceof Float)
258
zero = new Float(0.0);
259
else if (value instanceof Long)
262
throw new NumberClassNotFoundException(value.getClass()
263
+ " not currently supported.");
270
* figures out the class of this node's object and returns a new instance of
271
* it initialized with the value of "1".
273
* @return 1 as object
274
* @throws NumberClassNotFoundException if number class not supported
276
public Number getOneValue() throws NumberClassNotFoundException {
278
Number value = getValue();
281
if (value instanceof Double)
282
one = new Double(1.0);
283
else if (value instanceof Integer)
284
one = new Integer(1);
285
else if (value instanceof Float)
286
one = new Float(1.0);
287
else if (value instanceof Long)
290
throw new NumberClassNotFoundException(value.getClass()
291
+ " not currently supported.");
297
* figures out the class of this node's object and returns a new instance of
298
* it initialized with the value of "2".
300
* @return 2 as object
301
* @throws NumberClassNotFoundException if number class not supported
303
public Number getTwoValue() throws NumberClassNotFoundException {
305
Number value = getValue();
308
if (value instanceof Double)
309
two = new Double(2.0);
310
else if (value instanceof Integer)
311
two = new Integer(2);
312
else if (value instanceof Float)
313
two = new Float(2.0);
314
else if (value instanceof Long)
317
throw new NumberClassNotFoundException(value.getClass()
318
+ " not currently supported.");
324
* adds two objects that are instances of one of the child classes of
327
* @param a the first number
328
* @param b the second number
329
* @return the sum: a+b
330
* @throws NumberClassNotFoundException if number class not supported
332
public Number addNumbers(Number a, Number b)
333
throws NumberClassNotFoundException {
337
if (a instanceof Double && b instanceof Double) {
338
sum = new Double(roundDouble(a.doubleValue() + b.doubleValue()));
341
} else if (a instanceof Integer && b instanceof Integer) {
342
sum = new Integer(a.intValue() + b.intValue());
343
} else if (a instanceof Float && b instanceof Float) {
344
sum = new Float(roundFloat(a.floatValue() + b.floatValue()));
348
} else if (a instanceof Long && b instanceof Long) {
349
sum = new Long(a.longValue() + b.longValue());
351
throw new NumberClassNotFoundException(a.getClass() + " and "
352
+ b.getClass() + " not currently supported.");
358
* multiplies two objects that are instances of one of the child classes of
361
* @param a the first number
362
* @param b the second number
363
* @return the product: a*b
364
* @throws NumberClassNotFoundException if number class not supported
366
public Number multiplyNumbers(Number a, Number b)
367
throws NumberClassNotFoundException {
369
Number product = null;
371
if (a instanceof Double && b instanceof Double) {
372
product = new Double(roundDouble(a.doubleValue() * b.doubleValue()));
374
} else if (a instanceof Integer && b instanceof Integer) {
375
product = new Integer(a.intValue() * b.intValue());
376
} else if (a instanceof Float && b instanceof Float) {
377
product = new Float(roundFloat(a.floatValue() * b.floatValue()));
379
} else if (a instanceof Long && b instanceof Long) {
380
product = new Long(a.longValue() * b.longValue());
382
throw new NumberClassNotFoundException(a.getClass() + " and "
383
+ b.getClass() + " not currently supported.");
389
* tests if the first argument is greater than the second among two objects
390
* that are instances of one of the child classes of java.lang.Number
392
* @param a the first number
393
* @param b the second number
394
* @return true if a is less than b
395
* @throws NumberClassNotFoundException if number class not supported
397
public boolean lessThan(Number a, Number b)
398
throws NumberClassNotFoundException {
400
boolean greater = false;
402
if (a instanceof Double && b instanceof Double) {
403
if (a.doubleValue() < b.doubleValue())
405
} else if (a instanceof Integer && b instanceof Integer) {
406
if (a.intValue() < b.intValue())
408
} else if (a instanceof Float && b instanceof Float) {
409
if (a.floatValue() < b.floatValue())
411
} else if (a instanceof Long && b instanceof Long) {
412
if (a.longValue() < b.longValue())
415
throw new NumberClassNotFoundException(a.getClass() + " and "
416
+ b.getClass() + " not currently supported.");
424
* tests for equality among two objects that are instances of one of the
425
* child classes of java.lang.Number
427
* @param a the first number
428
* @param b the second number
429
* @return true if the two values are equal
430
* @throws NumberClassNotFoundException if number class not supported
432
public boolean equals(Number a, Number b)
433
throws NumberClassNotFoundException {
435
boolean equals = false;
437
if (a instanceof Double && b instanceof Double) {
438
if (Math.abs(a.doubleValue() - b.doubleValue()) < epsilon)
440
} else if (a instanceof Integer && b instanceof Integer) {
441
if (a.intValue() == b.intValue())
443
} else if (a instanceof Float && b instanceof Float) {
444
if (Math.abs(a.floatValue() - b.floatValue()) < epsilon)
446
} else if (a instanceof Long && b instanceof Long) {
447
if (a.longValue() == b.longValue())
450
throw new NumberClassNotFoundException(a.getClass() + " and "
451
+ b.getClass() + " not currently supported.");
458
* A helper method to figure out what number format should be used to
459
* display the numbers value in a formatted text box.
461
* @return the number format
462
* @throws NumberClassNotFoundException if number class not supported
464
public NumberFormat getNumberFormat() throws NumberClassNotFoundException {
465
NumberFormat numberFormat = null;
467
Number value = getValue();
469
if (value instanceof Double) {
470
numberFormat = NumberFormat.getInstance();
471
numberFormat.setMaximumFractionDigits(7);
472
} else if (value instanceof Integer) {
473
numberFormat = NumberFormat.getIntegerInstance();
474
} else if (value instanceof Float) {
475
numberFormat = NumberFormat.getInstance();
476
numberFormat.setMaximumFractionDigits(7);
477
} else if (value instanceof Long) {
478
numberFormat = NumberFormat.getIntegerInstance();
480
throw new NumberClassNotFoundException(value.getClass()
481
+ " not currently supported.");
b'\\ No newline at end of file'