001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.model.dataformat;
018
019import java.util.Map;
020import javax.xml.bind.annotation.XmlAccessType;
021import javax.xml.bind.annotation.XmlAccessorType;
022import javax.xml.bind.annotation.XmlAttribute;
023import javax.xml.bind.annotation.XmlRootElement;
024import javax.xml.namespace.QName;
025
026import org.apache.camel.CamelContext;
027import org.apache.camel.model.DataFormatDefinition;
028import org.apache.camel.spi.DataFormat;
029import org.apache.camel.spi.Metadata;
030import org.apache.camel.util.CamelContextHelper;
031import org.apache.camel.util.ObjectHelper;
032
033/**
034 * JAXB data format uses the JAXB2 XML marshalling standard to unmarshal an XML payload into Java objects or to marshal Java objects into an XML payload.
035 *
036 * @version 
037 */
038@Metadata(firstVersion = "1.0.0", label = "dataformat,transformation,xml", title = "JAXB")
039@XmlRootElement(name = "jaxb")
040@XmlAccessorType(XmlAccessType.FIELD)
041public class JaxbDataFormat extends DataFormatDefinition {
042    @XmlAttribute(required = true)
043    private String contextPath;
044    @XmlAttribute
045    private String schema;
046    @XmlAttribute @Metadata(enums = "0,1,2", defaultValue = "0")
047    private Integer schemaSeverityLevel;
048    @XmlAttribute
049    private Boolean prettyPrint;
050    @XmlAttribute
051    private Boolean objectFactory;
052    @XmlAttribute
053    private Boolean ignoreJAXBElement;
054    @XmlAttribute
055    private Boolean mustBeJAXBElement;
056    @XmlAttribute
057    private Boolean filterNonXmlChars;
058    @XmlAttribute
059    private String encoding;
060    @XmlAttribute
061    private Boolean fragment;
062    // Partial encoding
063    @XmlAttribute
064    private String partClass;
065    @XmlAttribute
066    private String partNamespace;
067    @XmlAttribute
068    private String namespacePrefixRef;
069    @XmlAttribute @Metadata(label = "advanced")
070    private String xmlStreamWriterWrapper;
071    @XmlAttribute
072    private String schemaLocation;
073    @XmlAttribute
074    private String noNamespaceSchemaLocation;
075    @XmlAttribute @Metadata(label = "advanced")
076    private String jaxbProviderProperties;
077
078    public JaxbDataFormat() {
079        super("jaxb");
080    }
081
082    public JaxbDataFormat(boolean prettyPrint) {
083        this();
084        setPrettyPrint(prettyPrint);
085    }
086
087    public String getContextPath() {
088        return contextPath;
089    }
090
091    /**
092     * Package name where your JAXB classes are located.
093     */
094    public void setContextPath(String contextPath) {
095        this.contextPath = contextPath;
096    }
097
098    public String getSchema() {
099        return schema;
100    }
101
102    /**
103     * To validate against an existing schema.
104     * Your can use the prefix classpath:, file:* or *http: to specify how the resource should by resolved.
105     * You can separate multiple schema files by using the ',' character.
106     */
107    public void setSchema(String schema) {
108        this.schema = schema;
109    }
110
111    public Integer getSchemaSeverityLevel() {
112        return schemaSeverityLevel;
113    }
114
115    /**
116     * Sets the schema severity level to use when validating against a schema.
117     * This level determines the minimum severity error that triggers JAXB to stop continue parsing.
118     * The default value of 0 (warning) means that any error (warning, error or fatal error) will trigger
119     * JAXB to stop. There are the following three levels: 0=warning, 1=error, 2=fatal error.
120     */
121    public void setSchemaSeverityLevel(Integer schemaSeverityLevel) {
122        this.schemaSeverityLevel = schemaSeverityLevel;
123    }
124
125    public Boolean getPrettyPrint() {
126        return prettyPrint;
127    }
128
129    /**
130     * To enable pretty printing output nicely formatted.
131     * <p/>
132     * Is by default false.
133     */
134    public void setPrettyPrint(Boolean prettyPrint) {
135        this.prettyPrint = prettyPrint;
136    }
137
138    public Boolean getObjectFactory() {
139        return objectFactory;
140    }
141
142    /**
143     * Whether to allow using ObjectFactory classes to create the POJO classes during marshalling.
144     * This only applies to POJO classes that has not been annotated with JAXB and providing jaxb.index descriptor files.
145     */
146    public void setObjectFactory(Boolean objectFactory) {
147        this.objectFactory = objectFactory;
148    }
149
150    public Boolean getIgnoreJAXBElement() {
151        return ignoreJAXBElement;
152    }
153
154    /**
155     * Whether to ignore JAXBElement elements - only needed to be set to false in very special use-cases.
156     */
157    public void setIgnoreJAXBElement(Boolean ignoreJAXBElement) {
158        this.ignoreJAXBElement = ignoreJAXBElement;
159    }
160
161    public Boolean getMustBeJAXBElement() {
162        return mustBeJAXBElement;
163    }
164
165    /**
166     * Whether marhsalling must be java objects with JAXB annotations. And if not then it fails.
167     * This option can be set to false to relax that, such as when the data is already in XML format.
168     */
169    public void setMustBeJAXBElement(Boolean mustBeJAXBElement) {
170        this.mustBeJAXBElement = mustBeJAXBElement;
171    }
172
173    /**
174     * To turn on marshalling XML fragment trees.
175     * By default JAXB looks for @XmlRootElement annotation on given class to operate on whole XML tree.
176     * This is useful but not always - sometimes generated code does not have @XmlRootElement annotation,
177     * sometimes you need unmarshall only part of tree.
178     * In that case you can use partial unmarshalling. To enable this behaviours you need set property partClass.
179     * Camel will pass this class to JAXB's unmarshaler.
180     */
181    public void setFragment(Boolean fragment) {
182        this.fragment = fragment;
183    }
184    
185    public Boolean getFragment() {
186        return fragment;
187    }
188
189    public Boolean getFilterNonXmlChars() {
190        return filterNonXmlChars;
191    }
192
193    /**
194     * To ignore non xml characheters and replace them with an empty space.
195     */
196    public void setFilterNonXmlChars(Boolean filterNonXmlChars) {
197        this.filterNonXmlChars = filterNonXmlChars;
198    }
199
200    public String getEncoding() {
201        return encoding;
202    }
203
204    /**
205     * To overrule and use a specific encoding
206     */
207    public void setEncoding(String encoding) {
208        this.encoding = encoding;
209    }
210
211    public String getPartClass() {
212        return partClass;
213    }
214
215    /**
216     * Name of class used for fragment parsing.
217     * <p/>
218     * See more details at the fragment option.
219     */
220    public void setPartClass(String partClass) {
221        this.partClass = partClass;
222    }
223
224    public String getPartNamespace() {
225        return partNamespace;
226    }
227
228    /**
229     * XML namespace to use for fragment parsing.
230     * <p/>
231     * See more details at the fragment option.
232     */
233    public void setPartNamespace(String partNamespace) {
234        this.partNamespace = partNamespace;
235    }
236
237    public String getNamespacePrefixRef() {
238        return namespacePrefixRef;
239    }
240
241    /**
242     * When marshalling using JAXB or SOAP then the JAXB implementation will automatic assign namespace prefixes,
243     * such as ns2, ns3, ns4 etc. To control this mapping, Camel allows you to refer to a map which contains the desired mapping.
244     */
245    public void setNamespacePrefixRef(String namespacePrefixRef) {
246        this.namespacePrefixRef = namespacePrefixRef;
247    }
248
249    public String getXmlStreamWriterWrapper() {
250        return xmlStreamWriterWrapper;
251    }
252
253    /**
254     * To use a custom xml stream writer.
255     */
256    public void setXmlStreamWriterWrapper(String xmlStreamWriterWrapperRef) {
257        this.xmlStreamWriterWrapper = xmlStreamWriterWrapperRef;
258    }
259
260    public String getSchemaLocation() {
261        return schemaLocation;
262    }
263
264    /**
265     * To define the location of the schema
266     */
267    public void setSchemaLocation(String schemaLocation) {
268        this.schemaLocation = schemaLocation;
269    }
270
271    public String getNoNamespaceSchemaLocation() {
272        return noNamespaceSchemaLocation;
273    }
274
275    /**
276     * To define the location of the namespaceless schema
277     */
278    public void setNoNamespaceSchemaLocation(String schemaLocation) {
279        this.noNamespaceSchemaLocation = schemaLocation;
280    }
281
282    public String getJaxbProviderProperties() {
283        return jaxbProviderProperties;
284    }
285
286    /**
287     * Refers to a custom java.util.Map to lookup in the registry containing custom JAXB provider properties
288     * to be used with the JAXB marshaller.
289     */
290    public void setJaxbProviderProperties(String jaxbProviderProperties) {
291        this.jaxbProviderProperties = jaxbProviderProperties;
292    }
293
294    @Override
295    protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) {
296        Boolean answer = ObjectHelper.toBoolean(getPrettyPrint());
297        if (answer != null && !answer) {
298            setProperty(camelContext, dataFormat, "prettyPrint", Boolean.FALSE);
299        } else { // the default value is true
300            setProperty(camelContext, dataFormat, "prettyPrint", Boolean.TRUE);
301        }
302        answer = ObjectHelper.toBoolean(getObjectFactory());
303        if (answer != null && !answer) {
304            setProperty(camelContext, dataFormat, "objectFactory", Boolean.FALSE);
305        } else { // the default value is true
306            setProperty(camelContext, dataFormat, "objectFactory", Boolean.TRUE);
307        }
308        answer = ObjectHelper.toBoolean(getIgnoreJAXBElement());
309        if (answer != null && !answer) {
310            setProperty(camelContext, dataFormat, "ignoreJAXBElement", Boolean.FALSE);
311        } else { // the default value is true
312            setProperty(camelContext, dataFormat, "ignoreJAXBElement", Boolean.TRUE);
313        }
314        answer = ObjectHelper.toBoolean(getMustBeJAXBElement());
315        if (answer != null && answer) {
316            setProperty(camelContext, dataFormat, "mustBeJAXBElement", Boolean.TRUE);
317        } else { // the default value is false
318            setProperty(camelContext, dataFormat, "mustBeJAXBElement", Boolean.FALSE);
319        }
320        answer = ObjectHelper.toBoolean(getFilterNonXmlChars());
321        if (answer != null && answer) {
322            setProperty(camelContext, dataFormat, "filterNonXmlChars", Boolean.TRUE);
323        } else { // the default value is false
324            setProperty(camelContext, dataFormat, "filterNonXmlChars", Boolean.FALSE);
325        }
326        answer = ObjectHelper.toBoolean(getFragment());
327        if (answer != null && answer) {
328            setProperty(camelContext, dataFormat, "fragment", Boolean.TRUE);
329        } else { // the default value is false
330            setProperty(camelContext, dataFormat, "fragment", Boolean.FALSE);
331        }
332
333        setProperty(camelContext, dataFormat, "contextPath", contextPath);
334        if (partClass != null) {
335            setProperty(camelContext, dataFormat, "partClass", partClass);
336        }
337        if (partNamespace != null) {
338            setProperty(camelContext, dataFormat, "partNamespace", QName.valueOf(partNamespace));
339        }
340        if (encoding != null) {
341            setProperty(camelContext, dataFormat, "encoding", encoding);
342        }
343        if (namespacePrefixRef != null) {
344            setProperty(camelContext, dataFormat, "namespacePrefixRef", namespacePrefixRef);
345        }
346        if (schema != null) {
347            setProperty(camelContext, dataFormat, "schema", schema);
348        }
349        if (schemaSeverityLevel != null) {
350            setProperty(camelContext, dataFormat, "schemaSeverityLevel", schemaSeverityLevel);
351        }
352        if (xmlStreamWriterWrapper != null) {
353            setProperty(camelContext, dataFormat, "xmlStreamWriterWrapper", xmlStreamWriterWrapper);
354        }
355        if (schemaLocation != null) {
356            setProperty(camelContext, dataFormat, "schemaLocation", schemaLocation);
357        }
358        if (noNamespaceSchemaLocation != null) {
359            setProperty(camelContext, dataFormat, "noNamespaceSchemaLocation", noNamespaceSchemaLocation);
360        }
361        if (jaxbProviderProperties != null) {
362            Map map = CamelContextHelper.mandatoryLookup(camelContext, jaxbProviderProperties, Map.class);
363            setProperty(camelContext, dataFormat, "jaxbProviderProperties", map);
364        }
365    }
366}