| Defines common operations to all Property implementations, and
in principle, represents a particular personalizable aspect, even though,
the concept is general enough to represent any kind of structured
information. Property corresponds to the "Component"
participant in the "Composite" pattern, that is, the root interface
declaring all common operations to derived classes/interfaces. Concrete
implementations will either be leaf or composite classes.
All properties have a simple name, that is, a String
(example: "numberOfHeadlines") and a value (univalued) or a
number of them (multivalued), even though the interface
hides such a diference by using a Object[] when refering
to the value (an array with only one element) or the values (an array
with potentially more than one value). In case of multivalued properties,
all values are supposed to be of the same type, and deep copies are never
done when setting or getting values (this is the usual semantics in Java).
In case of leaf properties, also called simple properties, in
general, their values are not properties (however, nothing prevents it,
because properties, of course, are also objects). The type of all values
must be the same. In case of composite classes, also called
compound properties, each value is a
PropertyStructure , which contains a number of properties,
which in turn can be leaf or composite properties. All values must be
a PropertyStructure with the same properties (with possibly
different values). In both cases, when needing to represent a property
not taking any value, the special value Object[0] (or a
subtype) must be used, and not the null value.
Properties taking the special value Object[0] are referred to
as optionally valued properties along the documentation.
Property interface has been maximized in order to increase
transparency, that is, it declares operations applicable to leaf and
composite objects (even though some of them could have no sense, and
in consequence, may be not implemented), and hides the difference between
univalued and multivalued properties, both in leaf and compound properties.
Two standard implementations of this interface are provided:
SimpleProperty and
CompoundProperty , with the standard
semantics.
As an example of a univalued compound property, you might consider the
personalizable properties of a news service. Such a property could be
called "newsServiceProperties", and its only value would be a property
structure with two simple properties, one for representing the number of
headlines and the other one for representing the names of the news sources
where to search. The former could be a univalued simple property with
simple name "numberOfHeadlines" and its value would be an
Integer (a particular case of Object[] with only
one integer). The latter could be a multivalued simple property with
simple name "sources" and its value would be an array of
String (a particular case of Object[] ). This
example also allows to introduce the concept of full property name.
The full names of these last properties would be
"newsServiceProperties.0.numberOfHeadlines" and
"newsServiceProperties.0.sources". Note that a "." is used for separating
simple names, and that a "0" is used between "newsServiceProperties" and
"numberOfHeadlines". This is because values are always treated as an array
of Object . So, when refering to the ist-elment (starting from
0) of a compound property, a ".i" must be used for specifying such an
element. In case of univalued compound properties, the array has only one
element, so you must refer to it with ".0". Note that the interface does
not allow you to refer to a concrete value of property. You must get or set
all of them, maybe removing or adding values with some auxiliary data
structure (probably a java.util.List ). So, in the above
example, it does not make sense the name "newsServiceProperties.0". A name
may also be relative to another one (examples: "0.sources" is relative to
"newsServiceProperties"). Note also that a full name never begins with a
".".
As an example of a multivalued compound property, you might consider the
personalizable properties of a "saved searches" service, that is, a
service that mantains a list of predefined searches. Each saved search
could specify its name and a number of keywords to take into account when
searching. The personalizable properties of such a service could be
represented with a multivalued compound property, with simple name
"savedSearchesProperties". Each value of such a property is a structure
of two simple properties: (1) the saved search name (simple name:
"savedSearchName") containing a String (a particular case of
Object[] with only one String), and (2)
the keywords (simple name: "keywords") containing a String[]
(a particular case of Object[] ). Assuming that the array
has at least two elements, the full name
"savedSearchesProperties.1.keywords" refers to the "keywords" property
of the second value of the compound property "savedSearchesProperties".
Name resolution, finding a property from another one, is always relative
to the second one. So, for example, considering the second example,
if you want to refer to the property "keywords" of the second element
of the multivalued compound property "savedSearchesProperties", you
must use the relative name "1.keywords" when looking for such a property
from "savedSearchesProperties".
Due to values will be specified and displayed as human-readable strings of
characters (tipically in HTML forms), Property defines
operations for setting the values from strings and viceversa.
NOTE: all implementation of this interface must redefine
hashCode() and equals(Object) in order to handle
property comparisons properly. Two properties are equal if their names
and their values are equal.
author: Fernando Bellas since: 1.0 |