ohair@286: /* alanb@368: * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package javax.xml.bind.annotation.adapters; ohair@286: ohair@286: /** ohair@286: * Adapts a Java type for custom marshaling. ohair@286: * ohair@286: *

Usage:

ohair@286: * ohair@286: *

ohair@286: * Some Java types do not map naturally to a XML representation, for ohair@286: * example HashMap or other non JavaBean classes. Conversely, ohair@286: * a XML repsentation may map to a Java type but an application may ohair@286: * choose to accesss the XML representation using another Java ohair@286: * type. For example, the schema to Java binding rules bind ohair@286: * xs:DateTime by default to XmlGregorianCalendar. But an application ohair@286: * may desire to bind xs:DateTime to a custom type, ohair@286: * MyXmlGregorianCalendar, for example. In both cases, there is a ohair@286: * mismatch between bound type , used by an application to ohair@286: * access XML content and the value type, that is mapped to an ohair@286: * XML representation. ohair@286: * ohair@286: *

ohair@286: * This abstract class defines methods for adapting a bound type to a value ohair@286: * type or vice versa. The methods are invoked by the JAXB binding ohair@286: * framework during marshaling and unmarshalling: ohair@286: * ohair@286: *

ohair@286: * ohair@286: * Writing an adapter therefore involves the following steps: ohair@286: * ohair@286: * ohair@286: * ohair@286: *

Example: Customized mapping of HashMap

ohair@286: *

The following example illustrates the use of ohair@286: * @XmlAdapter and @XmlJavaTypeAdapter to ohair@286: * customize the mapping of a HashMap. ohair@286: * ohair@286: *

Step 1: Determine the desired XML representation for HashMap. ohair@286: * ohair@286: *

ohair@286:  *     <hashmap>
ohair@286:  *         <entry key="id123">this is a value</entry>
ohair@286:  *         <entry key="id312">this is another value</entry>
ohair@286:  *         ...
ohair@286:  *       </hashmap>
ohair@286:  * 
ohair@286: * ohair@286: *

Step 2: Determine the schema definition that the ohair@286: * desired XML representation shown above should follow. ohair@286: * ohair@286: *

ohair@286:  *
ohair@286:  *     <xs:complexType name="myHashMapType">
ohair@286:  *       <xs:sequence>
ohair@286:  *         <xs:element name="entry" type="myHashMapEntryType"
ohair@286:  *                        minOccurs = "0" maxOccurs="unbounded"/>
ohair@286:  *       </xs:sequence>
ohair@286:  *     </xs:complexType>
ohair@286:  *
ohair@286:  *     <xs:complexType name="myHashMapEntryType">
ohair@286:  *       <xs:simpleContent>
ohair@286:  *         <xs:extension base="xs:string">
ohair@286:  *           <xs:attribute name="key" type="xs:int"/>
ohair@286:  *         </xs:extension>
ohair@286:  *       </xs:simpleContent>
ohair@286:  *     </xs:complexType>
ohair@286:  *
ohair@286:  * 
ohair@286: * ohair@286: *

Step 3: Write value types that can generate the above ohair@286: * schema definition. ohair@286: * ohair@286: *

ohair@286:  *     public class MyHashMapType {
ohair@286:  *         List<MyHashMapEntryType> entry;
ohair@286:  *     }
ohair@286:  *
ohair@286:  *     public class MyHashMapEntryType {
ohair@286:  *         @XmlAttribute
ohair@286:  *         public Integer key;
ohair@286:  *
ohair@286:  *         @XmlValue
ohair@286:  *         public String value;
ohair@286:  *     }
ohair@286:  * 
ohair@286: * ohair@286: *

Step 4: Write the adapter that adapts the value type, ohair@286: * MyHashMapType to a bound type, HashMap, used by the application. ohair@286: * ohair@286: *

ohair@286:  *     public final class MyHashMapAdapter extends
ohair@286:  *                        XmlAdapter<MyHashMapType,HashMap> { ... }
ohair@286:  *
ohair@286:  * 
ohair@286: * ohair@286: *

Step 5: Use the adapter. ohair@286: * ohair@286: *

ohair@286:  *     public class Foo {
ohair@286:  *         @XmlJavaTypeAdapter(MyHashMapAdapter.class)
ohair@286:  *         HashMap hashmap;
ohair@286:  *         ...
ohair@286:  *     }
ohair@286:  * 
ohair@286: * ohair@286: * The above code fragment will map to the following schema: ohair@286: * ohair@286: *
ohair@286:  *     <xs:complexType name="Foo">
ohair@286:  *       <xs:sequence>
ohair@286:  *         <xs:element name="hashmap" type="myHashMapType"
ohair@286:  *       </xs:sequence>
ohair@286:  *     </xs:complexType>
ohair@286:  * 
ohair@286: * ohair@286: * @param ohair@286: * The type that JAXB doesn't know how to handle. An adapter is written ohair@286: * to allow this type to be used as an in-memory representation through ohair@286: * the ValueType. ohair@286: * @param ohair@286: * The type that JAXB knows how to handle out of the box. ohair@286: * ohair@286: * @author ohair@286: * @see XmlJavaTypeAdapter ohair@286: * @since JAXB 2.0 ohair@286: */ ohair@286: public abstract class XmlAdapter { ohair@286: ohair@286: /** ohair@286: * Do-nothing constructor for the derived classes. ohair@286: */ ohair@286: protected XmlAdapter() {} ohair@286: ohair@286: /** ohair@286: * Convert a value type to a bound type. ohair@286: * ohair@286: * @param v ohair@286: * The value to be converted. Can be null. ohair@286: * @throws Exception ohair@286: * if there's an error during the conversion. The caller is responsible for ohair@286: * reporting the error to the user through {@link javax.xml.bind.ValidationEventHandler}. ohair@286: */ ohair@286: public abstract BoundType unmarshal(ValueType v) throws Exception; ohair@286: ohair@286: /** ohair@286: * Convert a bound type to a value type. ohair@286: * ohair@286: * @param v ohair@286: * The value to be convereted. Can be null. ohair@286: * @throws Exception ohair@286: * if there's an error during the conversion. The caller is responsible for ohair@286: * reporting the error to the user through {@link javax.xml.bind.ValidationEventHandler}. ohair@286: */ ohair@286: public abstract ValueType marshal(BoundType v) throws Exception; ohair@286: }