001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.persistence.impl;
016    
017    import com.liferay.portal.NoSuchModelException;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020    import com.liferay.portal.kernel.dao.orm.Dialect;
021    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
022    import com.liferay.portal.kernel.dao.orm.ORMException;
023    import com.liferay.portal.kernel.dao.orm.OrderFactoryUtil;
024    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
025    import com.liferay.portal.kernel.dao.orm.Session;
026    import com.liferay.portal.kernel.dao.orm.SessionFactory;
027    import com.liferay.portal.kernel.exception.SystemException;
028    import com.liferay.portal.kernel.log.Log;
029    import com.liferay.portal.kernel.log.LogFactoryUtil;
030    import com.liferay.portal.kernel.util.ListUtil;
031    import com.liferay.portal.kernel.util.OrderByComparator;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.model.BaseModel;
034    import com.liferay.portal.model.ModelListener;
035    import com.liferay.portal.service.ServiceContext;
036    import com.liferay.portal.service.ServiceContextThreadLocal;
037    import com.liferay.portal.service.persistence.BasePersistence;
038    
039    import java.io.Serializable;
040    
041    import java.sql.Connection;
042    
043    import java.util.List;
044    
045    import javax.sql.DataSource;
046    
047    /**
048     * The base implementation for all persistence classes. This class should never
049     * need to be used directly.
050     *
051     * <p>
052     * Caching information and settings can be found in
053     * <code>portal.properties</code>
054     * </p>
055     *
056     * @author Brian Wing Shun Chan
057     * @author Shuyang Zhou
058     */
059    public class BasePersistenceImpl<T extends BaseModel<T>>
060            implements BasePersistence<T>, SessionFactory {
061    
062            public static final String COUNT_COLUMN_NAME = "COUNT_VALUE";
063    
064            public void clearCache() {
065            }
066    
067            public void clearCache(T model) {
068            }
069    
070            public void closeSession(Session session) {
071                    _sessionFactory.closeSession(session);
072            }
073    
074            public long countWithDynamicQuery(DynamicQuery dynamicQuery)
075                    throws SystemException {
076    
077                    dynamicQuery.setProjection(ProjectionFactoryUtil.rowCount());
078    
079                    List<Long> results = findWithDynamicQuery(dynamicQuery);
080    
081                    if (results.isEmpty()) {
082                            return 0;
083                    }
084                    else {
085                            return (results.get(0)).longValue();
086                    }
087            }
088    
089            @SuppressWarnings("unused")
090            public T fetchByPrimaryKey(Serializable primaryKey) throws SystemException {
091                    throw new UnsupportedOperationException();
092            }
093    
094            @SuppressWarnings("unused")
095            public T findByPrimaryKey(Serializable primaryKey)
096                    throws NoSuchModelException, SystemException {
097    
098                    throw new UnsupportedOperationException();
099            }
100    
101            @SuppressWarnings("rawtypes")
102            public List findWithDynamicQuery(DynamicQuery dynamicQuery)
103                    throws SystemException {
104    
105                    Session session = null;
106    
107                    try {
108                            session = openSession();
109    
110                            dynamicQuery.compile(session);
111    
112                            return dynamicQuery.list();
113                    }
114                    catch (Exception e) {
115                            throw processException(e);
116                    }
117                    finally {
118                            closeSession(session);
119                    }
120            }
121    
122            @SuppressWarnings("rawtypes")
123            public List findWithDynamicQuery(
124                            DynamicQuery dynamicQuery, int start, int end)
125                    throws SystemException {
126    
127                    Session session = null;
128    
129                    try {
130                            session = openSession();
131    
132                            dynamicQuery.setLimit(start, end);
133    
134                            dynamicQuery.compile(session);
135    
136                            return dynamicQuery.list();
137                    }
138                    catch (Exception e) {
139                            throw processException(e);
140                    }
141                    finally {
142                            closeSession(session);
143                    }
144            }
145    
146            @SuppressWarnings("rawtypes")
147            public List findWithDynamicQuery(
148                            DynamicQuery dynamicQuery, int start, int end,
149                            OrderByComparator orderByComparator)
150                    throws SystemException {
151    
152                    OrderFactoryUtil.addOrderByComparator(dynamicQuery, orderByComparator);
153    
154                    return findWithDynamicQuery(dynamicQuery, start, end);
155            }
156    
157            public DataSource getDataSource() {
158                    return _dataSource;
159            }
160    
161            public DB getDB() {
162                    return _db;
163            }
164    
165            public Dialect getDialect() {
166                    return _dialect;
167            }
168    
169            public ModelListener<T>[] getListeners() {
170                    return listeners;
171            }
172    
173            public Session openNewSession(Connection connection) throws ORMException {
174                    return _sessionFactory.openNewSession(connection);
175            }
176    
177            public Session openSession() throws ORMException {
178                    return _sessionFactory.openSession();
179            }
180    
181            public SystemException processException(Exception e) {
182                    if (!(e instanceof ORMException)) {
183                            _log.error("Caught unexpected exception " + e.getClass().getName());
184                    }
185    
186                    if (_log.isDebugEnabled()) {
187                            _log.debug(e, e);
188                    }
189    
190                    return new SystemException(e);
191            }
192    
193            public void registerListener(ModelListener<T> listener) {
194                    List<ModelListener<T>> listenersList = ListUtil.fromArray(listeners);
195    
196                    listenersList.add(listener);
197    
198                    listeners = listenersList.toArray(
199                            new ModelListener[listenersList.size()]);
200            }
201    
202            @SuppressWarnings("unused")
203            public T remove(Serializable primaryKey)
204                    throws NoSuchModelException, SystemException {
205    
206                    throw new UnsupportedOperationException();
207            }
208    
209            public T remove(T model) throws SystemException {
210                    for (ModelListener<T> listener : listeners) {
211                            listener.onBeforeRemove(model);
212                    }
213    
214                    model = removeImpl(model);
215    
216                    for (ModelListener<T> listener : listeners) {
217                            listener.onAfterRemove(model);
218                    }
219    
220                    return model;
221            }
222    
223            public void setDataSource(DataSource dataSource) {
224                    _dataSource = dataSource;
225            }
226    
227            public void setSessionFactory(SessionFactory sessionFactory) {
228                    _sessionFactory = sessionFactory;
229                    _dialect = _sessionFactory.getDialect();
230                    _db = DBFactoryUtil.getDB(_dialect);
231            }
232    
233            public void unregisterListener(ModelListener<T> listener) {
234                    List<ModelListener<T>> listenersList = ListUtil.fromArray(listeners);
235    
236                    ListUtil.remove(listenersList, listener);
237    
238                    listeners = listenersList.toArray(
239                            new ModelListener[listenersList.size()]);
240            }
241    
242            public T update(T model, boolean merge) throws SystemException {
243                    boolean isNew = model.isNew();
244    
245                    for (ModelListener<T> listener : listeners) {
246                            if (isNew) {
247                                    listener.onBeforeCreate(model);
248                            }
249                            else {
250                                    listener.onBeforeUpdate(model);
251                            }
252                    }
253    
254                    model = updateImpl(model, merge);
255    
256                    for (ModelListener<T> listener : listeners) {
257                            if (isNew) {
258                                    listener.onAfterCreate(model);
259                            }
260                            else {
261                                    listener.onAfterUpdate(model);
262                            }
263                    }
264    
265                    return model;
266            }
267    
268            public T update(T model, boolean merge, ServiceContext serviceContext)
269                    throws SystemException {
270    
271                    try {
272                            ServiceContextThreadLocal.pushServiceContext(serviceContext);
273    
274                            update(model, merge);
275    
276                            return model;
277                    }
278                    finally {
279                            ServiceContextThreadLocal.popServiceContext();
280                    }
281            }
282    
283            protected void appendOrderByComparator(
284                    StringBundler query, String entityAlias,
285                    OrderByComparator orderByComparator) {
286    
287                    query.append(ORDER_BY_CLAUSE);
288    
289                    String[] orderByFields = orderByComparator.getOrderByFields();
290    
291                    for (int i = 0; i < orderByFields.length; i++) {
292                            query.append(entityAlias);
293                            query.append(orderByFields[i]);
294    
295                            if ((i + 1) < orderByFields.length) {
296                                    if (orderByComparator.isAscending()) {
297                                            query.append(ORDER_BY_ASC_HAS_NEXT);
298                                    }
299                                    else {
300                                            query.append(ORDER_BY_DESC_HAS_NEXT);
301                                    }
302                            }
303                            else {
304                                    if (orderByComparator.isAscending()) {
305                                            query.append(ORDER_BY_ASC);
306                                    }
307                                    else {
308                                            query.append(ORDER_BY_DESC);
309                                    }
310                            }
311                    }
312            }
313    
314            /**
315             * Removes the model instance from the database. {@link #update(BaseModel,
316             * boolean)} depends on this method to implement the remove operation; it
317             * only notifies the model listeners.
318             *
319             * @param  model the model instance to remove
320             * @return the model instance that was removed
321             * @throws SystemException if a system exception occurred
322             */
323            protected T removeImpl(T model) throws SystemException {
324                    throw new UnsupportedOperationException();
325            }
326    
327            /**
328             * Updates the model instance in the database or adds it if it does not yet
329             * exist. {@link #remove(BaseModel)} depends on this method to implement the
330             * update operation; it only notifies the model listeners.
331             *
332             * @param  model the model instance to update
333             * @param  merge whether to merge the model instance with the current
334             *         session. See {@link
335             *         com.liferay.portal.service.persistence.BatchSession#update(
336             *         com.liferay.portal.kernel.dao.orm.Session, BaseModel, boolean)}
337             *         for an explanation.
338             * @return the model instance that was updated
339             * @throws SystemException if a system exception occurred
340             */
341            protected T updateImpl(T model, boolean merge) throws SystemException {
342                    throw new UnsupportedOperationException();
343            }
344    
345            protected static final Object[] FINDER_ARGS_EMPTY = new Object[0];
346    
347            protected static final String ORDER_BY_ASC = " ASC";
348    
349            protected static final String ORDER_BY_ASC_HAS_NEXT = " ASC, ";
350    
351            protected static final String ORDER_BY_CLAUSE = " ORDER BY ";
352    
353            protected static final String ORDER_BY_DESC = " DESC";
354    
355            protected static final String ORDER_BY_DESC_HAS_NEXT = " DESC, ";
356    
357            protected static final String WHERE_AND = " AND ";
358    
359            protected static final String WHERE_LESSER_THAN = " <= ? ";
360    
361            protected static final String WHERE_LESSER_THAN_HAS_NEXT = " <= ? AND ";
362    
363            protected static final String WHERE_GREATER_THAN = " >= ? ";
364    
365            protected static final String WHERE_GREATER_THAN_HAS_NEXT = " >= ? AND ";
366    
367            protected static final String WHERE_OR = " OR ";
368    
369            protected ModelListener<T>[] listeners = new ModelListener[0];
370    
371            private static Log _log = LogFactoryUtil.getLog(BasePersistenceImpl.class);
372    
373            private DataSource _dataSource;
374            private DB _db;
375            private Dialect _dialect;
376            private SessionFactory _sessionFactory;
377    
378    }