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