J2XB Supports a large number of Java and XML types, and allows to resigter support for additional Java types. In this page we investigate what types are supported, what properties are supported for each type, and how to extend J2XB with new types.
Note that this section it limited to Java atomic types - that is Java primitives and types that are considered simple values and will be written to XML as XML simple types.
The mapping from Java Types to XML Simple Types is not a trivial 1:1 mapping, but rather an N:N mapping. Multiple XML Simple types can be mapped to the same Java type (e.g. the XML types string, normalizedString, token and language are all mapped to the Java String).
When mapping an atomic valued property or a collection of atomic values to XML, the default XML type used (in XML Schema generation) is selected according to the table below. However, it is possible to control the XML Schema type using the MOXmlDerivedType annotation.
For example, to specify that a Calendar property be mapped to an XML gYear , we use
@MOProperty(xmlName = "calDate", xmlOrder = 2, xmlOptional = true) @MOXmlDerivedType(MoXmlBaseSimpleType.xmlGYear) public Calendar getCalDate() {...}
J2XB Supports XML Facets for simple types using the MOValidationString and MOValidationNumber annotations.
The MOValidationString annotation allows to set the minimum length of strings, the maximum length and a set of patterns that the string has to match (match at least one of the patterns).
The MOValidationNumber annotation allows to set the minimum and maximum values for numeric attributes. The minimum and maximum can be inclusive or exclusive.
Note that at this time, those two annotations are only used for the XML Schema generation. The methods to read values or write values to XML do not check for the validations.
Java 5 style enumerations are supported, mapped to XML strings with enumeration facets. By default, each enumeration constant defined in Java is mapped to one enumeration value in the XML Schema. However, using the MOEnumXmlName allows to customize the XML names of the enumerations.
An example of enumeration mapping is
public enum EmployeeSalaryGroup { medium, @MOEnumXmlName("vp_salery_group")high }
which is mapped using the following XML Schema
<xs:simpleType name="EmployeeSalaryGroup"> <xs:restriction base="xs:string"> <xs:enumeration value="medium"/> <xs:enumeration value="vp_salery_group"/> </xs:restriction> </xs:simpleType>
Java Type | XML Default Type | Alternate XML Types | Validations |
String | string | normalizedString token language Name NCName ID IDREF ENTITY NMTOKEN ENTITY |
MOValidationString |
BigInteger | integer | nonPositiveInteger nonNegativeInteger positiveInteger negativeInteger unsignedLong |
MOValidationNumber |
Long long |
long | unsignedInt | MOValidationNumber |
Integer int |
int | unsignedShort | MOValidationNumber |
Short short |
short | unsignedByte | MOValidationNumber |
Byte byte |
byte | MOValidationNumber | |
BigDecimal | decimal | MOValidationNumber | |
Float float |
float | MOValidationNumber | |
Double double |
double | MOValidationNumber | |
Boolean boolean |
boolean | ||
enum | String | ||
javax.xml.namespace.QName | QName | ||
Calendar | dateTime | date time gYear gYearMonth gMonth gMonthDay gDay |
|
Date | date | ||
Time | time | ||
Byte[] byte[] |
by default mapped as an Array |
xmlHexBinary xmlBase64binary |
J2XB allows to extend the set of Java types that can be mapped to XML Simple types with now classes. This is done by writing implementation of MOPropertyEditor and registering them using the MoXmlBindingModel .
For example, we want to support a new Java class as a Simple XML value. The value class we are interested in is the IPAddressValue class and it is used by the NetworkDevice class.
We write a MOPropertyEditor implementation and register it with the xmlBindingModel . See the JavaDoc for the MOPropertyEditor description how to implement the property editor.
The Property Editor also here :
public class IPAddressPropertyEditor implements MOPropertyEditor { public Object fromString(Class<?> propertyValueType, String value) { return new IPAddressValue(value); } public String toString(Class<?> propertyValueType, Object value) { return value.toString(); } public MOValueValidationResult validateStringEncoding(Class propertyValueType, String value) { if (IPAddressValue.isValidStringValue(value)) return new MOValueValidationResult(); else return new MOValueValidationResult(false, propertyValueType, String.format("the value [%s] is not a valid ip address", value)); } public Object fromXmlValue(MOPropertySimpleTypeDescriptor simpleTypeDescriptor, XmlValue value) throws MOBeansException { return new IPAddressValue((String)value.getValue()); } public XmlValue toXmlValue(MOPropertySimpleTypeDescriptor simpleTypeDescriptor, Object value) { return new XmlValue(value.toString(), MoXmlBaseSimpleType.xmlString); } public boolean isCompatibleSimpleType(MoXmlBaseSimpleType xmlSimpleType) { return xmlSimpleType == MoXmlBaseSimpleType.xmlString; } public MoXmlBaseSimpleType getXmlDefaultSimpleType(MoXmlBaseSimpleType xmlSimpleType) { return MoXmlBaseSimpleType.xmlString; } public String[] getEnumerations(Class<?> propertyValueType) { return new String[0]; } public boolean supportsStringValidations() { return false; } public boolean supportsNumberValidations() { return false; } public int compareValues(Object obj_a, Object obj_b) { return obj_a.toString().compareTo(obj_b.toString()); } }
and registering it is done via
xmlBindingModel.getPropertyEditorRegistry().registerPropertyEditor(IPAddress.class, new IPAddressPropertyEditor());