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.language.simple.ast; 018 019 import org.apache.camel.Exchange; 020 import org.apache.camel.Expression; 021 import org.apache.camel.language.simple.types.SimpleIllegalSyntaxException; 022 import org.apache.camel.language.simple.types.SimpleParserException; 023 import org.apache.camel.language.simple.types.SimpleToken; 024 import org.apache.camel.util.StringHelper; 025 026 /** 027 * Starts a function 028 */ 029 public class SimpleFunctionStart extends BaseSimpleNode implements BlockStart { 030 031 private CompositeNodes block; 032 033 public SimpleFunctionStart(SimpleToken token) { 034 super(token); 035 this.block = new CompositeNodes(token); 036 } 037 038 @Override 039 public String toString() { 040 // output a nice toString so it makes debugging easier as we can see the entire block 041 return "${" + block + "}"; 042 } 043 044 @Override 045 public Expression createExpression(String expression) { 046 // a function can either be a simple literal function, or contain nested functions 047 if (block.getChildren().size() == 1 && block.getChildren().get(0) instanceof LiteralNode) { 048 return doCreateLiteralExpression(expression); 049 } else { 050 return doCreateCompositeExpression(expression); 051 } 052 } 053 054 private Expression doCreateLiteralExpression(final String expression) { 055 SimpleFunctionExpression function = new SimpleFunctionExpression(this.getToken()); 056 LiteralNode literal = (LiteralNode) block.getChildren().get(0); 057 function.addText(literal.getText()); 058 return function.createExpression(expression); 059 } 060 061 private Expression doCreateCompositeExpression(final String expression) { 062 final SimpleToken token = getToken(); 063 return new Expression() { 064 @Override 065 public <T> T evaluate(Exchange exchange, Class<T> type) { 066 StringBuilder sb = new StringBuilder(); 067 boolean quoteEmbeddedFunctions = false; 068 069 // we need to concat the block so we have the expression 070 for (SimpleNode child : block.getChildren()) { 071 if (child instanceof LiteralNode) { 072 String text = ((LiteralNode) child).getText(); 073 sb.append(text); 074 quoteEmbeddedFunctions |= ((LiteralNode) child).quoteEmbeddedNodes(); 075 // if its a function or quoted literal, then embed that as text 076 } else if (child instanceof SimpleFunctionStart || child instanceof SingleQuoteStart || child instanceof DoubleQuoteStart) { 077 try { 078 // pass in null when we evaluate the nested expressions 079 Expression nested = child.createExpression(null); 080 String text = nested.evaluate(exchange, String.class); 081 if (text != null) { 082 if (quoteEmbeddedFunctions && !StringHelper.isQuoted(text)) { 083 sb.append("'").append(text).append("'"); 084 } else { 085 sb.append(text); 086 } 087 } 088 } catch (SimpleParserException e) { 089 // must rethrow parser exception as illegal syntax with details about the location 090 throw new SimpleIllegalSyntaxException(expression, e.getIndex(), e.getMessage(), e); 091 } 092 } 093 } 094 095 // we have now concat the block as a String which contains the function expression 096 // which we then need to evaluate as a function 097 String exp = sb.toString(); 098 SimpleFunctionExpression function = new SimpleFunctionExpression(token); 099 function.addText(exp); 100 try { 101 return function.createExpression(exp).evaluate(exchange, type); 102 } catch (SimpleParserException e) { 103 // must rethrow parser exception as illegal syntax with details about the location 104 throw new SimpleIllegalSyntaxException(expression, e.getIndex(), e.getMessage(), e); 105 } 106 } 107 108 @Override 109 public String toString() { 110 return expression; 111 } 112 }; 113 } 114 115 @Override 116 public boolean acceptAndAddNode(SimpleNode node) { 117 // only accept literals, quotes or embedded functions 118 if (node instanceof LiteralNode || node instanceof SimpleFunctionStart 119 || node instanceof SingleQuoteStart || node instanceof DoubleQuoteStart) { 120 block.addChild(node); 121 return true; 122 } else { 123 return false; 124 } 125 } 126 127 }