User extension method hooksYou can use your own methods in combination with JiBX marshalling and unmarshalling to support your use of the framework. Figure 19 gives examples of the various types of user method calls supported. Figure 19. User method hooksStarting from the top of the binding definition, I've defined both
factory and pre-get methods for the The pre-get method defined for the For the You might notice that the pre-set method example uses a different
signature than the pre-get example. JiBX actually gives you three different
options for the signatures of any of these extension methods. The first is a
method with no arguments, as shown for the factory and pre-get examples. The
second is a single argument of type This post-set method is called by JiBX after the basic unmarshalling of the associated object (and all child objects) is complete. The only thing left to be done in the unmarshalling of the object at this point is to fill in links to forward-referenced IDs from the XML document, which won't take place until the referenced objects are unmarshalled. The post-set method is a great place to handle any special validation or linking of unmarshalled objects. Now that that's out of the way, here's the story on the signature variations.
The no-argument form of signature doesn't really require much explanation - JiBX
calls your method and the method does whatever it wants, working only with the
actual object (after creating the object, in the case of a factory method). If
you instead use a method with a single parameter of type
If you use a method with a single parameter of type
All the extension methods can be used with non-abstract mapping elements, and also with structure and collection elements that work with object properties (but not with a structure that only defines an element name without an associated object). Custom serializer and deserializer methodsYou can also easily use your own methods for converting values to and from
string representations. Figure 20 gives an example of
doing this for a couple of sample cases. The first is a dollars-and-cents value in the XML
representation that converts to a This shows two ways of defining custom conversions. The first, used for the dollars-and-cents values (highlighted in blue), associates the serializer and deserializer directly with the value to be converted by using the serializer and deserializer attributes of the value element. The second, used for the orders list (highlighted in green), sets custom defaults for handling a particular type of value by using the format element. This custom default then applies to all values of the specified type within the context of the definition. In the case of the Figure 20 example, this context is the entire binding definition, since the format element is a child of the binding element. The third way of defining custom conversions (not shown in the Figure 20 example) also uses the format element, but with the addition of a label attribute value. In this case the format does not become a default, but can be referenced by name wherever needed (using the format attribute of a value element). The methods used for custom conversions to and from XML just need to be static
methods that take a single argument and return a value of the appropriate type.
For the serializer method, the argument must be of the Java type being handled
(or a superclass) and the return must be a public static String serializeDollarsCents(int cents) { StringBuffer buff = new StringBuffer(); buff.append(cents / 100); int extra = cents % 100; if (extra != 0) { buff.append('.'); if (extra < 10) { buff.append('0'); } buff.append(extra); } return buff.toString(); } public static int deserializeDollarsCents(String text) { if (text == null) { return 0; } else { int split = text.indexOf('.'); int cents = 0; if (split > 0) { cents = Integer.parseInt(text.substring(0, split)) * 100; text = text.substring(split+1); } return cents + Integer.parseInt(text); } } public static String serializeIntArray(int[] values) { StringBuffer buff = new StringBuffer(); for (int i = 0; i < values.length; i++) { if (i > 0) { buff.append(' '); } buff.append(values[i]); } return buff.toString(); } private static int[] resizeArray(int[] array, int size) { int[] copy = new int[size]; System.arraycopy(array, 0, copy, 0, Math.min(array.length, size)); return copy; } public static int[] deserializeIntArray(String text) { if (text == null) { return new int[0]; } else { int split = 0; text = text.trim(); int fill = 0; int[] values = new int[10]; while (split < text.length()) { int base = split; split = text.indexOf(' ', split); if (split < 0) { split = text.length(); } int value = Integer.parseInt(text.substring(base, split)); if (fill >= values.length) { values = resizeArray(values, values.length*2); } values[fill++] = value; while (split < text.length() && text.charAt(++split) == ' '); } return resizeArray(values, fill); } } When an optional value is missing in the input document the JiBX binding code
will call the deserialize method with |