Naked Objects
By Richard Pawson and Robert Matthews

Enriching object behaviours

Manipulating value objects

Value objects are for holding simple, generic data values (such as a date, a string of characters, or a temperature) that belong to a single business object. All value objects must implement the org.nakedobjects.object.NakedValue interface.

All values must implement the NakedValue interface, which is normally done by extending AbstractNakedValue. The abstract Magnitude class provides the core ability to compare value objects based on a numeric value.

The following value objects are defined within the framework as subclasses of the org.nakedobjects.object.value.AbstractNakedValue class and new types can be added if needed. All are self explanatory bar the Option class, which permits the object to take one of a set number of values. The current viewing mechanism portrays this to users as a set of radio buttons or a drop-down selection box, depending on how many options there are. The following classes are all members of the org.nakedobjects.object.value package:

  • Date - 3-Jun-02 or 21/3/01
  • FloatingPointNumber - 1,234.5 or 0.125
  • Logical - set to True or False
  • Money - ₤5,120.50 or $10.99
  • Option - Saloon|SUV|Minivan|Coupe
  • Percentage - 0.1% or 99.99%
  • TextString - Alan McDonald
  • Time - 10:50 AM or 14:15
  • TimeStamp - 3-Jun-02 10:50 AM or 21/3/01 14:15
  • URLString - http://www.nakedobjects.org/downloads.html
  • WholeNumber - 18 or 1,200

The screenshot below shows and example of how the current viewing mechanism portrays each of these value objects to the user:

Each of these classes has three common constructors and a core set of methods. The zero-parameter constructor creates the object with its default value. The defaults are zero values for the numerical types, the current date and time for the temporal types, and an empty string for the string type. The one-parameter constructors take either an existing object of the same type and copies its value across, or a conventional Java type that can readily be mapped onto the value object type. The core methods are:

  • public Title title() returns a title string - as a Title object - formatted according to the default Java Locale.
  • public boolean isEmpty() determines if the object is empty: it does not contain a value.
  • public void clear() clears the value so it is empty.
  • public void reset() resets the object to its default value.
  • public boolean isValid() determines whether a value is currently valid according to the object's Validity strategy. For example the PositiveValue strategy, applied to a WholeNumber object, ensures that the number remains positive.
  • public void setValidity(Validity strategy) assigns a specific Validity strategy.
  • public void setAbout(About newAbout) assigns an About strategy. This is used to control the accessibility of the value object.
  • public void parse(String text) throws ValueParseException attempts to convert the specified Java String into the value object's type.

In addition to these common methods, each type has a number of typeValue and setValue methods that accept and return various related data types. For example, the Money class includes the methods doubleValue and intValue to convert the money value into double and int Java types. It also has setValue(double) and setValue(Money) to set the value using a Java double value or another Money object. The following shows all the conversion methods for the Money class followed by an example of them in use:

public short shortValue();
public int intValue();
public long longValue();
public float floatValue();
public double doubleValue();

public void setValue(double amount);
public void setValue(Money value);

Money m = new Money();
m.setValue(8.4);
float f = m.floatValue();

The numerical types also include a set of methods to perform basic arithmetic operations. So, for example, a FloatingPointNumber can have another FloatingPointNumber or a Java double added to it using the overloaded add method. These are provided to simplify the coding of mathematical operations, avoiding the need to repeatedly convert between Java primitive types and NakedValue types. The following shows the basic four arithmetic operations (overloaded to accept both double values and FloatingPoint objects) that are available for FloatingPoint objects followed by examples of their use:

public void add(double value);
public void add(FloatingPointNumber number);
public void subtract(double value);
public void subtract(FloatingPointNumber number);
public void multiply(double value);
public void multiply(FloatingPointNumber number);
public void divide(double value);
public void divide(FloatingPointNumber number);

FloatingPointNumber f = new FloatingPointNumber();
f.setValue(1.5);
FloatingPointNumber g = new FloatingPointNumber();
g.setValue(1.5);
f.add(g);
f.multiply(2.0);
double d = f.doubleValue();

As well as the arithmetic functions, the numerical types also have methods to compare themselves against other instances. So, for example, a Percentage object can be compared to another Percentage object to see if it is greater by using the isGreaterThan method. These methods are jointly implemented in the value object classes and the Magnitude class from which they are extended. The following are all the Magnitude methods, of which isEqualTo and isLessThan must be implemented by the subclass:

public boolean isEqualTo(Magnitude magnitude);
public boolean isLessThan(Magnitude magnitude);
public boolean isLessThanOrEqualTo(Magnitude magnitude);
public boolean isGreaterThan(Magnitude magnitude);
public boolean isGreaterThanOrEqualTo(Magnitude magnitude);
public boolean isBetween(Magnitude minMagnitude, 
		Magnitude maxMagnitude);
public Magnitude max(Magnitude magnitude);
public Magnitude min(Magnitude magnitude);

The TextString class, which is probably the most widely used value object, provides string methods such as contains, endsWith, isSameAs that can be invoked in either case sensitive or case insensitive manner. All the comparisons in the example below will return true:

public boolean isSameAs(String text);
public boolean isSameAs(String text, Case caseSensitive);
public boolean contains(String text);
public boolean contains(String text, Case caseSensitive);
public boolean startsWith(String text);
public boolean startsWith(String text, Case caseSensitive);
public boolean endsWith(String text);
public boolean endsWith(String text, Case caseSensitive);

TextString t = new TextString();
t.setValue("Form 1");
t.isSameAs("Form 1");
t.startsWith("form", Case.INSENSITIVE);
t.contains("1");

All the value classes and their methods are listed in their entirety in the API specification, which can be found in the Naked Objects distribution.