/** * 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. */ package org.apache.camel.model.dataformat; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import org.apache.camel.CamelContext; import org.apache.camel.model.DataFormatDefinition; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.RouteContext; import org.apache.camel.util.ObjectHelper; /** * YAML data format * * @version */ @Metadata(firstVersion = "2.17.0", label = "dataformat,transformation,yaml", title = "YAML") @XmlRootElement(name = "yaml") @XmlAccessorType(XmlAccessType.FIELD) public class YAMLDataFormat extends DataFormatDefinition { @XmlAttribute @Metadata(defaultValue = "SnakeYAML") private YAMLLibrary library = YAMLLibrary.SnakeYAML; @XmlTransient private ClassLoader classLoader; @XmlTransient private Class<?> unmarshalType; @XmlAttribute private String unmarshalTypeName; @XmlAttribute private String constructor; @XmlAttribute private String representer; @XmlAttribute private String dumperOptions; @XmlAttribute private String resolver; @XmlAttribute @Metadata(defaultValue = "true") private Boolean useApplicationContextClassLoader = true; @XmlAttribute @Metadata(defaultValue = "false") private Boolean prettyFlow = false; @XmlAttribute @Metadata(defaultValue = "false") private Boolean allowAnyType = false; @XmlElement(name = "typeFilter") private List<YAMLTypeFilterDefinition> typeFilters; public YAMLDataFormat() { this(YAMLLibrary.SnakeYAML); } public YAMLDataFormat(YAMLLibrary library) { super("yaml-" + library.name().toLowerCase()); this.library = library; } public YAMLDataFormat(YAMLLibrary library, Class<?> unmarshalType) { super("yaml-" + library.name().toLowerCase()); this.library = library; this.unmarshalType = unmarshalType; } public YAMLLibrary getLibrary() { return library; } /** * Which yaml library to use. * <p/> * By default it is SnakeYAML */ public void setLibrary(YAMLLibrary library) { this.library = library; setDataFormatName("yaml-" + library.name().toLowerCase()); } public Class<?> getUnmarshalType() { return unmarshalType; } /** * Class of the object to be created */ public void setUnmarshalType(Class<?> type) { this.unmarshalType = type; } public String getUnmarshalTypeName() { return unmarshalTypeName; } /** * Class name of the java type to use when unarmshalling */ public void setUnmarshalTypeName(String unmarshalTypeName) { this.unmarshalTypeName = unmarshalTypeName; } public ClassLoader getClassLoader() { return classLoader; } /** * Set a custom classloader */ public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } public String getConstructor() { return constructor; } /** * BaseConstructor to construct incoming documents. */ public void setConstructor(String constructor) { this.constructor = constructor; } public String getRepresenter() { return representer; } /** * Representer to emit outgoing objects. */ public void setRepresenter(String representer) { this.representer = representer; } public String getDumperOptions() { return dumperOptions; } /** * DumperOptions to configure outgoing objects. */ public void setDumperOptions(String dumperOptions) { this.dumperOptions = dumperOptions; } public String getResolver() { return resolver; } /** * Resolver to detect implicit type */ public void setResolver(String resolver) { this.resolver = resolver; } public boolean isUseApplicationContextClassLoader() { return useApplicationContextClassLoader; } /** * Use ApplicationContextClassLoader as custom ClassLoader */ public void setUseApplicationContextClassLoader(boolean useApplicationContextClassLoader) { this.useApplicationContextClassLoader = useApplicationContextClassLoader; } public boolean isPrettyFlow() { return prettyFlow; } /** * Force the emitter to produce a pretty YAML document when using the flow * style. */ public void setPrettyFlow(boolean prettyFlow) { this.prettyFlow = prettyFlow; } public boolean isAllowAnyType() { return allowAnyType; } /** * Allow any class to be un-marshaled */ public void setAllowAnyType(boolean allowAnyType) { this.allowAnyType = allowAnyType; } public List<YAMLTypeFilterDefinition> getTypeFilters() { return typeFilters; } /** * Set the types SnakeYAML is allowed to un-marshall */ public void setTypeFilters(List<YAMLTypeFilterDefinition> typeFilters) { this.typeFilters = typeFilters; } @Override protected DataFormat createDataFormat(RouteContext routeContext) { if (library == YAMLLibrary.SnakeYAML) { setProperty(routeContext.getCamelContext(), this, "dataFormatName", "yaml-snakeyaml"); } return super.createDataFormat(routeContext); } @Override protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) { if (library == YAMLLibrary.SnakeYAML) { configureSnakeDataFormat(dataFormat, camelContext); } } protected void configureSnakeDataFormat(DataFormat dataFormat, CamelContext camelContext) { Class<?> yamlUnmarshalType = unmarshalType; if (yamlUnmarshalType == null && unmarshalTypeName != null) { try { yamlUnmarshalType = camelContext.getClassResolver().resolveMandatoryClass(unmarshalTypeName); } catch (ClassNotFoundException e) { throw ObjectHelper.wrapRuntimeCamelException(e); } } setProperty(dataFormat, camelContext, "unmarshalType", yamlUnmarshalType); setProperty(dataFormat, camelContext, "classLoader", classLoader); setProperty(dataFormat, camelContext, "useApplicationContextClassLoader", useApplicationContextClassLoader); setProperty(dataFormat, camelContext, "prettyFlow", prettyFlow); setProperty(dataFormat, camelContext, "allowAnyType", allowAnyType); if (typeFilters != null && !typeFilters.isEmpty()) { List<String> typeFilterDefinitions = new ArrayList<>(typeFilters.size()); for (YAMLTypeFilterDefinition definition : typeFilters) { String value = definition.getValue(); if (!value.startsWith("type") && !value.startsWith("regexp")) { YAMLTypeFilterType type = definition.getType(); if (type == null) { type = YAMLTypeFilterType.type; } value = type.name() + ":" + value; } typeFilterDefinitions.add(value); } setProperty(dataFormat, camelContext, "typeFilterDefinitions", typeFilterDefinitions); } setPropertyRef(dataFormat, camelContext, "constructor", constructor); setPropertyRef(dataFormat, camelContext, "representer", representer); setPropertyRef(dataFormat, camelContext, "dumperOptions", dumperOptions); setPropertyRef(dataFormat, camelContext, "resolver", resolver); } protected void setProperty(DataFormat dataFormat, CamelContext camelContext, String propertyName, Object propertyValue) { if (ObjectHelper.isNotEmpty(propertyValue)) { setProperty(camelContext, dataFormat, propertyName, propertyValue); } } protected void setPropertyRef(DataFormat dataFormat, CamelContext camelContext, String propertyName, String propertyValue) { if (ObjectHelper.isNotEmpty(propertyValue)) { // must be a reference value String ref = propertyValue.startsWith("#") ? propertyValue : "#" + propertyValue; setProperty(camelContext, dataFormat, propertyName, ref); } } }