Skip to content

HyperJAXB3 Customization Guide

Laurent Schoelens edited this page May 17, 2024 · 1 revision

http://wiki.glassfish.java.net/Wiki.jsp?page=Hyperjaxb3ReferenceCustomizations

Introduction

There is no "one and only true" object-relational mapping for your classes. There are many ways to express object constructs, properties and associations relationally.

By default, Hyperjaxb3 does its best to generate the most suitable and reasonable mappings. However, Hyperjaxb3 also allows you to influence the generated object-relational mappings or annotations using the constomization elements.

Customization basics

Hyperjaxb3 customization elements are essentially XML elements in the Hyperjaxb3 customization namespace associated with target XML Schema constructs (complex types, elements, the schema itself and so on). This association can be done directly in the schema file or alternatively in external binding files.

When Hyperjaxb3 processes schema constructs, it detects the associated customization elements and use the provided information to customize the generated mappings.

Customizing in schema and in binding files

As mentioned before, customization elements can be provided directly in schema or in external binding files. In both cases you'll need to define customization namespaces:

  • xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
  • xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"

This is done by adding the appropriate prefixes (hj and orm for the declarations above) to the jaxb:extensionBindingPrefixes attribute.

In you customize in schema, this will look as follows:

src/main/resources/schema.xsd

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
  xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
  xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
  jaxb:extensionBindingPrefixes="hj orm">
  <!-- ... -->
</xsd:schema>

If you're customizing in an external binding file

src/main/resources/bindings.xjb

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings
    version="2.1"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
    xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
    jaxb:extensionBindingPrefixes="hj orm">
 
    <jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
        <!-- ... -->
    </jaxb:bindings>
</jaxb:bindings>

Note that in the declaration above the inner jaxb:bindings element is associated with the target schema located in src/main/resources/schema.xsd (schema location schema.xsd relative to the binding file src/main/resources/bindings.xjb).

If you want to define customization elements directly in schema, just include them into xsd:annotation/xsd:appinfo elements into the target construct. The following example associates the hj:basic customization element with productName element of the Items complex type:

<xsd:complexType name="Items">
  <!-- ... -->
    <xsd:element name="productName" type="xsd:string">
      <xsd:annotation>
        <xsd:appinfo>
          <hj:basic>
            <orm:column length="1024"/>
          </hj:basic>
        </xsd:appinfo>
      </xsd:annotation>
    </xsd:element>
  <!-- ... -->
</xsd:complexType>

On the Java side the customization above is applied to the productName field of the Items class. The hj:basic/orm:column/@length="1024" element instructs Hyperjaxb3 to generate the following property annotation:

@Basic
@Column(name = "PRODUCTNAME", length = 1024)
public String getProductName() {
        return productName;
}

As the result, the PRODUCTNAME column of the ITEMS database table will have the length of 1024.

If you prefer to customize in external binding files, you'll have to associate customization elements with target constructs using XPath expressions in jaxb:bindings/@node attribute:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings
    version="2.1"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
    xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
    jaxb:extensionBindingPrefixes="hj orm">
 
    <jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
        <jaxb:bindings node="xs:complexType[@name='Items']//xsd:element[@name='productName']">
            <hj:basic>
                <orm:column length="1024"/>
            </hj:basic>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

In this example, outer jaxb:bindings element is associated with the xs:schema element of the schema.xsd schema. Inner jaxb:bindings element is associated with the productName element of the Items complex type defined in this schema. This customization is actually the same as the in-schema customization demonstrated earlier.

Hyperjaxb3 customizations and JPA ORM mapping elements

Hyperjaxb3 customization elements are defined in the XML schema which can be found here. This schema is based on the XML schema for JPA persistence object-relational mapping. In fact, most of the Hyperjaxb3 customization elements are slightly extended or slightly modified elements of the JPA ORM schema. For instance, hj:basic element we've seen in examples above is a modification of the orm:basic element. Main difference between Hyperjaxb3 elements and ORM elements is that Hyperjaxb3 elements like hj:basic, hj:one-to-many do not specify the target field or property name.

The fact that Hyperjaxb3 elements are based on JPA ORM elements may help you to understand, which customizations you need to define for Hyperjaxb3 in order to get some specific result. I'll illustrate this with the following example.

Per default Hyperjaxb3 maps 1:M relationships as one-to-many associations using a join table. Consider the following schema fragment:

<xs:complexType name="one">
    <xs:sequence>
        <!-- ... -->
        <xs:element name="one-to-many" type="test:two" minOccurs="0" maxOccurs="unbounded"/>
        <!-- ... -->
    </xs:sequence>
</xs:complexType>

This will be represented by the following JPA annotations:

@OneToMany(targetEntity = ....Two.class, cascade = {
    CascadeType.ALL
})
@JoinTable(name = "ONE_ONETOMANY_TWO", joinColumns = {
    @JoinColumn(name = "PARENT_ONE_ID")
}, inverseJoinColumns = {
    @JoinColumn(name = "CHILD_TWO_ID")
})
public List<....Two> getOneToManyDefault() { ... }

The corresponding JPA mapping in XML will look as follows:

<orm:one-to-many name="oneToMany">
    <orm:join-table name="ONE_ONETOMANY_TWO">
        <orm:join-column name="PARENT_ONE_ID"/>
        <orm:inverse-join-column name="CHILD_TWO_ID"/>
    </orm:join-table>
</orm:one-to-many>

Now, assume you want 1:M join to be implemented via a join column (instead of a join table). If you were to define your JPA mapping in XML, you'd write something like:

<orm:one-to-many name="oneToMany">
    <orm:join-column name="ONE_TO_MANY_ONE_ID"/>
</orm:one-to-many>

To corresponding customization will look as follows:

<hj:one-to-many>
    <orm:join-column name="ONE_TO_MANY_ONE_ID"/>
</hj:one-to-many>

And the generated annotations will be:

@OneToMany(targetEntity = ....Two.class, cascade = {
    CascadeType.ALL
})
@JoinColumn(name = "ONE_TO_MANY_ONE_ID")
public List<....Two> getOneToMany() { ... }

It is not necessary to provide the name of the join column. If you omit it, Hyperjaxb3 will generate it for you.

I'd like to mention that this guide will not cover the details of JPA ORM schema. Please consult the JPA specification or check comments in this schema for more information.

Customizing classes

In order to customize a class you need to associate your customization with the appropriate XML schema construct which produces the class. Typically it is the complex type from which the class is derived. Here's a couple of examples.

Customizing complex type directly in schema:

<xs:complexType name="four">
    <xs:annotation>
        <xs:appinfo>
            <hj:entity>
                <orm:sequence-generator name="another-four-sequence" sequence-name="ANOTHER_FOUR_SEQ"/>
            </hj:entity> 
        </xs:appinfo>
    </xs:annotation>
    <!-- ... ->
<xs:complexType>

Customizing an anonymous complex type using external bindings:

Fragment of bindings.xjb

<jaxb:bindings schemaLocation="po.xsd" node="/xs:schema">
    <jaxb:bindings node="xs:complexType[@name='Items']//xs:complexType">
        <hj:entity>
            <orm:table name="item"/>
        </hj:entity>
    </jaxb:bindings>
</jaxb:bindings>

Fragment of po.xsd

<xsd:complexType name="Items">
    <xsd:sequence>
        <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
            <!-- Below is the customized complex type -->
            <xsd:complexType><!-- ... --></xsd:complexType>
        </xsd:element>
    </xsd:sequence>
</xsd:complexType>

Hyperjaxb3 supports the following customization elements for classes:

  • hj:ignored - ignores the class;
  • hj:enity - maps class as entity (default), customizes the entity mapping;
  • hj:mapped-superclass - maps class as mapped superclass, customizes the mapped superclass mapping;
  • hj:embeddable - maps class as embeddable, customizes the embeddable mapping.

Please note that these four customization options are mutually exclusive.

Ignoring classes

The hj:ignored element instructs Hyperjaxb3 not to map a certain class. Ignoring a class has the following consequences:

  • No annotations or mappings will be generated for the ignored class as well as its subclasses.
  • All properties and associations referencing this class will be made transient.

Customizing entity

By default, Hyperjaxb3 maps schema-derived classes as entities (unless otherwise specified by customizations). The hj:entity element customizes the generated entity mapping.

One of the most frequent usages of hj:entity customization is to customize table name for the entity:

<hj:entity>
    <orm:table name="MY_ENTITY_TBL"/>
</hj:entity>

Here's how you override the inheritance strategy:

<xs:complexType name="MyComplexType">
    <xs:annotation>
        <xs:appinfo>
            <hj:entity>
                <orm:inheritance strategy="TABLE_PER_CLASS"/>
            </hj:entity>
        </xs:appinfo>
    </xs:annotation>
    <xs:sequence> ... </xs:sequence>
</xs:complexType>

Cutomizing mapped superclass

In JPA, an entity may inherit from a superclass that provides persistent entity state and mapping information, but which is not itself an entity.

The hj:mapped-superclass element allows you to map a schema-derived class as such "mapped superclass" instead of entity.

Customizing embeddable classes

JPA defines a notion of embeddable class:

An entity may use other fine-grained classes to represent entity state. Instances of these classes, unlike entity instances themselves, do not have persistent identity. Instead, they exist only as embedded objects of the entity to which they belong.

If this notion better represents the semantics of your schema-derived class, you can map it as embeddable class using the hj:embeddable element.

Customizing properties and associations

In order to customize a schema-derived property you need to associate your annotation with the appropriate XML schema construct. This is typically xs:element or xs:attribute declaration.

Supported customization elements for properties or associations are:

  • hj:id - marks an existing property as identifier property;
  • hj:version - marks an existing property as version property;
  • hj:basic - customizes the basic property;
  • hj:many-to-one - maps X:1 property as many-to-one (default strategy), customizes the many-to-one mapping;
  • hj:one-to-one - maps X:1 property as one-to-one, customizes the one-to-one mapping;
  • hj:one-to-many - maps X:M property as one-to-many (default strategy), customizes the one-to-many mapping;
  • hj:many-to-many - maps X:M property as many-to-many, customizes the many-to-many mapping;
  • hj:embedded - maps the property as embedded, customizes the embedded mapping.
  • hj:generated-id - customizes the generated identifier property.
  • hj:generated-version - instructs Hyperjaxb3 to generate a version property an customizes it.
  • hj:generated-property - customizes artificially generated properties.

Selecting the identifier property

In JPA, every entity must have a primary key. With Hyperjaxb3, you have two options for the primary key: either let Hyperjaxb3 generate a default identifier property for you or mark one of existing properties as identifier property using the hj:id customization element.

In the following example I've selected an existing element id as identifier property, customized column name and the value generation strategy:

<xs:complexType name="myType">
    <xs:sequence>
        <!-- ... -->
        <xs:element name="id" type="xs:int" minOccurs="0">
            <xs:annotation>
                <xs:appinfo>
                    <hj:id>
                        <orm:column name="MY_ID"/>
                        <orm:generated-value strategy="SEQUENCE" generator="my-sequence"/>
                        <orm:sequence-generator name="my-sequence" sequence-name="MY_SEQ"/>
                    </hj:id> 
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <!-- ... -->
    </xs:sequence>
</xs:complexType>

The following customization would surely work as well:

<xs:element name="id" type="xs:int" minOccurs="0">
    <xs:annotation>
        <xs:appinfo>
            <hj:id/>
        </xs:appinfo>
    </xs:annotation>
</xs:element>

Selecting the version property

Similar to marking an existing property as identifier, you may mark an existing property as version property which can be used by persistence provider to perform optimistic locking. Use hj:version customization element for this purpose:

<xs:complexType name="myType">
    <xs:sequence>
        <!-- ... -->
        <xs:element name="lastModified" type="xs:dateTime">
            <xs:annotation>
                <xs:appinfo>
                    <hj:version/>
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <!-- ... -->
    </xs:sequence>
</xs:complexType>

Use the nested orm:column element to customize the database column that version property will be mapped to:

<hj:version>
   <orm:column name="MY_VERSION"/>
</hj:version>

Customizing the basic property

Customizing the basic enumerated property

Hyperjaxb3 automatically detects enumerated properties an generates the appropriate @Basic/@Enumerated annotation.

By default, JPA maps enums as strings or integers. You can select enumerated type using hj:basic/orm:enumerated element.

<hj:basic>
    <orm:enumerated>ORDINAL</orm:enumerated>
</hj:basic>

Hyperjaxb3 uses STRING enumerated type per default.

Apart from the default ORDINAL/STRING mappings, Hyperjaxb3 can also map enums by value. Use hj:basic/hj:enumerated-value customization element for this option:

<hj:basic>
    <hj:enumerated-value/>
</hj:basic>

In this case Hyperjaxb3 will generate an additional property which exposes the value of the enum. Generated wrapped property will be persisted, core property will be made transient.

protected Issue143BType issue143B;
 
 
@Transient
public Issue143BType getIssue143B() {
    return issue143B;
}
 
public void setIssue143B(Issue143BType value) {
    this.issue143B = value;
}
 
@Basic
@Column(name = "ISSUE143BITEM", precision = 1, scale = 2)
public Double getIssue143BItem() {
    return ((this.getIssue143B() == null)?null:this.getIssue143B().value());
}
 
public void setIssue143BItem(Double target) {
    setIssue143B(((target == null)?null:Issue143BType.fromValue(target)));
}

Please see tests/enum project for examples of enum customizations.

Customizing the many-to-one property

Customizing the one-to-one property

Customizing the one-to-many property

Order column for one-to-many property

With JPA 2 you can add an order column:

<xsd:element name="person" type="personType" minOccurs="0" maxOccurs="unbounded">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:one-to-many>
                <orm:order-column/>
            </hj:one-to-many>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>

You can customize name, nullable, insertable, updatable and column-definition. If you don't provide the name, it will be generated for you:

@OneToMany ...
@OrderColumn(name = "PERSON_ORDER")
public List<PersonType> getPerson() { ... }

Customizing the many-to-many property

Order column for many-to-many property

With JPA 2 you can add an order column:

<xsd:element name="persion" type="personType" minOccurs="0" maxOccurs="unbounded">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:many-to-many>
                <orm:order-column/>
            </hj:many-to-many>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>

See Order column for one-to-many property - it works exactly the same for many-to-many properties.

Customizing the embedded property

Customizing the generated identifier property

In some cases Hyperjaxb3 has to generate an identifier property for the entity. You may use the hj:generated-id customization element to customize this property:

<xs:complexType name="three">
    <xs:annotation>
        <xs:appinfo>
            <hj:generated-id name="ThreeId" attributeName="test:tid" transient="false"/>
        </xs:appinfo>
    </xs:annotation>
    <!-- ... -->
</xs:complexType>

The hj:generated-id customization element has a number of settings like Java type and XML Schema type of the generated id property, its name (in Java) an attribute (in XML) and so on (see Xsddoc on hj:generated-id for details).

One of the most important things worth mentioning here is the transient attribute. It is false by default which means that identifier property will appear as an attribute in XML. You may set it to false - in this case identifier property will be generated as @XmlTransient and will not appear in your XML.

Since 0.5.7 you can use the hj:generated-id customization on mapped superclasses. This will force generation of the identifier property on the mapped superclass.

Customizing the generated version property

By default Hyperjaxb3 does not generate artificial version properties. You can, however, generate a version property by customizing your type with hj:generated-version element:

<xs:complexType name="MyType">
    <xs:annotation>
        <xs:appinfo>
            <hj:generated-version name="Version" attributeName="test:version" transient="false"/>
        </xs:appinfo>
    </xs:annotation>
    <!-- ... -->
</xs:complexType>

See also:

Since 0.5.7 you can use the hj:generated-version customization on mapped superclasses. This will force generation of the version property on the mapped superclass.

Customizing generated properties

Apart from identifier and version, in certain cases Hyperjaxb3 may have to generate additional properties. For instance, consider a construct like:

<xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="1"/>

Since this "any" property can't be persisted directly with JPA, Hyperjaxb3 will generate an additiona wrapping property. The hj:generated-property customization element allows you to customize this generated property. For instance, you can customize the name of the generated property:

<xs:element name="any" type="xs:anyType">
    <hj:generated-property propertyName="Anything"/>
</xs:element>

Produces:

@XmlElement(required = true)
protected Object any;
 
@Transient
public Object getAny() { ... }
 
public void setAny(Object value) { ... }
 
@Basic
@Column(name = "ANYTHING")
public String getAnything() { ... }
public void setAnything(String target) { ... }

The hj:generated-property element can be specified in the bindings of the originating property (as shown above) or in the bindings of the class. In this case you must provide specify the name of the originating property in the name attribute:

<xsd:complexType name="....">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:generated-property name="Any" propertyName="Anything">
                <!-- ... -->
            </hj:generated-property>
        </xsd:appinfo>
    </xsd:annotation>
    <xsd:sequence>
        <!--
         ! Schema-derived property named "Any" with be accompanied
         ! by a generated wrapping property named "Anything" (see above)
         !-->
        <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="1"/>
    </xsd:sequence>
</xsd:complexType>

As of 2.1.13, JAXB RI seems to have a problem processing customizations for xsd:any. You can only customize such properties via the parent class as shown above.

Contents of the hj:generated-property will be used as customizations for the wrapping property. For instance, you could customize the mapping of the generated property:

<xsd:element name="any" type="xsd:anyType">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:generated-property propertyName="Anything">
                <hj:basic merged="false">
                    <orm:column name="EVERYTHING" length="3000"/>
                </hj:basic>
            </hj:generated-property>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>

Customizing default mappings

Customizing default mappings - Introduction

Although Hyperjaxb3 is highly customizable, you don't actually have to customize. If you don't customize, Hyperjaxb3 will follow its default strategies when generating mappings. For instance default strategy for collection mapping is one-to-many with join columns, default generated identifier property will be called Hjid and typed as long and so on.

No matter how reasonable and good default mappings are, there may be need to override the globally - for all entities, all properties. For instance, you may want map 1:M properties using a join table (instead of the default join column). While you you can surely use the hj:one-to-many customization for each of your 1:M properties, this will require a lot of work.

To address such "global customization tasks" Hyperjaxb3 provides the possibility to customize default mappings. This is accomplished by customizing the schema with the hj:persistence element:

<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
    <hj:persistence>
        <hj:default-one-to-many>
            <orm:join-table/>
        </hj:default-one-to-many>
    </hj:persistence>
</jaxb:bindings>

The hj:persistence element may contain a number of sub-elements which customize default mappings, applied globally. For example, you may make all generated identifier properties to be named Id (instead of Hjid):

<hj:persistence>
    <hj:default-generated-id name="Id"/>
</hj:persistence>

As the matter of fact, Hyperjaxb3 uses the hj:persistence element internally to define the default mappings:

So when you define your hj:persistence customization, you actually override the default hj:persistence.

You don't need to provide the complete configuration of the customization element. It is enough to define only what you need to override. Missing attrbutes and elements will be taken from default mappings.

Overriding and merging customizations

Customizing the default entity

Customizing the default mapped superclass

Customizing the default embeddable

Customizing the default identifier property

Customizing the default generated identifier property

See hj:default-generated-id.

<hj:persistence>
    <hj:default-generated-id name="MyId" transient="true">
        <orm:column name="MY_ID"/>
    </hj:default-generated-id>
</hj:persistence>

This will make all the generated identifier properties to be named MyId (instead of Hjid) by default. They'll be also generated transient.

Customizing the default embedded identifier property

Customizing the default version property

Customizing the default generated version property

See hj:default-generated-version.

Example:

<hj:persistence>
    <hj:default-generated-version name="Version"/>
</hj:persistence>

This will make all the generated version properties to be named Version (instead of Hjversion) by default.

Note that Hyperjaxb3 will not generate version properties by default. If you want to generate version property for a certain type, use the hj:generated-version customization. If you want to generate version properties for all the types, set the forced attribute of the hj:default-generated-version element to true:

<hj:persistence>
    <hj:default-generated-version forced="true"/>
</hj:persistence>

Customizing the default basic property

Customizing the default to-one mapping

Customizing the default to-many mapping

Customizing the default many-to-one mapping

Customizing the default one-to-many mapping

Customizing the default one-to-one mapping

Customizing the default many-to-many mapping

Customizing the default embedded mapping

Miscellaneous customizations

Customizing JAXB context path

"Any"-type properties need a JAXB context for marshalling/unmarshalling operations. By default the context path of this JAXB context is derived from the compiled schemas. In some cases it may not be suitable and you may want to customize the context path. In order to do it, you may use the hj:jaxb-context customization element:

<xsd:element name="any" type="xsd:anyType">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:generated-property propertyName="Anything">
                <hj:jaxb-context contextPath="org.jvnet.hyperjaxb3.ejb.tests.po"/>
            </hj:generated-property>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>

Produces:

public static final String AnythingContextPath = "org.jvnet.hyperjaxb3.ejb.tests.po";
 
public String getAnything() {
    if (JAXBContextUtils.isMarshallable(AnythingContextPath , this.getAny())) {
        return JAXBContextUtils.marshal(AnythingContextPath , this.getAny());
    } else {
        return null;
    }
}
 
public void setAnything(String target) {
    if (target!= null) {
        setAny(JAXBContextUtils.unmarshal(AnythingContextPath , target));
    }
}

You can make the context path field non-final:

<hj:jaxb-context ...>
   <hj:field final="false"/>
</hj:jaxb-context>

Per-type customization

Previous sections explained how you can customize mapping generated for a certain property. A further feature of Hyperjaxb3 is the ability to customize all properties of the certain type (I mean an XML Schema type here) with one shot. This allows you to express things like "all strings must be mapped to columns of length 1000" or "properties of xs:hexBinary are mapped as LOBs".

Since single and collection properties of the same type have different mappings, per-type customizations are distinguished by cardinality. You will typically use hj:default-single-property element for single properties and hj:default-collection-property element for collection properties.

Per-type customization for single properties

In order to customize certain type, define hj:default-single-property sub-element of hj:persistence:

<hj:persistence>
    <hj:default-single-property type="tns:mySimpleType">
        <hj:basic>
            <orm:column scale="2" precision="1"/>
            <hj:enumerated-value/>
        </hj:basic>
    </hj:default-single-property>
</hj:persistence>

You can even override the mappings for built-in types, for instance change the precision of xsd:double mapping (default is 10/20):

<hj:default-single-property type="xsd:double">
    <hj:basic>
        <orm:column scale="5" precision="10"/>
    </hj:basic>
</hj:default-single-property>

See the following project for example:

At the moment works only with simple types.

Per-type customization for collection properties

Not supported at the moment.

XML Schema for customizations

XML Schema files for customizations can be found here:

Xsddoc (generated documentation) for customization schema can be found here:

Clone this wiki locally