001    /**
002     *
003     * Licensed to the Apache Software Foundation (ASF) under one or more
004     * contributor license agreements.  See the NOTICE file distributed with
005     * this work for additional information regarding copyright ownership.
006     * The ASF licenses this file to You under the Apache License, Version 2.0
007     * (the "License"); you may not use this file except in compliance with
008     * the License.  You may obtain a copy of the License at
009     *
010     * http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.camel.component.jpa;
019    
020    import javax.persistence.EntityManager;
021    import javax.persistence.Query;
022    import java.util.Arrays;
023    import java.util.Collection;
024    import java.util.Map;
025    import java.util.Set;
026    
027    /**
028     * A builder of query expressions
029     *
030     * @version $Revision: 525537 $
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 parameters
098         *
099         * @param parameters the parameters to be configured on the query
100         * @return this query builder
101         */
102        public QueryBuilder parameters(final Collection parameters) {
103            checkNoParametersConfigured();
104            parameterBuilder = new ParameterBuilder() {
105                public void populateQuery(EntityManager entityManager, Query query) {
106                    int counter = 0;
107                    for (Object parameter : parameters) {
108                        query.setParameter(counter++, parameter);
109                    }
110                }
111    
112                @Override
113                public String toString() {
114                    return "Parameters: " + parameters;
115                }
116            };
117            return this;
118        }
119    
120        /**
121         * Specifies the parameters to the query as a Map of key/value pairs
122         *
123         * @param parameterMap the parameters to be configured on the query
124         * @return this query builder
125         */
126        public QueryBuilder parameters(final Map<String, Object> parameterMap) {
127            checkNoParametersConfigured();
128            parameterBuilder = new ParameterBuilder() {
129                public void populateQuery(EntityManager entityManager, Query query) {
130                    Set<Map.Entry<String, Object>> entries = parameterMap.entrySet();
131                    for (Map.Entry<String, Object> entry : entries) {
132                        query.setParameter(entry.getKey(), entry.getValue());
133                    }
134                }
135    
136                @Override
137                public String toString() {
138                    return "Parameters: " + parameterMap;
139                }
140            };
141            return this;
142        }
143    
144        protected void checkNoParametersConfigured() {
145            if (parameterBuilder != null) {
146                throw new IllegalArgumentException("Cannot add parameters to a QueryBuilder which already has parameters configured");
147            }
148        }
149    
150        public Query createQuery(EntityManager entityManager) {
151            Query query = makeQueryObject(entityManager);
152            populateQuery(entityManager, query);
153            return query;
154        }
155    
156        protected String getParameterDescription() {
157            if (parameterBuilder == null) {
158                return "";
159            }
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    }