Working with collections and arraysBesides working with individual objects, applications often need to deal with
collections of objects. Figure 8 gives a simple example
of using collections with JiBX. Here the classes represent the basics of an
airline flight timetable, which I'll expand on for the next examples. In this
example I'm using three collections in the root The Figure 8 binding definition uses a collection element for each collection. In the case of the first two collections there's a nested structure element to provide the details of the items present in the collection. I've highlighted the definitions for the collection of carriers in green, and the actual carrier information in blue, to emphasize the connection between the different components. The collection of airports is handled in the same way as the collection of carriers. The collection of notes differs from the other collections both in that it's
stored as an array, and that the values are simple In the case of the Figure 8 binding the collections are homogeneous, with all items in each collection of a particular type. You can also define heterogeneous collections, consisting of several types of items, by just including more than one structure (or value) element as a child of the collection element. Figure 9 demonstrates using a heterogeneous collection for the carrier and airport data from Figure 8, with the structure definitions for the carrier and airport components (shown in green) combined in a single collection. Figure 9. Heterogeneous collection, with factoryFigure 9 also demonstrates one way to work with
collection interfaces (shown in blue). I've changed the type of the collection field in the
As of the JiBX 1.1 release there's an easier way to accomplish the same effect as using a factory to supply instances of an implementation class. This is to use the new create-type attribute to specify the class used when creating new instances of an object. See the object attribute group descriptions for the full details. As with structure elements with multiple child components, heterogeneous collections can be either ordered (meaning the items of each type may be repeated, but the different types of items must always occur in the specified order) or unordered (meaning the items can be in any order). Either way, the child components of a collection are always treated as optional by JiBX (so zero or more instances are accepted). The collection element is generally similar to the structure element in usage and options, but accepts some additional attributes that are unique to working with collections of items. Most of the added attributes are for when you want to implement a custom form of collection, using your own methods to add and retrieve items in the collection. Another attribute, item-type, can be used to specify the type of items in the collection. For the prior examples I've used embedded structure elements to define the structure of items in the collection. This isn't the only way to use collections, though. You can instead leave a collection element empty to tell the binding compiler that objects in the collection will have their own mapping definitions. Specifying the type of items can be useful in this case to avoid ambiguity. Figure 10 shows an example of using mapping definitions in this way. Figure 10. Collections with mappingsIn Figure 10 I've converted the embedded carrier and
airport structure definitions used in the earlier examples into their own
mapping elements. The binding uses an item-type attribute to
specify that the first collection (shown in blue) contains only carriers, while
the second collection (shown in green) uses a generic You can nest collections inside other collections. This is the approach
used to represent multidimensional arrays, or Java collections made up of other
collections. You can also use value elements directly as the child of a
collection element, though only if the value representation is as
an element. This is the way you'd handle a collection of simple The collection element will work directly with all standard Java
collections implementing the Working with IDsFigure 11 gives a more complex example of working with collections. This builds on the Figure 10 XML and data structures. The prior collections of carrier and airport elements are still present, but now the XML representation uses wrapper elements (carriers and airports, respectively) for the collections of each type. The blue highlighting in the diagram shows this change. In the binding definition, the addition of the wrapper element is shown by just adding a name attribute to each collection element. Figure 11. Collections and IDsI've also added route and flight information to the Figure 11 binding. The most interesting part about these additions is the use of references back to the airport and carrier information. The carrier reference linkages are highlighted in green, the airport linkages in magenta. In the Java code, the linkages are direct object references. On the XML side, these are converted into ID and IDREF links - each carrier or airport defines an ID value, which is then referenced by flight or route elements. The binding definition shows these linkages through the use of an ident="def" attribute on the child value component of a mapping element supplying the ID, and an ident="ref" attribute on an IDREF value component that references an ID. Using ID and IDREF links allows references between objects to be marshalled and unmarshalled, but is subject to some limitations. Each object with an ID must have a mapping in the binding. The current JiBX code also requires that you define objects in some consistent way, though the references to the objects can be from anywhere (even before the actual definitions of the objects). In other words, you have to define each object once and only once. In Figure 11 the definitions occur in the carriers and airports collections. The current code also prohibits using IDREF values directly within a collection (so the definitions can be from a collection, but not the references) - to use references in a collection you need to define some sort of wrapper object that actually holds the reference. However, see JiBX extras for some support classes which extend the basic JiBX handling in these areas. |