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.language.tokenizer;
018
019import org.apache.camel.Expression;
020import org.apache.camel.IsSingleton;
021import org.apache.camel.Predicate;
022import org.apache.camel.builder.ExpressionBuilder;
023import org.apache.camel.spi.Language;
024import org.apache.camel.util.ExpressionToPredicateAdapter;
025import org.apache.camel.util.ObjectHelper;
026
027/**
028 * A language for tokenizer expressions.
029 * <p/>
030 * This tokenizer language can operator in the following modes:
031 * <ul>
032 *     <li>default - using a single tokenizer</li>
033 *     <li>pair - using both start and end tokens</li>
034 *     <li>xml - using both start and end tokens in XML mode, support inheriting namespaces</li>
035 * </ul>
036 * The default mode supports the <tt>headerName</tt> and <tt>regex</tt> options.
037 * Where as the pair mode only supports <tt>token</tt> and <tt>endToken</tt>.
038 * And the <tt>xml</tt> mode supports the <tt>inheritNamespaceTagName</tt> option.
039 */
040public class TokenizeLanguage implements Language, IsSingleton {
041
042    private String token;
043    private String endToken;
044    private String inheritNamespaceTagName;
045    private String headerName;
046    private boolean regex;
047    private boolean xml;
048    private boolean includeTokens;
049    private String group;
050    private boolean skipFirst;
051
052    public static Expression tokenize(String token) {
053        return tokenize(token, false);
054    }
055
056    public static Expression tokenize(String token, boolean regex) {
057        TokenizeLanguage language = new TokenizeLanguage();
058        language.setToken(token);
059        language.setRegex(regex);
060        return language.createExpression(null);
061    }
062
063    public static Expression tokenize(String headerName, String token) {
064        return tokenize(headerName, token, false);
065    }
066
067    public static Expression tokenize(String headerName, String token, boolean regex) {
068        TokenizeLanguage language = new TokenizeLanguage();
069        language.setHeaderName(headerName);
070        language.setToken(token);
071        language.setRegex(regex);
072        return language.createExpression(null);
073    }
074
075    public static Expression tokenizePair(String startToken, String endToken, boolean includeTokens) {
076        TokenizeLanguage language = new TokenizeLanguage();
077        language.setToken(startToken);
078        language.setEndToken(endToken);
079        language.setIncludeTokens(includeTokens);
080        return language.createExpression(null);
081    }
082
083    public static Expression tokenizeXML(String tagName, String inheritNamespaceTagName) {
084        TokenizeLanguage language = new TokenizeLanguage();
085        language.setToken(tagName);
086        language.setInheritNamespaceTagName(inheritNamespaceTagName);
087        language.setXml(true);
088        return language.createExpression(null);
089    }
090
091    public Predicate createPredicate(String expression) {
092        return ExpressionToPredicateAdapter.toPredicate(createExpression(expression));
093    }
094
095    /**
096     * Creates a tokenize expression.
097     */
098    public Expression createExpression() {
099        ObjectHelper.notNull(token, "token");
100
101        // validate some invalid combinations
102        if (endToken != null && inheritNamespaceTagName != null) {
103            throw new IllegalArgumentException("Cannot have both xml and pair tokenizer enabled.");
104        }
105        if (isXml() && (endToken != null || includeTokens)) {
106            throw new IllegalArgumentException("Cannot have both xml and pair tokenizer enabled.");
107        }
108
109        Expression answer = null;
110        if (isXml()) {
111            answer = ExpressionBuilder.tokenizeXMLExpression(token, inheritNamespaceTagName);
112        } else if (endToken != null) {
113            answer = ExpressionBuilder.tokenizePairExpression(token, endToken, includeTokens);
114        }
115
116        if (answer == null) {
117            // use the regular tokenizer
118            Expression exp = headerName == null ? ExpressionBuilder.bodyExpression() : ExpressionBuilder.headerExpression(headerName);
119            if (regex) {
120                answer = ExpressionBuilder.regexTokenizeExpression(exp, token);
121            } else {
122                answer = ExpressionBuilder.tokenizeExpression(exp, token);
123            }
124            if (group == null && skipFirst) {
125                // wrap in skip first (if group then it has its own skip first logic)
126                answer = ExpressionBuilder.skipFirstExpression(answer);
127            }
128        }
129
130        // if group then wrap answer in group expression
131        if (group != null) {
132            if (isXml()) {
133                answer = ExpressionBuilder.groupXmlIteratorExpression(answer, group);
134            } else {
135                answer = ExpressionBuilder.groupIteratorExpression(answer, token, group, skipFirst);
136            }
137        }
138
139        return answer;
140    }
141
142    public Expression createExpression(String expression) {
143        if (ObjectHelper.isNotEmpty(expression)) {
144            this.token = expression;
145        }
146        return createExpression();
147    }
148
149    public String getToken() {
150        return token;
151    }
152
153    public void setToken(String token) {
154        this.token = token;
155    }
156
157    public String getEndToken() {
158        return endToken;
159    }
160
161    public void setEndToken(String endToken) {
162        this.endToken = endToken;
163    }
164
165    public String getHeaderName() {
166        return headerName;
167    }
168
169    public void setHeaderName(String headerName) {
170        this.headerName = headerName;
171    }
172
173    public boolean isRegex() {
174        return regex;
175    }
176
177    public void setRegex(boolean regex) {
178        this.regex = regex;
179    }
180
181    public String getInheritNamespaceTagName() {
182        return inheritNamespaceTagName;
183    }
184
185    public void setInheritNamespaceTagName(String inheritNamespaceTagName) {
186        this.inheritNamespaceTagName = inheritNamespaceTagName;
187    }
188
189    public boolean isXml() {
190        return xml;
191    }
192
193    public void setXml(boolean xml) {
194        this.xml = xml;
195    }
196
197    public boolean isIncludeTokens() {
198        return includeTokens;
199    }
200
201    public void setIncludeTokens(boolean includeTokens) {
202        this.includeTokens = includeTokens;
203    }
204
205    public String getGroup() {
206        return group;
207    }
208
209    public void setGroup(String group) {
210        this.group = group;
211    }
212
213    public boolean isSkipFirst() {
214        return skipFirst;
215    }
216
217    public void setSkipFirst(boolean skipFirst) {
218        this.skipFirst = skipFirst;
219    }
220
221    public boolean isSingleton() {
222        return false;
223    }
224}