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.impl.transformer;
018
019import org.apache.camel.CamelContext;
020import org.apache.camel.Exchange;
021import org.apache.camel.Message;
022import org.apache.camel.Processor;
023import org.apache.camel.impl.DefaultExchange;
024import org.apache.camel.spi.DataType;
025import org.apache.camel.spi.Transformer;
026import org.apache.camel.util.ObjectHelper;
027import org.apache.camel.util.ServiceHelper;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/**
032 * A {@link Transformer} implementation which leverages {@link Processor} to perform transformation.
033 * 
034 * {@see Transformer}
035 */
036public class ProcessorTransformer extends Transformer {
037    private static final Logger LOG = LoggerFactory.getLogger(ProcessorTransformer.class);
038
039    private Processor processor;
040    private String transformerString;
041
042    public ProcessorTransformer(CamelContext context) {
043        setCamelContext(context);
044    }
045
046    /**
047     * Perform data transformation with specified from/to type using Processor.
048     * @param message message to apply transformation
049     * @param from 'from' data type
050     * @param to 'to' data type
051     */
052    @Override
053    public void transform(Message message, DataType from, DataType to) throws Exception {
054        Exchange exchange = message.getExchange();
055        CamelContext context = exchange.getContext();
056        if (from.isJavaType()) {
057            Object input = message.getBody();
058            Class<?> fromClass = context.getClassResolver().resolveClass(from.getName());
059            if (!fromClass.isAssignableFrom(input.getClass())) {
060                LOG.debug("Converting to '{}'", fromClass.getName());
061                input = context.getTypeConverter().mandatoryConvertTo(fromClass, input);
062                message.setBody(input);
063            }
064        }
065        
066        LOG.debug("Sending to transform processor '{}'", processor);
067        DefaultExchange transformExchange = new DefaultExchange(exchange);
068        transformExchange.setIn(message);
069        transformExchange.setProperties(exchange.getProperties());
070        processor.process(transformExchange);
071        Message answer = transformExchange.hasOut() ? transformExchange.getOut() : transformExchange.getIn();
072        
073        if (to.isJavaType()) {
074            Object answerBody = answer.getBody();
075            Class<?> toClass = context.getClassResolver().resolveClass(to.getName());
076            if (!toClass.isAssignableFrom(answerBody.getClass())) {
077                LOG.debug("Converting to '{}'", toClass.getName());
078                answerBody = context.getTypeConverter().mandatoryConvertTo(toClass, answerBody);
079                answer.setBody(answerBody);
080            }
081        }
082        
083        message.copyFrom(answer);
084    }
085
086    /**
087     * Set processor to use
088     *
089     * @param processor Processor
090     * @return this ProcessorTransformer instance
091     */
092    public ProcessorTransformer setProcessor(Processor processor) {
093        this.processor = processor;
094        this.transformerString = null;
095        return this;
096    }
097
098    @Override
099    public String toString() {
100        if (transformerString == null) {
101            transformerString =
102                String.format("ProcessorTransformer[scheme='%s', from='%s', to='%s', processor='%s']",
103                    getModel(), getFrom(), getTo(), processor);
104        }
105        return transformerString;
106    }
107
108    @Override
109    protected void doStart() throws Exception {
110        ObjectHelper.notNull(processor, "processor", this);
111        ServiceHelper.startService(this.processor);
112    }
113
114    @Override
115    protected void doStop() throws Exception {
116        ServiceHelper.stopService(this.processor);
117    }
118}