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 
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 + 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         * Creates a native SQL query with a provided resultClass
088         */
089        public static QueryBuilder nativeQuery(final String nativeQuery, final Class resultClass) {
090            return new QueryBuilder() {
091                protected Query makeQueryObject(EntityManager entityManager) {
092                    return entityManager.createNativeQuery(nativeQuery, resultClass);
093                }
094    
095                @Override
096                public String toString() {
097                    return "NativeQuery: " + nativeQuery + " resultClass:" + resultClass + getParameterDescription();
098                }
099            };
100        }
101    
102        /**
103         * Specifies the parameters to the query
104         * 
105         * @param parameters the parameters to be configured on the query
106         * @return this query builder
107         */
108        public QueryBuilder parameters(Object... parameters) {
109            return parameters(Arrays.asList(parameters));
110        }
111    
112        /**
113         * Specifies the parameters to the query as an ordered collection of
114         * parameters
115         * 
116         * @param parameters the parameters to be configured on the query
117         * @return this query builder
118         */
119        public QueryBuilder parameters(final Collection parameters) {
120            checkNoParametersConfigured();
121            parameterBuilder = new ParameterBuilder() {
122                public void populateQuery(EntityManager entityManager, Query query) {
123                    int counter = 0;
124                    for (Object parameter : parameters) {
125                        query.setParameter(counter++, parameter);
126                    }
127                }
128    
129                @Override
130                public String toString() {
131                    return "Parameters: " + parameters;
132                }
133            };
134            return this;
135        }
136    
137        /**
138         * Specifies the parameters to the query as a Map of key/value pairs
139         * 
140         * @param parameterMap the parameters to be configured on the query
141         * @return this query builder
142         */
143        public QueryBuilder parameters(final Map<String, Object> parameterMap) {
144            checkNoParametersConfigured();
145            parameterBuilder = new ParameterBuilder() {
146                public void populateQuery(EntityManager entityManager, Query query) {
147                    Set<Map.Entry<String, Object>> entries = parameterMap.entrySet();
148                    for (Map.Entry<String, Object> entry : entries) {
149                        query.setParameter(entry.getKey(), entry.getValue());
150                    }
151                }
152    
153                @Override
154                public String toString() {
155                    return "Parameters: " + parameterMap;
156                }
157            };
158            return this;
159        }
160    
161        protected void checkNoParametersConfigured() {
162            if (parameterBuilder != null) {
163                throw new IllegalArgumentException("Cannot add parameters to a QueryBuilder which already has parameters configured");
164            }
165        }
166    
167        public Query createQuery(EntityManager entityManager) {
168            Query query = makeQueryObject(entityManager);
169            populateQuery(entityManager, query);
170            return query;
171        }
172    
173        protected String getParameterDescription() {
174            if (parameterBuilder == null) {
175                return "";
176            } else {
177                return " " + parameterBuilder.toString();
178            }
179        }
180    
181        protected void populateQuery(EntityManager entityManager, Query query) {
182            if (parameterBuilder != null) {
183                parameterBuilder.populateQuery(entityManager, query);
184            }
185        }
186    
187        protected abstract Query makeQueryObject(EntityManager entityManager);
188    
189        /**
190         * A plugin strategy to populate the query with parameters
191         */
192        protected abstract static class ParameterBuilder {
193            public abstract void populateQuery(EntityManager entityManager, Query query);
194        }
195    }