/* * Copyright (c) 2009-2013 Clark & Parsia, LLC. <http://www.clarkparsia.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.clarkparsia.empire.impl; import com.clarkparsia.empire.ds.DataSource; import com.clarkparsia.empire.QueryFactory; import com.clarkparsia.empire.Empire; import com.clarkparsia.empire.Dialect; import com.google.common.collect.Maps; import javax.persistence.Query; import javax.persistence.NamedQuery; import javax.persistence.QueryHint; import javax.persistence.NamedQueries; import javax.persistence.NamedNativeQuery; import javax.persistence.NamedNativeQueries; import java.util.HashMap; import java.util.Map; import java.util.Collection; import java.util.Arrays; /** * <p>Implements the common operations of a {@link QueryFactory} and defers query language specific operations * to concrete implementations of this class.</p> * * @author Michael Grove * @since 0.1 * @version 0.6.5 */ public class RdfQueryFactory implements QueryFactory { /** * the data source the queries will be executed against */ private DataSource mSource; /** * The query language dialect supported by this factory */ private Dialect mDialect; /** * User-defined NamedQueries. The actual queries are evaluated on-demand, we'll just keep the annotations which * contain the information needed to create them here. */ private Map<String, NamedQueryInfo> mNamedQueries = Maps.newHashMap(); /** * Create a new AbstractQueryFactory * @param theSource the data source the queries will be executed against * @param theDialect the Query dialect supported by this query factory */ public RdfQueryFactory(final DataSource theSource, Dialect theDialect) { mSource = theSource; mDialect = theDialect; Collection<Class<?>> aClasses = Empire.get().getAnnotationProvider().getClassesWithAnnotation(NamedQuery.class); for (Class<?> aClass : aClasses) { addNamedQuery(new NamedQueryInfo(aClass.getAnnotation(NamedQuery.class))); } aClasses = Empire.get().getAnnotationProvider().getClassesWithAnnotation(NamedQueries.class); for (Class<?> aClass : aClasses) { NamedQueries aNamedQueries = aClass.getAnnotation(NamedQueries.class); for (NamedQuery aQuery : aNamedQueries.value()) { addNamedQuery(new NamedQueryInfo(aQuery)); } } aClasses = Empire.get().getAnnotationProvider().getClassesWithAnnotation(NamedNativeQuery.class); for (Class<?> aClass : aClasses) { addNamedQuery(new NamedQueryInfo(aClass.getAnnotation(NamedNativeQuery.class))); } aClasses = Empire.get().getAnnotationProvider().getClassesWithAnnotation(NamedNativeQueries.class); for (Class<?> aClass : aClasses) { NamedNativeQueries aQueries = aClass.getAnnotation(NamedNativeQueries.class); for (NamedNativeQuery aQuery : aQueries.value()) { addNamedQuery(new NamedQueryInfo(aQuery)); } } } /** * Create a new Query against the current data source with the given query string * @param theQuery the query string * @return a new query */ protected RdfQuery newQuery(String theQuery) { return new RdfQuery(mSource, theQuery); } /** * Return the data source the queries will be executed against * @return the data source */ protected DataSource getSource() { return mSource; } /** * Add a named query to this factory * @param theInfo the information about the query */ private void addNamedQuery(NamedQueryInfo theInfo) { mNamedQueries.put(theInfo.getName(), theInfo); } /** * @inheritDoc */ @Override public Dialect getDialect() { return mDialect; } /** * @inheritDoc */ @Override public Query createQuery(final String theQueryString) { return newQuery(theQueryString); } /** * @inheritDoc */ @Override public Query createNamedQuery(final String theName) { if (mNamedQueries.containsKey(theName)) { NamedQueryInfo aNamedQuery = mNamedQueries.get(theName); RdfQuery aQuery = newQuery(aNamedQuery.getQuery()); for (QueryHint aHint : aNamedQuery.getHints()) { aQuery.setHint(aHint.name(), aHint.value()); } aQuery.setSource(getSource()); return aQuery; } else { throw new IllegalArgumentException("Query named '" + theName + "' does not exist."); } } /** * @inheritDoc */ @Override public Query createNativeQuery(final String theQueryString) { return newQuery(theQueryString); } /** * @inheritDoc */ @Override public Query createNativeQuery(final String theQueryString, final Class theResultClass) { RdfQuery aQuery = newQuery(theQueryString); aQuery.setBeanClass(theResultClass); return aQuery; } /** * @inheritDoc */ @Override public Query createNativeQuery(final String theQueryString, final String theResultSetMapping) { throw new UnsupportedOperationException(); } private class NamedQueryInfo { private String mName; private String mQuery; private Class mResultClass; private Collection<QueryHint> mHints; private String mResultMapping; private NamedQueryInfo(final String theName, final String theQuery) { mName = theName; mQuery = theQuery; } private NamedQueryInfo(NamedQuery theQuery) { mName = theQuery.name(); mQuery = theQuery.query(); mHints = Arrays.asList(theQuery.hints()); } private NamedQueryInfo(NamedNativeQuery theQuery) { mName = theQuery.name(); mQuery = theQuery.query(); mResultMapping = theQuery.resultSetMapping(); mResultClass = theQuery.resultClass(); mHints = Arrays.asList(theQuery.hints()); } public String getName() { return mName; } public void setName(final String theName) { mName = theName; } public String getQuery() { return mQuery; } public void setQuery(final String theQuery) { mQuery = theQuery; } public Class getResultClass() { return mResultClass; } public void setResultClass(final Class theResultClass) { mResultClass = theResultClass; } public Collection<QueryHint> getHints() { return mHints; } public void setHints(final Collection<QueryHint> theHints) { mHints = theHints; } public String getResultMapping() { return mResultMapping; } public void setResultMapping(final String theResultMapping) { mResultMapping = theResultMapping; } } }