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.component.jpa;
018    
019    import java.util.Arrays;
020    import java.util.Collection;
021    import java.util.Map;
022    import java.util.Set;
023    
024    import javax.persistence.EntityManager;
025    import javax.persistence.Query;
026    
027    /**
028     * A builder of query expressions
029     * 
030     * @version $Revision: 630591 $
031     */
032    public abstract class QueryBuilder implements QueryFactory {
033        ParameterBuilder parameterBuilder;
034    
035        /**
036         * Creates a query builder using the JPA query syntax
037         * 
038         * @param query JPA query language to create
039         * @return a query builder
040         */
041        public static QueryBuilder query(final String query) {
042            return new QueryBuilder() {
043                protected Query makeQueryObject(EntityManager entityManager) {
044                    return entityManager.createQuery(query);
045                }
046    
047                @Override
048                public String toString() {
049                    return "Query: " + query + " params: " + getParameterDescription();
050                }
051            };
052        }
053    
054        /**
055         * Creates a named query
056         */
057        public static QueryBuilder namedQuery(final String namedQuery) {
058            return new QueryBuilder() {
059                protected Query makeQueryObject(EntityManager entityManager) {
060                    return entityManager.createNamedQuery(namedQuery);
061                }
062    
063                @Override
064                public String toString() {
065                    return "Named: " + namedQuery + getParameterDescription();
066                }
067            };
068        }
069    
070        /**
071         * Creates a native SQL query
072         */
073        public static QueryBuilder nativeQuery(final String nativeQuery) {
074            return new QueryBuilder() {
075                protected Query makeQueryObject(EntityManager entityManager) {
076                    return entityManager.createNativeQuery(nativeQuery);
077                }
078    
079                @Override
080                public String toString() {
081                    return "NativeQuery: " + nativeQuery + getParameterDescription();
082                }
083            };
084        }
085    
086        /**
087         * Specifies the parameters to the query
088         * 
089         * @param parameters the parameters to be configured on the query
090         * @return this query builder
091         */
092        public QueryBuilder parameters(Object... parameters) {
093            return parameters(Arrays.asList(parameters));
094        }
095    
096        /**
097         * Specifies the parameters to the query as an ordered collection of
098         * parameters
099         * 
100         * @param parameters the parameters to be configured on the query
101         * @return this query builder
102         */
103        public QueryBuilder parameters(final Collection parameters) {
104            checkNoParametersConfigured();
105            parameterBuilder = new ParameterBuilder() {
106                public void populateQuery(EntityManager entityManager, Query query) {
107                    int counter = 0;
108                    for (Object parameter : parameters) {
109                        query.setParameter(counter++, parameter);
110                    }
111                }
112    
113                @Override
114                public String toString() {
115                    return "Parameters: " + parameters;
116                }
117            };
118            return this;
119        }
120    
121        /**
122         * Specifies the parameters to the query as a Map of key/value pairs
123         * 
124         * @param parameterMap the parameters to be configured on the query
125         * @return this query builder
126         */
127        public QueryBuilder parameters(final Map<String, Object> parameterMap) {
128            checkNoParametersConfigured();
129            parameterBuilder = new ParameterBuilder() {
130                public void populateQuery(EntityManager entityManager, Query query) {
131                    Set<Map.Entry<String, Object>> entries = parameterMap.entrySet();
132                    for (Map.Entry<String, Object> entry : entries) {
133                        query.setParameter(entry.getKey(), entry.getValue());
134                    }
135                }
136    
137                @Override
138                public String toString() {
139                    return "Parameters: " + parameterMap;
140                }
141            };
142            return this;
143        }
144    
145        protected void checkNoParametersConfigured() {
146            if (parameterBuilder != null) {
147                throw new IllegalArgumentException("Cannot add parameters to a QueryBuilder which already has parameters configured");
148            }
149        }
150    
151        public Query createQuery(EntityManager entityManager) {
152            Query query = makeQueryObject(entityManager);
153            populateQuery(entityManager, query);
154            return query;
155        }
156    
157        protected String getParameterDescription() {
158            if (parameterBuilder == null) {
159                return "";
160            } else {
161                return " " + parameterBuilder.toString();
162            }
163        }
164    
165        protected void populateQuery(EntityManager entityManager, Query query) {
166            if (parameterBuilder != null) {
167                parameterBuilder.populateQuery(entityManager, query);
168            }
169        }
170    
171        protected abstract Query makeQueryObject(EntityManager entityManager);
172    
173        /**
174         * A plugin strategy to populate the query with parameters
175         */
176        protected abstract static class ParameterBuilder {
177            public abstract void populateQuery(EntityManager entityManager, Query query);
178        }
179    }