/* * Copyright 2004-2009 the original author or authors. * * 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 org.compass.core; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.compass.core.config.CompassSettings; import org.compass.core.impl.ExistingCompassSession; import org.compass.core.spi.InternalCompassSession; /** * Helper class that simplifies the Compass access code using the template * design pattern. * <p> * The central method is "execute", supporting Compass code implementing the * CompassCallback interface. It provides Compass Session handling such that * neither the CompassCallback implementation nor the calling code needs to * explicitly care about retrieving/closing Compass Sessions, handling Session * lifecycle exceptions, or managing transactions. The template code is similar * to * * <pre> * CompassSession session = compass.openSession(); * CompassTransaction tx = null; * try { * tx = session.beginTransaction(); * Object result = compassCallback.doInCompass(session); * tx.commit(); * return result; * } catch (RuntimeException e) { * if (tx != null) { * tx.rollback(); * } * throw e; * } finally { * session.close(); * } * </pre> * * <p> * The template must have a Compass reference set, either using the tempalte * constructor or using the set method. * <p> * CompassTemplate also provides the same operations available when working with * CompassSession, just that they are executed using the "execute" template * method, which means that they enjoy it's session lifecycle and transaction * support. * * @author kimchy */ public class CompassTemplate implements CompassOperations { private static Log log = LogFactory.getLog(CompassTemplate.class); private Compass compass; private CompassSettings globalSessionSettings = new CompassSettings(); private boolean readOnly; /** * Creates a new CompassTemplate instance (remember to set Compass using the * setCompass method). */ public CompassTemplate() { } /** * Creates a new CompassTemplate instance, already initialized with a * Compass instance. */ public CompassTemplate(Compass compass) { this.compass = compass; } /** * Sets the compass instance that will be used by the template. */ public void setCompass(Compass compass) { this.compass = compass; } /** * Sets the {@link org.compass.core.CompassSession} to be read only. * * @see CompassSession#setReadOnly() */ public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } /** * Returns the compass instance used by the template. * * @return the compass instance */ public Compass getCompass() { return compass; } /** * Executes the compass callback within a session and a transaction context. * * @param action The action to execute witin a compass transaction * @return An object as the result of the compass action * @throws CompassException */ public <T> T execute(CompassCallback<T> action) throws CompassException { CompassSession session = compass.openSession(); if (readOnly) { session.setReadOnly(); } session.getSettings().addSettings(globalSessionSettings); CompassTransaction tx = null; try { tx = session.beginTransaction(); // we wrap with existing session so if #close is called within the callback, it won't be closed T result = action.doInCompass(new ExistingCompassSession((InternalCompassSession) session)); tx.commit(); return result; } catch (RuntimeException e) { if (tx != null) { try { tx.rollback(); } catch (Exception e1) { log.error("Failed to rollback transaction, ignoring", e1); } } throw e; } catch (Error err) { if (tx != null) { try { tx.rollback(); } catch (Exception e1) { log.error("Failed to rollback transaction, ignoring", e1); } } throw err; } finally { session.close(); } } /** * Executes the compass callback within a session and a <b>local</b> transaction context. * Applies the given transaction isolation level. * * @param action The action to execute witin a compass transaction * @return An object as the result of the compass action * @throws CompassException */ public <T> T executeLocal(CompassCallback<T> action) throws CompassException { CompassSession session = compass.openSession(); session.getSettings().addSettings(globalSessionSettings); CompassTransaction tx = null; try { tx = session.beginLocalTransaction(); // we wrap with existing session so if #close is called within the callback, it won't be closed T result = action.doInCompass(new ExistingCompassSession((InternalCompassSession) session)); tx.commit(); return result; } catch (RuntimeException e) { if (tx != null) { try { tx.rollback(); } catch (Exception e1) { log.error("Failed to rollback transaction, ignoring", e1); } } throw e; } catch (Error err) { if (tx != null) { try { tx.rollback(); } catch (Exception e1) { log.error("Failed to rollback transaction, ignoring", e1); } } throw err; } finally { session.close(); } } /** * A helper execute method for find operations. * * @param action the callback to execute. * @return The hits that match the query * @throws CompassException */ public CompassHitsOperations executeFind(CompassCallback<CompassHitsOperations> action) throws CompassException { return execute(action); } // Compass Operations public CompassSettings getSettings() { throw new CompassException("getSettings should not be used with CompassTemplate. Either use getGlobalSettings or execute"); } public void create(final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.create(obj); return null; } }); } public void create(final String alias, final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.create(alias, obj); return null; } }); } public void delete(final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(obj); return null; } }); } public void delete(final Resource resource) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(resource); return null; } }); } public void delete(final Class clazz, final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(clazz, obj); return null; } }); } public void delete(final String alias, final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(alias, obj); return null; } }); } public void delete(final CompassQuery query) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(query); return null; } }); } public CompassHits find(final String query) throws CompassException { return execute(new CompassCallback<CompassHits>() { public CompassHits doInCompass(CompassSession session) throws CompassException { return session.find(query); } }); } public CompassDetachedHits findWithDetach(final String query) throws CompassException { return execute(new CompassCallback<CompassDetachedHits>() { public CompassDetachedHits doInCompass(CompassSession session) throws CompassException { return session.find(query).detach(); } }); } public CompassDetachedHits findWithDetach(final String query, final int from, final int size) throws CompassException { return execute(new CompassCallback<CompassDetachedHits>() { public CompassDetachedHits doInCompass(CompassSession session) throws CompassException { return session.find(query).detach(from, size); } }); } public <T> T get(final Class<T> clazz, final Object id) throws CompassException { return execute(new CompassCallback<T>() { public T doInCompass(CompassSession session) throws CompassException { return session.get(clazz, id); } }); } public Object get(final String alias, final Object id) throws CompassException { return execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { return session.get(alias, id); } }); } public Resource getResource(final Class clazz, final Object id) throws CompassException { return (Resource) execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { return session.getResource(clazz, id); } }); } public Resource getResource(final String alias, final Object id) throws CompassException { return (Resource) execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { return session.getResource(alias, id); } }); } public <T> T load(Class<T> clazz, Object... ids) throws CompassException { return load(clazz, (Object) ids); } public <T> T load(final Class<T> clazz, final Object id) throws CompassException { return execute(new CompassCallback<T>() { public T doInCompass(CompassSession session) throws CompassException { return session.load(clazz, id); } }); } public Object load(String alias, Object... ids) throws CompassException { return load(alias, (Object) ids); } public Object load(final String alias, final Object id) throws CompassException { return execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { return session.load(alias, id); } }); } public Resource loadResource(final Class clazz, final Object id) throws CompassException { return (Resource) execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { return session.loadResource(clazz, id); } }); } public Resource loadResource(final String alias, final Object id) throws CompassException { return (Resource) execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { return session.loadResource(alias, id); } }); } public void save(final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.save(obj); return null; } }); } public void save(final String alias, final Object obj) throws CompassException { execute(new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.save(alias, obj); return null; } }); } public void evict(final Object obj) { execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { session.evict(obj); } }); } public void evict(final String alias, final Object id) { execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { session.evict(alias, id); } }); } public void evict(final Resource resource) { execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { session.evict(resource); } }); } public void evictAll() { execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { session.evictAll(); } }); } public Resource getResource(Class clazz, Object... ids) throws CompassException { return getResource(clazz, (Object) ids); } public Resource getResource(String alias, Object... ids) throws CompassException { return getResource(alias, (Object) ids); } public Resource loadResource(Class clazz, Object... ids) throws CompassException { return loadResource(clazz, (Object) ids); } public Resource loadResource(String alias, Object... ids) throws CompassException { return loadResource(alias, (Object) ids); } public void delete(String alias, Object... ids) throws CompassException { delete(alias, (Object) ids); } public void delete(Class clazz, Object... ids) throws CompassException { delete(clazz, (Object) ids); } public <T> T get(Class<T> clazz, Object... ids) throws CompassException { return get(clazz, (Object) ids); } public Object get(String alias, Object... ids) throws CompassException { return get(alias, (Object) ids); } }