blob: c1110523b8aaa3565cd51d7ee87ff6867ce3a67b [file] [log] [blame]
<!--
/***************************************************************************************************************************
* 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>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/id&gt;
&lt;b&gt;<xv>123</xv>&lt;/name&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;X&gt;
&lt;a&gt;<xv>foo</xv>&lt;/id&gt;
&lt;b&gt;<xv>123</xv>&lt;/name&gt;
&lt;/X&gt;
</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>
&lt;object&gt;
&lt;a&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/a&gt;
&lt;b <xa>_type</xa>=<xs>'X'</xs>&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/b&gt;
&lt;/object&gt;
</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#beanDictionary() @Bean(beanDictionary)} 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>
&lt;object&gt;
&lt;b1&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/b1&gt;
&lt;b2&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/b2&gt;
&lt;b3&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/b3&gt;
&lt;/object&gt;
</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>
&lt;object&gt;
&lt;b1&gt;
&lt;array&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/array&gt;
&lt;/b1&gt;
&lt;b2&gt;
&lt;array&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/array&gt;
&lt;/b2&gt;
&lt;b3&gt;
&lt;array&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/array&gt;
&lt;/b3&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>})
<jk>class</jk> BeanWithMapPropertiesWithTypeNames {
<jk>public</jk> Map&lt;String,BeanX&gt; b1 = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k1"</js>, <jk>new</jk> BeanX());
}};
<jk>public</jk> Map&lt;String,Object&gt; b2 = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k2"</js>, <jk>new</jk> BeanX());
}}
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;b1&gt;
&lt;k1&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/k1&gt;
&lt;/b1&gt;
&lt;b2&gt;
&lt;k2 <xa>_type</xa>=<xs>'X'</xs>&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/k2&gt;
&lt;/b2&gt;
&lt;/object&gt;
</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>
&lt;object&gt;
&lt;a&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/a&gt;
&lt;ia <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/ia&gt;
&lt;aa <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/aa&gt;
&lt;o <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/o&gt;
&lt;/object&gt;
</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>
&lt;object&gt;
&lt;a&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/a&gt;
&lt;ia1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia1&gt;
&lt;ia2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia2&gt;
&lt;aa1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa1&gt;
&lt;aa2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa2&gt;
&lt;o1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o1&gt;
&lt;o2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o2&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={A.<jk>class</jk>})
<jk>class</jk> BeanWithAbstractMapFields {
<jk>public</jk> Map&lt;String,A&gt; a = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k1"</js>, <jk>new</jk> A());
}};
<jk>public</jk> Map&lt;String,AA&gt; b = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k2"</js>, <jk>new</jk> A());
}};
<jk>public</jk> Map&lt;String,Object&gt; c = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k3"</js>, <jk>new</jk> A());
}};
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;k1&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/k1&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;k2 <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/k2&gt;
&lt;/b&gt;
&lt;c&gt;
&lt;k3 <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/k3&gt;
&lt;/c&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={A.<jk>class</jk>})
<jk>class</jk> BeanWithAbstractMapArrayFields {
<jk>public</jk> Map&lt;String,A[]&gt; a = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
put(<js>"a1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()});
}};
<jk>public</jk> Map&lt;String,IA[]&gt; ia = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
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&lt;String,AA[]&gt; aa = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
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&lt;String,Object[]&gt; o = <jk>new</jk>LinkedHashMap&lt;&gt;() {{
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>
&lt;object&gt;
&lt;a&gt;
&lt;a1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/a1&gt;
&lt;/a&gt;
&lt;ia&gt;
&lt;ia1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia1&gt;
&lt;ia2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia2&gt;
&lt;/ia&gt;
&lt;aa&gt;
&lt;aa1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa1&gt;
&lt;aa2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa2&gt;
&lt;/aa&gt;
&lt;o&gt;
&lt;o1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o1&gt;
&lt;o2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o2&gt;
&lt;/o&gt;
&lt;/object&gt;
</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>
&lt;object&gt;
&lt;a&gt;<xv>_x0020_ _x0008__x000C_&amp;#x000a;&amp;#x0009;&amp;#x000d; _x0020_</xv>&lt;/a&gt;
&lt;/object&gt;
</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>
&lt;_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
&lt;_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
<xv>_x0020_ _x0008__x000C_&amp;#x000a;&amp;#x0009;&amp;#x000d; _x0020_</xv>
&lt;/_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
&lt;/_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
</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>