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 javax.xml.bind.annotation.XmlAccessType;
020import javax.xml.bind.annotation.XmlAccessorType;
021import javax.xml.bind.annotation.XmlAttribute;
022import javax.xml.bind.annotation.XmlRootElement;
023import javax.xml.bind.annotation.XmlTransient;
024
025import org.apache.camel.CamelContext;
026import org.apache.camel.model.DataFormatDefinition;
027import org.apache.camel.spi.DataFormat;
028import org.apache.camel.spi.Metadata;
029import org.apache.camel.spi.RouteContext;
030import org.apache.camel.util.ObjectHelper;
031
032/**
033 * YAML data format
034 *
035 * @version 
036 */
037@Metadata(label = "dataformat,transformation,yaml", title = "YAML")
038@XmlRootElement(name = "yaml")
039@XmlAccessorType(XmlAccessType.FIELD)
040public class YAMLDataFormat extends DataFormatDefinition {
041    @XmlAttribute @Metadata(defaultValue = "SnakeYAML")
042    private YAMLLibrary library = YAMLLibrary.SnakeYAML;
043    @XmlTransient
044    private ClassLoader classLoader;
045    @XmlTransient
046    private Class<?> unmarshalType;
047    @XmlAttribute
048    private String unmarshalTypeName;
049    @XmlAttribute
050    private String constructor;
051    @XmlAttribute
052    private String representer;
053    @XmlAttribute
054    private String dumperOptions;
055    @XmlAttribute
056    private String resolver;
057    @XmlAttribute @Metadata(defaultValue = "true")
058    private Boolean useApplicationContextClassLoader = true;
059    @XmlAttribute @Metadata(defaultValue = "false")
060    private Boolean prettyFlow = false;
061
062    public YAMLDataFormat() {
063        this(YAMLLibrary.SnakeYAML);
064    }
065
066    public YAMLDataFormat(YAMLLibrary library) {
067        super("yaml-" + library.name().toLowerCase());
068        this.library = library;
069    }
070
071    public YAMLDataFormat(YAMLLibrary library, Class<?> unmarshalType) {
072        super("yaml-" + library.name().toLowerCase());
073        this.library = library;
074        this.unmarshalType = unmarshalType;
075    }
076
077    public YAMLLibrary getLibrary() {
078        return library;
079    }
080
081    /**
082     * Which yaml library to use such.
083     * <p/>
084     * Is by default SnakeYAML
085     */
086    public void setLibrary(YAMLLibrary library) {
087        this.library = library;
088        setDataFormatName("yaml-" + library.name().toLowerCase());
089    }
090
091    public Class<?> getUnmarshalType() {
092        return unmarshalType;
093    }
094
095    /**
096     * Class of the object to be created
097     */
098    public void setUnmarshalType(Class<?> type) {
099        this.unmarshalType = type;
100    }
101
102    public String getUnmarshalTypeName() {
103        return unmarshalTypeName;
104    }
105
106    /**
107     * Class name of the java type to use when unarmshalling
108     */
109    public void setUnmarshalTypeName(String unmarshalTypeName) {
110        this.unmarshalTypeName = unmarshalTypeName;
111    }
112
113    public ClassLoader getClassLoader() {
114        return classLoader;
115    }
116
117    /**
118     * Set a custom classloader
119     */
120    public void setClassLoader(ClassLoader classLoader) {
121        this.classLoader = classLoader;
122    }
123
124    public String getConstructor() {
125        return constructor;
126    }
127
128    /**
129     * BaseConstructor to construct incoming documents.
130     */
131    public void setConstructor(String constructor) {
132        this.constructor = constructor;
133    }
134
135    public String getRepresenter() {
136        return representer;
137    }
138
139    /**
140     * Representer to emit outgoing objects.
141     */
142    public void setRepresenter(String representer) {
143        this.representer = representer;
144    }
145
146    public String getDumperOptions() {
147        return dumperOptions;
148    }
149
150    /**
151     * DumperOptions to configure outgoing objects.
152     */
153    public void setDumperOptions(String dumperOptions) {
154        this.dumperOptions = dumperOptions;
155    }
156
157    public String getResolver() {
158        return resolver;
159    }
160
161    /**
162     * Resolver to detect implicit type
163     */
164    public void setResolver(String resolver) {
165        this.resolver = resolver;
166    }
167
168    public boolean isUseApplicationContextClassLoader() {
169        return useApplicationContextClassLoader;
170    }
171
172    /**
173     * Use ApplicationContextClassLoader as custom ClassLoader
174     */
175    public void setUseApplicationContextClassLoader(boolean useApplicationContextClassLoader) {
176        this.useApplicationContextClassLoader = useApplicationContextClassLoader;
177    }
178
179    public boolean isPrettyFlow() {
180        return prettyFlow;
181    }
182
183    /**
184     * Force the emitter to produce a pretty YAML document when using the flow
185     * style.
186     */
187    public void setPrettyFlow(boolean prettyFlow) {
188        this.prettyFlow = prettyFlow;
189    }
190
191    @Override
192    protected DataFormat createDataFormat(RouteContext routeContext) {
193        if (library == YAMLLibrary.SnakeYAML) {
194            setProperty(routeContext.getCamelContext(), this, "dataFormatName", "yaml-snakeyaml");
195        }
196
197        return super.createDataFormat(routeContext);
198    }
199
200    @Override
201    protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) {
202        if (library == YAMLLibrary.SnakeYAML) {
203            configureSnakeDataFormat(dataFormat, camelContext);
204        }
205    }
206
207    protected void configureSnakeDataFormat(DataFormat dataFormat, CamelContext camelContext) {
208        Class<?> yamlUnmarshalType =  unmarshalType;
209        if (yamlUnmarshalType == null && unmarshalTypeName != null) {
210            try {
211                yamlUnmarshalType = camelContext.getClassResolver().resolveMandatoryClass(unmarshalTypeName);
212            } catch (ClassNotFoundException e) {
213                throw ObjectHelper.wrapRuntimeCamelException(e);
214            }
215        }
216
217        setProperty(dataFormat, camelContext, "unmarshalType", yamlUnmarshalType);
218        setProperty(dataFormat, camelContext, "classLoader", classLoader);
219        setProperty(dataFormat, camelContext, "useApplicationContextClassLoader", useApplicationContextClassLoader);
220        setProperty(dataFormat, camelContext, "prettyFlow", prettyFlow);
221
222        setPropertyRef(dataFormat, camelContext, "constructor", constructor);
223        setPropertyRef(dataFormat, camelContext, "representer", representer);
224        setPropertyRef(dataFormat, camelContext, "dumperOptions", dumperOptions);
225        setPropertyRef(dataFormat, camelContext, "resolver", resolver);
226    }
227
228    protected void setProperty(DataFormat dataFormat, CamelContext camelContext, String propertyName, Object propertyValue) {
229        if (ObjectHelper.isNotEmpty(propertyValue)) {
230            setProperty(camelContext, dataFormat, propertyName, propertyValue);
231        }
232    }
233
234    protected void setPropertyRef(DataFormat dataFormat, CamelContext camelContext, String propertyName, String propertyValue) {
235        if (ObjectHelper.isNotEmpty(propertyValue)) {
236            // must be a reference value
237            String ref = propertyValue.startsWith("#") ? propertyValue : "#" + propertyValue;
238            setProperty(camelContext, dataFormat, propertyName, ref);
239        }
240    }
241}