16
16
17
17
import org .xmlunit .builder .Input .Builder ;
18
18
19
- import javax .xml .bind .DataBindingException ;
20
- import javax .xml .bind .JAXBContext ;
21
- import javax .xml .bind .JAXBElement ;
22
- import javax .xml .bind .JAXBException ;
23
- import javax .xml .bind .Marshaller ;
24
- import javax .xml .bind .PropertyException ;
25
- import javax .xml .bind .annotation .XmlRootElement ;
26
- import javax .xml .bind .util .JAXBSource ;
27
- import javax .xml .namespace .QName ;
28
- import javax .xml .transform .Source ;
29
-
30
- import java .beans .Introspector ;
31
- import java .lang .reflect .Method ;
32
-
33
19
/**
34
- * {@link Builder} for Jaxb-Object and creating a {@link JAXBSource}.
35
- * <p>
36
- * If no custom {@link Marshaller} is set by {@link #withMarshaller(Marshaller)}, then the same logic as in {@link JAXB}
37
- * is used the create a default {@link Marshaller}.
20
+ * {@link Builder} for Jaxb-Object and creating a {@code JAXBSource}.
38
21
*/
39
- public class JaxbBuilder implements Builder {
22
+ public abstract class JaxbBuilder implements Builder {
40
23
41
24
private final Object object ;
42
- private Marshaller marshaller ;
43
- private boolean userObjectFactory ;
25
+ private Object marshaller ;
26
+ private boolean useObjectFactory ;
44
27
45
28
/**
46
29
* Creates a builder based on the given object.
@@ -50,126 +33,58 @@ protected JaxbBuilder(final Object object) {
50
33
}
51
34
52
35
/**
53
- * Sets a non-default {@link Marshaller} to use when creating the {@link Source}.
36
+ * Sets a non-default {@code Marshaller} to use when creating the {@link Source}.
54
37
*/
55
- public JaxbBuilder withMarshaller (final Marshaller marshaller ) {
38
+ public JaxbBuilder withMarshaller (final Object marshaller ) {
56
39
this .marshaller = marshaller ;
57
40
return this ;
58
41
}
59
42
60
43
/**
61
- * If the given Object has no {@link XmlRootElement} annotation and is not an instants of {@link JAXBElement} it
62
- * must be wrapped by a {@link JAXBElement}.
44
+ * Whether the given Object has no {@code XmlRootElement} annotation and is not an instants of {@code JAXBElement} it
45
+ * must be wrapped by a {@code JAXBElement}.
63
46
* <p>
64
47
* This method will find the {@code ObjectFactory} class (normally generated by jaxb) and use the first matching
65
- * factory-method for the given Object to create the {@link JAXBElement}-Wrapper.
48
+ * factory-method for the given Object to create the {@code JAXBElement}-Wrapper.
66
49
* <p>
67
50
* If no ObjectFactory and method exists for the given object, the default behavior (same behavior as by
68
- * {@link JAXB}) will be used to create the {@link JAXBElement}-Wrapper for the given Object.
51
+ * {@code JAXB}) will be used to create the {@code JAXBElement}-Wrapper for the given Object.
69
52
* <p>
70
53
* If you don't use the {@code xjc:simple} flag to generate your JAXB-Objects, the use of the OjectFactory is most likely
71
54
* required to generate Schema-Valid XML.
72
55
*/
73
56
public JaxbBuilder useObjectFactory () {
74
- this .userObjectFactory = true ;
57
+ this .useObjectFactory = true ;
75
58
return this ;
76
59
}
77
60
78
- @ Override
79
- public Source build () {
80
- try {
81
- if (marshaller == null ) {
82
- createDefaultMarshaller ();
83
- }
84
-
85
- final Object jaxbObject = getPreparedJaxbObject ();
86
- final JAXBSource jaxbSource = new JAXBSource (marshaller , jaxbObject );
87
- // the fake InputSource cannot be used (the Convert.java
88
- // will create a working one if it is null)
89
- jaxbSource .setInputSource (null );
90
- return jaxbSource ;
91
- } catch (final JAXBException e ) {
92
- throw new DataBindingException (e );
93
- }
94
- }
95
-
96
- private Object getPreparedJaxbObject () {
97
- final Object jaxbObject ;
98
- if (object instanceof JAXBElement ) {
99
- jaxbObject = object ;
100
- } else {
101
- final Class <?> clazz = object .getClass ();
102
- final XmlRootElement r = clazz .getAnnotation (XmlRootElement .class );
103
- if (r == null ) {
104
- if (userObjectFactory ) {
105
- jaxbObject = createJAXBElement (object );
106
- } else {
107
- jaxbObject = createInferredJAXBElement (object );
108
- }
109
- } else {
110
- jaxbObject = object ;
111
- }
112
- }
113
- return jaxbObject ;
114
- }
115
-
116
- private void createDefaultMarshaller () throws JAXBException , PropertyException {
117
- JAXBContext context ;
118
- if (object instanceof JAXBElement ) {
119
- context = JAXBContext .newInstance (((JAXBElement <?>) object ).getDeclaredType ());
120
- } else {
121
- final Class <?> clazz = object .getClass ();
122
- context = JAXBContext .newInstance (clazz );
123
- }
124
- marshaller = context .createMarshaller ();
125
- marshaller .setProperty (Marshaller .JAXB_FORMATTED_OUTPUT , true );
126
- }
127
-
128
- @ SuppressWarnings ("unchecked" )
129
- private static <T > JAXBElement <T > createInferredJAXBElement (final T object ) {
130
- final Class <T > clazz = (Class <T >) object .getClass ();
131
- // we need to infer the name
132
- return new JAXBElement <T >(new QName (inferName (clazz )), clazz , object );
133
- }
134
-
135
- private static <T > JAXBElement <T > createJAXBElement (final T jaxbObj ) {
136
- final JAXBElement <T > jaxbElementFromObjectFactory = createJaxbElementFromObjectFactory (jaxbObj );
137
- if (jaxbElementFromObjectFactory == null ) {
138
- return createInferredJAXBElement (jaxbObj );
139
- } else {
140
- return jaxbElementFromObjectFactory ;
141
- }
61
+ /**
62
+ * Provides the configured object.
63
+ * @return the configured object
64
+ * @since 2.9.0
65
+ */
66
+ protected final Object getObject () {
67
+ return object ;
142
68
}
143
69
144
- @ SuppressWarnings ("unchecked" )
145
- private static <T > JAXBElement <T > createJaxbElementFromObjectFactory (final T obj ) {
146
- try {
147
- final Class <?> objFactClass = getObjectFactoryClass (obj );
148
- final Object objFact = objFactClass .newInstance ();
149
- final Method [] methods = objFactClass .getMethods ();
150
-
151
- Object jaxbObj = null ;
152
- for (final Method method : methods ) {
153
- final Class <?>[] params = method .getParameterTypes ();
154
- if (params .length == 1 && params [0 ] == obj .getClass ()
155
- && method .getReturnType ().isAssignableFrom (JAXBElement .class )) {
156
- jaxbObj = method .invoke (objFact , obj );
157
- break ;
158
- }
159
- }
160
- return (JAXBElement <T >) jaxbObj ;
161
- } catch (final Exception e ) {
162
- // ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException
163
- return null ;
164
- }
70
+ /**
71
+ * Provides the custom Marshaller.
72
+ * @return the configured Marshaller
73
+ * @since 2.9.0
74
+ */
75
+ protected final Object getMarshaller () {
76
+ return marshaller ;
165
77
}
166
78
167
- private static <T > Class <?> getObjectFactoryClass (final T obj ) throws ClassNotFoundException {
168
- final String objFactClassName = obj .getClass ().getPackage ().getName () + ".ObjectFactory" ;
169
- return Thread .currentThread ().getContextClassLoader ().loadClass (objFactClassName );
79
+ /**
80
+ * Provides whether the given Object has no {@code XmlRootElement} annotation and is not an instants of {@code JAXBElement} it
81
+ * must be wrapped by a {@code JAXBElement}.
82
+ * @return whether the given Object has no {@code XmlRootElement} annotation and is not an instants of {@code JAXBElement} it
83
+ * must be wrapped by a {@code JAXBElement}.
84
+ * @since 2.9.0
85
+ */
86
+ protected final boolean getUseObjectFactory () {
87
+ return useObjectFactory ;
170
88
}
171
89
172
- private static String inferName (final Class clazz ) {
173
- return Introspector .decapitalize (clazz .getSimpleName ());
174
- }
175
90
}
0 commit comments