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     */
017    package org.apache.camel.model.dataformat;
018    
019    import javax.xml.bind.annotation.XmlAccessType;
020    import javax.xml.bind.annotation.XmlAccessorType;
021    import javax.xml.bind.annotation.XmlTransient;
022    import javax.xml.bind.annotation.XmlType;
023    
024    import org.apache.camel.model.IdentifiedType;
025    import org.apache.camel.spi.DataFormat;
026    import org.apache.camel.spi.RouteContext;
027    import org.apache.camel.util.IntrospectionSupport;
028    import org.apache.camel.util.ObjectHelper;
029    
030    /**
031     * Represents the base XML type for DataFormat.
032     *
033     * @version $Revision: 750806 $
034     */
035    @XmlType(name = "dataFormat")
036    @XmlAccessorType(XmlAccessType.FIELD)
037    public class DataFormatDefinition extends IdentifiedType {
038        @XmlTransient
039        private DataFormat dataFormat;
040        @XmlTransient
041        private String dataFormatName;
042    
043        public DataFormatDefinition() {
044        }
045    
046        public DataFormatDefinition(DataFormat dataFormat) {
047            this.dataFormat = dataFormat;
048        }
049    
050        protected DataFormatDefinition(String dataFormatName) {
051            this.dataFormatName = dataFormatName;
052        }
053    
054        /**
055         * Factory method to create the data format
056         * @param routeContext route context
057         * @param type the data format type
058         * @param ref  reference to lookup for a data format
059         * @return the data format or null if not possible to create
060         */
061        public static DataFormat getDataFormat(RouteContext routeContext, DataFormatDefinition type, String ref) {
062            if (type == null) {
063                ObjectHelper.notNull(ref, "ref or dataFormat");
064    
065                DataFormat dataFormat = lookup(routeContext, ref, DataFormat.class);
066                if (dataFormat == null) {
067                    // lookup type and create the data format from it
068                    type = lookup(routeContext, ref, DataFormatDefinition.class);
069                    if (type == null) {
070                        type = routeContext.getDataFormat(ref);
071                    }
072                    if (type != null) {
073                        dataFormat = type.getDataFormat(routeContext);
074                    }
075                }
076    
077                if (dataFormat == null) {
078                    throw new IllegalArgumentException("Cannot find data format in registry with ref: " + ref);
079                }
080    
081                return dataFormat;
082            } else {
083                return type.getDataFormat(routeContext);
084            }
085        }
086    
087        private static <T> T lookup(RouteContext routeContext, String ref, Class<T> type) {
088            try {
089                return routeContext.lookup(ref, type);
090            } catch (Exception e) {
091                // need to ignore not same type and return it as null
092                return null;
093            }
094        }
095    
096        public DataFormat getDataFormat(RouteContext routeContext) {
097            if (dataFormat == null) {
098                dataFormat = createDataFormat(routeContext);
099                ObjectHelper.notNull(dataFormat, "dataFormat");
100                configureDataFormat(dataFormat);
101            }
102            return dataFormat;
103        }
104    
105        /**
106         * Factory method to create the data format instance
107         */
108        @SuppressWarnings("unchecked")
109        protected DataFormat createDataFormat(RouteContext routeContext) {
110            if (dataFormatName != null) {
111                Class type = routeContext.getCamelContext().getClassResolver().resolveClass(dataFormatName);
112                if (type == null) {
113                    throw new IllegalArgumentException("The class " + dataFormatName + " is not on the classpath! Cannot use the dataFormat " + this);
114                }
115                return (DataFormat) ObjectHelper.newInstance(type);
116            }
117            return null;
118        }
119    
120        /**
121         * Allows derived classes to customize the data format
122         */
123        protected void configureDataFormat(DataFormat dataFormat) {
124        }
125    
126        /**
127         * Sets a named property on the data format instance using introspection
128         */
129        protected void setProperty(Object bean, String name, Object value) {
130            try {
131                IntrospectionSupport.setProperty(bean, name, value);
132            } catch (Exception e) {
133                throw new IllegalArgumentException("Failed to set property: " + name + " on: " + bean + ". Reason: " + e, e);
134            }
135        }
136    }
137