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.builder.sql;
018
019 import org.apache.camel.Exchange;
020 import org.apache.camel.Expression;
021 import org.apache.camel.Message;
022 import org.apache.camel.Predicate;
023 import org.apache.camel.RuntimeExpressionException;
024 import org.apache.camel.util.ObjectHelper;
025 import org.josql.Query;
026 import org.josql.QueryExecutionException;
027 import org.josql.QueryParseException;
028
029 import java.util.Collections;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.Set;
033 import java.util.HashMap;
034
035 /**
036 * A builder of SQL {@link org.apache.camel.Expression} and {@link org.apache.camel.Predicate} implementations
037 *
038 * @version $Revision: $
039 */
040 public class SqlBuilder<E extends Exchange> implements Expression<E>, Predicate<E> {
041
042 private Query query;
043 private Map<String,Object> variables = new HashMap<String, Object>();
044
045 public SqlBuilder(Query query) {
046 this.query = query;
047 }
048
049 public Object evaluate(E exchange) {
050 return evaluateQuery(exchange);
051 }
052
053 public boolean matches(E exchange) {
054 List list = evaluateQuery(exchange);
055 return matches(exchange, list);
056 }
057
058 public void assertMatches(String text, E exchange) throws AssertionError {
059 List list = evaluateQuery(exchange);
060 if (!matches(exchange, list)) {
061 throw new AssertionError(this + " failed on " + exchange + " as found " + list);
062 }
063 }
064
065 // Builder API
066 //-----------------------------------------------------------------------
067
068 /**
069 * Creates a new builder for the given SQL query string
070 *
071 * @param sql the SQL query to perform
072 * @return a new builder
073 * @throws QueryParseException if there is an issue with the SQL
074 */
075 public static <E extends Exchange> SqlBuilder<E> sql(String sql) throws QueryParseException {
076 Query q = new Query();
077 q.parse(sql);
078 return new SqlBuilder(q);
079 }
080
081 /**
082 * Adds the variable value to be used by the SQL query
083 */
084 public SqlBuilder<E> variable(String name, Object value) {
085 getVariables().put(name, value);
086 return this;
087 }
088
089
090 // Properties
091 //-----------------------------------------------------------------------
092 public Map<String, Object> getVariables() {
093 return variables;
094 }
095
096 public void setVariables(Map<String, Object> properties) {
097 this.variables = properties;
098 }
099
100
101 // Implementation methods
102 //-----------------------------------------------------------------------
103 protected boolean matches(E exchange, List list) {
104 return ObjectHelper.matches(list);
105 }
106
107 protected List evaluateQuery(E exchange) {
108 configureQuery(exchange);
109 Message in = exchange.getIn();
110 List list = in.getBody(List.class);
111 if (list == null) {
112 list = Collections.singletonList(in.getBody());
113 }
114 try {
115 return query.execute(list).getResults();
116 }
117 catch (QueryExecutionException e) {
118 throw new RuntimeExpressionException(e);
119 }
120 }
121
122 protected void configureQuery(E exchange) {
123 // lets pass in the headers as variables that the SQL can use
124 addVariables(exchange.getProperties());
125 addVariables(exchange.getIn().getHeaders());
126 addVariables(getVariables());
127
128 query.setVariable("exchange", exchange);
129 query.setVariable("in", exchange.getIn());
130 query.setVariable("out", exchange.getOut());
131 }
132
133 protected void addVariables(Map <String, Object> map) {
134 Set<Map.Entry<String, Object>> propertyEntries = map.entrySet();
135 for (Map.Entry<String, Object> entry : propertyEntries) {
136 query.setVariable(entry.getKey(), entry.getValue());
137 }
138 }
139 }