| <!-- |
| /*************************************************************************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations under the License. |
| ***************************************************************************************************************************/ |
| --> |
| |
| @Bean(typeName) Annotation |
| |
| <p> |
| The {@link oaj.annotation.Bean#typeName() @Bean(typeName)} annotation can be used to |
| override the Juneau default name on bean elements. |
| Types names serve two distinct purposes: |
| </p> |
| <ol> |
| <li>To override the element name. |
| <li>To serve as a class identifier so that the bean class can be inferred during parsing if it |
| cannot automatically be inferred through reflection. |
| </ol> |
| |
| <h5 class='figure'>Example</h5> |
| <table class='styled w800'> |
| <tr> |
| <th>Data type</th> |
| <th>JSON example</th> |
| <th>Without annotation</th> |
| <th>With annotation</th> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(typeName=<js>"X"</js>) |
| <jk>class</jk> MyBean { |
| <jk>public</jk> String a; |
| <jk>public int</jk> b; |
| } |
| </td> |
| <td class='code'> |
| { |
| a: <js>'foo'</js>, |
| b: 123 |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a><xv>foo</xv></id> |
| <b><xv>123</xv></name> |
| </object> |
| </xt></td> |
| <td class='code'><xt> |
| <X> |
| <a><xv>foo</xv></id> |
| <b><xv>123</xv></name> |
| </X> |
| </xt></td> |
| </tr> |
| </table> |
| <p> |
| On bean properties, a <xa>_type</xa> attribute will be added if a type name is present and the bean |
| class cannot be inferred through reflection. |
| </p> |
| <p> |
| In the following example, a type attribute is used on property 'b' but not property 'a' since |
| 'b' is of type <c>Object</c> and therefore the bean class cannot be inferred. |
| </p> |
| |
| <h5 class='figure'>Example</h5> |
| <table class='styled w800'> |
| <tr> |
| <th>Java</th> |
| <th>Without annotation</th> |
| <th>With annotation</th> |
| </tr> |
| <tr> |
| <td class='code'> |
| <jk>class</jk> MyBean { |
| <jk>public</jk> BeanX a = <jk>new</jk> BeanX(); |
| <jk>public</jk> Object b = <jk>new</jk> BeanX(); |
| } |
| |
| <ja>@Bean</ja>(typeName=<js>"X"</js>) |
| <jk>class</jk> BeanX { |
| <jk>public</jk> String fx = <js>"foo"</js>; |
| } |
| |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a> |
| <fx><xv>foo</xv></fx> |
| </a> |
| <b> |
| <fx><xv>foo</xv></fx> |
| </b> |
| </object> |
| </xt></td> |
| <td class='code'><xt> |
| <object> |
| <a> |
| <fx><xv>foo</xv></fx> |
| </a> |
| <b <xa>_type</xa>=<xs>'X'</xs>> |
| <fx><xv>foo</xv></fx> |
| </b> |
| </object> |
| </xt></td> |
| </tr> |
| </table> |
| <div class='info'> |
| <c>string</c>, <c>number</c>, <c>boolean</c>, <c>object</c>, |
| <c>array</c>, and <c>null</c> are reserved keywords that cannot be used as type names. |
| </div> |
| <p> |
| Beans with type names are often used in conjunction with the |
| {@link oaj.annotation.Bean#dictionary() @Bean(dictionary)} and |
| {@link oaj.annotation.Beanp#dictionary() @Beanp(dictionary)} |
| annotations so that the beans can be resolved at parse time. |
| These annotations are not necessary during serialization, but are needed during parsing in order to |
| resolve the bean types. |
| </p> |
| <p> |
| The following examples show how type names are used under various circumstances. |
| </p> |
| <p> |
| Pay special attention to when <xa>_type</xa> attributes are and are not used. |
| </p> |
| |
| <h5 class='figure'>Examples</h5> |
| <table class='styled w800'> |
| <tr> |
| <th>Java</th> |
| <th>XML</th> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>}) |
| <jk>class</jk> BeanWithArrayPropertiesWithTypeNames { |
| <jk>public</jk> BeanX[] b1 = <jk>new</jk> BeanX[]{ |
| <jk>new</jk> BeanX() |
| }; |
| <jk>public</jk> Object[] b2 = <jk>new</jk> BeanX[]{ |
| <jk>new</jk> BeanX() |
| }; |
| <jk>public</jk> Object[] b3 = <jk>new</jk> Object[]{ |
| <jk>new</jk> BeanX() |
| }; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <b1> |
| <X> |
| <fx><xv>foo</xv></fx> |
| </X> |
| </b1> |
| <b2> |
| <X> |
| <fx><xv>foo</xv></fx> |
| </X> |
| </b2> |
| <b3> |
| <X> |
| <fx><xv>foo</xv></fx> |
| </X> |
| </b3> |
| </object> |
| </xt></td> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>}) |
| <jk>class</jk> BeanWith2dArrayPropertiesWithTypeNames { |
| <jk>public</jk> BeanX[][] b1 = <jk>new</jk> BeanX[][]{{ |
| <jk>new</jk> BeanX() |
| }}; |
| <jk>public</jk> Object[][] b2 = <jk>new</jk> BeanX[][]{{ |
| <jk>new</jk> BeanX() |
| }}; |
| <jk>public</jk> Object[][] b3 = <jk>new</jk> Object[][]{{ |
| <jk>new</jk> BeanX() |
| }}; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <b1> |
| <array> |
| <X> |
| <fx><xv>foo</xv></fx> |
| </X> |
| </array> |
| </b1> |
| <b2> |
| <array> |
| <X> |
| <fx><xv>foo</xv></fx> |
| </X> |
| </array> |
| </b2> |
| <b3> |
| <array> |
| <X> |
| <fx><xv>foo</xv></fx> |
| </X> |
| </array> |
| </b3> |
| </object> |
| </xt></td> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>}) |
| <jk>class</jk> BeanWithMapPropertiesWithTypeNames { |
| <jk>public</jk> Map<String,BeanX> b1 = <jk>new</jk> HashMap<>() {{ |
| put(<js>"k1"</js>, <jk>new</jk> BeanX()); |
| }}; |
| <jk>public</jk> Map<String,Object> b2 = <jk>new</jk> HashMap<>() {{ |
| put(<js>"k2"</js>, <jk>new</jk> BeanX()); |
| }} |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <b1> |
| <k1> |
| <fx><xv>foo</xv></fx> |
| </k1> |
| </b1> |
| <b2> |
| <k2 <xa>_type</xa>=<xs>'X'</xs>> |
| <fx><xv>foo</xv></fx> |
| </k2> |
| </b2> |
| </object> |
| </xt></td> |
| </tr> |
| </table> |
| <p> |
| Bean type names are also used for resolution when abstract fields are used. |
| The following examples show how they are used in a variety of circumstances. |
| </p> |
| <table class='styled w800'> |
| <tr> |
| <th>Java</th> |
| <th>XML</th> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={A.<jk>class</jk>}) |
| <jk>class</jk> BeanWithAbstractFields { |
| <jk>public</jk> A a = <jk>new</jk> A(); |
| <jk>public</jk> IA ia = <jk>new</jk> A(); |
| <jk>public</jk> AA aa = <jk>new</jk> A(); |
| <jk>public</jk> Object o = <jk>new</jk> A(); |
| } |
| |
| <jk>interface</jk> IA {} |
| |
| <jk>abstract class</jk> AA <jk>implements</jk> IA {} |
| |
| <ja>@Bean</ja>(typeName=<js>"A"</js>) |
| <jk>class</jk> A <jk>extends</jk> AA { |
| <jk>public</jk> String fa = <js>"foo"</js>; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a> |
| <fa><xv>foo</xv></fa> |
| </a> |
| <ia <xa>_type</xa>=<xs>'A'</xs>> |
| <fa><xv>foo</xv></fa> |
| </ia> |
| <aa <xa>_type</xa>=<xs>'A'</xs>> |
| <fa><xv>foo</xv></fa> |
| </aa> |
| <o <xa>_type</xa>=<xs>'A'</xs>> |
| <fa><xv>foo</xv></fa> |
| </o> |
| </object> |
| </xt></td> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={A.<jk>class</jk>}) |
| <jk>class</jk> BeanWithAbstractArrayFields { |
| <jk>public</jk> A[] a = <jk>new</jk> A[]{<jk>new</jk> A()}; |
| <jk>public</jk> IA[] ia1 = <jk>new</jk> A[]{<jk>new</jk> A()}; |
| <jk>public</jk> IA[] ia2 = <jk>new</jk> IA[]{<jk>new</jk> A()}; |
| <jk>public</jk> AA[] aa1 = <jk>new</jk> A[]{<jk>new</jk> A()}; |
| <jk>public</jk> AA[] aa2 = <jk>new</jk> AA[]{<jk>new</jk> A()}; |
| <jk>public</jk> Object[] o1 = <jk>new</jk> A[]{<jk>new</jk> A()}; |
| <jk>public</jk> Object[] o2 = <jk>new</jk> Object[]{<jk>new</jk> A()}; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </a> |
| <ia1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </ia1> |
| <ia2> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </ia2> |
| <aa1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </aa1> |
| <aa2> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </aa2> |
| <o1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </o1> |
| <o2> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </o2> |
| </object> |
| </xt></td> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={A.<jk>class</jk>}) |
| <jk>class</jk> BeanWithAbstractMapFields { |
| <jk>public</jk> Map<String,A> a = <jk>new</jk> HashMap<>() {{ |
| put(<js>"k1"</js>, <jk>new</jk> A()); |
| }}; |
| <jk>public</jk> Map<String,AA> b = <jk>new</jk> HashMap<>() {{ |
| put(<js>"k2"</js>, <jk>new</jk> A()); |
| }}; |
| <jk>public</jk> Map<String,Object> c = <jk>new</jk> HashMap<>() {{ |
| put(<js>"k3"</js>, <jk>new</jk> A()); |
| }}; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a> |
| <k1> |
| <fa><xv>foo</xv></fa> |
| </k1> |
| </a> |
| <b> |
| <k2 <xa>_type</xa>=<xs>'A'</xs>> |
| <fa><xv>foo</xv></fa> |
| </k2> |
| </b> |
| <c> |
| <k3 <xa>_type</xa>=<xs>'A'</xs>> |
| <fa><xv>foo</xv></fa> |
| </k3> |
| </c> |
| </object> |
| </xt></td> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(dictionary={A.<jk>class</jk>}) |
| <jk>class</jk> BeanWithAbstractMapArrayFields { |
| <jk>public</jk> Map<String,A[]> a = <jk>new</jk> LinkedHashMap<>() {{ |
| put(<js>"a1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()}); |
| }}; |
| <jk>public</jk> Map<String,IA[]> ia = <jk>new</jk> LinkedHashMap<>() {{ |
| put(<js>"ia1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()}); |
| put(<js>"ia2"</js>, <jk>new</jk> IA[]{<jk>new</jk> A()}); |
| }}; |
| <jk>public</jk> Map<String,AA[]> aa = <jk>new</jk> LinkedHashMap<>() {{ |
| put(<js>"aa1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()}); |
| put(<js>"aa2"</js>, <jk>new</jk> AA[]{<jk>new</jk> A()}); |
| }}; |
| <jk>public</jk> Map<String,Object[]> o = <jk>new</jk>LinkedHashMap<>() {{ |
| put(<js>"o1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()}); |
| put(<js>"o2"</js>, <jk>new</jk> AA[]{<jk>new</jk> A()}); |
| }}; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a> |
| <a1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </a1> |
| </a> |
| <ia> |
| <ia1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </ia1> |
| <ia2> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </ia2> |
| </ia> |
| <aa> |
| <aa1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </aa1> |
| <aa2> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </aa2> |
| </aa> |
| <o> |
| <o1> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </o1> |
| <o2> |
| <A> |
| <fa><xv>foo</xv></fa> |
| </A> |
| </o2> |
| </o> |
| </object> |
| </xt></td> |
| </tr> |
| </table> |
| <p> |
| On a side note, characters that cannot be represented in XML 1.0 are encoded using a simple encoding. |
| Note in the examples below, some characters such as <js>'\n'</js>, <js>'\t</js>', and <js>'\r'</js> |
| can be represented as XML entities when used in text but not in element names. Other characters such as |
| <js>'\b'</js> and <js>'\f'</js> cannot be encoded in XML 1.0 at all without inventing our own notation. |
| Whitespace characters in element names are encoded as well as whitespace end characters in text. |
| </p> |
| <table class='styled w800'> |
| <tr> |
| <th>Java</th> |
| <th>XML</th> |
| </tr> |
| <tr> |
| <td class='code'> |
| <jk>class</jk> BeanWithSpecialCharacters { |
| <jk>public</jk> String a = <js>" \b\f\n\t\r "</js>; |
| } |
| </td> |
| <td class='code'><xt> |
| <object> |
| <a><xv>_x0020_ _x0008__x000C_&#x000a;&#x0009;&#x000d; _x0020_</xv></a> |
| </object> |
| </xt></td> |
| </tr> |
| <tr> |
| <td class='code'> |
| <ja>@Bean</ja>(typeName=<js>" \b\f\n\t\r "</js>) |
| <jk>class</jk> BeanWithNamesWithSpecialCharacters { |
| <ja>@Beanp</ja>(name=<js>" \b\f\n\t\r "</js>) |
| <jk>public</jk> String a = <js>" \b\f\n\t\r "</js>; |
| } |
| </td> |
| <td class='code'><xt> |
| <_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_> |
| <_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_> |
| <xv>_x0020_ _x0008__x000C_&#x000a;&#x0009;&#x000d; _x0020_</xv> |
| </_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_> |
| </_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_> |
| </xt></td> |
| </tr> |
| </table> |
| <p> |
| While it's true that these characters CAN be represented in XML 1.1, it's impossible to parse XML 1.1 |
| text in Java without the XML containing an XML declaration. |
| Unfortunately, this, and the uselessness of the |
| {@link javax.xml.stream.XMLInputFactory#IS_REPLACING_ENTITY_REFERENCES} setting in Java |
| forced us to make some hard design decisions that may not be the most elegant. |
| </p> |