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