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; 018 019import java.util.Map; 020import javax.xml.bind.annotation.XmlAccessType; 021import javax.xml.bind.annotation.XmlAccessorType; 022import javax.xml.bind.annotation.XmlAnyAttribute; 023import javax.xml.bind.annotation.XmlTransient; 024import javax.xml.bind.annotation.XmlType; 025import javax.xml.namespace.QName; 026 027import org.apache.camel.CamelContext; 028import org.apache.camel.spi.DataFormat; 029import org.apache.camel.spi.Metadata; 030import org.apache.camel.spi.RouteContext; 031import org.apache.camel.util.IntrospectionSupport; 032import org.apache.camel.util.ObjectHelper; 033 034import static org.apache.camel.util.EndpointHelper.isReferenceParameter; 035 036/** 037 * Represents a Camel data format 038 */ 039@Metadata(label = "dataformat,transformation") 040@XmlType(name = "dataFormat") 041@XmlAccessorType(XmlAccessType.FIELD) 042public class DataFormatDefinition extends IdentifiedType implements OtherAttributesAware { 043 @XmlTransient 044 private DataFormat dataFormat; 045 @XmlTransient 046 private String dataFormatName; 047 // use xs:any to support optional property placeholders 048 @XmlAnyAttribute 049 private Map<QName, Object> otherAttributes; 050 051 public DataFormatDefinition() { 052 } 053 054 public DataFormatDefinition(DataFormat dataFormat) { 055 this.dataFormat = dataFormat; 056 } 057 058 protected DataFormatDefinition(String dataFormatName) { 059 this.dataFormatName = dataFormatName; 060 } 061 062 /** 063 * Factory method to create the data format 064 * 065 * @param routeContext route context 066 * @param type the data format type 067 * @param ref reference to lookup for a data format 068 * @return the data format or null if not possible to create 069 */ 070 public static DataFormat getDataFormat(RouteContext routeContext, DataFormatDefinition type, String ref) { 071 if (type == null) { 072 ObjectHelper.notNull(ref, "ref or type"); 073 074 // try to let resolver see if it can resolve it, its not always possible 075 type = routeContext.getCamelContext().resolveDataFormatDefinition(ref); 076 077 if (type != null) { 078 return type.getDataFormat(routeContext); 079 } 080 081 DataFormat dataFormat = routeContext.getCamelContext().resolveDataFormat(ref); 082 if (dataFormat == null) { 083 throw new IllegalArgumentException("Cannot find data format in registry with ref: " + ref); 084 } 085 086 return dataFormat; 087 } else { 088 return type.getDataFormat(routeContext); 089 } 090 } 091 092 public DataFormat getDataFormat(RouteContext routeContext) { 093 if (dataFormat == null) { 094 Runnable propertyPlaceholdersChangeReverter = ProcessorDefinitionHelper.createPropertyPlaceholdersChangeReverter(); 095 096 // resolve properties before we create the data format 097 try { 098 ProcessorDefinitionHelper.resolvePropertyPlaceholders(routeContext.getCamelContext(), this); 099 } catch (Exception e) { 100 throw new IllegalArgumentException("Error resolving property placeholders on data format: " + this, e); 101 } 102 try { 103 dataFormat = createDataFormat(routeContext); 104 if (dataFormat != null) { 105 configureDataFormat(dataFormat, routeContext.getCamelContext()); 106 } else { 107 throw new IllegalArgumentException( 108 "Data format '" + (dataFormatName != null ? dataFormatName : "<null>") + "' could not be created. " 109 + "Ensure that the data format is valid and the associated Camel component is present on the classpath"); 110 } 111 } finally { 112 propertyPlaceholdersChangeReverter.run(); 113 } 114 } 115 return dataFormat; 116 } 117 118 /** 119 * Factory method to create the data format instance 120 */ 121 protected DataFormat createDataFormat(RouteContext routeContext) { 122 // must use getDataFormatName() as we need special logic in json dataformat 123 if (getDataFormatName() != null) { 124 return routeContext.getCamelContext().resolveDataFormat(getDataFormatName()); 125 } 126 return null; 127 } 128 129 /** 130 * Allows derived classes to customize the data format 131 * 132 * @deprecated use {@link #configureDataFormat(org.apache.camel.spi.DataFormat, org.apache.camel.CamelContext)} 133 */ 134 @Deprecated 135 protected void configureDataFormat(DataFormat dataFormat) { 136 } 137 138 /** 139 * Allows derived classes to customize the data format 140 */ 141 protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) { 142 } 143 144 /** 145 * Sets a named property on the data format instance using introspection 146 * 147 * @deprecated use {@link #setProperty(org.apache.camel.CamelContext, Object, String, Object)} 148 */ 149 @Deprecated 150 protected void setProperty(Object bean, String name, Object value) { 151 setProperty(null, bean, name, value); 152 } 153 154 /** 155 * Sets a named property on the data format instance using introspection 156 */ 157 protected void setProperty(CamelContext camelContext, Object bean, String name, Object value) { 158 try { 159 String ref = value instanceof String ? value.toString() : null; 160 if (isReferenceParameter(ref) && camelContext != null) { 161 IntrospectionSupport.setProperty(camelContext, camelContext.getTypeConverter(), bean, name, null, ref, true); 162 } else { 163 IntrospectionSupport.setProperty(bean, name, value); 164 } 165 } catch (Exception e) { 166 throw new IllegalArgumentException("Failed to set property: " + name + " on: " + bean + ". Reason: " + e, e); 167 } 168 } 169 170 public String getDataFormatName() { 171 return dataFormatName; 172 } 173 174 public void setDataFormatName(String dataFormatName) { 175 this.dataFormatName = dataFormatName; 176 } 177 178 public DataFormat getDataFormat() { 179 return dataFormat; 180 } 181 182 public void setDataFormat(DataFormat dataFormat) { 183 this.dataFormat = dataFormat; 184 } 185 186 public Map<QName, Object> getOtherAttributes() { 187 return otherAttributes; 188 } 189 190 /** 191 * Adds an optional attribute 192 */ 193 public void setOtherAttributes(Map<QName, Object> otherAttributes) { 194 this.otherAttributes = otherAttributes; 195 } 196 197 public String getShortName() { 198 String name = getClass().getSimpleName(); 199 if (name.endsWith("DataFormat")) { 200 name = name.substring(0, name.indexOf("DataFormat")); 201 } 202 return name; 203 } 204 205} 206