PageRenderTime 42ms CodeModel.GetById 36ms app.highlight 5ms RepoModel.GetById 0ms app.codeStats 0ms

/api/src/main/java/org/switchyard/transform/TransformSequence.java

https://github.com/lincolnthree/switchyard-core
Java | 229 lines | 102 code | 30 blank | 97 comment | 29 complexity | 78bc4bda25b484d270adf9c9c37d3496 MD5 | raw file
  1/* 
  2 * JBoss, Home of Professional Open Source 
  3 * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
  4 * as indicated by the @author tags. All rights reserved. 
  5 * See the copyright.txt in the distribution for a 
  6 * full listing of individual contributors.
  7 *
  8 * This copyrighted material is made available to anyone wishing to use, 
  9 * modify, copy, or redistribute it subject to the terms and conditions 
 10 * of the GNU Lesser General Public License, v. 2.1. 
 11 * This program is distributed in the hope that it will be useful, but WITHOUT A 
 12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
 13 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details. 
 14 * You should have received a copy of the GNU Lesser General Public License, 
 15 * v.2.1 along with this distribution; if not, write to the Free Software 
 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 17 * MA  02110-1301, USA.
 18 */
 19
 20package org.switchyard.transform;
 21
 22import java.io.Serializable;
 23import java.util.ArrayList;
 24import java.util.List;
 25
 26import javax.xml.namespace.QName;
 27
 28import org.apache.log4j.Logger;
 29import org.switchyard.Exchange;
 30import org.switchyard.Message;
 31import org.switchyard.Property;
 32import org.switchyard.Scope;
 33
 34/**
 35 * Transformation sequence/pipeline.
 36 * <p/>
 37 * Allows the stringing together of a sequence of transformers and then associating that
 38 * with a Message context e.g.
 39 * <pre>
 40 * TransformSequence.from("a").to("b").to("c').associateWith(messageContext);
 41 * </pre>
 42 *
 43 * @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
 44 */
 45public final class TransformSequence implements Serializable {
 46
 47    /**
 48     * Serial UID
 49     */
 50    static final long serialVersionUID = -1;
 51    /**
 52     * Logger.
 53     */
 54    private static final Logger LOGGER = Logger.getLogger(TransformSequence.class);
 55
 56    /**
 57     * Transform Sequence.
 58     */
 59    private List<QName> _sequence = new ArrayList<QName>();
 60
 61    /**
 62     * Create an {@link #associateWith(Exchange, Scope) unassociated} sequence.
 63     */
 64    private TransformSequence() {
 65    }
 66
 67    /**
 68     * Associate this instance with the supplied message context.
 69     * @param exchange associate the transform to this exchange
 70     * @param scope associate the transform with this scope
 71     */
 72    public void associateWith(Exchange exchange, Scope scope) {
 73        exchange.getContext().setProperty(
 74                TransformSequence.class.getName(), this, scope);
 75    }
 76
 77    /**
 78     * Start the transformation sequence.
 79     *
 80     * @param typeName The from type.
 81     * @return The sequence.
 82     */
 83    public static TransformSequence from(final QName typeName) {
 84        TransformSequence newSequence = new TransformSequence();
 85        newSequence.add(typeName);
 86        return newSequence;
 87    }
 88
 89    /**
 90     * Add to the transformation sequence.
 91     *
 92     * @param typeName The from type.
 93     * @return The sequence.
 94     */
 95    public TransformSequence to(final QName typeName) {
 96        add(typeName);
 97        return this;
 98    }
 99
100    /**
101     * Apply this {@link TransformSequence} to the supplied {@link Message} instance.
102     * @param message Message instance.
103     * @param registry Transformation Registry.
104     */
105    public void apply(Message message, TransformerRegistry registry) {
106
107        while (_sequence.size() > 1) {
108            QName from = _sequence.get(0);
109            QName to = _sequence.get(1);
110            Transformer transformer = registry.getTransformer(from, to);
111
112            if (transformer == null) {
113                break;
114            }
115
116            Object result;
117            if (Message.class.isAssignableFrom(transformer.getFromType())) {
118                // A returned object just indicates that the transformation took place.
119                result = transformer.transform(message);
120            } else {
121                // A returned object indicates that the transformation took place and is
122                // used as the new Message payload.
123                result = transformer.transform(message.getContent(transformer.getFromType()));
124                if (result != null) {
125                    message.setContent(result);
126                }
127            }
128
129            if (result != null) {
130                // We can now remove the 1st element in the sequence.  2nd element will become the
131                // "from" for the next transformation in the sequence, if one is required...
132                _sequence.remove(0);
133                if (LOGGER.isDebugEnabled()) {
134                    LOGGER.debug("Transformed Message (" + System.identityHashCode(message) + ") from '" + transformer.getFrom() + "' to '" + transformer.getTo() + "' using transformer type '" + transformer.getClass().getName() + "'.");
135                }
136            } else {
137                LOGGER.warn("Transformer '" + transformer.getClass().getName() + "' returned a null transformation result.  Check input payload matches requirements of the Transformer implementation.");
138                break;
139            }
140        }
141    }
142
143    /**
144     * Get the current message type for the specified exchange.
145     *
146     * @param exchange The exchange.
147     * @return The current exchange message type, or null if
148     *         no TransformSequence is set on the exchange.
149     */
150    public static QName getCurrentMessageType(final Exchange exchange) {
151        TransformSequence transformSequence = get(exchange);
152
153        if (transformSequence != null && !transformSequence._sequence.isEmpty()) {
154            return transformSequence._sequence.get(0);
155        }
156
157        return null;
158    }
159
160    /**
161     * Get the target message type for the specified exchange phase.
162     *
163     * @param exchange The exchange.
164     * @return The target exchange message type, or null if
165     *         no TransformSequence is set on the exchange.
166     */
167    public static QName getTargetMessageType(final Exchange exchange) {
168        TransformSequence transformSequence = get(exchange);
169
170        if (transformSequence != null && !transformSequence._sequence.isEmpty()) {
171            // Return the last entry in the sequence...
172            return transformSequence._sequence.get(transformSequence._sequence.size() - 1);
173        }
174
175        return null;
176    }
177
178    /**
179     * Utility assertion method for checking if the source to destination transformations
180     * have been applied to the Exchange.
181     *
182     * @param exchange The exchange instance.
183     * @return True if the transformations have been applied (or are not specified), otherwise false.
184     */
185    public static boolean assertTransformsApplied(final Exchange exchange) {
186        QName fromName = getCurrentMessageType(exchange);
187        QName toName = getTargetMessageType(exchange);
188
189        if (fromName != null && toName != null && !fromName.equals(toName)) {
190            return false;
191        }
192
193        return true;
194    }
195
196    /**
197     * Apply the active exchange transformation sequence to the supplied
198     * Exchange Message.
199     *
200     * @param exchange The Exchange instance.
201     * @param registry The transformation registry.
202     */
203    public static void applySequence(final Exchange exchange, final TransformerRegistry registry) {
204        Message message = exchange.getMessage();
205        TransformSequence transformSequence = get(exchange);
206
207        if (transformSequence == null) {
208            return;
209        }
210
211        transformSequence.apply(message, registry);
212    }
213
214    private void add(final QName typeName) {
215        if (typeName == null) {
216            throw new IllegalArgumentException("null 'typeName' arg passed.");
217        }
218        _sequence.add(typeName);
219    }
220
221    private static TransformSequence get(final Exchange exchange) {
222        Property sequenceProperty = exchange.getContext().getProperty(TransformSequence.class.getName(), Scope.activeScope(exchange));
223        if (sequenceProperty != null) {
224            return (TransformSequence)sequenceProperty.getValue();
225        } else {
226            return null;
227        }
228    }
229}