Author: davsclaus Date: Thu Nov 3 14:53:02 2011 New Revision: 1197168 URL: http://svn.apache.org/viewvc?rev=1197168&view=rev Log: CAMEL-4610: Tokenizer XML mode which supports namespaces.
Added: camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java - copied, changed from r1197028, camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenXMLPairNamespaceSplitTest.java - copied, changed from r1197028, camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairPredicateTest.java camel/trunk/components/camel-spring/src/test/java/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.java camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.xml - copied, changed from r1197028, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/aopbefore.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java camel/trunk/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairIteratorSplitChoicePerformanceTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenizerTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionBuilder.java Thu Nov 3 14:53:02 2011 @@ -42,6 +42,7 @@ import org.apache.camel.model.language.M import org.apache.camel.spi.Language; import org.apache.camel.support.ExpressionAdapter; import org.apache.camel.support.TokenPairExpressionIterator; +import org.apache.camel.support.TokenXMLPairExpressionIterator; import org.apache.camel.util.ExchangeHelper; import org.apache.camel.util.FileUtil; import org.apache.camel.util.IOHelper; @@ -1027,11 +1028,39 @@ public final class ExpressionBuilder { /** * Returns an {@link TokenPairExpressionIterator} expression */ - public static Expression tokenizePairExpression(final String startToken, final String endToken) { + public static Expression tokenizePairExpression(String startToken, String endToken) { return new TokenPairExpressionIterator(startToken, endToken); } /** + * Returns an {@link TokenXMLPairExpressionIterator} expression + */ + public static Expression tokenizeXMLExpression(String tagName, String inheritNamespaceTagName) { + ObjectHelper.notEmpty(tagName, "tagName"); + + // must be XML tokens + if (!tagName.startsWith("<")) { + tagName = "<" + tagName; + } + if (!tagName.endsWith(">")) { + tagName = tagName + ">"; + } + + String endToken = "</" + tagName.substring(1); + + if (inheritNamespaceTagName != null) { + if (!inheritNamespaceTagName.startsWith("<")) { + inheritNamespaceTagName = "<" + inheritNamespaceTagName; + } + if (!inheritNamespaceTagName.endsWith(">")) { + inheritNamespaceTagName = inheritNamespaceTagName + ">"; + } + } + + return new TokenXMLPairExpressionIterator(tagName, endToken, inheritNamespaceTagName); + } + + /** * Returns a tokenize expression which will tokenize the string with the * given regex */ Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java Thu Nov 3 14:53:02 2011 @@ -435,6 +435,27 @@ public class ExpressionClause<T> extends } /** + * Evaluates a XML token expression on the message body with XML content + * + * @param tagName the the tag name of the child nodes to tokenize + * @return the builder to continue processing the DSL + */ + public T tokenizeXML(String tagName) { + return tokenizeXML(tagName, null); + } + + /** + * Evaluates a token pair expression on the message body with XML content + * + * @param tagName the the tag name of the child nodes to tokenize + * @param inheritNamespaceTagName parent or root tag name that contains namespace(s) to inherit + * @return the builder to continue processing the DSL + */ + public T tokenizeXML(String tagName, String inheritNamespaceTagName) { + return delegate.tokenizeXMLPair(tagName, inheritNamespaceTagName); + } + + /** * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath * expression</a> * Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/ExpressionClauseSupport.java Thu Nov 3 14:53:02 2011 @@ -486,6 +486,22 @@ public class ExpressionClauseSupport<T> } /** + * Evaluates a token pair expression on the message body with XML content + * + * @param tagName the the tag name of the child nodes to tokenize + * @param inheritNamespaceTagName optional parent or root tag name that contains namespace(s) to inherit + * @return the builder to continue processing the DSL + */ + public T tokenizeXMLPair(String tagName, String inheritNamespaceTagName) { + TokenizerExpression expression = new TokenizerExpression(); + expression.setToken(tagName); + expression.setInheritNamespaceTagName(inheritNamespaceTagName); + expression.setXml(true); + setExpressionType(expression); + return result; + } + + /** * Evaluates an <a href="http://camel.apache.org/xpath.html">XPath * expression</a> * Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java Thu Nov 3 14:53:02 2011 @@ -27,20 +27,24 @@ import org.apache.camel.util.ObjectHelpe /** * A language for tokenizer expressions. * <p/> - * This tokenizer language can operator in two modes + * This tokenizer language can operator in the following modes: * <ul> * <li>default - using a single tokenizer</li> * <li>pair - using both start and end tokens</li> + * <li>xml - using both start and end tokens in XML mode, support inheriting namespaces</li> * </ul> * The default mode supports the <tt>headerName</tt> and <tt>regex</tt> options. * Where as the pair mode only supports <tt>token</tt> and <tt>endToken</tt>. + * And the <tt>xml</tt> mode supports the <tt>inheritNamespaceTagName</tt> option. */ public class TokenizeLanguage implements Language, IsSingleton { private String token; private String endToken; + private String inheritNamespaceTagName; private String headerName; private boolean regex; + private boolean xml; public static Expression tokenize(String token) { return tokenize(token, false); @@ -72,6 +76,14 @@ public class TokenizeLanguage implements return language.createExpression(null); } + public static Expression tokenizeXML(String tagName, String inheritNamespaceTagName) { + TokenizeLanguage language = new TokenizeLanguage(); + language.setToken(tagName); + language.setInheritNamespaceTagName(inheritNamespaceTagName); + language.setXml(true); + return language.createExpression(null); + } + public Predicate createPredicate(String expression) { return ExpressionToPredicateAdapter.toPredicate(createExpression(expression)); } @@ -82,8 +94,9 @@ public class TokenizeLanguage implements public Expression createExpression() { ObjectHelper.notNull(token, "token"); - // if end token is provided then use the tokenize pair expression - if (endToken != null) { + if (isXml()) { + return ExpressionBuilder.tokenizeXMLExpression(token, inheritNamespaceTagName); + } else if (endToken != null) { return ExpressionBuilder.tokenizePairExpression(token, endToken); } @@ -135,7 +148,23 @@ public class TokenizeLanguage implements this.regex = regex; } + public String getInheritNamespaceTagName() { + return inheritNamespaceTagName; + } + + public void setInheritNamespaceTagName(String inheritNamespaceTagName) { + this.inheritNamespaceTagName = inheritNamespaceTagName; + } + + public boolean isXml() { + return xml; + } + + public void setXml(boolean xml) { + this.xml = xml; + } + public boolean isSingleton() { return false; } -} \ No newline at end of file +} Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/TokenizerExpression.java Thu Nov 3 14:53:02 2011 @@ -40,9 +40,13 @@ public class TokenizerExpression extends @XmlAttribute private String endToken; @XmlAttribute + private String inheritNamespaceTagName; + @XmlAttribute private String headerName; @XmlAttribute private Boolean regex; + @XmlAttribute + private Boolean xml; public TokenizerExpression() { } @@ -84,15 +88,35 @@ public class TokenizerExpression extends return regex; } + public String getInheritNamespaceTagName() { + return inheritNamespaceTagName; + } + + public void setInheritNamespaceTagName(String inheritNamespaceTagName) { + this.inheritNamespaceTagName = inheritNamespaceTagName; + } + + public Boolean getXml() { + return xml; + } + + public void setXml(Boolean xml) { + this.xml = xml; + } + @Override public Expression createExpression(CamelContext camelContext) { TokenizeLanguage language = new TokenizeLanguage(); language.setToken(token); language.setEndToken(endToken); + language.setInheritNamespaceTagName(inheritNamespaceTagName); language.setHeaderName(headerName); if (regex != null) { language.setRegex(regex); } + if (xml != null) { + language.setXml(xml); + } return language.createExpression(); } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java Thu Nov 3 14:53:02 2011 @@ -34,12 +34,12 @@ import org.apache.camel.util.ObjectHelpe * The message body must be able to convert to {@link InputStream} type which is used as stream * to access the message body. * <p/> - * Can be used to split big XML files + * For splitting XML files use {@link TokenXMLPairExpressionIterator} instead. */ public class TokenPairExpressionIterator extends ExpressionAdapter { - private final String startToken; - private final String endToken; + protected final String startToken; + protected final String endToken; public TokenPairExpressionIterator(String startToken, String endToken) { this.startToken = startToken; @@ -54,13 +54,26 @@ public class TokenPairExpressionIterator InputStream in = exchange.getIn().getMandatoryBody(InputStream.class); // we may read from a file, and want to support custom charset defined on the exchange String charset = IOHelper.getCharsetName(exchange); - return new TokenPairIterator(startToken, endToken, in, charset); + return createIterator(in, charset); } catch (InvalidPayloadException e) { exchange.setException(e); return null; } } + /** + * Strategy to create the iterator + * + * @param in input stream to iterate + * @param charset charset + * @return the iterator + */ + protected Iterator createIterator(InputStream in, String charset) { + TokenPairIterator iterator = new TokenPairIterator(startToken, endToken, in, charset); + iterator.init(); + return iterator; + } + @Override public String toString() { return "tokenize[body() using tokens: " + startToken + "..." + endToken + "]"; @@ -69,22 +82,29 @@ public class TokenPairExpressionIterator /** * Iterator to walk the input stream */ - private static final class TokenPairIterator implements Iterator, Closeable { + static class TokenPairIterator implements Iterator, Closeable { - private final String startToken; - private final String endToken; - private final Scanner scanner; - private Object image; + final String startToken; + final String endToken; + final InputStream in; + final String charset; + Scanner scanner; + Object image; - private TokenPairIterator(String startToken, String endToken, InputStream in, String charset) { + TokenPairIterator(String startToken, String endToken, InputStream in, String charset) { this.startToken = startToken; this.endToken = endToken; + this.in = in; + this.charset = charset; + } + + void init() { // use end token as delimiter this.scanner = new Scanner(in, charset).useDelimiter(endToken); // this iterator will do look ahead as we may have data // after the last end token, which the scanner would find // so we need to be one step ahead of the scanner - this.image = scanner.hasNext() ? next() : null; + this.image = scanner.hasNext() ? next(true) : null; } @Override @@ -94,10 +114,14 @@ public class TokenPairExpressionIterator @Override public Object next() { + return next(false); + } + + Object next(boolean first) { Object answer = image; // calculate next if (scanner.hasNext()) { - image = getNext(); + image = getNext(first); } else { image = null; } @@ -109,7 +133,7 @@ public class TokenPairExpressionIterator return answer; } - private Object getNext() { + Object getNext(boolean first) { String next = scanner.next(); // only grab text after the start token Copied: camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java (from r1197028, camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java?p2=camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java&p1=camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java&r1=1197028&r2=1197168&rev=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenPairExpressionIterator.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/support/TokenXMLPairExpressionIterator.java Thu Nov 3 14:53:02 2011 @@ -16,128 +16,177 @@ */ package org.apache.camel.support; -import java.io.Closeable; -import java.io.IOException; import java.io.InputStream; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import org.apache.camel.Exchange; -import org.apache.camel.InvalidPayloadException; -import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; /** - * {@link org.apache.camel.Expression} to walk a {@link org.apache.camel.Message} body - * using an {@link Iterator}, which grabs the content between a start and end token. + * {@link org.apache.camel.Expression} to walk a {@link org.apache.camel.Message} XML body + * using an {@link java.util.Iterator}, which grabs the content between a XML start and end token. * <p/> - * The message body must be able to convert to {@link InputStream} type which is used as stream + * The message body must be able to convert to {@link java.io.InputStream} type which is used as stream * to access the message body. * <p/> - * Can be used to split big XML files + * Can be used to split big XML files. + * <p/> + * This implementation supports inheriting namespaces from a parent/root tag. */ -public class TokenPairExpressionIterator extends ExpressionAdapter { - - private final String startToken; - private final String endToken; +public class TokenXMLPairExpressionIterator extends TokenPairExpressionIterator { - public TokenPairExpressionIterator(String startToken, String endToken) { - this.startToken = startToken; - this.endToken = endToken; - ObjectHelper.notEmpty(startToken, "startToken"); - ObjectHelper.notEmpty(endToken, "endToken"); - } - - @Override - public Object evaluate(Exchange exchange) { - try { - InputStream in = exchange.getIn().getMandatoryBody(InputStream.class); - // we may read from a file, and want to support custom charset defined on the exchange - String charset = IOHelper.getCharsetName(exchange); - return new TokenPairIterator(startToken, endToken, in, charset); - } catch (InvalidPayloadException e) { - exchange.setException(e); - return null; + private static final Pattern NAMESPACE_PATTERN = Pattern.compile("xmlns(:\\w+|)=\\\"(.*?)\\\""); + private static final String SCAN_TOKEN_REGEX = "(\\s+.*?|)>"; + protected final String inheritNamespaceToken; + + public TokenXMLPairExpressionIterator(String startToken, String endToken, String inheritNamespaceToken) { + super(startToken, endToken); + // namespace token is optional + this.inheritNamespaceToken = inheritNamespaceToken; + + // must be XML tokens + if (!startToken.startsWith("<") || !startToken.endsWith(">")) { + throw new IllegalArgumentException("Start token must be a valid XML token, was: " + startToken); + } + if (!endToken.startsWith("<") || !endToken.endsWith(">")) { + throw new IllegalArgumentException("End token must be a valid XML token, was: " + endToken); + } + if (inheritNamespaceToken != null && (!inheritNamespaceToken.startsWith("<") || !inheritNamespaceToken.endsWith(">"))) { + throw new IllegalArgumentException("Namespace token must be a valid XML token, was: " + inheritNamespaceToken); } } @Override - public String toString() { - return "tokenize[body() using tokens: " + startToken + "..." + endToken + "]"; + protected Iterator createIterator(InputStream in, String charset) { + XMLTokenPairIterator iterator = new XMLTokenPairIterator(startToken, endToken, inheritNamespaceToken, in, charset); + iterator.init(); + return iterator; } /** * Iterator to walk the input stream */ - private static final class TokenPairIterator implements Iterator, Closeable { + static class XMLTokenPairIterator extends TokenPairIterator { + + private final Pattern startTokenPattern; + private final String scanEndToken; + private final String inheritNamespaceToken; + private Pattern inheritNamespaceTokenPattern; + private String rootTokenNamespaces; + + XMLTokenPairIterator(String startToken, String endToken, String inheritNamespaceToken, InputStream in, String charset) { + super(startToken, endToken, in, charset); + + // remove any ending > as we need to support attributes on the tags, so we need to use a reg exp pattern + String token = startToken.substring(0, startToken.length() - 1) + SCAN_TOKEN_REGEX; + this.startTokenPattern = Pattern.compile(token); + this.scanEndToken = endToken.substring(0, endToken.length() - 1) + SCAN_TOKEN_REGEX; + this.inheritNamespaceToken = inheritNamespaceToken; + if (inheritNamespaceToken != null) { + token = inheritNamespaceToken.substring(0, inheritNamespaceToken.length() - 1) + SCAN_TOKEN_REGEX; + this.inheritNamespaceTokenPattern = Pattern.compile(token); + } + } - private final String startToken; - private final String endToken; - private final Scanner scanner; - private Object image; - - private TokenPairIterator(String startToken, String endToken, InputStream in, String charset) { - this.startToken = startToken; - this.endToken = endToken; - // use end token as delimiter - this.scanner = new Scanner(in, charset).useDelimiter(endToken); + @Override + void init() { + // use scan end token as delimiter which supports attributes/namespaces + this.scanner = new Scanner(in, charset).useDelimiter(scanEndToken); // this iterator will do look ahead as we may have data // after the last end token, which the scanner would find // so we need to be one step ahead of the scanner - this.image = scanner.hasNext() ? next() : null; + this.image = scanner.hasNext() ? (String) next(true) : null; } @Override - public boolean hasNext() { - return image != null; - } + String getNext(boolean first) { + String next = scanner.next(); + if (next == null) { + return null; + } - @Override - public Object next() { - Object answer = image; - // calculate next - if (scanner.hasNext()) { - image = getNext(); + // initialize inherited namespaces on first + if (first && inheritNamespaceToken != null) { + rootTokenNamespaces = getNamespacesFromNamespaceToken(next); + } + + // make sure next is positioned at start token as we can have leading data + // or we reached EOL and there is no more start tags + Matcher matcher = startTokenPattern.matcher(next); + if (!matcher.find()) { + return null; } else { - image = null; + int index = matcher.start(); + next = next.substring(index); } - if (answer == null) { - // first time the image may be null - answer = image; + // build answer accordingly to whether namespaces should be inherited or not + StringBuilder sb = new StringBuilder(); + if (inheritNamespaceToken != null && rootTokenNamespaces != null) { + // append root namespaces to local start token + String tag = ObjectHelper.before(next, ">"); + // grab the text + String text = ObjectHelper.after(next, ">"); + // build result with inherited namespaces + next = sb.append(tag).append(rootTokenNamespaces).append(">").append(text).append(endToken).toString(); + } else { + next = sb.append(next).append(endToken).toString(); } - return answer; + + return next; } - private Object getNext() { - String next = scanner.next(); + private String getNamespacesFromNamespaceToken(String text) { + if (text == null) { + return null; + } - // only grab text after the start token - if (next != null && next.contains(startToken)) { - next = ObjectHelper.after(next, startToken); - - // include tokens in answer - if (next != null) { - StringBuilder sb = new StringBuilder(); - next = sb.append(startToken).append(next).append(endToken).toString(); - } + // grab the namespace tag + Matcher mat = inheritNamespaceTokenPattern.matcher(text); + if (mat.find()) { + text = mat.group(0); } else { - // must have start token, otherwise we have reached beyond last tokens - // and should not return more data + // cannot find namespace tag return null; } - return next; - } + // find namespaces (there can be attributes mixed, so we should only grab the namespaces) + Map<String, String> namespaces = new LinkedHashMap<String, String>(); + Matcher matcher = NAMESPACE_PATTERN.matcher(text); + while (matcher.find()) { + String prefix = matcher.group(1); + String url = matcher.group(2); + if (ObjectHelper.isEmpty(prefix)) { + prefix = "_DEFAULT_"; + } else { + // skip leading : + prefix = prefix.substring(1); + } + namespaces.put(prefix, url); + } - @Override - public void remove() { - // noop - } + // did we find any namespaces + if (namespaces.isEmpty()) { + return null; + } - @Override - public void close() throws IOException { - scanner.close(); + // build namespace String + StringBuilder sb = new StringBuilder(); + for (Map.Entry<String, String> entry : namespaces.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + if ("_DEFAULT_".equals(key)) { + sb.append(" xmlns=\"").append(value).append("\""); + } else { + sb.append(" xmlns:").append(key).append("=\"").append(value).append("\""); + } + } + + return sb.toString(); } } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairIteratorSplitChoicePerformanceTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairIteratorSplitChoicePerformanceTest.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairIteratorSplitChoicePerformanceTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairIteratorSplitChoicePerformanceTest.java Thu Nov 3 14:53:02 2011 @@ -83,7 +83,7 @@ public class TokenPairIteratorSplitChoic watch.restart(); } }) - .split().tokenizePair("<order>", "</order>").streaming() + .split().tokenizeXML("<order>", "</order>").streaming() .choice() .when().xpath("/order/amount < 10") .process(new Processor() { Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenXMLPairNamespaceSplitTest.java (from r1197028, camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairPredicateTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenXMLPairNamespaceSplitTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenXMLPairNamespaceSplitTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairPredicateTest.java&r1=1197028&r2=1197168&rev=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenPairPredicateTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenXMLPairNamespaceSplitTest.java Thu Nov 3 14:53:02 2011 @@ -16,16 +16,15 @@ */ package org.apache.camel.language; -import java.io.File; - import org.apache.camel.ContextTestSupport; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; /** * */ -public class TokenPairPredicateTest extends ContextTestSupport { +public class TokenXMLPairNamespaceSplitTest extends ContextTestSupport { @Override protected void setUp() throws Exception { @@ -33,20 +32,27 @@ public class TokenPairPredicateTest exte super.setUp(); } - public void testTokenPairPredicate() throws Exception { - getMockEndpoint("mock:result").expectedMessageCount(1); + public void testTokenXMLPair() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:split"); + mock.expectedMessageCount(3); + mock.message(0).body().isEqualTo("<order id=\"1\" xmlns=\"http:acme.com\">Camel in Action</order>"); + mock.message(1).body().isEqualTo("<order id=\"2\" xmlns=\"http:acme.com\">ActiveMQ in Action</order>"); + mock.message(2).body().isEqualTo("<order id=\"3\" xmlns=\"http:acme.com\">DSL in Action</order>"); - template.sendBodyAndHeader("file:target/pair", "<hello>world!</hello>", Exchange.FILE_NAME, "hello.xml"); + String body = createBody(); + template.sendBodyAndHeader("file:target/pair", body, Exchange.FILE_NAME, "orders.xml"); assertMockEndpointsSatisfied(); + } - oneExchangeDone.matchesMockWaitTime(); - - File file = new File("target/pair/hello.xml"); - assertFalse("File should not exists " + file, file.exists()); - - file = new File("target/pair/ok/hello.xml"); - assertTrue("File should exists " + file, file.exists()); + private String createBody() { + StringBuilder sb = new StringBuilder("<?xml version=\"1.0\"?>\n"); + sb.append("<orders xmlns=\"http:acme.com\">\n"); + sb.append(" <order id=\"1\">Camel in Action</order>\n"); + sb.append(" <order id=\"2\">ActiveMQ in Action</order>\n"); + sb.append(" <order id=\"3\">DSL in Action</order>\n"); + sb.append("</orders>"); + return sb.toString(); } @Override @@ -54,12 +60,12 @@ public class TokenPairPredicateTest exte return new RouteBuilder() { @Override public void configure() throws Exception { - from("file:target/pair?move=ok") - .choice() - // does not make so much sense to use a tokenPair in a predicate - // but you can do it nevertheless - .when().tokenizePair("<hello>", "</hello>").to("mock:result") - .end(); + // START SNIPPET: e1 + from("file:target/pair") + // split the order child tags, and inherit namespaces from the orders root tag + .split().tokenizeXML("order", "orders") + .to("mock:split"); + // END SNIPPET: e1 } }; } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenizerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenizerTest.java?rev=1197168&r1=1197167&r2=1197168&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenizerTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/TokenizerTest.java Thu Nov 3 14:53:02 2011 @@ -99,8 +99,8 @@ public class TokenizerTest extends Excha assertEquals(false, lan.isSingleton()); } - public void testTokenizePair() throws Exception { - Expression exp = TokenizeLanguage.tokenizePair("<person>", "</person>"); + public void testTokenizeXMLPair() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); exchange.getIn().setBody("<persons><person>James</person><person>Claus</person><person>Jonathan</person><person>Hadrian</person></persons>"); @@ -113,8 +113,22 @@ public class TokenizerTest extends Excha assertEquals("<person>Hadrian</person>", names.get(3)); } - public void testTokenizePairWithNoise() throws Exception { - Expression exp = TokenizeLanguage.tokenizePair("<person>", "</person>"); + public void testTokenizeXMLPairNoXMLTag() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("person", null); + + exchange.getIn().setBody("<persons><person>James</person><person>Claus</person><person>Jonathan</person><person>Hadrian</person></persons>"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person>James</person>", names.get(0)); + assertEquals("<person>Claus</person>", names.get(1)); + assertEquals("<person>Jonathan</person>", names.get(2)); + assertEquals("<person>Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithNoise() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); exchange.getIn().setBody("<?xml version=\"1.0\"?><!-- bla bla --><persons>\n<person>James</person>\n<person>Claus</person>\n" + "<!-- more bla bla --><person>Jonathan</person>\n<person>Hadrian</person>\n</persons> "); @@ -128,8 +142,8 @@ public class TokenizerTest extends Excha assertEquals("<person>Hadrian</person>", names.get(3)); } - public void testTokenizePairEmpty() throws Exception { - Expression exp = TokenizeLanguage.tokenizePair("<person>", "</person>"); + public void testTokenizeXMLPairEmpty() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); exchange.getIn().setBody("<?xml version=\"1.0\"?><!-- bla bla --><persons></persons> "); @@ -137,8 +151,8 @@ public class TokenizerTest extends Excha assertEquals(0, names.size()); } - public void testTokenizePairNoData() throws Exception { - Expression exp = TokenizeLanguage.tokenizePair("<person>", "</person>"); + public void testTokenizeXMLPairNoData() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); exchange.getIn().setBody(""); @@ -146,8 +160,8 @@ public class TokenizerTest extends Excha assertEquals(0, names.size()); } - public void testTokenizePairNullData() throws Exception { - Expression exp = TokenizeLanguage.tokenizePair("<person>", "</person>"); + public void testTokenizeXMLPairNullData() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); exchange.getIn().setBody(null); @@ -155,4 +169,139 @@ public class TokenizerTest extends Excha assertNull(names); } + public void testTokenizeXMLPairWithDefaultNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", "<persons>"); + + exchange.getIn().setBody("<?xml version=\"1.0\"?><persons xmlns=\"http:acme.com/persons\">\n<person>James</person>\n<person>Claus</person>\n" + + "<person>Jonathan</person>\n<person>Hadrian</person>\n</persons>\n"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person xmlns=\"http:acme.com/persons\">James</person>", names.get(0)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Claus</person>", names.get(1)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Jonathan</person>", names.get(2)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithDefaultNamespaceNotInherit() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); + + exchange.getIn().setBody("<?xml version=\"1.0\"?><persons xmlns=\"http:acme.com/persons\">\n<person>James</person>\n<person>Claus</person>\n" + + "<person>Jonathan</person>\n<person>Hadrian</person>\n</persons>\n"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person>James</person>", names.get(0)); + assertEquals("<person>Claus</person>", names.get(1)); + assertEquals("<person>Jonathan</person>", names.get(2)); + assertEquals("<person>Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithDefaultAndFooNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", "<persons>"); + + exchange.getIn().setBody("<?xml version=\"1.0\"?><persons xmlns=\"http:acme.com/persons\" xmlns:foo=\"http:foo.com\">\n<person>James</person>\n<person>Claus</person>\n" + + "<person>Jonathan</person>\n<person>Hadrian</person>\n</persons>\n"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person xmlns=\"http:acme.com/persons\" xmlns:foo=\"http:foo.com\">James</person>", names.get(0)); + assertEquals("<person xmlns=\"http:acme.com/persons\" xmlns:foo=\"http:foo.com\">Claus</person>", names.get(1)); + assertEquals("<person xmlns=\"http:acme.com/persons\" xmlns:foo=\"http:foo.com\">Jonathan</person>", names.get(2)); + assertEquals("<person xmlns=\"http:acme.com/persons\" xmlns:foo=\"http:foo.com\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithLocalNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); + + exchange.getIn().setBody("<?xml version=\"1.0\"?><persons>\n<person xmlns=\"http:acme.com/persons\">James</person>\n<person xmlns=\"http:acme.com/persons\">Claus</person>\n" + + "<person xmlns=\"http:acme.com/persons\">Jonathan</person>\n<person xmlns=\"http:acme.com/persons\">Hadrian</person>\n</persons>\n"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person xmlns=\"http:acme.com/persons\">James</person>", names.get(0)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Claus</person>", names.get(1)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Jonathan</person>", names.get(2)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithLocalAndInheritedNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", "<persons>"); + + exchange.getIn().setBody("<?xml version=\"1.0\"?><persons xmlns=\"http:acme.com/persons\">\n<person xmlns:foo=\"http:foo.com\">James</person>\n<person>Claus</person>\n" + + "<person>Jonathan</person>\n<person xmlns:bar=\"http:bar.com\">Hadrian</person>\n</persons>\n"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person xmlns:foo=\"http:foo.com\" xmlns=\"http:acme.com/persons\">James</person>", names.get(0)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Claus</person>", names.get(1)); + assertEquals("<person xmlns=\"http:acme.com/persons\">Jonathan</person>", names.get(2)); + assertEquals("<person xmlns:bar=\"http:bar.com\" xmlns=\"http:acme.com/persons\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithLocalAndNotInheritedNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); + + exchange.getIn().setBody("<?xml version=\"1.0\"?><persons xmlns=\"http:acme.com/persons\">\n<person xmlns:foo=\"http:foo.com\">James</person>\n" + + "<person>Claus</person>\n<person>Jonathan</person>\n<person xmlns:bar=\"http:bar.com\">Hadrian</person>\n</persons>\n"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person xmlns:foo=\"http:foo.com\">James</person>", names.get(0)); + assertEquals("<person>Claus</person>", names.get(1)); + assertEquals("<person>Jonathan</person>", names.get(2)); + assertEquals("<person xmlns:bar=\"http:bar.com\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithAttributes() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", null); + + exchange.getIn().setBody("<persons><person id=\"1\">James</person><person id=\"2\">Claus</person><person id=\"3\">Jonathan</person>" + + "<person id=\"4\">Hadrian</person></persons>"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person id=\"1\">James</person>", names.get(0)); + assertEquals("<person id=\"2\">Claus</person>", names.get(1)); + assertEquals("<person id=\"3\">Jonathan</person>", names.get(2)); + assertEquals("<person id=\"4\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithAttributesInheritNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", "<persons>"); + + exchange.getIn().setBody("<persons xmlns=\"http:acme.com/persons\"><person id=\"1\">James</person><person id=\"2\">Claus</person>" + + "<person id=\"3\">Jonathan</person><person id=\"4\">Hadrian</person></persons>"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person id=\"1\" xmlns=\"http:acme.com/persons\">James</person>", names.get(0)); + assertEquals("<person id=\"2\" xmlns=\"http:acme.com/persons\">Claus</person>", names.get(1)); + assertEquals("<person id=\"3\" xmlns=\"http:acme.com/persons\">Jonathan</person>", names.get(2)); + assertEquals("<person id=\"4\" xmlns=\"http:acme.com/persons\">Hadrian</person>", names.get(3)); + } + + public void testTokenizeXMLPairWithAttributes2InheritNamespace() throws Exception { + Expression exp = TokenizeLanguage.tokenizeXML("<person>", "<persons>"); + + exchange.getIn().setBody("<persons riders=\"true\" xmlns=\"http:acme.com/persons\"><person id=\"1\">James</person><person id=\"2\">Claus</person>" + + "<person id=\"3\">Jonathan</person><person id=\"4\">Hadrian</person></persons>"); + + List names = exp.evaluate(exchange, List.class); + assertEquals(4, names.size()); + + assertEquals("<person id=\"1\" xmlns=\"http:acme.com/persons\">James</person>", names.get(0)); + assertEquals("<person id=\"2\" xmlns=\"http:acme.com/persons\">Claus</person>", names.get(1)); + assertEquals("<person id=\"3\" xmlns=\"http:acme.com/persons\">Jonathan</person>", names.get(2)); + assertEquals("<person id=\"4\" xmlns=\"http:acme.com/persons\">Hadrian</person>", names.get(3)); + } + } \ No newline at end of file Added: camel/trunk/components/camel-spring/src/test/java/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.java?rev=1197168&view=auto ============================================================================== --- camel/trunk/components/camel-spring/src/test/java/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.java (added) +++ camel/trunk/components/camel-spring/src/test/java/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.java Thu Nov 3 14:53:02 2011 @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.language; + +import org.apache.camel.CamelContext; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * + */ +public class SpringTokenXMLPairNamespaceSplitTest extends TokenXMLPairNamespaceSplitTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.xml"); + } + +} Copied: camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.xml (from r1197028, camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/aopbefore.xml) URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.xml?p2=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.xml&p1=camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/aopbefore.xml&r1=1197028&r2=1197168&rev=1197168&view=diff ============================================================================== --- camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/processor/aopbefore.xml (original) +++ camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/language/SpringTokenXMLPairNamespaceSplitTest.xml Thu Nov 3 14:53:02 2011 @@ -22,16 +22,19 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> - <!-- START SNIPPET: e1 --> - <camelContext xmlns="http://camel.apache.org/schema/spring"> - <route> - <from uri="direct:start"/> - <aop beforeUri="mock:before"> - <transform><constant>Bye World</constant></transform> - <to uri="mock:result"/> - </aop> - </route> - </camelContext> - <!-- END SNIPPET: e1 --> + <!-- START SNIPPET: e1 --> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="file:target/pair"/> + <split> + <!-- split the file using XML tokenizer, where we grab the order tag, + and inherit the namespaces from the parent/root orders tag + the xml attribute must be set to true, to enable XML mode --> + <tokenize token="order" inheritNamespaceTagName="orders" xml="true"/> + <to uri="mock:split"/> + </split> + </route> + </camelContext> + <!-- END SNIPPET: e1 --> </beans>