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