Apache Jakarta and Beyond: A Java Programmeramp;#039;s Introduction [Electronic resources]

Larne Pekowsky

نسخه متنی -صفحه : 207/ 63
نمايش فراداده

8.5. Nested Properties

Often the value of a bean property is itself a bean; indeed this is what makes trees of beans possible. It is always possible to traverse such a structure by repeatedly calling the appropriate set methods. For example, the name of an artist's first album could be obtained with

Album album =
(Album) PropertyUtils.getIndexedProperty(artist,
"orderedAlbums[0]");
String name =
(String) PropertyUtils.getSimpleProperty(album, name);

Clearly this requires several of lines of code along with a lot of casting. Once again, BeanUtils provides an easier way by introducing the concept of

nested properties. If an expression such as "track[2]" or "albums(Wishfire)" would result in a bean, a property of that bean can be specified by appending a dot followed by the name of the property.

PropertyUtils.getNestedProperty(artist,
"orderedAlbums[0].name");

Note that this still resembles Java syntax, although it pretends that all the members are public and hides the fact that under the covers get and set methods are being called. Properties can be set using the same syntax.

Finally, there are two methods of PropertyUtils that are so useful that they practically subsume all the other methods discussed. These are getProperty() and setProperty(). These allow an arbitrary sequence of simple, indexed, mapped, and nested properties to be specified by a single string. For example, to get the name of the first track on "Sever" by This Ascension:

PropertyUtils.getProperty(collection,
"artist(This Ascension).orderedAlbums[0].tracks[0].name");

There is also a set method, which could be used to mark the first track of an album as a live recording as

PropertyUtils.setProperty(collection,
"artists(VNV Nation).albums(Honor 2003)."   +
"track[1].annotations(live)",
Boolean.TRUE);

The first argument string is broken into two pieces to make it fit the printed page, but this also illustrates an important point. Because the argument is just a string, it is easy to dynamically build and traverse paths. For example, the following code could be used to get the name of the first tracks on all albums by Sunshine Blind:

Integer count =
(Integer)
PropertyUtils.getProperty(
collection,
"artist(Sunshine Blind).numAlbums");
for int(i=0;i<count.intValue();i++) {
System.out.println(PropertyUtils.getProperty(collection,
"artist(Sunshine Blind).album[" +
i +
"].track[0].name");
}

Given how powerful the general getProperty() and setProperty() methods are, it is natural at this point to wonder why anyone would ever use the more specific, limited methods discussed earlier in this chapter. The answer has to do with error conditions. If any of the elements in a long expression does not exist, an exception will be thrown and it may be difficult to find the exact point at which the failure occurred and recover appropriately. There are lots of reasons such an expression might fail: The name of a simple property might have been mistyped, or an indexed property might not have as many elements as expected, or a mapped property might be missing the given key. In light of these possibilities it sometimes makes sense to traverse a tree step by step.